diff --git a/gulpfile.js b/gulpfile.js index 0bb8c47fb..71a099320 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -184,6 +184,14 @@ gulp.task('build/zone-patch-electron.min.js', ['compile-esm'], function(cb) { return generateScript('./lib/extra/electron.ts', 'zone-patch-electron.min.js', true, cb); }); +gulp.task('build/zone-patch-user-media.js', ['compile-esm'], function(cb) { + return generateScript('./lib/browser/webapis-user-media.ts', 'zone-patch-user-media.js', false, cb); +}); + +gulp.task('build/zone-patch-user-media.min.js', ['compile-esm'], function(cb) { + return generateScript('./lib/browser/webapis-user-media.ts', 'zone-patch-user-media.min.js', true, cb); +}); + gulp.task('build/bluebird.js', ['compile-esm'], function(cb) { return generateScript('./lib/extra/bluebird.ts', 'zone-bluebird.js', false, cb); }); @@ -287,6 +295,8 @@ gulp.task('build', [ 'build/zone-patch-cordova.min.js', 'build/zone-patch-electron.js', 'build/zone-patch-electron.min.js', + 'build/zone-patch-user-media.js', + 'build/zone-patch-user-media.min.js', 'build/zone-mix.js', 'build/bluebird.js', 'build/bluebird.min.js', diff --git a/lib/browser/browser.ts b/lib/browser/browser.ts index ce9a77c22..03f3b00db 100644 --- a/lib/browser/browser.ts +++ b/lib/browser/browser.ts @@ -12,20 +12,20 @@ import {findEventTasks} from '../common/events'; import {patchTimer} from '../common/timers'; -import {patchArguments, patchClass, patchMacroTask, patchMethod, patchOnProperties, patchPrototype, wrapFunctionArgs, zoneSymbol} from '../common/utils'; +import {bindArguments, i, j, o, patchClass, patchMacroTask, patchMethod, patchOnProperties, patchPrototype, r, zoneSymbol} from '../common/utils'; import {propertyPatch} from './define-property'; import {eventTargetPatch, patchEvent} from './event-target'; import {propertyDescriptorPatch} from './property-descriptor'; import {registerElementPatch} from './register-element'; -Zone.__load_patch('util', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('util', (global: any, Zone: ZoneType, api: _ZonePrivate) => { api.patchOnProperties = patchOnProperties; api.patchMethod = patchMethod; - api.patchArguments = patchArguments; + api.bindArguments = bindArguments; }); -Zone.__load_patch('timers', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('timers', (global: any) => { const set = 'set'; const clear = 'clear'; patchTimer(global, set, clear, 'Timeout'); @@ -33,27 +33,27 @@ Zone.__load_patch('timers', (global: any, Zone: ZoneType, api: _ZonePrivate) => patchTimer(global, set, clear, 'Immediate'); }); -Zone.__load_patch('requestAnimationFrame', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('requestAnimationFrame', (global: any) => { patchTimer(global, 'request', 'cancel', 'AnimationFrame'); patchTimer(global, 'mozRequest', 'mozCancel', 'AnimationFrame'); patchTimer(global, 'webkitRequest', 'webkitCancel', 'AnimationFrame'); }); -Zone.__load_patch('blocking', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('blocking', (global: any, Zone: ZoneType) => { const blockingMethods = ['alert', 'prompt', 'confirm']; for (let i = 0; i < blockingMethods.length; i++) { const name = blockingMethods[i]; patchMethod(global, name, (delegate, symbol, name) => { return function(s: any, args: any[]) { - return Zone.current.run(delegate, global, args, name); + return (Zone as any).c.r(delegate, global, args, name); }; }); } }); -Zone.__load_patch('EventTarget', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('EventTarget', (global: any, Zone: ZoneType, api: _ZonePrivate) => { // load blackListEvents from global - const SYMBOL_BLACK_LISTED_EVENTS = Zone.__symbol__('BLACK_LISTED_EVENTS'); + const SYMBOL_BLACK_LISTED_EVENTS = (Zone as any).s('BLACK_LISTED_EVENTS'); if (global[SYMBOL_BLACK_LISTED_EVENTS]) { (Zone as any)[SYMBOL_BLACK_LISTED_EVENTS] = global[SYMBOL_BLACK_LISTED_EVENTS]; } @@ -71,23 +71,23 @@ Zone.__load_patch('EventTarget', (global: any, Zone: ZoneType, api: _ZonePrivate patchClass('FileReader'); }); -Zone.__load_patch('on_property', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('on_property', (global: any, Zone: ZoneType, api: _ZonePrivate) => { propertyDescriptorPatch(api, global); propertyPatch(); registerElementPatch(global); }); -Zone.__load_patch('canvas', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('canvas', (global: any) => { const HTMLCanvasElement = global['HTMLCanvasElement']; - if (typeof HTMLCanvasElement !== 'undefined' && HTMLCanvasElement.prototype && + if (typeof HTMLCanvasElement !== o && HTMLCanvasElement.prototype && HTMLCanvasElement.prototype.toBlob) { patchMacroTask(HTMLCanvasElement.prototype, 'toBlob', (self: any, args: any[]) => { - return {name: 'HTMLCanvasElement.toBlob', target: self, callbackIndex: 0, args: args}; + return {name: 'HTMLCanvasElement.toBlob', target: self, cbIdx: 0, args: args}; }); } }); -Zone.__load_patch('XHR', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('XHR', (global: any, Zone: ZoneType) => { // Treat XMLHTTPRequest as a macrotask. patchXHR(global); @@ -105,21 +105,21 @@ Zone.__load_patch('XHR', (global: any, Zone: ZoneType, api: _ZonePrivate) => { } function patchXHR(window: any) { + const XMLHttpRequestPrototype: any = XMLHttpRequest.prototype; + function findPendingTask(target: any) { const pendingTask: Task = target[XHR_TASK]; return pendingTask; } - const SYMBOL_ADDEVENTLISTENER = zoneSymbol('addEventListener'); - const SYMBOL_REMOVEEVENTLISTENER = zoneSymbol('removeEventListener'); - - let oriAddListener = (XMLHttpRequest.prototype as any)[SYMBOL_ADDEVENTLISTENER]; - let oriRemoveListener = (XMLHttpRequest.prototype as any)[SYMBOL_REMOVEEVENTLISTENER]; + let oriAddListener = XMLHttpRequestPrototype[i]; + let oriRemoveListener = XMLHttpRequestPrototype[j]; if (!oriAddListener) { const XMLHttpRequestEventTarget = window['XMLHttpRequestEventTarget']; if (XMLHttpRequestEventTarget) { - oriAddListener = XMLHttpRequestEventTarget.prototype[SYMBOL_ADDEVENTLISTENER]; - oriRemoveListener = XMLHttpRequestEventTarget.prototype[SYMBOL_REMOVEEVENTLISTENER]; + const XMLHttpRequestEventTargetPrototype = XMLHttpRequestEventTarget.prototype; + oriAddListener = XMLHttpRequestEventTargetPrototype[i]; + oriRemoveListener = XMLHttpRequestEventTargetPrototype[j]; } } @@ -133,8 +133,8 @@ Zone.__load_patch('XHR', (global: any, Zone: ZoneType, api: _ZonePrivate) => { // remove existing event listener const listener = target[XHR_LISTENER]; if (!oriAddListener) { - oriAddListener = target[SYMBOL_ADDEVENTLISTENER]; - oriRemoveListener = target[SYMBOL_REMOVEEVENTLISTENER]; + oriAddListener = target[i]; + oriRemoveListener = target[j]; } if (listener) { @@ -170,17 +170,17 @@ Zone.__load_patch('XHR', (global: any, Zone: ZoneType, api: _ZonePrivate) => { return abortNative.apply(data.target, data.args); } - const openNative: Function = patchMethod( - window.XMLHttpRequest.prototype, 'open', () => function(self: any, args: any[]) { + const openNative: Function = + patchMethod(XMLHttpRequestPrototype, 'open', () => function(self: any, args: any[]) { self[XHR_SYNC] = args[2] == false; self[XHR_URL] = args[1]; return openNative.apply(self, args); }); const XMLHTTPREQUEST_SOURCE = 'XMLHttpRequest.send'; - const sendNative: Function = patchMethod( - window.XMLHttpRequest.prototype, 'send', () => function(self: any, args: any[]) { - const zone = Zone.current; + const sendNative: Function = + patchMethod(XMLHttpRequestPrototype, 'send', () => function(self: any, args: any[]) { + const zone = (Zone as any).c; if (self[XHR_SYNC]) { // if the XHR is sync there is no task to schedule, just execute the code. return sendNative.apply(self, args); @@ -193,49 +193,38 @@ Zone.__load_patch('XHR', (global: any, Zone: ZoneType, api: _ZonePrivate) => { args: args, aborted: false }; - return zone.scheduleMacroTask( + return zone.sc( XMLHTTPREQUEST_SOURCE, placeholderCallback, options, scheduleTask, clearTask); } }); - const STRING_TYPE = 'string'; - - const abortNative = patchMethod( - window.XMLHttpRequest.prototype, 'abort', - (delegate: Function) => function(self: any, args: any[]) { - const task: Task = findPendingTask(self); - if (task && typeof task.type == STRING_TYPE) { - // If the XHR has already completed, do nothing. - // If the XHR has already been aborted, do nothing. - // Fix #569, call abort multiple times before done will cause - // macroTask task count be negative number - if (task.cancelFn == null || (task.data && (task.data).aborted)) { - return; - } - task.zone.cancelTask(task); - } - // Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no - // task - // to cancel. Do nothing. - }); + const abortNative = patchMethod(XMLHttpRequestPrototype, 'abort', () => function(self: any) { + const task: Task = findPendingTask(self); + if (task && typeof task.type == r) { + // If the XHR has already completed, do nothing. + // If the XHR has already been aborted, do nothing. + // Fix #569, call abort multiple times before done will cause + // macroTask task count be negative number + if (task.cancelFn == null || (task.data && (task.data).aborted)) { + return; + } + (task.zone as any).ct(task); + } + // Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no + // task + // to cancel. Do nothing. + }); } }); -Zone.__load_patch('geolocation', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('geolocation', (global: any) => { /// GEO_LOCATION if (global['navigator'] && global['navigator'].geolocation) { patchPrototype(global['navigator'].geolocation, ['getCurrentPosition', 'watchPosition']); } }); -Zone.__load_patch('getUserMedia', (global: any, Zone: ZoneType, api: _ZonePrivate) => { - let navigator = global['navigator']; - if (navigator && navigator.getUserMedia) { - navigator.getUserMedia = wrapFunctionArgs(navigator.getUserMedia); - } -}); - -Zone.__load_patch('PromiseRejectionEvent', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('PromiseRejectionEvent', (global: any, Zone: ZoneType) => { // handle unhandled promise rejection function findPromiseRejectionHandler(evtName: string) { return function(e: any) { diff --git a/lib/browser/define-property.ts b/lib/browser/define-property.ts index 2a2f0e18f..ae966c86e 100644 --- a/lib/browser/define-property.ts +++ b/lib/browser/define-property.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {zoneSymbol} from '../common/utils'; +import {o, p, zoneSymbol} from '../common/utils'; /* * This is necessary for Chrome and Chrome mobile, to enable * things like redefining `createdCallback` on an element. @@ -17,9 +17,6 @@ const _getOwnPropertyDescriptor = (Object as any)[zoneSymbol('getOwnPropertyDesc Object.getOwnPropertyDescriptor; const _create = Object.create; const unconfigurablesKey = zoneSymbol('unconfigurables'); -const PROTOTYPE = 'prototype'; -const OBJECT = 'object'; -const UNDEFINED = 'undefined'; export function propertyPatch() { Object.defineProperty = function(obj, prop, desc) { @@ -27,7 +24,7 @@ export function propertyPatch() { throw new TypeError('Cannot assign to read only property \'' + prop + '\' of ' + obj); } const originalConfigurableFlag = desc.configurable; - if (prop !== PROTOTYPE) { + if (prop !== 'prototype') { desc = rewriteDescriptor(obj, prop, desc); } return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag); @@ -41,7 +38,7 @@ export function propertyPatch() { }; Object.create = function(obj: any, proto: any) { - if (typeof proto === OBJECT && !Object.isFrozen(proto)) { + if (typeof proto === p && !Object.isFrozen(proto)) { Object.keys(proto).forEach(function(prop) { proto[prop] = rewriteDescriptor(obj, prop, proto[prop]); }); @@ -92,7 +89,7 @@ function _tryDefineProperty(obj: any, prop: string, desc: any, originalConfigura if (desc.configurable) { // In case of errors, when the configurable flag was likely set by rewriteDescriptor(), let's // retry with the original flag value - if (typeof originalConfigurableFlag == UNDEFINED) { + if (typeof originalConfigurableFlag == o) { delete desc.configurable; } else { desc.configurable = originalConfigurableFlag; diff --git a/lib/browser/event-target.ts b/lib/browser/event-target.ts index 2972cfbd6..d0bb6a897 100644 --- a/lib/browser/event-target.ts +++ b/lib/browser/event-target.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {FALSE_STR, globalSources, patchEventPrototype, patchEventTarget, TRUE_STR, ZONE_SYMBOL_PREFIX, zoneSymbolEventNames} from '../common/events'; -import {attachOriginToPatched, isIEOrEdge, zoneSymbol} from '../common/utils'; +import {ens, gs, patchEventPrototype, patchEventTarget} from '../common/events'; +import {isIEOrEdge, k, l, m} from '../common/utils'; import {eventNames} from './property-descriptor'; @@ -45,19 +45,19 @@ export function eventTargetPatch(_global: any, api: _ZonePrivate) { // predefine all __zone_symbol__ + eventName + true/false string for (let i = 0; i < eventNames.length; i++) { const eventName = eventNames[i]; - const falseEventName = eventName + FALSE_STR; - const trueEventName = eventName + TRUE_STR; - const symbol = ZONE_SYMBOL_PREFIX + falseEventName; - const symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName; - zoneSymbolEventNames[eventName] = {}; - zoneSymbolEventNames[eventName][FALSE_STR] = symbol; - zoneSymbolEventNames[eventName][TRUE_STR] = symbolCapture; + const falseEventName = eventName + l; + const trueEventName = eventName + k; + const symbol = m + falseEventName; + const symbolCapture = m + trueEventName; + ens[eventName] = {}; + ens[eventName][l] = symbol; + ens[eventName][k] = symbolCapture; } // predefine all task.source string for (let i = 0; i < WTF_ISSUE_555.length; i++) { const target: any = WTF_ISSUE_555_ARRAY[i]; - const targets: any = globalSources[target] = {}; + const targets: any = gs[target] = {}; for (let j = 0; j < eventNames.length; j++) { const eventName = eventNames[j]; targets[eventName] = target + ADD_EVENT_LISTENER_SOURCE + eventName; @@ -101,7 +101,7 @@ export function eventTargetPatch(_global: any, api: _ZonePrivate) { const type = _global[apis[i]]; apiTypes.push(type && type.prototype); } - patchEventTarget(_global, apiTypes, {validateHandler: checkIEAndCrossContext}); + patchEventTarget(_global, apiTypes, {vh: checkIEAndCrossContext}); api.patchEventTarget = patchEventTarget; return true; diff --git a/lib/browser/property-descriptor.ts b/lib/browser/property-descriptor.ts index 55c2df789..f8945947e 100644 --- a/lib/browser/property-descriptor.ts +++ b/lib/browser/property-descriptor.ts @@ -10,7 +10,7 @@ * @suppress {globalThis} */ -import {isBrowser, isMix, isNode, patchClass, patchOnProperties, zoneSymbol} from '../common/utils'; +import {a, b, d, isBrowser, isMix, isNode, o, patchClass, patchOnProperties, zoneSymbol} from '../common/utils'; import * as webSocketPatch from './websocket'; @@ -265,21 +265,19 @@ export function propertyDescriptorPatch(api: _ZonePrivate, _global: any) { return; } - const supportsWebSocket = typeof WebSocket !== 'undefined'; + const supportsWebSocket = typeof WebSocket !== o; if (canPatchViaPropertyDescriptor()) { const ignoreProperties: IgnoreProperty[] = _global.__Zone_ignore_on_properties; // for browsers that we can patch the descriptor: Chrome & Firefox if (isBrowser) { + const w: any = window; // in IE/Edge, onProp not exist in window object, but in WindowPrototype // so we need to pass WindowPrototype to check onProp exist or not - patchFilteredProperties( - window, eventNames.concat(['messageerror']), ignoreProperties, - Object.getPrototypeOf(window)); + patchFilteredProperties(w, eventNames.concat(['messageerror']), ignoreProperties, d(w)); patchFilteredProperties(Document.prototype, eventNames, ignoreProperties); - if (typeof(window)['SVGElement'] !== 'undefined') { - patchFilteredProperties( - (window)['SVGElement'].prototype, eventNames, ignoreProperties); + if (typeof w['SVGElement'] !== o) { + patchFilteredProperties(w['SVGElement'].prototype, eventNames, ignoreProperties); } patchFilteredProperties(Element.prototype, eventNames, ignoreProperties); patchFilteredProperties(HTMLElement.prototype, eventNames, ignoreProperties); @@ -292,11 +290,11 @@ export function propertyDescriptorPatch(api: _ZonePrivate, _global: any) { patchFilteredProperties(HTMLFrameElement.prototype, frameEventNames, ignoreProperties); patchFilteredProperties(HTMLIFrameElement.prototype, frameEventNames, ignoreProperties); - const HTMLMarqueeElement = (window as any)['HTMLMarqueeElement']; + const HTMLMarqueeElement = w['HTMLMarqueeElement']; if (HTMLMarqueeElement) { patchFilteredProperties(HTMLMarqueeElement.prototype, marqueeEventNames, ignoreProperties); } - const Worker = (window as any)['Worker']; + const Worker = w['Worker']; if (Worker) { patchFilteredProperties(Worker.prototype, workerEventNames, ignoreProperties); } @@ -308,7 +306,7 @@ export function propertyDescriptorPatch(api: _ZonePrivate, _global: any) { XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype, XMLHttpRequestEventNames, ignoreProperties); } - if (typeof IDBIndex !== 'undefined') { + if (typeof IDBIndex !== o) { patchFilteredProperties(IDBIndex.prototype, IDBIndexEventNames, ignoreProperties); patchFilteredProperties(IDBRequest.prototype, IDBIndexEventNames, ignoreProperties); patchFilteredProperties(IDBOpenDBRequest.prototype, IDBIndexEventNames, ignoreProperties); @@ -330,15 +328,17 @@ export function propertyDescriptorPatch(api: _ZonePrivate, _global: any) { } function canPatchViaPropertyDescriptor() { - if ((isBrowser || isMix) && !Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'onclick') && - typeof Element !== 'undefined') { + if ((isBrowser || isMix) && !a(HTMLElement.prototype, 'onclick') && typeof Element !== o) { // WebKit https://bugs.webkit.org/show_bug.cgi?id=134364 // IDL interface attributes are not configurable - const desc = Object.getOwnPropertyDescriptor(Element.prototype, 'onclick'); + const desc = a(Element.prototype, 'onclick'); if (desc && !desc.configurable) return false; } - const xhrDesc = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'onreadystatechange'); + const ON_READY_STATE_CHANGE = 'onreadystatechange'; + const XMLHttpRequestPrototype = XMLHttpRequest.prototype; + + const xhrDesc = a(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE); // add enumerable and configurable here because in opera // by default XMLHttpRequest.prototype.onreadystatechange is undefined @@ -347,7 +347,7 @@ function canPatchViaPropertyDescriptor() { // and if XMLHttpRequest.prototype.onreadystatechange is undefined, // we should set a real desc instead a fake one if (xhrDesc) { - Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', { + b(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, { enumerable: true, configurable: true, get: function() { @@ -357,11 +357,11 @@ function canPatchViaPropertyDescriptor() { const req = new XMLHttpRequest(); const result = !!req.onreadystatechange; // restore original desc - Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {}); + b(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, xhrDesc || {}); return result; } else { - const SYMBOL_FAKE_ONREADYSTATECHANGE = zoneSymbol('fakeonreadystatechange'); - Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', { + const SYMBOL_FAKE_ONREADYSTATECHANGE = zoneSymbol('fake'); + b(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, { enumerable: true, configurable: true, get: function() { @@ -398,7 +398,7 @@ function patchViaCapturingAllTheEvents() { } while (elt) { if (elt[onproperty] && !elt[onproperty][unboundKey]) { - bound = Zone.current.wrap(elt[onproperty], source); + bound = (Zone as any).c.w(elt[onproperty], source); bound[unboundKey] = elt[onproperty]; elt[onproperty] = bound; } diff --git a/lib/browser/register-element.ts b/lib/browser/register-element.ts index 0f6f9a49a..74e1ccd05 100644 --- a/lib/browser/register-element.ts +++ b/lib/browser/register-element.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {attachOriginToPatched, isBrowser, isMix} from '../common/utils'; +import {a, attachOriginToPatched, isBrowser, isMix} from '../common/utils'; import {_redefineProperty} from './define-property'; @@ -23,16 +23,17 @@ export function registerElementPatch(_global: any) { if (opts && opts.prototype) { callbacks.forEach(function(callback) { const source = 'Document.registerElement::' + callback; - if (opts.prototype.hasOwnProperty(callback)) { - const descriptor = Object.getOwnPropertyDescriptor(opts.prototype, callback); + const p = opts.prototype; + if (p.hasOwnProperty(callback)) { + const descriptor = a(p, callback); if (descriptor && descriptor.value) { - descriptor.value = Zone.current.wrap(descriptor.value, source); + descriptor.value = (Zone as any).c.w(descriptor.value, source); _redefineProperty(opts.prototype, callback, descriptor); } else { - opts.prototype[callback] = Zone.current.wrap(opts.prototype[callback], source); + p[callback] = (Zone as any).c.w(p[callback], source); } - } else if (opts.prototype[callback]) { - opts.prototype[callback] = Zone.current.wrap(opts.prototype[callback], source); + } else if (p[callback]) { + p[callback] = (Zone as any).c.w(p[callback], source); } }); } diff --git a/lib/browser/shadydom.ts b/lib/browser/shadydom.ts index 2a0173a84..d02590204 100644 --- a/lib/browser/shadydom.ts +++ b/lib/browser/shadydom.ts @@ -5,7 +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 */ -Zone.__load_patch('shadydom', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('shadydom', (global: any, Zone: ZoneType, api: _ZonePrivate) => { // https://github.com/angular/zone.js/issues/782 // in web components, shadydom will patch addEventListener/removeEventListener of // Node.prototype and WindowPrototype, this will have conflict with zone.js @@ -21,4 +21,4 @@ Zone.__load_patch('shadydom', (global: any, Zone: ZoneType, api: _ZonePrivate) = (Node.prototype as any)[Zone.__symbol__('removeEventListener')] = null; api.patchEventTarget(global, [Node.prototype]); } -}); \ No newline at end of file +}); diff --git a/lib/browser/webapis-media-query.ts b/lib/browser/webapis-media-query.ts index d1fcd53d8..b26831327 100644 --- a/lib/browser/webapis-media-query.ts +++ b/lib/browser/webapis-media-query.ts @@ -5,11 +5,10 @@ * 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 */ -Zone.__load_patch('mediaQuery', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('mediaQuery', (global: any, Zone: ZoneType, api: _ZonePrivate) => { if (!global['MediaQueryList']) { return; } api.patchEventTarget( - global, [global['MediaQueryList'].prototype], - {addEventListenerFnName: 'addListener', removeEventListenerFnName: 'removeListener'}); -}); \ No newline at end of file + global, [global['MediaQueryList'].prototype], {add: 'addListener', rm: 'removeListener'}); +}); diff --git a/lib/browser/webapis-notification.ts b/lib/browser/webapis-notification.ts index 1bccaa9c9..b714b3830 100644 --- a/lib/browser/webapis-notification.ts +++ b/lib/browser/webapis-notification.ts @@ -5,7 +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 */ -Zone.__load_patch('notification', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('notification', (global: any, Zone: ZoneType, api: _ZonePrivate) => { const Notification = global['Notification']; if (!Notification || !Notification.prototype) { return; @@ -15,4 +15,4 @@ Zone.__load_patch('notification', (global: any, Zone: ZoneType, api: _ZonePrivat return; } api.patchOnProperties(Notification.prototype, null); -}); \ No newline at end of file +}); diff --git a/lib/browser/webapis-rtc-peer-connection.ts b/lib/browser/webapis-rtc-peer-connection.ts index 2551ae234..666b4482d 100644 --- a/lib/browser/webapis-rtc-peer-connection.ts +++ b/lib/browser/webapis-rtc-peer-connection.ts @@ -5,7 +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 */ -Zone.__load_patch('RTCPeerConnection', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('RTCPeerConnection', (global: any, Zone: ZoneType, api: _ZonePrivate) => { const RTCPeerConnection = global['RTCPeerConnection']; if (!RTCPeerConnection) { return; @@ -22,5 +22,5 @@ Zone.__load_patch('RTCPeerConnection', (global: any, Zone: ZoneType, api: _ZoneP RTCPeerConnection.prototype[addSymbol] = null; RTCPeerConnection.prototype[removeSymbol] = null; - api.patchEventTarget(global, [RTCPeerConnection.prototype], {useGlobalCallback: false}); + api.patchEventTarget(global, [RTCPeerConnection.prototype], {useG: false}); }); diff --git a/lib/browser/webapis-user-media.ts b/lib/browser/webapis-user-media.ts new file mode 100644 index 000000000..f93085a83 --- /dev/null +++ b/lib/browser/webapis-user-media.ts @@ -0,0 +1,20 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * 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 + */ +(Zone as any).l('getUserMedia', (global: any, Zone: any, api: _ZonePrivate) => { + function wrapFunctionArgs(func: Function, source?: string): Function { + return function() { + const args = Array.prototype.slice.call(arguments); + const wrappedArgs = api.bindArguments(args, source ? source : (func as any).name); + return func.apply(this, wrappedArgs); + }; + } + let navigator = global['navigator']; + if (navigator && navigator.getUserMedia) { + navigator.getUserMedia = wrapFunctionArgs(navigator.getUserMedia); + } +}); diff --git a/lib/browser/websocket.ts b/lib/browser/websocket.ts index d9f3354c9..5714b6c77 100644 --- a/lib/browser/websocket.ts +++ b/lib/browser/websocket.ts @@ -7,7 +7,7 @@ */ import {patchEventTarget} from '../common/events'; -import {patchOnProperties} from '../common/utils'; +import {a, e, f, g, h, patchOnProperties} from '../common/utils'; // we have to patch the instance since the proto is non-configurable export function apply(api: _ZonePrivate, _global: any) { @@ -17,27 +17,27 @@ export function apply(api: _ZonePrivate, _global: any) { if (!(_global).EventTarget) { patchEventTarget(_global, [WS.prototype]); } - (_global).WebSocket = function(a: any, b: any) { - const socket = arguments.length > 1 ? new WS(a, b) : new WS(a); + (_global).WebSocket = function(x: any, y: any) { + const socket = arguments.length > 1 ? new WS(x, y) : new WS(x); let proxySocket: any; let proxySocketProto: any; // Safari 7.0 has non-configurable own 'onmessage' and friends properties on the socket instance - const onmessageDesc = Object.getOwnPropertyDescriptor(socket, 'onmessage'); + const onmessageDesc = a(socket, 'onmessage'); if (onmessageDesc && onmessageDesc.configurable === false) { - proxySocket = Object.create(socket); + proxySocket = e(socket); // socket have own property descriptor 'onopen', 'onmessage', 'onclose', 'onerror' // but proxySocket not, so we will keep socket as prototype and pass it to // patchOnProperties method proxySocketProto = socket; - ['addEventListener', 'removeEventListener', 'send', 'close'].forEach(function(propName) { + [g, h, 'send', 'close'].forEach(function(propName) { proxySocket[propName] = function() { - const args = Array.prototype.slice.call(arguments); - if (propName === 'addEventListener' || propName === 'removeEventListener') { + const args = f.call(arguments); + if (propName === g || propName === h) { const eventName = args.length > 0 ? args[0] : undefined; if (eventName) { - const propertySymbol = Zone.__symbol__('ON_PROPERTY' + eventName); + const propertySymbol = (Zone as any).s('ON_PROPERTY' + eventName); socket[propertySymbol] = proxySocket[propertySymbol]; } } diff --git a/lib/common/events.ts b/lib/common/events.ts index c5424a782..5b349ab75 100644 --- a/lib/common/events.ts +++ b/lib/common/events.ts @@ -10,56 +10,56 @@ * @suppress {missingRequire} */ -import {attachOriginToPatched, zoneSymbol} from './utils'; +import {attachOriginToPatched, d, g, h, k, l, m, n, p, zoneSymbol} from './utils'; -export const TRUE_STR = 'true'; -export const FALSE_STR = 'false'; - -export interface EventTaskData extends TaskData { readonly isUsingGlobalCallback?: boolean; } +/** @internal **/ +interface EventTaskData extends TaskData { + // use global callback or not + readonly useG?: boolean; +} // an identifier to tell ZoneTask do not create a new invoke closure -export const OPTIMIZED_ZONE_EVENT_TASK_DATA: EventTaskData = { - isUsingGlobalCallback: true +const OPTIMIZED_ZONE_EVENT_TASK_DATA: EventTaskData = { + useG: true }; -export const zoneSymbolEventNames: any = {}; -export const globalSources: any = {}; - -export const CONSTRUCTOR_NAME = 'name'; - -export const FUNCTION_TYPE = 'function'; -export const OBJECT_TYPE = 'object'; - -export const ZONE_SYMBOL_PREFIX = '__zone_symbol__'; +export const ens: any = {}; +export const gs: any = {}; const EVENT_NAME_SYMBOL_REGX = /^__zone_symbol__(\w+)(true|false)$/; - const IMMEDIATE_PROPAGATION_SYMBOL = ('__zone_symbol__propagationStopped'); export interface PatchEventTargetOptions { - validateHandler?: (nativeDelegate: any, delegate: any, target: any, args: any) => boolean; - addEventListenerFnName?: string; - removeEventListenerFnName?: string; - prependEventListenerFnName?: string; - listenersFnName?: string; - removeAllFnName?: string; - useGlobalCallback?: boolean; - checkDuplicate?: boolean; - returnTarget?: boolean; - compareTaskCallbackVsDelegate?: (task: any, delegate: any) => boolean; + // validateHandler + vh?: (nativeDelegate: any, delegate: any, target: any, args: any) => boolean; + // addEventListener function name + add?: string; + // removeEventListener function name + rm?: string; + // prependEventListener function name + prepend?: string; + // listeners function name + listeners?: string; + // removeAllListeners function name + rmAll?: string; + // useGlobalCallback flag + useG?: boolean; + // check duplicate flag when addEventListener + chkDup?: boolean; + // return target flag when addEventListener + rt?: boolean; + // event compare handler + diff?: (task: any, delegate: any) => boolean; } export function patchEventTarget( _global: any, apis: any[], patchOptions?: PatchEventTargetOptions) { - const ADD_EVENT_LISTENER = - (patchOptions && patchOptions.addEventListenerFnName) || 'addEventListener'; - const REMOVE_EVENT_LISTENER = - (patchOptions && patchOptions.removeEventListenerFnName) || 'removeEventListener'; + const ADD_EVENT_LISTENER = (patchOptions && patchOptions.add) || g; + const REMOVE_EVENT_LISTENER = (patchOptions && patchOptions.rm) || h; - const LISTENERS_EVENT_LISTENER = - (patchOptions && patchOptions.listenersFnName) || 'eventListeners'; + const LISTENERS_EVENT_LISTENER = (patchOptions && patchOptions.listeners) || 'eventListeners'; const REMOVE_ALL_LISTENERS_EVENT_LISTENER = - (patchOptions && patchOptions.removeAllFnName) || 'removeAllListeners'; + (patchOptions && patchOptions.rmAll) || 'removeAllListeners'; const zoneSymbolAddEventListener = zoneSymbol(ADD_EVENT_LISTENER); @@ -75,7 +75,7 @@ export function patchEventTarget( return; } const delegate = task.callback; - if (typeof delegate === OBJECT_TYPE && delegate.handleEvent) { + if (typeof delegate === p && delegate.handleEvent) { // create the bind version of handleEvent when invoke task.callback = (event: Event) => delegate.handleEvent(event); task.originalDelegate = delegate; @@ -83,7 +83,7 @@ export function patchEventTarget( // invoke static task.invoke task.invoke(task, target, [event]); const options = task.options; - if (options && typeof options === 'object' && options.once) { + if (options && typeof options === p && options.once) { // if options.once is true, after invoke once remove listener here // only browser need to do this, nodejs eventEmitter will cal removeListener // inside EventEmitter.once @@ -103,7 +103,7 @@ export function patchEventTarget( // event.target is needed for Samusung TV and SourceBuffer // || global is needed https://github.com/angular/zone.js/issues/190 const target: any = this || event.target || _global; - const tasks = target[zoneSymbolEventNames[event.type][FALSE_STR]]; + const tasks = target[ens[event.type][l]]; if (tasks) { // invoke all tasks which attached to current target with given event.type and capture = false // for performance concern, if task.length === 1, just invoke @@ -135,7 +135,7 @@ export function patchEventTarget( // event.target is needed for Samusung TV and SourceBuffer // || global is needed https://github.com/angular/zone.js/issues/190 const target: any = this || event.target || _global; - const tasks = target[zoneSymbolEventNames[event.type][TRUE_STR]]; + const tasks = target[ens[event.type][k]]; if (tasks) { // invoke all tasks which attached to current target with given event.type and capture = false // for performance concern, if task.length === 1, just invoke @@ -162,24 +162,24 @@ export function patchEventTarget( } let useGlobalCallback = true; - if (patchOptions && patchOptions.useGlobalCallback !== undefined) { - useGlobalCallback = patchOptions.useGlobalCallback; + if (patchOptions && patchOptions.useG !== undefined) { + useGlobalCallback = patchOptions.useG; } - const validateHandler = patchOptions && patchOptions.validateHandler; + const validateHandler = patchOptions && patchOptions.vh; let checkDuplicate = true; - if (patchOptions && patchOptions.checkDuplicate !== undefined) { - checkDuplicate = patchOptions.checkDuplicate; + if (patchOptions && patchOptions.chkDup !== undefined) { + checkDuplicate = patchOptions.chkDup; } let returnTarget = false; - if (patchOptions && patchOptions.returnTarget !== undefined) { - returnTarget = patchOptions.returnTarget; + if (patchOptions && patchOptions.rt !== undefined) { + returnTarget = patchOptions.rt; } let proto = obj; while (proto && !proto.hasOwnProperty(ADD_EVENT_LISTENER)) { - proto = Object.getPrototypeOf(proto); + proto = d(proto); } if (!proto && obj[ADD_EVENT_LISTENER]) { // somehow we did not find it, but we can see it. This happens on IE for Window properties. @@ -207,9 +207,9 @@ export function patchEventTarget( proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER]; let nativePrependEventListener: any; - if (patchOptions && patchOptions.prependEventListenerFnName) { - nativePrependEventListener = proto[zoneSymbol(patchOptions.prependEventListenerFnName)] = - proto[patchOptions.prependEventListenerFnName]; + if (patchOptions && patchOptions.prepend) { + nativePrependEventListener = proto[zoneSymbol(patchOptions.prepend)] = + proto[patchOptions.prepend]; } const customScheduleGlobal = function(task: Task) { @@ -230,10 +230,10 @@ export function patchEventTarget( // from Zone.prototype.cancelTask, we should remove the task // from tasksList of target first if (!task.isRemoved) { - const symbolEventNames = zoneSymbolEventNames[task.eventName]; + const symbolEventNames = ens[task.eventName]; let symbolEventName; if (symbolEventNames) { - symbolEventName = symbolEventNames[task.capture ? TRUE_STR : FALSE_STR]; + symbolEventName = symbolEventNames[task.capture ? k : l]; } const existingTasks = symbolEventName && task.target[symbolEventName]; if (existingTasks) { @@ -286,26 +286,24 @@ export function patchEventTarget( const compareTaskCallbackVsDelegate = function(task: any, delegate: any) { const typeOfDelegate = typeof delegate; - if ((typeOfDelegate === FUNCTION_TYPE && task.callback === delegate) || - (typeOfDelegate === OBJECT_TYPE && task.originalDelegate === delegate)) { + if ((typeOfDelegate === n && task.callback === delegate) || + (typeOfDelegate === p && task.originalDelegate === delegate)) { // same callback, same capture, same event name, just return return true; } return false; }; - const compare = (patchOptions && patchOptions.compareTaskCallbackVsDelegate) ? - patchOptions.compareTaskCallbackVsDelegate : - compareTaskCallbackVsDelegate; + const compare = + (patchOptions && patchOptions.diff) ? patchOptions.diff : compareTaskCallbackVsDelegate; - const blackListedEvents: string[] = (Zone as any)[Zone.__symbol__('BLACK_LISTED_EVENTS')]; + const blackListedEvents: string[] = (Zone as any)[(Zone as any).s('BLACK_LISTED_EVENTS')]; const makeAddListener = function( nativeListener: any, addSource: string, customScheduleFn: any, customCancelFn: any, returnTarget = false, prepend = false) { return function() { const target = this || _global; - const targetZone = Zone.current; let delegate = arguments[1]; if (!delegate) { return nativeListener.apply(this, arguments); @@ -315,7 +313,7 @@ export function patchEventTarget( // case here to improve addEventListener performance // we will create the bind delegate when invoke let isHandleEvent = false; - if (typeof delegate !== FUNCTION_TYPE) { + if (typeof delegate !== n) { if (!delegate.handleEvent) { return nativeListener.apply(this, arguments); } @@ -351,21 +349,21 @@ export function patchEventTarget( once = options ? !!options.once : false; } - const zone = Zone.current; - const symbolEventNames = zoneSymbolEventNames[eventName]; + const zone = (Zone as any).c; + const symbolEventNames = ens[eventName]; let symbolEventName; if (!symbolEventNames) { // the code is duplicate, but I just want to get some better performance - const falseEventName = eventName + FALSE_STR; - const trueEventName = eventName + TRUE_STR; - const symbol = ZONE_SYMBOL_PREFIX + falseEventName; - const symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName; - zoneSymbolEventNames[eventName] = {}; - zoneSymbolEventNames[eventName][FALSE_STR] = symbol; - zoneSymbolEventNames[eventName][TRUE_STR] = symbolCapture; + const falseEventName = eventName + l; + const trueEventName = eventName + k; + const symbol = m + falseEventName; + const symbolCapture = m + trueEventName; + ens[eventName] = {}; + ens[eventName][l] = symbol; + ens[eventName][k] = symbolCapture; symbolEventName = capture ? symbolCapture : symbol; } else { - symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR]; + symbolEventName = symbolEventNames[capture ? k : l]; } let existingTasks = target[symbolEventName]; let isExisting = false; @@ -384,8 +382,8 @@ export function patchEventTarget( existingTasks = target[symbolEventName] = []; } let source; - const constructorName = target.constructor[CONSTRUCTOR_NAME]; - const targetSource = globalSources[constructorName]; + const constructorName = target.constructor['name']; + const targetSource = gs[constructorName]; if (targetSource) { source = targetSource[eventName]; } @@ -414,7 +412,7 @@ export function patchEventTarget( } const task: any = - zone.scheduleEventTask(source, delegate, data, customScheduleFn, customCancelFn); + (zone as any).se(source, delegate, data, customScheduleFn, customCancelFn); // should clear taskData.target to avoid memory leak // issue, https://github.com/angular/angular/issues/20442 @@ -485,10 +483,10 @@ export function patchEventTarget( return; } - const symbolEventNames = zoneSymbolEventNames[eventName]; + const symbolEventNames = ens[eventName]; let symbolEventName; if (symbolEventNames) { - symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR]; + symbolEventName = symbolEventNames[capture ? k : l]; } const existingTasks = symbolEventName && target[symbolEventName]; if (existingTasks) { @@ -505,7 +503,7 @@ export function patchEventTarget( (existingTask as any).allRemoved = true; target[symbolEventName] = null; } - existingTask.zone.cancelTask(existingTask); + (existingTask.zone as any).ct(existingTask); return; } } @@ -553,10 +551,10 @@ export function patchEventTarget( // remove removeListener listener finally this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].apply(this, ['removeListener']); } else { - const symbolEventNames = zoneSymbolEventNames[eventName]; + const symbolEventNames = ens[eventName]; if (symbolEventNames) { - const symbolEventName = symbolEventNames[FALSE_STR]; - const symbolCaptureEventName = symbolEventNames[TRUE_STR]; + const symbolEventName = symbolEventNames[l]; + const symbolCaptureEventName = symbolEventNames[k]; const tasks = target[symbolEventName]; const captureTasks = target[symbolCaptureEventName]; diff --git a/lib/common/promise.ts b/lib/common/promise.ts index 7d0484f4a..c9a7a0ddf 100644 --- a/lib/common/promise.ts +++ b/lib/common/promise.ts @@ -5,7 +5,12 @@ * 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 */ -Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePrivate) => { + const a = Object.getOwnPropertyDescriptor; + const b = Object.defineProperty; + const n = 'function'; + const p = 'object'; + function readableObjectToString(obj: any) { if (obj && obj.toString === Object.prototype.toString) { const className = obj.constructor && obj.constructor.name; @@ -48,7 +53,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr while (_uncaughtPromiseErrors.length) { const uncaughtPromiseError: UncaughtPromiseError = _uncaughtPromiseErrors.shift(); try { - uncaughtPromiseError.zone.runGuarded(() => { + (uncaughtPromiseError.zone as any).rg(() => { throw uncaughtPromiseError; }); } catch (error) { @@ -64,7 +69,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr api.onUnhandledError(e); try { const handler = (Zone as any)[UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL]; - if (handler && typeof handler === 'function') { + if (handler && typeof handler === n) { handler.apply(this, [e]); } } catch (err) { @@ -117,8 +122,6 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr }; const TYPE_ERROR = 'Promise resolved with itself'; - const OBJECT = 'object'; - const FUNCTION = 'function'; const CURRENT_TASK_TRACE_SYMBOL = __symbol__('currentTaskTrace'); // Promise Resolution @@ -132,7 +135,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr // should only get value.then once based on promise spec. let then: any = null; try { - if (typeof value === OBJECT || typeof value === FUNCTION) { + if (typeof value === p || typeof value === n) { then = value && value.then; } } catch (err) { @@ -147,7 +150,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr (value as any)[symbolState] !== UNRESOLVED) { clearRejectedNoCatch(>value); resolvePromise(promise, (value as any)[symbolState], (value as any)[symbolValue]); - } else if (state !== REJECTED && typeof then === FUNCTION) { + } else if (state !== REJECTED && typeof then === n) { try { then.apply(value, [ onceWrapper(makeResolver(promise, state)), onceWrapper(makeResolver(promise, false)) @@ -170,9 +173,8 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr (Zone.currentTask.data as any)[creationTrace]; if (trace) { // only keep the long stack trace into error when in longStackTraceZone - Object.defineProperty( - value, CURRENT_TASK_TRACE_SYMBOL, - {configurable: true, enumerable: false, writable: true, value: trace}); + b(value, CURRENT_TASK_TRACE_SYMBOL, + {configurable: true, enumerable: false, writable: true, value: trace}); } } @@ -190,7 +192,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr const error: UncaughtPromiseError = err; error.rejection = value; error.promise = promise; - error.zone = Zone.current; + error.zone = (Zone as any).c; error.task = Zone.currentTask; _uncaughtPromiseErrors.push(error); api.scheduleMicroTask(); // to make sure that it is running @@ -212,7 +214,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr // eventHandler try { const handler = (Zone as any)[REJECTION_HANDLED_HANDLER]; - if (handler && typeof handler === FUNCTION) { + if (handler && typeof handler === n) { handler.apply(this, [{rejection: (promise as any)[symbolValue], promise: promise}]); } } catch (err) { @@ -231,12 +233,13 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr onFulfilled?: (value: R) => U1, onRejected?: (error: any) => U2): void { clearRejectedNoCatch(promise); const delegate = (promise as any)[symbolState] ? - (typeof onFulfilled === FUNCTION) ? onFulfilled : forwardResolution : - (typeof onRejected === FUNCTION) ? onRejected : forwardRejection; - zone.scheduleMicroTask(source, () => { + (typeof onFulfilled === n) ? onFulfilled : forwardResolution : + (typeof onRejected === n) ? onRejected : forwardRejection; + (zone as any).si(source, () => { try { resolvePromise( - chainPromise, true, zone.run(delegate, undefined, [(promise as any)[symbolValue]])); + chainPromise, true, + (zone as any).r(delegate, undefined, [(promise as any)[symbolValue]])); } catch (error) { resolvePromise(chainPromise, false, error); } @@ -331,7 +334,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr null): Promise { const chainPromise: Promise = new (this.constructor as typeof ZoneAwarePromise)(null); - const zone = Zone.current; + const zone = (Zone as any).c; if ((this as any)[symbolState] == UNRESOLVED) { ((this as any)[symbolValue]).push(zone, chainPromise, onFulfilled, onRejected); } else { @@ -353,9 +356,9 @@ 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'); + const ZONE_AWARE_PROMISE = (Zone as any).s('ZoneAwarePromise'); - let desc = Object.getOwnPropertyDescriptor(global, 'Promise'); + let desc = a(global, 'Promise'); if (!desc || desc.configurable) { desc && delete desc.writable; desc && delete desc.value; @@ -388,7 +391,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr } }; - Object.defineProperty(global, 'Promise', desc); + b(global, 'Promise', desc); } global['Promise'] = ZoneAwarePromise; @@ -403,9 +406,9 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr // check Ctor.prototype.then propertyDescritor is writable or not // in meteor env, writable is false, we have to make it to be true. - const prop = Object.getOwnPropertyDescriptor(Ctor.prototype, 'then'); + const prop = a(Ctor.prototype, 'then'); if (prop && prop.writable === false && prop.configurable) { - Object.defineProperty(Ctor.prototype, 'then', {writable: true}); + b(Ctor.prototype, 'then', {writable: true}); } Ctor.prototype.then = function(onResolve: any, onReject: any) { @@ -435,12 +438,12 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr patchThen(NativePromise); let fetch = global['fetch']; - if (typeof fetch == FUNCTION) { + if (typeof fetch == n) { global['fetch'] = zoneify(fetch); } } // This is not part of public API, but it is useful for tests, so we expose it. - (Promise as any)[Zone.__symbol__('uncaughtPromiseErrors')] = _uncaughtPromiseErrors; + (Promise as any)[(Zone as any).s('uncaughtPromiseErrors')] = _uncaughtPromiseErrors; return ZoneAwarePromise; }); diff --git a/lib/common/timers.ts b/lib/common/timers.ts index 5f8d9aa1e..82266f0ad 100644 --- a/lib/common/timers.ts +++ b/lib/common/timers.ts @@ -10,7 +10,7 @@ * @suppress {missingRequire} */ -import {patchMethod, zoneSymbol} from './utils'; +import {n, patchMethod, q, r, zoneSymbol} from './utils'; const taskSymbol = zoneSymbol('zoneTask'); @@ -26,12 +26,6 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam cancelName += nameSuffix; const tasksByHandleId: {[id: number]: Task} = {}; - const NUMBER = 'number'; - const STRING = 'string'; - const FUNCTION = 'function'; - const INTERVAL = 'Interval'; - const TIMEOUT = 'Timeout'; - const NOT_SCHEDULED = 'notScheduled'; function scheduleTask(task: Task) { const data = task.data; @@ -45,7 +39,7 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam // setInterval return; } - if (typeof data.handleId === NUMBER) { + if (typeof data.handleId === q) { // in non-nodejs env, we remove timerId // from local cache delete tasksByHandleId[data.handleId]; @@ -67,21 +61,21 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam setNative = patchMethod(window, setName, (delegate: Function) => function(self: any, args: any[]) { - if (typeof args[0] === FUNCTION) { - const zone = Zone.current; + if (typeof args[0] === n) { + const zone = (Zone as any).c; const options: TimerOptions = { handleId: null, - isPeriodic: nameSuffix === INTERVAL, - delay: (nameSuffix === TIMEOUT || nameSuffix === INTERVAL) ? args[1] || 0 : null, + isPeriodic: nameSuffix === 'Interval', + delay: (nameSuffix === 'Timeout' || nameSuffix === 'Interval') ? args[1] || 0 : null, args: args }; - const task = zone.scheduleMacroTask(setName, args[0], options, scheduleTask, clearTask); + const task = (zone as any).sc(setName, args[0], options, scheduleTask, clearTask); if (!task) { return task; } // Node.js must additionally support the ref and unref functions. const handle: any = (task.data).handleId; - if (typeof handle === NUMBER) { + if (typeof handle === q) { // for non nodejs env, we save handleId: task // mapping in local cache for clearTimeout tasksByHandleId[handle] = task; @@ -93,12 +87,12 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam // check whether handle is null, because some polyfill or browser // may return undefined from setTimeout/setInterval/setImmediate/requestAnimationFrame - if (handle && handle.ref && handle.unref && typeof handle.ref === FUNCTION && - typeof handle.unref === FUNCTION) { + if (handle && handle.ref && handle.unref && typeof handle.ref === n && + typeof handle.unref === n) { (task).ref = (handle).ref.bind(handle); (task).unref = (handle).unref.bind(handle); } - if (typeof handle === NUMBER || handle) { + if (typeof handle === q || handle) { return handle; } return task; @@ -112,7 +106,7 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam patchMethod(window, cancelName, (delegate: Function) => function(self: any, args: any[]) { const id = args[0]; let task: Task; - if (typeof id === NUMBER) { + if (typeof id === q) { // non nodejs env. task = tasksByHandleId[id]; } else { @@ -123,16 +117,16 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam task = id; } } - if (task && typeof task.type === STRING) { - if (task.state !== NOT_SCHEDULED && + if (task && typeof task.type === r) { + if (task.state !== 'notScheduled' && (task.cancelFn && task.data.isPeriodic || task.runCount === 0)) { - if (typeof id === NUMBER) { + if (typeof id === q) { delete tasksByHandleId[id]; } else if (id) { id[taskSymbol] = null; } // Do not cancel already canceled functions - task.zone.cancelTask(task); + (task.zone as any).ct(task); } } else { // cause an error by calling it directly. diff --git a/lib/common/to-string.ts b/lib/common/to-string.ts index 9e7d7fe71..0499f6016 100644 --- a/lib/common/to-string.ts +++ b/lib/common/to-string.ts @@ -5,24 +5,23 @@ * 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 './utils'; +import {n, zoneSymbol} from './utils'; // override Function.prototype.toString to make zone.js patched function // look like native function -Zone.__load_patch('toString', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('toString', (global: any, Zone: ZoneType) => { // patch Func.prototype.toString to let them look like native const originalFunctionToString = (Zone as any)['__zone_symbol__originalToString'] = Function.prototype.toString; - const FUNCTION = 'function'; const ORIGINAL_DELEGATE_SYMBOL = zoneSymbol('OriginalDelegate'); const PROMISE_SYMBOL = zoneSymbol('Promise'); const ERROR_SYMBOL = zoneSymbol('Error'); Function.prototype.toString = function() { - if (typeof this === FUNCTION) { + if (typeof this === n) { const originalDelegate = this[ORIGINAL_DELEGATE_SYMBOL]; if (originalDelegate) { - if (typeof originalDelegate === FUNCTION) { + if (typeof originalDelegate === n) { return originalFunctionToString.apply(this[ORIGINAL_DELEGATE_SYMBOL], arguments); } else { return Object.prototype.toString.call(originalDelegate); diff --git a/lib/common/utils.ts b/lib/common/utils.ts index 938935f77..b792439a1 100644 --- a/lib/common/utils.ts +++ b/lib/common/utils.ts @@ -11,50 +11,51 @@ * @suppress {undefinedVars,globalThis,missingRequire} */ +// issue #989, to reduce bundle size, use short name +export const a = Object.getOwnPropertyDescriptor; +export const b = Object.defineProperty; +export const c = Object.defineProperties; +export const d = Object.getPrototypeOf; +export const e = Object.create; +export const f = Array.prototype.slice; +export const g = 'addEventListener'; +export const h = 'removeEventListener'; +export const i = (Zone as any).s(g); +export const j = (Zone as any).s(h); +export const k = 'true'; +export const l = 'false'; +export const m = '__zone_symbol__'; +export const n = 'function'; +export const o = 'undefined'; +export const p = 'object'; +export const q = 'number'; +export const r = 'string'; + // Hack since TypeScript isn't compiling this for a worker. declare const WorkerGlobalScope: any; export const zoneSymbol = Zone.__symbol__; -const _global: any = - typeof window === 'object' && window || typeof self === 'object' && self || global; +const _global: any = typeof window === p && window || typeof self === p && self || global; -const FUNCTION = 'function'; -const UNDEFINED = 'undefined'; const REMOVE_ATTRIBUTE = 'removeAttribute'; const NULL_ON_PROP_VALUE: any[] = [null]; export function bindArguments(args: any[], source: string): any[] { for (let i = args.length - 1; i >= 0; i--) { - if (typeof args[i] === FUNCTION) { - args[i] = Zone.current.wrap(args[i], source + '_' + i); + if (typeof args[i] === n) { + args[i] = (Zone as any).c.w(args[i], source + '_' + i); } } return args; } -export function wrapFunctionArgs(func: Function, source?: string): Function { - return function() { - const args = Array.prototype.slice.call(arguments); - const wrappedArgs = bindArguments(args, source ? source : (func as any).name); - return func.apply(this, wrappedArgs); - }; -} - -export function patchArguments(target: any, name: string, source: string): Function { - return patchMethod( - target, name, - (delegate: Function, delegateName: string, name: string) => (self: any, args: any[]) => { - return delegate && delegate.apply(self, bindArguments(args, source)); - }); -} - export function patchPrototype(prototype: any, fnNames: string[]) { const source = prototype.constructor['name']; for (let i = 0; i < fnNames.length; i++) { const name = fnNames[i]; const delegate = prototype[name]; if (delegate) { - const prototypeDesc = Object.getOwnPropertyDescriptor(prototype, name); + const prototypeDesc = a(prototype, name); if (!isPropertyWritable(prototypeDesc)) { continue; } @@ -78,7 +79,7 @@ export function isPropertyWritable(propertyDesc: any) { return false; } - if (typeof propertyDesc.get === FUNCTION && typeof propertyDesc.set === UNDEFINED) { + if (typeof propertyDesc.get === n && typeof propertyDesc.set === o) { return false; } @@ -86,23 +87,23 @@ export function isPropertyWritable(propertyDesc: any) { } export const isWebWorker: boolean = - (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope); + (typeof WorkerGlobalScope !== o && self instanceof WorkerGlobalScope); // Make sure to access `process` through `_global` so that WebPack does not accidently browserify // this code. export const isNode: boolean = - (!('nw' in _global) && typeof _global.process !== 'undefined' && + (!('nw' in _global) && typeof _global.process !== o && {}.toString.call(_global.process) === '[object process]'); export const isBrowser: boolean = - !isNode && !isWebWorker && !!(typeof window !== 'undefined' && (window as any)['HTMLElement']); + !isNode && !isWebWorker && !!(typeof window !== o && (window as any)['HTMLElement']); // we are in electron of nw, so we are both browser and nodejs // Make sure to access `process` through `_global` so that WebPack does not accidently browserify // this code. -export const isMix: boolean = typeof _global.process !== 'undefined' && +export const isMix: boolean = typeof _global.process !== o && {}.toString.call(_global.process) === '[object process]' && !isWebWorker && - !!(typeof window !== 'undefined' && (window as any)['HTMLElement']); + !!(typeof window !== o && (window as any)['HTMLElement']); const zoneSymbolEventNames: {[eventName: string]: string} = {}; @@ -128,10 +129,10 @@ const wrapFn = function(event: Event) { }; export function patchProperty(obj: any, prop: string, prototype?: any) { - let desc = Object.getOwnPropertyDescriptor(obj, prop); + let desc = a(obj, prop); if (!desc && prototype) { // when patch window object, use prototype to check prop exist or not - const prototypeDesc = Object.getOwnPropertyDescriptor(prototype, prop); + const prototypeDesc = a(prototype, prop); if (prototypeDesc) { desc = {enumerable: true, configurable: true}; } @@ -181,7 +182,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) { originalDescSet.apply(target, NULL_ON_PROP_VALUE); } - if (typeof newValue === 'function') { + if (typeof newValue === n) { target[eventNameSymbol] = newValue; target.addEventListener(eventName, wrapFn, false); } else { @@ -214,7 +215,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) { let value = originalDescGet && originalDescGet.apply(this); if (value) { desc.set.apply(this, [value]); - if (typeof target[REMOVE_ATTRIBUTE] === FUNCTION) { + if (typeof target[REMOVE_ATTRIBUTE] === n) { target.removeAttribute(prop); } return value; @@ -223,7 +224,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) { return null; }; - Object.defineProperty(obj, prop, desc); + b(obj, prop, desc); } export function patchOnProperties(obj: any, properties: string[], prototype?: any) { @@ -286,15 +287,15 @@ export function patchClass(className: string) { // https://bugs.webkit.org/show_bug.cgi?id=44721 if (className === 'XMLHttpRequest' && prop === 'responseBlob') continue; (function(prop) { - if (typeof instance[prop] === 'function') { + if (typeof instance[prop] === n) { _global[className].prototype[prop] = function() { return this[originalInstanceKey][prop].apply(this[originalInstanceKey], arguments); }; } else { - Object.defineProperty(_global[className].prototype, prop, { + b(_global[className].prototype, prop, { set: function(fn) { - if (typeof fn === 'function') { - this[originalInstanceKey][prop] = Zone.current.wrap(fn, className + '.' + prop); + if (typeof fn === n) { + this[originalInstanceKey][prop] = (Zone as any).c.w(fn, className + '.' + prop); // keep callback in wrapped function so we can // use it in Function.prototype.toString to return // the native one. @@ -324,7 +325,7 @@ export function patchMethod( any): Function { let proto = target; while (proto && !proto.hasOwnProperty(name)) { - proto = Object.getPrototypeOf(proto); + proto = d(proto); } if (!proto && target[name]) { // somehow we did not find it, but we can see it. This happens on IE for Window properties. @@ -337,7 +338,7 @@ export function patchMethod( delegate = proto[delegateName] = proto[name]; // check whether proto[name] is writable // some property is readonly in safari, such as HtmlCanvasElement.prototype.toBlob - const desc = proto && Object.getOwnPropertyDescriptor(proto, name); + const desc = proto && a(proto, name); if (isPropertyWritable(desc)) { const patchDelegate = patchFn(delegate, delegateName, name); proto[name] = function() { @@ -352,7 +353,7 @@ export function patchMethod( export interface MacroTaskMeta extends TaskData { name: string; target: any; - callbackIndex: number; + cbIdx: number; args: any[]; } @@ -363,7 +364,7 @@ export function patchMacroTask( function scheduleTask(task: Task) { const data = task.data; - data.args[data.callbackIndex] = function() { + data.args[data.cbIdx] = function() { task.invoke.apply(this, arguments); }; setNative.apply(data.target, data.args); @@ -372,9 +373,8 @@ export function patchMacroTask( setNative = patchMethod(obj, funcName, (delegate: Function) => function(self: any, args: any[]) { const meta = metaCreator(self, args); - if (meta.callbackIndex >= 0 && typeof args[meta.callbackIndex] === 'function') { - const task = Zone.current.scheduleMacroTask( - meta.name, args[meta.callbackIndex], meta, scheduleTask, null); + if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === n) { + const task = (Zone as any).c.sc(meta.name, args[meta.cbIdx], meta, scheduleTask, null); return task; } else { // cause an error by calling it directly. @@ -386,7 +386,7 @@ export function patchMacroTask( export interface MicroTaskMeta extends TaskData { name: string; target: any; - callbackIndex: number; + cbIdx: number; args: any[]; } @@ -396,7 +396,7 @@ export function patchMicroTask( function scheduleTask(task: Task) { const data = task.data; - data.args[data.callbackIndex] = function() { + data.args[data.cbIdx] = function() { task.invoke.apply(this, arguments); }; setNative.apply(data.target, data.args); @@ -405,9 +405,8 @@ export function patchMicroTask( setNative = patchMethod(obj, funcName, (delegate: Function) => function(self: any, args: any[]) { const meta = metaCreator(self, args); - if (meta.callbackIndex >= 0 && typeof args[meta.callbackIndex] === 'function') { - const task = - Zone.current.scheduleMicroTask(meta.name, args[meta.callbackIndex], meta, scheduleTask); + if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === n) { + const task = (Zone as any).c.si(meta.name, args[meta.cbIdx], meta, scheduleTask); return task; } else { // cause an error by calling it directly. @@ -432,7 +431,6 @@ export function isIEOrEdge() { try { const ua = window.navigator.userAgent; - const msie = ua.indexOf('MSIE '); if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1 || ua.indexOf('Edge/') !== -1) { ieOrEdge = true; } diff --git a/lib/extra/bluebird.ts b/lib/extra/bluebird.ts index 0a70f5cbf..d3f9b9cca 100644 --- a/lib/extra/bluebird.ts +++ b/lib/extra/bluebird.ts @@ -5,7 +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 */ -Zone.__load_patch('bluebird', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('bluebird', (global: any, Zone: ZoneType, api: _ZonePrivate) => { // TODO: @JiaLiPassion, we can automatically patch bluebird // if global.Promise = Bluebird, but sometimes in nodejs, // global.Promise is not Bluebird, and Bluebird is just be @@ -14,7 +14,7 @@ Zone.__load_patch('bluebird', (global: any, Zone: ZoneType, api: _ZonePrivate) = const BLUEBIRD = 'bluebird'; (Zone as any)[Zone.__symbol__(BLUEBIRD)] = function patchBluebird(Bluebird: any) { Bluebird.setScheduler((fn: Function) => { - Zone.current.scheduleMicroTask(BLUEBIRD, fn); + (Zone as any).c.si(BLUEBIRD, fn); }); }; -}); \ No newline at end of file +}); diff --git a/lib/extra/cordova.ts b/lib/extra/cordova.ts index 5f8518ce5..4d32a46a0 100644 --- a/lib/extra/cordova.ts +++ b/lib/extra/cordova.ts @@ -5,7 +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 */ -Zone.__load_patch('cordova', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('cordova', (global: any, Zone: ZoneType, api: _ZonePrivate) => { if (global.cordova) { const SUCCESS_SOURCE = 'cordova.exec.success'; const ERROR_SOURCE = 'cordova.exec.error'; @@ -13,17 +13,17 @@ Zone.__load_patch('cordova', (global: any, Zone: ZoneType, api: _ZonePrivate) => const nativeExec: Function = api.patchMethod( global.cordova, 'exec', (delegate: Function) => function(self: any, args: any[]) { if (args.length > 0 && typeof args[0] === FUNCTION) { - args[0] = Zone.current.wrap(args[0], SUCCESS_SOURCE); + args[0] = (Zone as any).c.w(args[0], SUCCESS_SOURCE); } if (args.length > 1 && typeof args[1] === FUNCTION) { - args[1] = Zone.current.wrap(args[1], ERROR_SOURCE); + args[1] = (Zone as any).c.w(args[1], ERROR_SOURCE); } return nativeExec.apply(self, args); }); } }); -Zone.__load_patch('cordova.FileReader', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('cordova.FileReader', (global: any, Zone: ZoneType, api: _ZonePrivate) => { if (global.cordova && typeof global['FileReader'] !== 'undefined') { document.addEventListener('deviceReady', () => { const FileReader = global['FileReader']; @@ -38,4 +38,4 @@ Zone.__load_patch('cordova.FileReader', (global: any, Zone: ZoneType, api: _Zone }); }); } -}); \ No newline at end of file +}); diff --git a/lib/extra/electron.ts b/lib/extra/electron.ts index 7f618f48c..9ed842b21 100644 --- a/lib/extra/electron.ts +++ b/lib/extra/electron.ts @@ -5,17 +5,21 @@ * 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 */ -Zone.__load_patch('electron', (global: any, Zone: ZoneType, api: _ZonePrivate) => { - const FUNCTION = 'function'; +(Zone as any).l('electron', (global: any, Zone: ZoneType, api: _ZonePrivate) => { + function patchArguments(target: any, name: string, source: string): Function { + return api.patchMethod(target, name, (delegate: Function) => (self: any, args: any[]) => { + return delegate && delegate.apply(self, api.bindArguments(args, source)); + }); + } const {desktopCapturer, shell, CallbackRegistry} = require('electron'); // patch api in renderer process directly // desktopCapturer if (desktopCapturer) { - api.patchArguments(desktopCapturer, 'getSources', 'electron.desktopCapturer.getSources'); + patchArguments(desktopCapturer, 'getSources', 'electron.desktopCapturer.getSources'); } // shell if (shell) { - api.patchArguments(shell, 'openExternal', 'electron.shell.openExternal'); + patchArguments(shell, 'openExternal', 'electron.shell.openExternal'); } // patch api in main process through CallbackRegistry @@ -23,5 +27,5 @@ Zone.__load_patch('electron', (global: any, Zone: ZoneType, api: _ZonePrivate) = return; } - api.patchArguments(CallbackRegistry.prototype, 'add', 'CallbackRegistry.add'); -}); \ No newline at end of file + patchArguments(CallbackRegistry.prototype, 'add', 'CallbackRegistry.add'); +}); diff --git a/lib/node/events.ts b/lib/node/events.ts index 3130b93ad..223721f1d 100644 --- a/lib/node/events.ts +++ b/lib/node/events.ts @@ -6,9 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ -import {globalSources, patchEventTarget, zoneSymbolEventNames} from '../common/events'; +import {ens, gs, patchEventTarget} from '../common/events'; -Zone.__load_patch('EventEmitter', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('EventEmitter', (global: any, Zone: ZoneType, api: _ZonePrivate) => { const callAndReturnFirstParam = (fn: (self: any, args: any[]) => any) => { return (self: any, args: any[]) => { fn(self, args); @@ -34,15 +34,15 @@ Zone.__load_patch('EventEmitter', (global: any, Zone: ZoneType, api: _ZonePrivat function patchEventEmitterMethods(obj: any) { const result = patchEventTarget(global, [obj], { - useGlobalCallback: false, - addEventListenerFnName: EE_ADD_LISTENER, - removeEventListenerFnName: EE_REMOVE_LISTENER, - prependEventListenerFnName: EE_PREPEND_LISTENER, - removeAllFnName: EE_REMOVE_ALL_LISTENER, - listenersFnName: EE_LISTENERS, - checkDuplicate: false, - returnTarget: true, - compareTaskCallbackVsDelegate: compareTaskCallbackVsDelegate + useG: false, + add: EE_ADD_LISTENER, + rm: EE_REMOVE_LISTENER, + prepend: EE_PREPEND_LISTENER, + rmAll: EE_REMOVE_ALL_LISTENER, + listeners: EE_LISTENERS, + chkDup: false, + rt: true, + diff: compareTaskCallbackVsDelegate }); if (result && result[0]) { obj[EE_ON] = obj[EE_ADD_LISTENER]; diff --git a/lib/node/fs.ts b/lib/node/fs.ts index 79de87a30..11c115436 100644 --- a/lib/node/fs.ts +++ b/lib/node/fs.ts @@ -8,7 +8,7 @@ import {patchMacroTask} from '../common/utils'; -Zone.__load_patch('fs', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('fs', (global: any, Zone: ZoneType, api: _ZonePrivate) => { let fs: any; try { fs = require('fs'); @@ -32,10 +32,10 @@ Zone.__load_patch('fs', (global: any, Zone: ZoneType, api: _ZonePrivate) => { return { name: 'fs.' + name, args: args, - callbackIndex: args.length > 0 ? args.length - 1 : -1, + cbIdx: args.length > 0 ? args.length - 1 : -1, target: self }; }); }); } -}); \ No newline at end of file +}); diff --git a/lib/node/node.ts b/lib/node/node.ts index 78111dc79..388d00195 100644 --- a/lib/node/node.ts +++ b/lib/node/node.ts @@ -11,18 +11,18 @@ import './fs'; import {findEventTasks} from '../common/events'; import {patchTimer} from '../common/timers'; -import {isMix, patchArguments, patchMacroTask, patchMethod, patchMicroTask, patchOnProperties} from '../common/utils'; +import {bindArguments, f, isMix, patchMacroTask, patchMethod, patchMicroTask, patchOnProperties} from '../common/utils'; const set = 'set'; const clear = 'clear'; -Zone.__load_patch('node_util', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('node_util', (global: any, Zone: ZoneType, api: _ZonePrivate) => { api.patchOnProperties = patchOnProperties; api.patchMethod = patchMethod; - api.patchArguments = patchArguments; + api.bindArguments = bindArguments; }); -Zone.__load_patch('node_timers', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('node_timers', (global: any, Zone: ZoneType, api: _ZonePrivate) => { // Timers let globalUseTimeoutFromTimer = false; try { @@ -76,20 +76,20 @@ Zone.__load_patch('node_timers', (global: any, Zone: ZoneType, api: _ZonePrivate }); // patch process related methods -Zone.__load_patch('nextTick', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('nextTick', (global: any, Zone: ZoneType, api: _ZonePrivate) => { // patch nextTick as microTask patchMicroTask(process, 'nextTick', (self: any, args: any[]) => { return { name: 'process.nextTick', args: args, - callbackIndex: (args.length > 0 && typeof args[0] === 'function') ? 0 : -1, + cbIdx: (args.length > 0 && typeof args[0] === 'function') ? 0 : -1, target: process }; }); }); -Zone.__load_patch( - 'handleUnhandledPromiseRejection', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any) + .l('handleUnhandledPromiseRejection', (global: any, Zone: ZoneType, api: _ZonePrivate) => { (Zone as any)[api.symbol('unhandledPromiseRejectionHandler')] = findProcessPromiseRejectionHandler('unhandledRejection'); @@ -116,7 +116,7 @@ Zone.__load_patch( // Crypto -Zone.__load_patch('crypto', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('crypto', (global: any, Zone: ZoneType, api: _ZonePrivate) => { let crypto: any; try { crypto = require('crypto'); @@ -131,7 +131,7 @@ Zone.__load_patch('crypto', (global: any, Zone: ZoneType, api: _ZonePrivate) => return { name: 'crypto.' + name, args: args, - callbackIndex: (args.length > 0 && typeof args[args.length - 1] === 'function') ? + cbIdx: (args.length > 0 && typeof args[args.length - 1] === 'function') ? args.length - 1 : -1, target: crypto @@ -141,15 +141,15 @@ Zone.__load_patch('crypto', (global: any, Zone: ZoneType, api: _ZonePrivate) => } }); -Zone.__load_patch('console', (global: any, Zone: ZoneType, api: _ZonePrivate) => { +(Zone as any).l('console', (global: any, Zone: ZoneType, api: _ZonePrivate) => { const consoleMethods = ['dir', 'log', 'info', 'error', 'warn', 'assert', 'debug', 'timeEnd', 'trace']; consoleMethods.forEach((m: string) => { const originalMethod = (console as any)[Zone.__symbol__(m)] = (console as any)[m]; if (originalMethod) { (console as any)[m] = function() { - const args = Array.prototype.slice.call(arguments); - if (Zone.current === Zone.root) { + const args = f.call(arguments); + if ((Zone as any).c === Zone.root) { return originalMethod.apply(this, args); } else { return Zone.root.run(originalMethod, this, args); diff --git a/lib/rxjs/rxjs.ts b/lib/rxjs/rxjs.ts index 23d5287a9..11c116b8a 100644 --- a/lib/rxjs/rxjs.ts +++ b/lib/rxjs/rxjs.ts @@ -19,14 +19,11 @@ import {Subscriber} from 'rxjs/Subscriber'; import {Subscription} from 'rxjs/Subscription'; import {rxSubscriber} from 'rxjs/symbol/rxSubscriber'; -(Zone as any).__load_patch('rxjs', (global: any, Zone: ZoneType, api: any) => { +(Zone as any).__load_patch('rxjs', (global: any, Zone: ZoneType) => { const symbol: (symbolString: string) => string = (Zone as any).__symbol__; - const subscribeSource = 'rxjs.subscribe'; const nextSource = 'rxjs.Subscriber.next'; const errorSource = 'rxjs.Subscriber.error'; const completeSource = 'rxjs.Subscriber.complete'; - const unsubscribeSource = 'rxjs.Subscriber.unsubscribe'; - const teardownSource = 'rxjs.Subscriber.teardownLogic'; const empty = { closed: true, @@ -321,7 +318,6 @@ import {rxSubscriber} from 'rxjs/symbol/rxSubscriber'; } const scheduleSymbol = symbol('scheduleSymbol'); - const flushSymbol = symbol('flushSymbol'); const zoneSymbol = symbol('zone'); if (asap[scheduleSymbol]) { return; @@ -359,4 +355,4 @@ import {rxSubscriber} from 'rxjs/symbol/rxSubscriber'; patchObservableFactoryArgs(Observable, 'fromEventPattern'); patchMulticast(); patchImmediate(asap); -}); \ No newline at end of file +}); diff --git a/lib/zone-spec/fake-async-test.ts b/lib/zone-spec/fake-async-test.ts index 5123743a5..31f1fae35 100644 --- a/lib/zone-spec/fake-async-test.ts +++ b/lib/zone-spec/fake-async-test.ts @@ -330,7 +330,7 @@ // arguments let addtionalArgs: any[]; if (args) { - let callbackIndex = (task.data as any).callbackIndex; + let callbackIndex = (task.data as any).cbIdx; if (typeof args.length === 'number' && args.length > callbackIndex + 1) { addtionalArgs = Array.prototype.slice.call(args, callbackIndex + 1); } diff --git a/lib/zone.ts b/lib/zone.ts index 038a88e74..d65149400 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -327,7 +327,7 @@ interface _ZonePrivate { (target: any, name: string, patchFn: (delegate: Function, delegateName: string, name: string) => (self: any, args: any[]) => any) => Function; - patchArguments: (target: any, name: string, source: string) => Function; + bindArguments: (args: any[], source: string) => any[]; } /** @internal */ @@ -656,7 +656,7 @@ const Zone: ZoneType = (function(global: any) { } static get root(): AmbientZone { - let zone = Zone.current; + let zone = Zone.c; while (zone.parent) { zone = zone.parent; } @@ -667,6 +667,10 @@ const Zone: ZoneType = (function(global: any) { return _currentZoneFrame.zone; } + static get c(): AmbientZone { + return _currentZoneFrame.zone; + } + static get currentTask(): Task { return _currentTask; } @@ -1167,7 +1171,8 @@ const Zone: ZoneType = (function(global: any) { this.cancelFn = cancelFn; this.callback = callback; const self = this; - if (type === eventTask && options && (options as any).isUsingGlobalCallback) { + // TODO: @JiaLiPassion options should have interface + if (type === eventTask && options && (options as any).useG) { this.invoke = ZoneTask.invokeTask; } else { this.invoke = function() { @@ -1318,7 +1323,7 @@ const Zone: ZoneType = (function(global: any) { patchEventTarget: () => [], patchOnProperties: noop, patchMethod: () => noop, - patchArguments: () => noop, + bindArguments: () => null, setNativePromise: (NativePromise: any) => { // sometimes NativePromise.resolve static function // is not ready yet, (such as core-js/es6.promise) @@ -1338,7 +1343,19 @@ const Zone: ZoneType = (function(global: any) { return '__zone_symbol__' + name; } - performanceMeasure('Zone', 'Zone'); + const z: any = Zone.prototype; + z.w = z.wrap; + z.f = z.fork; + z.r = z.run; + z.rg = z.runGuarded; + z.rt = z.runTask; + z.st = z.scheduleTask; + z.sc = z.scheduleMacroTask; + z.si = z.scheduleMicroTask; + z.se = z.scheduleEventTask; + z.ct = z.cancelTask; + (Zone as any).l = Zone.__load_patch; + (Zone as any).s = Zone.__symbol__; return global['Zone'] = Zone; })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); diff --git a/test/browser-zone-setup.ts b/test/browser-zone-setup.ts index 1c16e96a8..bdefeff31 100644 --- a/test/browser-zone-setup.ts +++ b/test/browser-zone-setup.ts @@ -10,6 +10,7 @@ if (typeof window !== 'undefined') { } import '../lib/common/to-string'; import '../lib/browser/browser'; +import '../lib/browser/webapis-user-media'; import '../lib/zone-spec/async-test'; import '../lib/zone-spec/fake-async-test'; import '../lib/zone-spec/long-stack-trace'; @@ -17,4 +18,4 @@ import '../lib/zone-spec/proxy'; import '../lib/zone-spec/sync-test'; import '../lib/zone-spec/task-tracking'; import '../lib/zone-spec/wtf'; -import '../lib/extra/cordova'; \ No newline at end of file +import '../lib/extra/cordova'; diff --git a/test/browser_entry_point.ts b/test/browser_entry_point.ts index 0d49c69af..4ec6e5776 100644 --- a/test/browser_entry_point.ts +++ b/test/browser_entry_point.ts @@ -25,4 +25,3 @@ import './browser/Worker.spec'; import './mocha-patch.spec'; import './jasmine-patch.spec'; import './extra/cordova.spec'; -import './rxjs/rxjs.spec'; \ No newline at end of file diff --git a/test/common/util.spec.ts b/test/common/util.spec.ts index 9d450cab1..b6b122d10 100644 --- a/test/common/util.spec.ts +++ b/test/common/util.spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {patchMethod, patchProperty, patchPrototype, wrapFunctionArgs, zoneSymbol} from '../../lib/common/utils'; +import {patchMethod, patchProperty, patchPrototype, zoneSymbol} from '../../lib/common/utils'; describe('utils', function() { @@ -329,30 +329,4 @@ describe('utils', function() { expect(log).toEqual(['property2']); }); }); - - describe('wrapFunctionArgs', () => { - it('wrapFunctionArgs should make function arguments in zone', () => { - const func = function(arg1: string, arg2: Function, arg3: Function) { - arg2(arg1); - arg3(arg1); - }; - - const zone = Zone.current.fork({name: 'wrap'}); - - wrapFunctionArgs(func); - - zone.run(() => { - func( - 'test', - function(arg: string) { - expect(arg).toEqual('test'); - expect(Zone.current.name).toEqual(zone.name); - }, - function(arg: string) { - expect(arg).toEqual('test'); - expect(Zone.current.name).toEqual(zone.name); - }); - }); - }); - }); }); diff --git a/test/common_tests.ts b/test/common_tests.ts index 186274955..bb507dec6 100644 --- a/test/common_tests.ts +++ b/test/common_tests.ts @@ -21,6 +21,6 @@ import './zone-spec/sync-test.spec'; import './zone-spec/fake-async-test.spec'; import './zone-spec/proxy.spec'; import './zone-spec/task-tracking.spec'; -import './rxjs/rxjs.spec'; +// import './rxjs/rxjs.spec'; -Error.stackTraceLimit = Number.POSITIVE_INFINITY; \ No newline at end of file +Error.stackTraceLimit = Number.POSITIVE_INFINITY; diff --git a/test/zone-spec/fake-async-test.spec.ts b/test/zone-spec/fake-async-test.spec.ts index 8c53da96b..7e2dfe5c8 100644 --- a/test/zone-spec/fake-async-test.spec.ts +++ b/test/zone-spec/fake-async-test.spec.ts @@ -732,7 +732,7 @@ describe('FakeAsyncTestZoneSpec', () => { patchMacroTask( TestClass.prototype, 'myTimeout', (self: any, args: any[]) => - ({name: 'TestClass.myTimeout', target: self, callbackIndex: 0, args: args})); + ({name: 'TestClass.myTimeout', target: self, cbIdx: 0, args: args})); const testClass = new TestClass(); testClass.myTimeout(function(callbackArgs: any) { @@ -758,7 +758,7 @@ describe('FakeAsyncTestZoneSpec', () => { patchMacroTask( TestClass.prototype, 'myTimeout', (self: any, args: any[]) => - ({name: 'TestClass.myTimeout', target: self, callbackIndex: 0, args: args})); + ({name: 'TestClass.myTimeout', target: self, cbIdx: 0, args: args})); const testClass = new TestClass(); testClass.myTimeout(() => { @@ -787,7 +787,7 @@ describe('FakeAsyncTestZoneSpec', () => { patchMacroTask( TestClass.prototype, 'myInterval', (self: any, args: any[]) => - ({name: 'TestClass.myInterval', target: self, callbackIndex: 0, args: args})); + ({name: 'TestClass.myInterval', target: self, cbIdx: 0, args: args})); const testClass = new TestClass(); const id = testClass.myInterval(() => {