提交 e4dd8b64 编写于 作者: J Johannes Rieken

add native promise polyfill, #35516

上级 6d8cbf85
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Promise as WinJSPromise } from './winjs.base';
/**
* A polyfill for the native promises. The implementation is based on
* WinJS promises but tries to gap differences between winjs promises
* and native promises.
*/
export class PolyfillPromise<T = any> implements Promise<T> {
static all(thenables: Thenable<any>[]): PolyfillPromise {
return new PolyfillPromise(WinJSPromise.join(thenables).then(null, values => {
// WinJSPromise returns a sparse array whereas
// native promises return the *first* error
for (var key in values) {
if (values.hasOwnProperty(key)) {
return values[key];
}
}
}));
}
static race(thenables: Thenable<any>[]): PolyfillPromise {
// WinJSPromise returns `{ key: <index/key>, value: <promise> }`
// from the `any` call and Promise.race just wants the value
return new PolyfillPromise(WinJSPromise.any(thenables).then(entry => entry.value, err => err.value));
}
static resolve(value): PolyfillPromise {
return new PolyfillPromise(WinJSPromise.wrap(value));
}
static reject(value): PolyfillPromise {
return new PolyfillPromise(WinJSPromise.wrapError(value));
}
private _winjsPromise: WinJSPromise;
constructor(winjsPromise: WinJSPromise);
constructor(callback: (resolve: (value?: T) => void, reject: (err?: any) => void) => any);
constructor(callback: WinJSPromise | ((resolve: (value?: T) => void, reject: (err?: any) => void) => any)) {
if (WinJSPromise.is(callback)) {
this._winjsPromise = callback;
} else {
this._winjsPromise = new WinJSPromise((resolve, reject) => {
let initializing = true;
callback(function (value) {
if (!initializing) {
resolve(value);
} else {
setImmediate(resolve, value);
}
}, function (err) {
if (!initializing) {
reject(err);
} else {
setImmediate(reject, err);
}
});
initializing = false;
});
}
}
then(onFulfilled?: any, onRejected?: any): PolyfillPromise {
return new PolyfillPromise(this._winjsPromise.then(onFulfilled, onRejected));
}
catch(onRejected?: any): PolyfillPromise {
return new PolyfillPromise(this._winjsPromise.then(null, onRejected));
}
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { PolyfillPromise } from 'vs/base/common/winjs.polyfill.promise';
import { Promise as WinJSPromise } from 'vs/base/common/winjs.base';
suite('Polyfill Promise', function () {
test('sync-resolve, NativePromise', function () {
// native promise behaviour
const actual: string[] = [];
const promise = new Promise(resolve => {
actual.push('inCtor');
resolve(null);
}).then(() => actual.push('inThen'));
actual.push('afterCtor');
return promise.then(() => {
assert.deepEqual(actual, ['inCtor', 'afterCtor', 'inThen']);
});
});
test('sync-resolve, WinJSPromise', function () {
// winjs promise behaviour
const actual: string[] = [];
const promise = new WinJSPromise(resolve => {
actual.push('inCtor');
resolve(null);
}).then(() => actual.push('inThen'));
actual.push('afterCtor');
return promise.then(() => {
assert.deepEqual(actual, ['inCtor', 'inThen', 'afterCtor']);
});
});
test('sync-resolve, PolyfillPromise', function () {
// winjs promise behaviour
const actual: string[] = [];
const promise = new PolyfillPromise(resolve => {
actual.push('inCtor');
resolve(null);
}).then(() => actual.push('inThen'));
actual.push('afterCtor');
return promise.then(() => {
assert.deepEqual(actual, ['inCtor', 'afterCtor', 'inThen']);
});
});
test('PolyfillPromise, executor has two params', function () {
return new PolyfillPromise(function () {
assert.equal(arguments.length, 2);
assert.equal(typeof arguments[0], 'function');
assert.equal(typeof arguments[1], 'function');
arguments[0]();
});
});
// run the same tests for the native and polyfill promise
(<any[]>[Promise, PolyfillPromise]).forEach(PromiseCtor => {
test(PromiseCtor.name + ', resolved value', function () {
return new PromiseCtor(resolve => resolve(1)).then(value => assert.equal(value, 1));
});
test(PromiseCtor.name + ', rejected value', function () {
return new PromiseCtor((_, reject) => reject(1)).then(null, value => assert.equal(value, 1));
});
test(PromiseCtor.name + ', catch', function () {
return new PromiseCtor((_, reject) => reject(1)).catch(value => assert.equal(value, 1));
});
test(PromiseCtor.name + ', static-resolve', function () {
return PromiseCtor.resolve(42).then(value => assert.equal(value, 42));
});
test(PromiseCtor.name + ', static-reject', function () {
return PromiseCtor.reject(42).then(null, value => assert.equal(value, 42));
});
test(PromiseCtor.name + ', static-all, 1', function () {
return PromiseCtor.all([
PromiseCtor.resolve(1),
PromiseCtor.resolve(2)
]).then(values => {
assert.deepEqual(values, [1, 2]);
});
});
test(PromiseCtor.name + ', static-all, 2', function () {
return PromiseCtor.all([
PromiseCtor.resolve(1),
3,
PromiseCtor.resolve(2)
]).then(values => {
assert.deepEqual(values, [1, 3, 2]);
});
});
test(PromiseCtor.name + ', static-all, 3', function () {
return PromiseCtor.all([
PromiseCtor.resolve(1),
PromiseCtor.reject(13),
PromiseCtor.reject(12),
]).catch(values => {
assert.deepEqual(values, 13);
});
});
test(PromiseCtor.name + ', static-race, 1', function () {
return PromiseCtor.race([
PromiseCtor.resolve(1),
PromiseCtor.resolve(2),
]).then(value => {
assert.deepEqual(value, 1);
});
});
test(PromiseCtor.name + ', static-race, 2', function () {
return PromiseCtor.race([
PromiseCtor.reject(-1),
PromiseCtor.resolve(2),
]).catch(value => {
assert.deepEqual(value, -1);
});
});
test(PromiseCtor.name + ', static-race, 3', function () {
return PromiseCtor.race([
PromiseCtor.resolve(1),
PromiseCtor.reject(2),
]).then(value => {
assert.deepEqual(value, 1);
});
});
test(PromiseCtor.name + ', throw in ctor', function () {
return new PromiseCtor(() => {
throw new Error('sooo bad');
}).catch(err => {
assert.equal(err.message, 'sooo bad');
});
});
});
});
...@@ -19,6 +19,13 @@ import { createMonacoEditorAPI } from 'vs/editor/standalone/browser/standaloneEd ...@@ -19,6 +19,13 @@ import { createMonacoEditorAPI } from 'vs/editor/standalone/browser/standaloneEd
import { createMonacoLanguagesAPI } from 'vs/editor/standalone/browser/standaloneLanguages'; import { createMonacoLanguagesAPI } from 'vs/editor/standalone/browser/standaloneLanguages';
import { EDITOR_DEFAULTS, WrappingIndent } from 'vs/editor/common/config/editorOptions'; import { EDITOR_DEFAULTS, WrappingIndent } from 'vs/editor/common/config/editorOptions';
// When missing, polyfill the native promise
// with our winjs-based polyfill
import { PolyfillPromise } from 'vs/base/common/winjs.polyfill.promise';
if (typeof global.Promise === 'undefined') {
global.Promise = PolyfillPromise;
}
// Set defaults for standalone editor // Set defaults for standalone editor
(<any>EDITOR_DEFAULTS).wrappingIndent = WrappingIndent.None; (<any>EDITOR_DEFAULTS).wrappingIndent = WrappingIndent.None;
(<any>EDITOR_DEFAULTS.contribInfo).folding = false; (<any>EDITOR_DEFAULTS.contribInfo).folding = false;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册