Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
fix(promise): can set native promise after loading zone.js
Browse files Browse the repository at this point in the history
  • Loading branch information
JiaLiPassion committed Sep 13, 2017
1 parent e999593 commit d07a832
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 7 deletions.
1 change: 1 addition & 0 deletions karma-base.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = function (config) {
{pattern: 'node_modules/rxjs/**/**/*.js', included: false, watched: false },
{pattern: 'node_modules/rxjs/**/**/*.js.map', included: false, watched: false },
{pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
{pattern: 'node_modules/es6-promise/**/*.js', included: false, watched: false },
{pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false },
{pattern: 'test/assets/**/*.*', watched: true, served: true, included: false},
{pattern: 'build/**/*.js.map', watched: true, served: true, included: false},
Expand Down
38 changes: 38 additions & 0 deletions lib/common/promise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,44 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
ZoneAwarePromise['all'] = ZoneAwarePromise.all;

const NativePromise = global[symbolPromise] = global['Promise'];
const ZONE_AWARE_PROMISE = Zone.__symbol__('ZoneAwarePromise');

let desc = Object.getOwnPropertyDescriptor(global, 'Promise');
if (!desc || desc.configurable) {
desc && delete desc.writable;
desc && delete desc.value;
if (!desc) {
desc = {configurable: true, enumerable: true};
}
desc.get = function() {
// if we already set ZoneAwarePromise, use patched one
// otherwise return native one.
return global[ZONE_AWARE_PROMISE] ? global[ZONE_AWARE_PROMISE] : global[symbolPromise];
};
desc.set = function(NewNativePromise) {
if (NewNativePromise === ZoneAwarePromise) {
// if the NewNativePromise is ZoneAwarePromise
// save to global
global[ZONE_AWARE_PROMISE] = NewNativePromise;
} else {
// if the NewNativePromise is not ZoneAwarePromise
// for example: after load zone.js, some library just
// set es6-promise to global, if we set it to global
// directly, assertZonePatched will fail and angular
// will not loaded, so we just set the NewNativePromise
// to global[symbolPromise], so the result is just like
// we load ES6 Promise before zone.js
global[symbolPromise] = NewNativePromise;
if (!NewNativePromise.prototype[symbolThen]) {
patchThen(NewNativePromise);
}
api.setNativePromise(NewNativePromise);
}
};

Object.defineProperty(global, 'Promise', desc);
}

global['Promise'] = ZoneAwarePromise;

const symbolThenPatched = __symbol__('thenPatched');
Expand Down
4 changes: 4 additions & 0 deletions lib/zone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ interface _ZonePrivate {
showUncaughtError: () => boolean;
patchEventTarget: (global: any, apis: any[], options?: any) => boolean[];
patchOnProperties: (obj: any, properties: string[]) => void;
setNativePromise: (nativePromise: any) => void;
patchMethod:
(target: any, name: string,
patchFn: (delegate: Function, delegateName: string, name: string) =>
Expand Down Expand Up @@ -1318,6 +1319,9 @@ const Zone: ZoneType = (function(global: any) {
patchEventTarget: () => [],
patchOnProperties: noop,
patchMethod: () => noop,
setNativePromise: (NativePromise: any) => {
nativeMicroTaskQueuePromise = NativePromise.resolve(0);
},
};
let _currentZoneFrame: _ZoneFrame = {parent: null, zone: new Zone(null, null)};
let _currentTask: Task = null;
Expand Down
27 changes: 26 additions & 1 deletion test/common/Promise.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {isNode} from '../../lib/common/utils';
import {isNode, zoneSymbol} from '../../lib/common/utils';
import {ifEnvSupports} from '../test-util';

declare const global: any;
Expand Down Expand Up @@ -58,6 +58,31 @@ describe(
log = [];
});

xit('should allow set es6 Promise after load ZoneAwarePromise', (done) => {
const ES6Promise = require('es6-promise').Promise;
const NativePromise = global[zoneSymbol('Promise')];

try {
global['Promise'] = ES6Promise;
Zone.assertZonePatched();
expect(global[zoneSymbol('Promise')]).toBe(ES6Promise);
const promise = Promise.resolve(0);
console.log('promise', promise);
promise
.then(value => {
expect(value).toBe(0);
done();
})
.catch(error => {
fail(error);
});
} finally {
global['Promise'] = NativePromise;
Zone.assertZonePatched();
expect(global[zoneSymbol('Promise')]).toBe(NativePromise);
}
});

it('should pretend to be a native code', () => {
expect(String(Promise).indexOf('[native code]') >= 0).toBe(true);
});
Expand Down
15 changes: 11 additions & 4 deletions test/common/zone.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {zoneSymbol} from '../../lib/common/utils';

describe('Zone', function() {
const rootZone = Zone.current;
Expand Down Expand Up @@ -326,17 +327,23 @@ describe('Zone', function() {
Zone.assertZonePatched();
});

it('should throw when Promise has been patched', () => {
class WrongPromise {}
it('should keep ZoneAwarePromise has been patched', () => {
class WrongPromise {
static resolve(value: any) {}

then() {}
}

const ZoneAwarePromise = global.Promise;
const NativePromise = (global as any)[zoneSymbol('Promise')];
global.Promise = WrongPromise;
try {
expect(ZoneAwarePromise).toBeTruthy();
expect(() => Zone.assertZonePatched()).toThrow();
Zone.assertZonePatched();
expect(global.Promise).toBe(ZoneAwarePromise);
} finally {
// restore it.
global.Promise = ZoneAwarePromise;
global.Promise = NativePromise;
}
Zone.assertZonePatched();
});
Expand Down
7 changes: 5 additions & 2 deletions test/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ __karma__.loaded = function() {};
(window as any).global = window;
System.config({
defaultJSExtensions: true,
map: {'rxjs': 'base/node_modules/rxjs'},
map: {
'rxjs': 'base/node_modules/rxjs',
'es6-promise': 'base/node_modules/es6-promise/dist/es6-promise'
},
});

let browserPatchedPromise: any = null;
Expand All @@ -43,4 +46,4 @@ browserPatchedPromise.then(() => {
console.error(error.stack || error);
});
});
});
});

0 comments on commit d07a832

Please sign in to comment.