diff --git a/test/performance/eventTarget.js b/test/performance/eventTarget.js
new file mode 100644
index 000000000..0456b32ac
--- /dev/null
+++ b/test/performance/eventTarget.js
@@ -0,0 +1,84 @@
+/**
+ * @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
+ */
+(function(_global) {
+ var testRunner = _global['__zone_symbol__testRunner'];
+ var mark = _global['__zone_symbol__mark'];
+ var measure = _global['__zone_symbol__measure'];
+ var zone = _global['__zone_symbol__callbackZone'];
+ var button;
+ var testTarget = {
+ title: 'addEventListener',
+ times: 10,
+ before: function() {
+ button = document.createElement('button');
+ document.body.appendChild(button);
+ _global['__zone_symbol__callbackContext'].measureName = 'addEventListener_callback';
+ _global['__zone_symbol__callbackContext'].type = 'eventTask';
+ _global['__zone_symbol__callbackContext'].source = 'addEventListener';
+ },
+ after: function() {
+ document.body.removeChild(button);
+ button = null;
+ },
+ apis: [
+ {
+ supportClear: true,
+ method: 'addEventListener',
+ nativeMethod: '__zone_symbol__addEventListener',
+ clearMethod: 'removeEventListener',
+ nativeClearMethod: '__zone_symbol__removeEventListener',
+ run: function() {
+ var listener = function() {};
+ button.addEventListener('click', listener);
+ return listener;
+ },
+ runClear: function(timerId) {
+ return button.removeEventListener('click', timerId);
+ },
+ nativeRun: function() {
+ var listener = function() {};
+ button['__zone_symbol__addEventListener']('click', listener);
+ return listener;
+ },
+ nativeRunClear: function(timerId) {
+ return button['__zone_symbol__removeEventListener']('click', timerId);
+ }
+ },
+ {
+ isCallback: true,
+ supportClear: false,
+ method: 'addEventListener_callback',
+ nativeMethod: 'native_addEventListener_callback',
+ run: function() {
+ var listener = function() {};
+ zone.run(function() {
+ button.addEventListener('click', listener);
+ });
+ var event = document.createEvent('Event');
+ event.initEvent('click', true, true);
+ button.dispatchEvent(event);
+ button.removeEventListener('click', listener);
+ },
+ nativeRun: function() {
+ var func = function() {};
+ var listener = function() {
+ mark('native_addEventListener_callback');
+ func.apply(this, arguments);
+ measure('native_addEventListener_callback', 'native_addEventListener_callback');
+ };
+ button['__zone_symbol__addEventListener']('click', listener);
+ var event = document.createEvent('Event');
+ event.initEvent('click', true, true);
+ button.dispatchEvent(event);
+ button['__zone_symbol__removeEventListener']('click', listener);
+ }
+ }
+ ],
+ };
+ return testRunner(testTarget);
+}(typeof window === 'undefined' ? global : window));
diff --git a/test/performance/performance.html b/test/performance/performance.html
new file mode 100644
index 000000000..37d5b5943
--- /dev/null
+++ b/test/performance/performance.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Performance Bencnhmark of Zone.js vs Native Delegate!
+
+
+
+
+
+
diff --git a/test/performance/performance_setup.js b/test/performance/performance_setup.js
new file mode 100644
index 000000000..4ec59891b
--- /dev/null
+++ b/test/performance/performance_setup.js
@@ -0,0 +1,298 @@
+/**
+ * @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
+ */
+(function(_global) {
+ var allTasks = _global['__zone_symbol__performance_tasks'];
+ if (!allTasks) {
+ allTasks = _global['__zone_symbol__performance_tasks'] = [];
+ }
+
+ var mark = _global['__zone_symbol__mark'] = function(name) {
+ performance && performance['mark'] && performance['mark'](name);
+ };
+
+ var measure = _global['__zone_symbol__measure'] = function(name, label) {
+ performance && performance['measure'] && performance['measure'](name, label);
+ };
+
+ var getEntries = _global['__zone_symbol__getEntries'] = function() {
+ performance && performance['getEntries'] && performance['getEntries']();
+ };
+
+ var getEntriesByName = _global['__zone_symbol__getEntriesByName'] = function(name) {
+ return performance && performance['getEntriesByName'] && performance['getEntriesByName'](name);
+ };
+
+ var clearMarks = _global['__zone_symbol__clearMarks'] = function(name) {
+ return performance && performance['clearMarks'] && performance['clearMarks'](name);
+ };
+
+ var clearMeasures = _global['__zone_symbol__clearMeasures'] = function(name) {
+ return performance && performance['clearMeasures'] && performance['clearMeasures'](name);
+ };
+
+ var averageMeasures = _global['__zone_symbol__averageMeasures'] = function(name, times) {
+ var sum = _global['__zone_symbol__getEntriesByName'](name)
+ .filter(function(m) {
+ return m.entryType === 'measure';
+ })
+ .map(function(m) {
+ return m.duration
+ })
+ .reduce(function(sum, d) {
+ return sum + d;
+ });
+ return sum / times;
+ };
+
+ var serialPromise = _global['__zone_symbol__serialPromise'] =
+ function(promiseFactories) {
+ let lastPromise;
+ for (var i = 0; i < promiseFactories.length; i++) {
+ var promiseFactory = promiseFactories[i];
+ if (!lastPromise) {
+ lastPromise = promiseFactory.factory(promiseFactory.context).then(function(value) {
+ return {value, idx: 0};
+ });
+ } else {
+ lastPromise = lastPromise.then(function(ctx) {
+ var idx = ctx.idx + 1;
+ var promiseFactory = promiseFactories[idx];
+ return promiseFactory.factory(promiseFactory.context).then(function(value) {
+ return {value, idx};
+ });
+ });
+ }
+ }
+ return lastPromise;
+ }
+
+ var callbackContext = _global['__zone_symbol__callbackContext'] = {};
+ var zone = _global['__zone_symbol__callbackZone'] = Zone.current.fork({
+ name: 'callback',
+ onScheduleTask: function(delegate, curr, target, task) {
+ delegate.scheduleTask(target, task);
+ if (task.type === callbackContext.type &&
+ task.source.indexOf(callbackContext.source) !== -1) {
+ if (task.type === 'macroTask' || task.type === 'eventTask') {
+ var invoke = task.invoke;
+ task.invoke = function() {
+ mark(callbackContext.measureName);
+ var result = invoke.apply(this, arguments);
+ measure(callbackContext.measureName, callbackContext.measureName);
+ return result;
+ };
+ } else if (task.type === 'microTask') {
+ var callback = task.callback;
+ task.callback = function() {
+ mark(callbackContext.measureName);
+ var result = callback.apply(this, arguments);
+ measure(callbackContext.measureName, callbackContext.measureName);
+ return result;
+ };
+ }
+ }
+ return task;
+ }
+ });
+
+ var runAsync = _global['__zone_symbol__runAsync'] = function(testFn, times, _delay) {
+ var delay = _delay | 100;
+ const fnPromise = function() {
+ return new Promise(function(res, rej) {
+ // run test with a setTimeout
+ // several times to decrease measurement error
+ setTimeout(function() {
+ testFn().then(function() {
+ res();
+ });
+ }, delay);
+ });
+ };
+ var promiseFactories = [];
+ for (var i = 0; i < times; i++) {
+ promiseFactories.push({factory: fnPromise, context: {}});
+ }
+
+ return serialPromise(promiseFactories);
+ };
+
+ var getNativeMethodName = function(nativeWithSymbol) {
+ return nativeWithSymbol.replace('__zone_symbol__', 'native_');
+ };
+
+ function testAddRemove(api, count) {
+ var timerId = [];
+
+ var name = api.method;
+ mark(name);
+ for (var i = 0; i < count; i++) {
+ timerId.push(api.run());
+ }
+ measure(name, name);
+
+ if (api.supportClear) {
+ var clearName = api.clearMethod;
+ mark(clearName);
+ for (var i = 0; i < count; i++) {
+ api.runClear(timerId[i]);
+ }
+ measure(clearName, clearName);
+ }
+
+ timerId = [];
+
+ var nativeName = getNativeMethodName(api.nativeMethod);
+ mark(nativeName);
+ for (var i = 0; i < count; i++) {
+ timerId.push(api.nativeRun());
+ }
+ measure(nativeName, nativeName);
+
+ if (api.supportClear) {
+ var nativeClearName = getNativeMethodName(api.nativeClearMethod);
+ mark(nativeClearName);
+ for (var i = 0; i < count; i++) {
+ api.nativeRunClear(timerId[i]);
+ }
+ measure(nativeClearName, nativeClearName);
+ }
+
+ return Promise.resolve(1);
+ }
+
+ function testCallback(api, count) {
+ var promises = [Promise.resolve(1)];
+ for (var i = 0; i < count; i++) {
+ var r = api.run();
+ if (api.isAsync) {
+ promises.push(r);
+ }
+ }
+
+ for (var i = 0; i < count; i++) {
+ var r = api.nativeRun();
+ if (api.isAsync) {
+ promises.push(r);
+ }
+ }
+ return Promise.all(promises);
+ }
+
+ function measureCallback(api, ops) {
+ var times = ops.times;
+ var displayText = ops.displayText;
+ var rawData = ops.rawData;
+ var summary = ops.summary;
+
+ var name = api.method;
+ var nativeName = getNativeMethodName(api.nativeMethod);
+ var measure = averageMeasures(name, times);
+ var nativeMeasure = averageMeasures(nativeName, times);
+ displayText += `- ${name} costs ${measure} ms\n`;
+ displayText += `- ${nativeName} costs ${nativeMeasure} ms\n`;
+ var absolute = Math.floor(1000 * (measure - nativeMeasure)) / 1000;
+ displayText += `# ${name} is ${absolute}ms slower than ${nativeName}\n`;
+ rawData[name + '_measure'] = measure;
+ rawData[nativeName + '_measure'] = nativeMeasure;
+ summary[name] = absolute + 'ms';
+ }
+
+ function measureAddRemove(api, ops) {
+ var times = ops.times;
+ var displayText = ops.displayText;
+ var rawData = ops.rawData;
+ var summary = ops.summary;
+
+ var name = api.method;
+ var nativeName = getNativeMethodName(api.nativeMethod);
+
+ var measure = averageMeasures(name, times);
+ var nativeMeasure = averageMeasures(nativeName, times);
+ displayText += `- ${name} costs ${measure} ms\n`;
+ displayText += `- ${nativeName} costs ${nativeMeasure} ms\n`;
+ var percent = Math.floor(100 * (measure - nativeMeasure) / nativeMeasure);
+ displayText += `# ${name} is ${percent}% slower than ${nativeName}\n`;
+ rawData[name + '_measure'] = measure;
+ rawData[nativeName + '_measure'] = nativeMeasure;
+ summary[name] = percent + '%';
+ if (api.supportClear) {
+ var clearName = api.clearMethod;
+ var nativeClearName = getNativeMethodName(api.nativeClearMethod);
+ var clearMeasure = averageMeasures(clearName, times);
+ var nativeClearMeasure = averageMeasures(nativeClearName, times);
+ var clearPercent = Math.floor(100 * (clearMeasure - nativeClearMeasure) / nativeClearMeasure);
+ displayText += `- ${clearName} costs ${clearMeasure} ms\n`;
+ displayText += `- ${nativeClearName} costs ${nativeClearMeasure} ms\n`;
+ displayText += `# ${clearName} is ${clearPercent}% slower than ${nativeClearName}\n`;
+ rawData[clearName + '_measure'] = clearMeasure;
+ rawData[nativeClearName + '_measure'] = nativeClearMeasure;
+ summary[clearName] = clearPercent + '%';
+ }
+ }
+
+ var testRunner = _global['__zone_symbol__testRunner'] = function(testTarget) {
+ var title = testTarget.title;
+ var apis = testTarget.apis;
+ var methods = apis.reduce(function(acc, api) {
+ return acc.concat([
+ api.method, api.nativeMethod
+ ].concat(api.supportClear ? [api.clearMethod, api.nativeClearMethod] : [])
+ .concat[api.method + '_callback', api.nativeMethod + '_callback']);
+
+ }, []);
+ var times = testTarget.times;
+
+ allTasks.push({
+ title: title,
+ cleanFn: function() {
+ methods.forEach(function(m) {
+ clearMarks(m);
+ clearMeasures(m);
+ });
+ },
+ before: function() {
+ testTarget.before && testTarget.before();
+ },
+ after: function() {
+ testTarget.after && testTarget.after();
+ },
+ testFn: function() {
+ var count = typeof testTarget.count === 'number' ? testTarget.count : 10000;
+ var times = typeof testTarget.times === 'number' ? testTarget.times : 5;
+
+ var testFunction = function() {
+ var promises = [];
+ apis.forEach(function(api) {
+ if (api.isCallback) {
+ var r = testCallback(api, count / 100);
+ promises.push(api.isAsync ? r : Promise.resolve(1));
+ } else {
+ var r = testAddRemove(api, count);
+ promises.push[api.isAsync ? r : Promise.resolve(1)];
+ }
+ });
+ return Promise.all(promises);
+ };
+
+ return runAsync(testFunction, times).then(function() {
+ var displayText = `running ${count} times\n`;
+ var rawData = {};
+ var summary = {};
+ apis.forEach(function(api) {
+ if (api.isCallback) {
+ measureCallback(api, {times, displayText, rawData, summary});
+ } else {
+ measureAddRemove(api, {times, displayText, rawData, summary});
+ }
+ });
+ return Promise.resolve({displayText: displayText, rawData: rawData, summary: summary});
+ });
+ }
+ });
+ };
+}(typeof window === 'undefined' ? global : window));
diff --git a/test/performance/performance_ui.js b/test/performance/performance_ui.js
new file mode 100644
index 000000000..5a6140053
--- /dev/null
+++ b/test/performance/performance_ui.js
@@ -0,0 +1,162 @@
+/**
+ * @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
+ */
+(function(_global) {
+ var options;
+
+ function setAttributes(elem, attrs) {
+ if (!attrs) {
+ return;
+ }
+ Object.keys(attrs).forEach(function(key) {
+ elem.setAttribute(key, attrs[key]);
+ });
+ }
+
+ function createLi(attrs) {
+ var li = document.createElement('li');
+ setAttributes(li, attrs);
+ return li;
+ }
+
+ function createLabel(attrs) {
+ var label = document.createElement('label');
+ setAttributes(label, attrs);
+ return label;
+ }
+
+ function createButton(attrs, innerHtml) {
+ var button = document.createElement('button');
+ button.innerHTML = innerHtml;
+ setAttributes(button, attrs);
+ return button;
+ }
+
+ function createTextNode(text) {
+ return document.createTextNode(text);
+ }
+
+ function createCheckbox(attrs, checked) {
+ var checkbox = document.createElement('input');
+ checkbox.type = 'checkbox';
+ checkbox.checked = !!checked;
+ setAttributes(checkbox, attrs);
+ return checkbox;
+ }
+
+ function createUl(attrs) {
+ var ul = document.createElement('ul');
+ setAttributes(ul, attrs);
+ return ul;
+ }
+
+ var serailPromise = _global['__zone_symbol__serialPromise'];
+
+ _global['__zone_symbol__testTargetsUIBuild'] = function(_options) {
+ options = _options;
+ var allButton = createButton({}, 'test selected');
+ allButton.addEventListener('click', function() {
+ var promiseFactories = [];
+ for (var i = 0; i < options.tests.length; i++) {
+ var checkbox = document.getElementById('testcheck' + i);
+ if (checkbox.checked) {
+ var test = options.tests[i];
+ promiseFactories.push({
+ factory: function(context) {
+ return doTest(context.test, context.idx);
+ },
+ context: {test: test, idx: i}
+ });
+ }
+ }
+ serailPromise(promiseFactories);
+ });
+ options.targetContainer.appendChild(allButton);
+
+ var ul = createUl();
+ options.targetContainer.appendChild(ul);
+
+ for (var i = 0; i < options.tests.length; i++) {
+ buildTestItemUI(ul, options.tests[i], i);
+ }
+ };
+
+ function buildTestItemUI(ul, testItem, idx) {
+ var li = createLi({'id': 'test' + idx});
+
+ var button = createButton({'id': 'buttontest' + idx}, 'begin test');
+ buildButtonClickHandler(button);
+
+ var title = createTextNode(options.tests[idx].title);
+ var checkbox = createCheckbox({'id': 'testcheck' + idx}, true);
+ var label = createLabel({'id': 'label' + idx});
+
+ li.appendChild(checkbox);
+ li.appendChild(title);
+ li.appendChild(button);
+ li.appendChild(label);
+
+ ul.appendChild(li);
+ }
+
+ function processTestResult(test, result, id) {
+ var split = result.displayText.split('\n');
+ options.jsonResult[test.title] = result.rawData;
+ options.jsonContainer.innerHTML =
+ '' + JSON.stringify(options.jsonResult) + '
';
+
+ var summary = result.summary;
+ var row = options.resultsContainer.insertRow();
+ var cell = row.insertCell();
+ cell.innerHTML = test.title;
+ cell.rowSpan = Object.keys(summary).length;
+ var idx = 0;
+ Object.keys(summary).forEach(function(key) {
+ var tableRow = row;
+ if (idx !== 0) {
+ tableRow = options.resultsContainer.insertRow();
+ }
+ var keyCell = tableRow.insertCell();
+ keyCell.innerHTML = key;
+ var valueCell = tableRow.insertCell();
+ valueCell.innerHTML = summary[key];
+ idx++;
+ });
+
+ var testLi = document.getElementById('test' + id);
+ for (var j = 0; j < split.length; j++) {
+ var br = document.createElement('br');
+ var s = document.createTextNode(split[j]);
+ testLi.appendChild(br);
+ testLi.appendChild(s);
+ }
+ }
+
+ function doTest(test, id) {
+ test.cleanFn();
+ test.before();
+ var button = document.getElementById('buttontest' + id);
+ button.setAttribute('enabled', 'false');
+ var label = document.getElementById('label' + id);
+ label.innerHTML = 'Testing';
+ return test.testFn().then(function(result) {
+ processTestResult(test, result, id);
+ test.after();
+ label.innerHTML = 'Finished';
+ button.setAttribute('enabled', 'true');
+ });
+ }
+
+ function buildButtonClickHandler(button) {
+ button.onclick = function(event) {
+ var target = event.target;
+ var id = target.getAttribute('id').substring(10);
+ var test = options.tests[id];
+ doTest(test, id);
+ };
+ }
+}(typeof window === 'undefined' ? global : window));
diff --git a/test/performance/promise.js b/test/performance/promise.js
new file mode 100644
index 000000000..6657c4cd9
--- /dev/null
+++ b/test/performance/promise.js
@@ -0,0 +1,63 @@
+/**
+ * @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
+ */
+(function(_global) {
+ var mark = _global['__zone_symbol__mark'];
+ var measure = _global['__zone_symbol__measure'];
+ var testRunner = _global['__zone_symbol__testRunner'];
+ var zone = _global['__zone_symbol__callbackZone'];
+ var nativePromise = _global['__zone_symbol__Promise'];
+ var resolved = Promise.resolve(1);
+ var nativeResolved = nativePromise.resolve(1);
+ var testTarget = {
+ title: 'Promise',
+ times: 10,
+ before: function() {
+ _global['__zone_symbol__callbackContext'].measureName = 'Promise_callback';
+ _global['__zone_symbol__callbackContext'].type = 'microTask';
+ _global['__zone_symbol__callbackContext'].source = 'Promise.then';
+ },
+ apis: [
+ {
+ supportClear: false,
+ isAsync: true,
+ method: 'Promise',
+ nativeMethod: 'native_Promise',
+ run: function() {
+ return resolved.then(function() {});
+ },
+ nativeRun: function() {
+ return nativeResolved['__zone_symbol__then'](function() {});
+ },
+ },
+ {
+ isCallback: true,
+ isAsync: true,
+ supportClear: false,
+ method: 'Promise_callback',
+ nativeMethod: 'native_Promise_callback',
+ run: function() {
+ return zone.run(function() {
+ return Promise.resolve(1).then(function(v) {
+ return v;
+ });
+ });
+ },
+ nativeRun: function() {
+ var func = function() {};
+ return _global['__zone_symbol__Promise'].resolve(1)['__zone_symbol__then'](function() {
+ mark('native_Promise_callback');
+ var result = func.apply(this, arguments);
+ measure('native_Promise_callback', 'native_Promise_callback');
+ return result;
+ });
+ }
+ }
+ ],
+ };
+ return testRunner(testTarget);
+}(typeof window === 'undefined' ? global : window));
diff --git a/test/performance/requestAnimationFrame.js b/test/performance/requestAnimationFrame.js
new file mode 100644
index 000000000..2bdd8cfcc
--- /dev/null
+++ b/test/performance/requestAnimationFrame.js
@@ -0,0 +1,68 @@
+/**
+ * @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
+ */
+(function(_global) {
+ var mark = _global['__zone_symbol__mark'];
+ var measure = _global['__zone_symbol__measure'];
+ var zone = _global['__zone_symbol__callbackZone'];
+ var testRunner = _global['__zone_symbol__testRunner'];
+ var raf = _global['requestAnimationFrame'];
+ var cancel = _global['cancelAnimationFrame'];
+ var nativeRaf = _global['__zone_symbol__requestAnimationFrame'];
+ var nativeCancel = _global['__zone_symbol__cancelAnimationFrame'];
+ var testTarget = {
+ title: 'requestAnimationFrame',
+ times: 10,
+ before: function() {
+ _global['__zone_symbol__callbackContext'].measureName = 'requestAnimationFrame_callback';
+ _global['__zone_symbol__callbackContext'].type = 'macroTask';
+ _global['__zone_symbol__callbackContext'].source = 'requestAnimationFrame';
+ },
+ apis: [
+ {
+ supportClear: true,
+ method: 'requestAnimationFrame',
+ nativeMethod: '__zone_symbol__requestAnimationFrame',
+ clearMethod: 'cancelAnimationFrame',
+ nativeClearMethod: '__zone_symbol__cancelAnimationFrame',
+ run: function() {
+ return raf(function() {});
+ },
+ runClear: function(timerId) {
+ return cancel(timerId);
+ },
+ nativeRun: function() {
+ return nativeRaf(function() {});
+ },
+ nativeRunClear: function(timerId) {
+ return nativeCancel(timerId);
+ }
+ },
+ {
+ isCallback: true,
+ supportClear: false,
+ method: 'requestAnimationFrame_callback',
+ nativeMethod: 'native_requestAnimationFrame_callback',
+ run: function() {
+ zone.run(function() {
+ raf(function() {});
+ });
+ },
+ nativeRun: function() {
+ var func = function() {};
+ nativeRaf(function() {
+ mark('native_requestAnimationFrame_callback');
+ func.apply(this, arguments);
+ measure(
+ 'native_requestAnimationFrame_callback', 'native_requestAnimationFrame_callback');
+ });
+ }
+ }
+ ],
+ };
+ return testRunner(testTarget);
+}(typeof window === 'undefined' ? global : window));
diff --git a/test/performance/timeout.js b/test/performance/timeout.js
new file mode 100644
index 000000000..71df71abe
--- /dev/null
+++ b/test/performance/timeout.js
@@ -0,0 +1,67 @@
+/**
+ * @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
+ */
+(function(_global) {
+ var mark = _global['__zone_symbol__mark'];
+ var measure = _global['__zone_symbol__measure'];
+ var testRunner = _global['__zone_symbol__testRunner'];
+ var setTimeout = _global['setTimeout'];
+ var clearTimeout = _global['clearTimeout'];
+ var nativeSetTimeout = _global['__zone_symbol__setTimeout'];
+ var nativeClearTimeout = _global['__zone_symbol__clearTimeout'];
+ var zone = _global['__zone_symbol__callbackZone'];
+ var testTarget = {
+ title: 'timer',
+ times: 10,
+ before: function() {
+ _global['__zone_symbol__callbackContext'].measureName = 'setTimeout_callback';
+ _global['__zone_symbol__callbackContext'].type = 'macroTask';
+ _global['__zone_symbol__callbackContext'].source = 'setTimeout';
+ },
+ apis: [
+ {
+ supportClear: true,
+ method: 'setTimeout',
+ nativeMethod: '__zone_symbol__setTimeout',
+ clearMethod: 'clearTimeout',
+ nativeClearMethod: '__zone_symbol__clearTimeout',
+ run: function() {
+ return setTimeout(function() {});
+ },
+ runClear: function(timerId) {
+ return clearTimeout(timerId);
+ },
+ nativeRun: function() {
+ return nativeSetTimeout(function() {});
+ },
+ nativeRunClear: function(timerId) {
+ return nativeClearTimeout(timerId);
+ }
+ },
+ {
+ isCallback: true,
+ supportClear: false,
+ method: 'setTimeout_callback',
+ nativeMethod: 'native_setTimeout_callback',
+ run: function() {
+ zone.run(function() {
+ setTimeout(function() {});
+ });
+ },
+ nativeRun: function() {
+ var func = function() {};
+ nativeSetTimeout(function() {
+ mark('native_setTimeout_callback');
+ func.apply(this, arguments);
+ measure('native_setTimeout_callback', 'native_setTimeout_callback');
+ });
+ }
+ }
+ ],
+ };
+ return testRunner(testTarget);
+}(typeof window === 'undefined' ? global : window));
diff --git a/test/performance/xhr.js b/test/performance/xhr.js
new file mode 100644
index 000000000..c507a058c
--- /dev/null
+++ b/test/performance/xhr.js
@@ -0,0 +1,51 @@
+/**
+ * @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
+ */
+(function(_global) {
+ var mark = _global['__zone_symbol__mark'];
+ var measure = _global['__zone_symbol__measure'];
+ var testRunner = _global['__zone_symbol__testRunner'];
+ var zone = _global['__zone_symbol__callbackZone'];
+ var testTarget = {
+ title: 'xhr',
+ times: 3,
+ count: 1000,
+ before: function() {
+ _global['__zone_symbol__callbackContext'].measureName = 'xhr_callback';
+ _global['__zone_symbol__callbackContext'].type = 'macroTask';
+ _global['__zone_symbol__callbackContext'].source = 'send';
+ },
+ apis: [
+ {
+ supportClear: true,
+ method: 'XHR.send',
+ nativeMethod: 'native.XHR.send',
+ clearMethod: 'XHR.abort',
+ nativeClearMethod: 'native.XHR.abort',
+ run: function() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('get', 'http://localhost:8080', true);
+ xhr.send();
+ return xhr;
+ },
+ runClear: function(xhr) {
+ xhr.abort();
+ },
+ nativeRun: function() {
+ var xhr = new XMLHttpRequest();
+ xhr['__zone_symbol__open']('get', 'http://localhost:8080', true);
+ xhr['__zone_symbol__send']();
+ return xhr;
+ },
+ nativeRunClear: function(xhr) {
+ xhr['__zone_symbol__abort']();
+ }
+ },
+ ],
+ };
+ return testRunner(testTarget);
+}(typeof window === 'undefined' ? global : window));