From 4afa14297a18b02183c2002ccc3c296559f79729 Mon Sep 17 00:00:00 2001 From: Thomas Lebeau Date: Tue, 3 Dec 2024 14:21:30 +0100 Subject: [PATCH 01/12] =?UTF-8?q?=E2=9C=A8=20add=20diagnostic=20test=20sui?= =?UTF-8?q?te?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/common/extension.types.ts | 9 + .../src/common/panelTabConstants.ts | 3 +- .../src/content-scripts/main.ts | 2 +- .../src/panel/components/panel.tsx | 5 + .../tabs/diagnosticTab/data/es2016plus.ts | 8919 ++++++ .../components/tabs/diagnosticTab/data/es5.ts | 2498 ++ .../components/tabs/diagnosticTab/data/es6.ts | 26030 ++++++++++++++++ .../tabs/diagnosticTab/data/esnext.ts | 1161 + .../tabs/diagnosticTab/data/index.ts | 33 + .../components/tabs/diagnosticTab/index.tsx | 200 + 10 files changed, 38858 insertions(+), 2 deletions(-) create mode 100644 developer-extension/src/panel/components/tabs/diagnosticTab/data/es2016plus.ts create mode 100644 developer-extension/src/panel/components/tabs/diagnosticTab/data/es5.ts create mode 100644 developer-extension/src/panel/components/tabs/diagnosticTab/data/es6.ts create mode 100644 developer-extension/src/panel/components/tabs/diagnosticTab/data/esnext.ts create mode 100644 developer-extension/src/panel/components/tabs/diagnosticTab/data/index.ts create mode 100644 developer-extension/src/panel/components/tabs/diagnosticTab/index.tsx diff --git a/developer-extension/src/common/extension.types.ts b/developer-extension/src/common/extension.types.ts index 131e32ce5d..a1036be3dc 100644 --- a/developer-extension/src/common/extension.types.ts +++ b/developer-extension/src/common/extension.types.ts @@ -8,6 +8,11 @@ export type BackgroundToDevtoolsMessage = { message: SdkMessage } +export type BackgroundTestResult = { + id: string + status: 'running' | 'passed' | 'failed' +} + export type DevtoolsToBackgroundMessage = { type: 'update-net-request-rules' options: NetRequestRulesOptions @@ -42,6 +47,10 @@ export type SdkMessage = segment: BrowserSegmentMetadata } } + | { + type: 'test-result' + payload: BackgroundTestResult + } export type EventCollectionStrategy = 'sdk' | 'requests' diff --git a/developer-extension/src/common/panelTabConstants.ts b/developer-extension/src/common/panelTabConstants.ts index f0fb92b2d7..21b370176d 100644 --- a/developer-extension/src/common/panelTabConstants.ts +++ b/developer-extension/src/common/panelTabConstants.ts @@ -3,6 +3,7 @@ export const enum PanelTabs { Infos = 'infos', Settings = 'settings', Replay = 'replay', + Dignostics = 'diagnostics', } -export const DEFAULT_PANEL_TAB = PanelTabs.Events +export const DEFAULT_PANEL_TAB = PanelTabs.Dignostics diff --git a/developer-extension/src/content-scripts/main.ts b/developer-extension/src/content-scripts/main.ts index 7b79335a62..e66db261af 100644 --- a/developer-extension/src/content-scripts/main.ts +++ b/developer-extension/src/content-scripts/main.ts @@ -14,7 +14,7 @@ declare global { type SdkPublicApi = { [key: string]: (...args: any[]) => unknown } function main() { - // Prevent multiple executions when the devetools are reconnecting + // Prevent multiple executions when the devtools are reconnecting if (window.__ddBrowserSdkExtensionCallback) { return } diff --git a/developer-extension/src/panel/components/panel.tsx b/developer-extension/src/panel/components/panel.tsx index 8f57b83389..916ff16dd4 100644 --- a/developer-extension/src/panel/components/panel.tsx +++ b/developer-extension/src/panel/components/panel.tsx @@ -13,6 +13,7 @@ import { SettingsTab } from './tabs/settingsTab' import { InfosTab } from './tabs/infosTab' import { EventsTab, DEFAULT_COLUMNS } from './tabs/eventsTab' import { ReplayTab } from './tabs/replayTab' +import { DiagnosticTab } from './tabs/diagnosticTab' import * as classes from './panel.module.css' @@ -65,6 +66,7 @@ export function Panel() { > Settings + Disgnostic + + + ) } diff --git a/developer-extension/src/panel/components/tabs/diagnosticTab/data/es2016plus.ts b/developer-extension/src/panel/components/tabs/diagnosticTab/data/es2016plus.ts new file mode 100644 index 0000000000..7f2cf4e9d8 --- /dev/null +++ b/developer-extension/src/panel/components/tabs/diagnosticTab/data/es2016plus.ts @@ -0,0 +1,8919 @@ +/* eslint-disable */ +// @ts-nocheck + +const babel = {} +const typescript = {} +const firefox = {} +const chrome = {} +const edge = {} +const graalvm = {} + +export const data = [ + { + name: 'exponentiation (**) operator', + category: '2016 features', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/7.0/index.html#sec-exp-operator', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation_(**)', + subtests: [ + { + name: 'basic support', + exec() { + /* + return 2 ** 3 === 8 && -(5 ** 2) === -25 && (-5) ** 2 === 25; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox42: firefox.nightly, + firefox52: true, + opera10_50: false, + chrome51: chrome.experimental, + chrome52: true, + safari10_1: true, + duktape2_0: true, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'assignment', + exec() { + /* + var a = 2; a **= 3; return a === 8; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox48: firefox.nightly, + firefox52: true, + opera10_50: false, + chrome51: chrome.experimental, + chrome52: true, + safari10_1: true, + duktape2_0: true, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'early syntax error for unary negation without parens', + exec() { + /* + if (2 ** 3 !== 8) { return false; } + try { + Function ("-5 ** 2")(); + } catch (e) { + return true; + } + */ + }, + res: { + babel6corejs2: true, + closure: true, + ie11: false, + edge14: true, + firefox2: false, + firefox52: true, + opera10_50: false, + chrome51: chrome.experimental, + chrome52: true, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + ], + }, + { + name: 'Object static methods', + spec: 'https://tc39.github.io/ecma262/#sec-properties-of-the-object-constructor', + category: '2017 features', + significance: 'medium', + subtests: [ + { + name: 'Object.values', + spec: 'https://tc39.github.io/ecma262/#sec-object.values', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values', + category: '2017 features', + significance: 'medium', + exec() { + /* + var obj = Object.create({ a: "qux", d: "qux" }); + obj.a = "foo"; + obj.b = "bar"; + obj.c = "baz"; + var v = Object.values(obj); + return Array.isArray(v) && String(v) === "foo,bar,baz"; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + es7shim: true, + typescript1corejs2: typescript.corejs, + firefox2: false, + firefox45: firefox.nightly, + firefox47: true, + opera10_50: false, + chrome51: chrome.experimental, + chrome54: true, + ie11: false, + edge14: true, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'Object.entries', + spec: 'https://tc39.github.io/ecma262/#sec-object.entries', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries', + exec() { + /* + var obj = Object.create({ a: "qux", d: "qux" }); + obj.a = "foo"; + obj.b = "bar"; + obj.c = "baz"; + var e = Object.entries(obj); + return Array.isArray(e) + && e.length === 3 + && String(e[0]) === "a,foo" + && String(e[1]) === "b,bar" + && String(e[2]) === "c,baz"; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + es7shim: true, + typescript1corejs2: typescript.corejs, + firefox2: false, + firefox45: firefox.nightly, + firefox47: true, + opera10_50: false, + chrome51: chrome.experimental, + chrome54: true, + ie11: false, + edge14: true, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'Object.getOwnPropertyDescriptors', + spec: 'https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptors', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors', + exec() { + /* + var object = {a: 1}; + var B = typeof Symbol === 'function' ? Symbol('b') : 'b'; + object[B] = 2; + var O = Object.defineProperty(object, 'c', {value: 3}); + var D = Object.getOwnPropertyDescriptors(O); + + return D.a.value === 1 && D.a.enumerable === true && D.a.configurable === true && D.a.writable === true + && D[B].value === 2 && D[B].enumerable === true && D[B].configurable === true && D[B].writable === true + && D.c.value === 3 && D.c.enumerable === false && D.c.configurable === false && D.c.writable === false; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + es7shim: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + chrome51: chrome.experimental, + chrome54: true, + firefox2: false, + firefox50: true, + opera10_50: false, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: "Object.getOwnPropertyDescriptors doesn't provide undefined descriptors", + exec() { + /* + var P = new Proxy({ a: 1 }, { + getOwnPropertyDescriptor: function (t, k) {} + }); + return !Object.getOwnPropertyDescriptors(P).hasOwnProperty('a'); + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox50: true, + opera10_50: false, + chrome54: true, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Array.prototype.includes', + spec: 'http://www.ecma-international.org/ecma-262/7.0/index.html#sec-array.prototype.includes', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes', + category: '2016 features', + significance: 'small', + subtests: [ + { + name: 'Array.prototype.includes', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes', + exec() { + /* + return [1, 2, 3].includes(1) + && ![1, 2, 3].includes(4) + && ![1, 2, 3].includes(1, 1) + && [NaN].includes(NaN); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + es7shim: true, + typescript1corejs2: typescript.corejs, + safari9: true, + chrome47: true, + ie11: false, + edge14: true, + firefox2: false, + firefox43: true, + opera10_50: false, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.prototype.includes handles sparse arrays', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes', + exec() { + /* + return [,].includes() + && Array(1).includes(); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + es7shim: true, + typescript1corejs2: typescript.corejs, + safari9: true, + chrome47: true, + ie11: false, + edge14: true, + firefox2: false, + firefox43: true, + firefox99: false, + firefox102: true, + opera10_50: false, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.prototype.includes is generic', + exec() { + /* + var passed = 0; + return [].includes.call( + { + get "0"() { + passed = NaN; + return 'foo'; + }, + get "11"() { + passed += 1; + return 0; + }, + get "19"() { + passed += 1; + return 'foo'; + }, + get "21"() { + passed = NaN; + return 'foo'; + }, + get length() { + passed += 1; + return 24; + } + }, + 'foo', + 6 + ) === true && passed === 3; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20180402: true, + es7shim: true, + typescript1corejs2: typescript.corejs, + safari9: true, + chrome47: true, + ie11: false, + edge14: true, + firefox2: false, + firefox43: true, + opera10_50: false, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: '%TypedArray%.prototype.includes', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/includes', + exec() { + /* + return [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array + ].every(function (TypedArray) { + return new TypedArray([1, 2, 3]).includes(1) + && !new TypedArray([1, 2, 3]).includes(4) + && !new TypedArray([1, 2, 3]).includes(1, 1); + }); + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + chrome47: true, + ie11: false, + edge14: true, + firefox2: false, + firefox43: true, + opera10_50: false, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'String padding', + category: '2017 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-string-pad-start-end', + subtests: [ + { + name: 'String.prototype.padStart', + spec: 'https://tc39.github.io/ecma262/#sec-string.prototype.padstart', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart', + exec() { + /* + return 'hello'.padStart(10) === ' hello' + && 'hello'.padStart(10, '1234') === '12341hello' + && 'hello'.padStart() === 'hello' + && 'hello'.padStart(6, '123') === '1hello' + && 'hello'.padStart(3) === 'hello' + && 'hello'.padStart(3, '123') === 'hello'; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + es7shim: true, + firefox2: false, + firefox48: true, + opera10_50: false, + ie11: false, + edge14: edge.experimental, + edge15: true, + chrome52: chrome.experimental, + chrome57: true, + node8: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.padEnd', + spec: 'https://tc39.github.io/ecma262/#sec-string.prototype.padend', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd', + exec() { + /* + return 'hello'.padEnd(10) === 'hello ' + && 'hello'.padEnd(10, '1234') === 'hello12341' + && 'hello'.padEnd() === 'hello' + && 'hello'.padEnd(6, '123') === 'hello1' + && 'hello'.padEnd(3) === 'hello' + && 'hello'.padEnd(3, '123') === 'hello'; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + es7shim: true, + firefox2: false, + firefox48: true, + opera10_50: false, + ie11: false, + edge14: edge.experimental, + edge15: true, + chrome52: chrome.experimental, + chrome57: true, + node8: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'trailing commas in function syntax', + spec: 'https://github.com/tc39/proposal-trailing-function-commas', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas', + category: '2017 features', + significance: 'small', + subtests: [ + { + name: 'in parameter lists', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas#Parameter_definitions', + exec() { + /* + return typeof function f( a, b, ) {} === 'function'; + */ + }, + res: { + babel6corejs2: true, + closure: true, + typescript2corejs2: true, + ie11: false, + edge14: true, + chrome57: chrome.experimental, + chrome58: true, + firefox2: false, + firefox52: true, + opera10_50: false, + node8: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'in argument lists', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas#Function_calls', + exec() { + /* + return Math.min(1,2,3,) === 1; + */ + }, + res: { + babel6corejs2: true, + closure: true, + typescript2corejs2: true, + ie11: false, + edge14: true, + chrome57: chrome.experimental, + chrome58: true, + firefox2: false, + firefox52: true, + opera10_50: false, + node8: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'async functions', + category: '2017 features', + significance: 'large', + spec: 'https://tc39.github.io/ecma262/#sec-async-function-definitions', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function', + subtests: [ + { + // Should test that async functions return promises + // that (without await) resolve to the returned value. + name: 'return', + exec() { + /* + async function a() { + return "foo"; + } + var p = a(); + if (!(p instanceof Promise)) { + return false; + } + p.then(function (result) { + if (result === "foo") { + asyncTestPassed(); + } + }); + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + chrome52: chrome.experimental, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'throw', + exec() { + /* + async function a() { + throw "foo"; + } + var p = a(); + if (!(p instanceof Promise)) { + return false; + } + p.catch (function (result) { + if (result === "foo") { + asyncTestPassed(); + } + }); + */ + }, + res: { + tr: null, + babel6corejs2: null, + babel7corejs2: babel.regenerator, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + chrome52: null, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'no line break between async and function', + exec() { + /* + async function a() {} + try { Function ("async\n function a() {await 0}")(); } catch (e) { return true; } + */ + }, + res: { + tr: null, + babel6corejs2: null, + babel7corejs3: true, + closure: true, + typescript1corejs2: null, + chrome52: null, + chrome55: true, + ie11: false, + edge13: false, + edge14: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'no "prototype" property', + exec() { + /* + async function a() {}; + return !a.hasOwnProperty("prototype"); + */ + }, + res: { + tr: null, + babel6corejs2: null, + closure: false, + typescript1corejs2: false, + chrome52: null, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'await', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await', + exec() { + /* + (async function () { + await Promise.resolve(); + var a1 = await new Promise(function (resolve) { setTimeout(resolve,800,"foo"); }); + var a2 = await new Promise(function (resolve) { setTimeout(resolve,800,"bar"); }); + if (a1 + a2 === "foobar") { + asyncTestPassed(); + } + }()); + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + chrome52: chrome.experimental, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'await, rejection', + exec() { + /* + (async function () { + await Promise.resolve(); + try { + var a1 = await new Promise(function (_, reject) { setTimeout(reject,800,"foo"); }); + } catch (e) { + if (e === "foo") { + asyncTestPassed(); + } + } + }()); + */ + }, + res: { + tr: null, + babel6corejs2: null, + babel7corejs2: babel.regenerator, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + chrome52: null, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'must await a value', + exec() { + /* + async function a() { await Promise.resolve(); } + try { Function ("(async function a() { await; }())")(); } catch (e) { return true; } + */ + }, + res: { + tr: null, + babel6corejs2: null, + babel7corejs3: true, + closure: true, + typescript1corejs2: null, + chrome52: null, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'can await non-Promise values', + exec() { + /* + (async function () { + await Promise.resolve(); + var e = await "foo"; + if (e === "foo") { + asyncTestPassed(); + } + }()); + */ + }, + res: { + tr: null, + babel6corejs2: null, + babel7corejs2: babel.regenerator, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + chrome52: null, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'cannot await in parameters', + exec() { + /* + async function a() { await Promise.resolve(); } + try { Function ("(async function a(b = await Promise.resolve()) {}())")(); } catch (e) { return true; } + */ + }, + res: { + tr: null, + babel6corejs2: null, + babel7corejs3: true, + closure: false, + closure20200614: true, + typescript1corejs2: null, + chrome52: null, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'async methods, object literals', + exec() { + /* + var o = { + async a() { return await Promise.resolve("foo"); } + }; + var p = o.a(); + if (!(p instanceof Promise)) { + return false; + } + p.then(function (result) { + if (result === "foo") { + asyncTestPassed(); + } + }); + */ + }, + res: { + tr: null, + babel6corejs2: null, + babel7corejs2: babel.regenerator, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + chrome52: null, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'async methods, classes', + exec() { + /* + class C { + async a() { return await Promise.resolve("foo"); } + }; + var p = new C().a(); + if (!(p instanceof Promise)) { + return false; + } + p.then(function (result) { + if (result === "foo") { + asyncTestPassed(); + } + }); + */ + }, + res: { + tr: null, + babel6corejs2: null, + babel7corejs2: babel.regenerator, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + chrome52: null, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'async arrow functions in methods, classes', + exec() { + /* + function doSomething(callback) { + callback(); + } + class C { + a() { + doSomething(async () => { + await 1; + asyncTestPassed(); + }); + } + }; + var p = new C().a(); + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + chrome52: chrome.experimental, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10: false, + safari10_1: false, + safari11: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'async arrow functions', + exec() { + /* + var a = async () => await Promise.resolve("foo"); + var p = a(); + if (!(p instanceof Promise)) { + return false; + } + p.then(function (result) { + if (result === "foo") { + asyncTestPassed(); + } + }); + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + chrome52: chrome.experimental, + chrome55: true, + ie11: false, + edge13: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'correct prototype chain', + exec() { + /* + var asyncFunctionProto = Object.getPrototypeOf(async function () {}); + return asyncFunctionProto !== function () {}.prototype + && Object.getPrototypeOf(asyncFunctionProto) === Function.prototype; + */ + }, + res: { + tr: null, + babel6corejs2: null, + closure: false, + typescript1corejs2: false, + chrome52: null, + chrome55: true, + ie11: false, + edge13: false, + edge14: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'async function prototype, Symbol.toStringTag', + exec() { + /* + return Object.getPrototypeOf(async function () {})[Symbol.toStringTag] === "AsyncFunction"; + */ + }, + res: { + tr: null, + babel6corejs2: null, + closure: false, + typescript1corejs2: false, + chrome52: null, + chrome55: true, + ie11: false, + edge13: false, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'async function constructor', + exec() { + /* + var a = async function () {}.constructor("return 'foo';"); + var p = a(); + if (!(p instanceof Promise)) { + return false; + } + p.then(function (result) { + if (result === "foo") { + asyncTestPassed(); + } + }); + */ + }, + res: { + tr: null, + babel6corejs2: null, + closure: false, + typescript1corejs2: false, + chrome52: null, + chrome55: true, + ie11: false, + edge13: false, + edge14: edge.experimental, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'shared memory and atomics', + category: '2017 features', + significance: 'medium', + subtests: [ + { + name: 'SharedArrayBuffer', + spec: 'https://tc39.github.io/ecma262/#sec-sharedarraybuffer-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer', + exec() { + /* + return typeof SharedArrayBuffer === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { + val: false, + note_id: 'edg-shared-memory-spectre', + note_html: 'The feature was temporarily disabled to mitigate the Meltdown and Spectre CPU bugs.', + }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { + val: 'flagged', + note_id: 'fx-shared-memory-spectre', + note_html: + 'The feature was temporarily disabled to mitigate the Meltdown and Spectre CPU bugs. It can be enabled via javascript.options.shared_memory setting under about:config', + }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox77: { + val: false, + note_id: 'fx-shared-memory-esr-disable', + note_html: 'The feature was intentionally disabled to prepare for Firefox 78 ESR', + }, + firefox79: { + val: true, + note_id: 'fx-shared-memory-cors-isolation', + note_html: + 'The feature is available with properly set CORS isolation headers or via enabling dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled setting under about:config', + }, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { + val: false, + note_id: 'chr-shared-memory-spectre', + note_html: 'The feature was temporarily disabled to mitigate the Meltdown and Spectre CPU bugs.', + }, + chrome68: true, + safari10_1: true, + safari11: { + val: false, + note_id: 'sf-shared-memory-spectre', + note_html: + 'The feature was temporarily disabled to mitigate the Meltdown and Spectre CPU bugs.', + }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'SharedArrayBuffer[Symbol.species]', + exec() { + /* + return SharedArrayBuffer[Symbol.species] === SharedArrayBuffer; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox52: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox77: { val: false, note_id: 'fx-shared-memory-esr-disable' }, + firefox79: { val: true, note_id: 'fx-shared-memory-cors-isolation' }, + opera10_50: false, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'SharedArrayBuffer.prototype.byteLength', + spec: 'https://tc39.github.io/ecma262/#sec-get-sharedarraybuffer.prototype.bytelength', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/byteLength', + exec() { + /* + return 'byteLength' in SharedArrayBuffer.prototype; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox77: { val: false, note_id: 'fx-shared-memory-esr-disable' }, + firefox79: { val: true, note_id: 'fx-shared-memory-cors-isolation' }, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari11: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'SharedArrayBuffer.prototype.slice', + spec: 'https://tc39.github.io/ecma262/#sec-sharedarraybuffer.prototype.slice', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/slice', + exec() { + /* + return typeof SharedArrayBuffer.prototype.slice === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox52: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox77: { val: false, note_id: 'fx-shared-memory-esr-disable' }, + firefox79: { val: true, note_id: 'fx-shared-memory-cors-isolation' }, + opera10_50: false, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'SharedArrayBuffer.prototype[Symbol.toStringTag]', + spec: 'https://tc39.github.io/ecma262/#sec-sharedarraybuffer.prototype.toString', + exec() { + /* + return SharedArrayBuffer.prototype[Symbol.toStringTag] === 'SharedArrayBuffer'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox52: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox77: { val: false, note_id: 'fx-shared-memory-esr-disable' }, + firefox79: { val: true, note_id: 'fx-shared-memory-cors-isolation' }, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.add', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.add', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/add', + exec() { + /* + return typeof Atomics.add === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.and', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.and', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/and', + exec() { + /* + return typeof Atomics.and === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.compareExchange', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.compareExchange', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/compareExchange', + exec() { + /* + return typeof Atomics.compareExchange === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.exchange', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.exchange', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/exchange', + exec() { + /* + return typeof Atomics.exchange === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.wait', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.wait', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/wait', + exec() { + /* + return typeof Atomics.wait === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox48: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.notify', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.notify', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/notify', + exec() { + /* + return typeof Atomics.notify === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox48: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: false, + graalvm20: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.isLockFree', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.isLockFree', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/isLockFree', + exec() { + /* + return typeof Atomics.isLockFree === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.load', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.load', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/load', + exec() { + /* + return typeof Atomics.load === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.or', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.or', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/or', + exec() { + /* + return typeof Atomics.or === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.store', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.store', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/store', + exec() { + /* + return typeof Atomics.store === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.sub', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.sub', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/sub', + exec() { + /* + return typeof Atomics.sub === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Atomics.xor', + spec: 'https://tc39.github.io/ecma262/#sec-atomics.xor', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/xor', + exec() { + /* + return typeof Atomics.xor === 'function'; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + edge16: true, + edge17: { val: false, note_id: 'edg-shared-memory-spectre' }, + firefox2: false, + firefox46: firefox.nightly, + firefox51: firefox.developer, + firefox53: firefox.sharedmem, + firefox55: true, + firefox57: { val: 'flagged', note_id: 'fx-shared-memory-spectre' }, + firefox72: firefox.nightly, + firefox74: firefox.beta, + firefox78: true, + opera10_50: false, + chrome48: chrome.sharedmem, + chrome60: true, + chrome63: { val: false, note_id: 'chr-shared-memory-spectre' }, + chrome68: true, + safari10_1: true, + safari11_1: { val: false, note_id: 'sf-shared-memory-spectre' }, + safari15_2: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'generator functions can\'t be used with "new"', + category: '2016 misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/7.0/index.html#sec-createdynamicfunction', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*#Generators_are_not_constructable', + links: [ + { + note_id: 'new-gen-fn', + note_html: + 'TC39 meeting notes from July 28, 2015.', + }, + ], + exec() { + /* + function * generator() { + yield 3; + } + try { + new generator(); + } catch (e) { + return true; + } + */ + }, + res: { + ie11: false, + edge13: true, + firefox2: false, + firefox43: true, + opera10_50: false, + chrome50: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'generator throw() caught by inner generator', + category: '2016 misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/7.0/index.html#sec-generatorfunction-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*#IteratorResult_object_returned_instead_of_throwing', + links: [ + { + note_id: 'gen-throw', + note_html: + '\'Semantics of yield* in throw case\' GitHub issue in ECMA-262 repo.', + }, + ], + exec() { + /* + function * generator() { + yield * (function * () { + try { + yield 'foo'; + } + catch (e) { + return; + } + }()); + yield 'bar'; + } + var iter = generator(); + iter.next(); + return iter['throw']().value === 'bar'; + */ + }, + res: { + babel7corejs3: true, + closure: false, + closure20180319: true, + typescript1corejs2: typescript.downlevelIteration, + ie11: false, + edge14: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome39: true, + node0_12: 'flagged', + node4: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'strict fn w/ non-strict non-simple params is error', + category: '2016 misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/7.0/index.html#sec-functiondeclarationinstantiation', + links: [ + { + note_id: 'strict-fn-non-strict-params', + note_html: + 'TC39 meeting notes from July 29, 2015.', + }, + ], + exec() { + /* + function foo(...a) {} + try { + Function ("function bar(...a) {'use strict';}")(); + } catch (e) { + return true; + } + */ + }, + res: { + babel7corejs3: true, + ie11: false, + edge12: true, + firefox2: false, + firefox52: true, + opera10_50: false, + chrome47: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'nested rest destructuring, declarations', + category: '2016 misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/7.0/index.html#sec-destructuring-assignment', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Nested_object_and_array_destructuring', + links: [ + { + note_id: 'nested-rest-destruct-decl', + note_html: + 'TC39 meeting notes from July 28, 2015.', + }, + ], + exec() { + /* + var [x, ...[y, ...z]] = [1,2,3,4]; + return x === 1 && y === 2 && z + '' === '3,4'; + */ + }, + res: { + babel6corejs2: true, + closure: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox47: true, + opera10_50: false, + chrome49: true, + safari10_1: true, + typescript1corejs2: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'nested rest destructuring, parameters', + category: '2016 misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/7.0/index.html#sec-destructuring-assignment', + links: [ + { + note_id: 'nested-rest-destruct-params', + note_html: + 'TC39 meeting notes from July 28, 2015.', + }, + ], + exec() { + /* + return function ([x, ...[y, ...z]]) { + return x === 1 && y === 2 && z + '' === '3,4'; + }([1,2,3,4]); + */ + }, + res: { + babel6corejs2: true, + closure: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox47: true, + opera10_50: false, + typescript1corejs2: true, + chrome49: true, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Proxy, "enumerate" handler removed', + category: '2016 misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/7.0/index.html#sec-proxy-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/enumerate', + links: [ + { + note_id: 'proxy-enumerate-removed', + note_html: + '\'Normative: Remove [[Enumerate]] and associated reflective capabilities\' GitHub Pull Request in ECMA-262 repo.', + }, + ], + exec() { + /* + var passed = true; + var proxy = new Proxy({}, { + enumerate: function () { + passed = false; + } + }); + for (var key in proxy); // Should not throw, nor execute the 'enumerate' method. + return passed; + */ + }, + res: { + ie11: false, + edge15: true, + firefox2: false, + firefox18: true, + firefox25: false, + firefox47: true, + opera10_50: false, + chrome50: true, + safari10: true, + duktape2_0: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Proxy internal calls, Array.prototype.includes', + category: '2016 misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/7.0/index.html#sec-array.prototype.includes', + exec() { + /* + // Array.prototype.includes -> Get -> [[Get]] + var get = []; + var p = new Proxy({length: 3, 0: '', 1: '', 2: '', 3: ''}, { get: function (o, k) { get.push(k); return o[k]; }}); + Array.prototype.includes.call(p, {}); + if (get + '' !== "length,0,1,2") return; + + get = []; + p = new Proxy({length: 4, 0: NaN, 1: '', 2: NaN, 3: ''}, { get: function (o, k) { get.push(k); return o[k]; }}); + Array.prototype.includes.call(p, NaN, 1); + return (get + '' === "length,1,2"); + */ + }, + res: { + firefox2: false, + firefox43: true, + opera10_50: false, + chrome49: true, + ie11: false, + edge14: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Object.prototype getter/setter methods', + spec: 'https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__', + category: '2017 annex b', + significance: 'tiny', + subtests: [ + { + name: '__defineGetter__', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineGetter__', + exec() { + /* + var obj = {}; + function bar() { return "bar"; } + Object.prototype.__defineGetter__.call(obj, "foo", bar); + var prop = Object.getOwnPropertyDescriptor(obj, "foo"); + return prop.get === bar && !prop.writable && prop.configurable + && prop.enumerable; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox4: true, + opera10_50: false, + opera12: true, + chrome30: true, + node0_12: true, + safari4: true, + safari9: true, + android4_0: true, + ios5_1: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '__defineGetter__, symbols', + exec() { + /* + var obj = {}; + var sym = Symbol(); + function bar() { return "bar"; } + Object.prototype.__defineGetter__.call(obj, sym, bar); + var prop = Object.getOwnPropertyDescriptor(obj, sym); + return prop.get === bar && !prop.writable && prop.configurable + && prop.enumerable; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome38: true, + node0_12: true, + safari9: true, + android4_0: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '__defineGetter__, ToObject(this)', + exec() { + /* + var key = '__accessors_test__'; + __defineGetter__.call(1, key, function () {}); + try { + __defineGetter__.call(null, key, function () {}); + } catch (e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge16: true, + firefox2: false, + firefox48: true, + opera10_50: false, + opera12: true, + chrome60: chrome.harmony, + chrome62: true, + safari5_1: true, + safari9: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '__defineSetter__', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineSetter__', + exec() { + /* + var obj = {}; + function bar() {} + Object.prototype.__defineSetter__.call(obj, "foo", bar); + var prop = Object.getOwnPropertyDescriptor(obj, "foo"); + return prop.set === bar && !prop.writable && prop.configurable + && prop.enumerable; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox4: true, + opera10_50: false, + opera12: true, + chrome30: true, + node0_12: true, + safari4: true, + safari9: true, + android4_0: true, + ios5_1: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '__defineSetter__, symbols', + exec() { + /* + var obj = {}; + var sym = Symbol(); + function bar(baz) {} + Object.prototype.__defineSetter__.call(obj, sym, bar); + var prop = Object.getOwnPropertyDescriptor(obj, sym); + return prop.set === bar && !prop.writable && prop.configurable + && prop.enumerable; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome38: true, + node0_12: true, + safari9: true, + android4_0: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '__defineSetter__, ToObject(this)', + exec() { + /* + var key = '__accessors_test__'; + __defineSetter__.call(1, key, function () {}); + try { + __defineSetter__.call(null, key, function () {}); + } catch (e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge16: true, + firefox2: false, + firefox48: true, + opera10_50: false, + opera12: true, + chrome60: chrome.harmony, + chrome62: true, + safari5_1: true, + safari9: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '__lookupGetter__', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__lookupGetter__', + exec() { + /* + var obj = { + get foo() { return "bar"}, + qux: 1 + }; + var foo = Object.prototype.__lookupGetter__.call(obj, "foo"); + return foo() === "bar" + && Object.prototype.__lookupGetter__.call(obj, "qux") === void undefined + && Object.prototype.__lookupGetter__.call(obj, "baz") === void undefined; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: true, + opera10_50: true, + opera12: true, + chrome30: true, + node0_12: true, + safari3_1: true, + safari9: true, + android4_0: true, + ios5_1: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '__lookupGetter__, prototype chain', + exec() { + /* + var obj = { + get foo() { return "bar"}, + qux: 1 + }; + var foo = Object.prototype.__lookupGetter__.call(Object.create(obj), "foo"); + return foo() === "bar" + && Object.prototype.__lookupGetter__.call(obj, "qux") === void undefined + && Object.prototype.__lookupGetter__.call(obj, "baz") === void undefined; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox4: true, + opera10_50: false, + opera12: true, + chrome30: true, + node0_12: true, + safari4: true, + safari9: true, + android4_0: true, + ios5_1: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '__lookupGetter__, symbols', + exec() { + /* + var sym = Symbol(); + var sym2 = Symbol(); + var obj = {}; + Object.defineProperty(obj, sym, { get: function () { return "bar"; }}); + Object.defineProperty(obj, sym2, { value: 1 }); + var foo = Object.prototype.__lookupGetter__.call(obj, sym); + return foo() === "bar" + && Object.prototype.__lookupGetter__.call(obj, sym2) === void undefined + && Object.prototype.__lookupGetter__.call(obj, Symbol()) === void undefined; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome38: true, + node0_12: true, + safari9: true, + android4_0: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '__lookupGetter__, ToObject(this)', + exec() { + /* + __lookupGetter__.call(1, 'key'); + try { + __lookupGetter__.call(null, 'key'); + } catch (e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox24: true, + opera10_50: false, + opera12: true, + chrome60: chrome.harmony, + chrome62: true, + safari5_1: true, + safari9: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '__lookupGetter__, data properties can shadow accessors', + exec() { + /* + var a = {}; + var b = Object.create(a); + b.foo = 1; + a.__defineGetter__("foo", function () {}); + return b.__lookupGetter__("foo") === void undefined; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + firefox2: false, + firefox4: true, + opera10_50: false, + opera12: true, + chrome57: true, + node8: true, + safari4: true, + safari9: true, + ios5_1: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '__lookupSetter__', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__lookupSetter__', + exec() { + /* + var obj = { + set foo(baz) { return "bar"; }, + qux: 1 + }; + var foo = Object.prototype.__lookupSetter__.call(obj, "foo"); + return foo() === "bar" + && Object.prototype.__lookupSetter__.call(obj, "qux") === void undefined + && Object.prototype.__lookupSetter__.call(obj, "baz") === void undefined; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: true, + opera10_50: true, + opera12: true, + chrome30: true, + node0_12: true, + safari3_1: true, + safari9: true, + android4_0: true, + ios5_1: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '__lookupSetter__, prototype chain', + exec() { + /* + var obj = { + set foo(baz) { return "bar"; }, + qux: 1 + }; + var foo = Object.prototype.__lookupSetter__.call(Object.create(obj), "foo"); + return foo() === "bar" + && Object.prototype.__lookupSetter__.call(obj, "qux") === void undefined + && Object.prototype.__lookupSetter__.call(obj, "baz") === void undefined; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox4: true, + opera10_50: false, + opera12: true, + chrome30: true, + node0_12: true, + safari4: true, + safari9: true, + android4_0: true, + ios5_1: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '__lookupSetter__, symbols', + exec() { + /* + var sym = Symbol(); + var sym2 = Symbol(); + var obj = {}; + Object.defineProperty(obj, sym, { set: function (baz) { return "bar"; }}); + Object.defineProperty(obj, sym2, { value: 1 }); + var foo = Object.prototype.__lookupSetter__.call(obj, sym); + return foo() === "bar" + && Object.prototype.__lookupSetter__.call(obj, sym2) === void undefined + && Object.prototype.__lookupSetter__.call(obj, Symbol()) === void undefined; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome38: true, + node0_12: true, + safari9: true, + android4_0: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '__lookupSetter__, ToObject(this)', + exec() { + /* + __lookupSetter__.call(1, 'key'); + try { + __lookupSetter__.call(null, 'key'); + } catch (e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox24: true, + opera10_50: false, + opera12: true, + chrome60: chrome.harmony, + chrome62: true, + safari5_1: true, + safari9: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '__lookupSetter__, data properties can shadow accessors', + exec() { + /* + var a = {}; + var b = Object.create(a); + b.foo = 1; + a.__defineSetter__("foo", function () {}) + return b.__lookupSetter__("foo") === void undefined + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + firefox2: false, + firefox4: true, + opera10_50: false, + opera12: true, + chrome57: true, + node8: true, + safari4: true, + safari9: true, + ios5_1: true, + duktape2_0: false, + duktape2_2: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'Proxy internal calls, getter/setter methods', + spec: 'https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__', + category: '2017 annex b', + significance: 'tiny', + subtests: [ + { + name: '__defineGetter__', + exec() { + /* + // Object.prototype.__defineGetter__ -> DefinePropertyOrThrow -> [[DefineOwnProperty]] + var def = []; + var p = new Proxy({}, { + defineProperty: function (o, v, desc) { + def.push(v); + Object.defineProperty(o, v, desc); + return true; + } + }); + Object.prototype.__defineGetter__.call(p, "foo", Object); + return def + '' === "foo"; + */ + }, + res: { + firefox2: false, + firefox18: true, + opera10_50: false, + ie11: false, + edge13: true, + chrome52: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '__defineSetter__', + exec() { + /* + // Object.prototype.__defineSetter__ -> DefinePropertyOrThrow -> [[DefineOwnProperty]] + var def = []; + var p = new Proxy({}, { + defineProperty: function (o, v, desc) { + def.push(v); + Object.defineProperty(o, v, desc); + return true; + } + }); + Object.prototype.__defineSetter__.call(p, "foo", Object); + return def + '' === "foo"; + */ + }, + res: { + firefox2: false, + firefox18: true, + opera10_50: false, + ie11: false, + edge13: true, + chrome52: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '__lookupGetter__', + exec() { + /* + // Object.prototype.__lookupGetter__ -> [[GetOwnProperty]] + // Object.prototype.__lookupGetter__ -> [[GetPrototypeOf]] + var gopd = []; + var gpo = false; + var p = new Proxy({}, { + getPrototypeOf: function (o) { + gpo = true; + return Object.getPrototypeOf(o); + }, + getOwnPropertyDescriptor: function (o, v) { + gopd.push(v); + return Object.getOwnPropertyDescriptor(o, v); + } + }); + Object.prototype.__lookupGetter__.call(p, "foo"); + return gopd + '' === "foo" && gpo; + */ + }, + res: { + ie11: false, + edge14: true, + chrome57: true, + firefox2: false, + firefox49: true, + opera10_50: false, + node8: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '__lookupSetter__', + exec() { + /* + // Object.prototype.__lookupSetter__ -> [[GetOwnProperty]] + // Object.prototype.__lookupSetter__ -> [[GetPrototypeOf]] + var gopd = []; + var gpo = false; + var p = new Proxy({}, { + getPrototypeOf: function (o) { + gpo = true; + return Object.getPrototypeOf(o); + }, + getOwnPropertyDescriptor: function (o, v) { + gopd.push(v); + return Object.getOwnPropertyDescriptor(o, v); + } + }); + Object.prototype.__lookupSetter__.call(p, "foo"); + return gopd + '' === "foo" && gpo; + */ + }, + res: { + ie11: false, + edge14: true, + chrome57: true, + firefox2: false, + firefox49: true, + opera10_50: false, + node8: true, + safari10: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Proxy "ownKeys" handler, duplicate keys for non-extensible targets', + category: '2018 misc', + significance: 'tiny', + spec: 'https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/ownKeys', + exec() { + /* + var p = new Proxy({}, { + ownKeys() { + return ["a", "a"]; + } + }); + try { + Object.keys(p); + } catch (e) { + return e instanceof TypeError; + } + return false; + */ + }, + res: { + ie11: false, + edge16: false, + chrome75: true, + firefox57: true, + firefox70: true, + safari13: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: false, + graalvm20: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp "u" flag, case folding', + category: '2017 misc', + significance: 'tiny', + spec: 'https://github.com/tc39/ecma262/pull/525', + exec() { + /* + return "ſ".match(/\w/iu) && !"ſ".match(/\W/iu) + && "\u212a".match(/\w/iu) && !"\u212a".match(/\W/iu) + && "\u212a".match(/.\b/iu) && "ſ".match(/.\b/iu) + && !"\u212a".match(/.\B/iu) && !"ſ".match(/.\B/iu); + */ + }, + res: { + ie11: false, + firefox2: false, + firefox54: true, + opera10_50: false, + chrome59: true, + safari10: true, + safari10_1: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'assignments allowed in for-in head in non-strict mode', + spec: 'https://tc39.github.io/ecma262/#sec-initializers-in-forin-statement-heads', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in#Compatibility_Initializer_expressions_in_strict_mode', + category: '2017 annex b', + significance: 'tiny', + exec() { + /* + for (var i = 0 in {}) {} + return i === 0; + */ + }, + res: { + tr: true, + babel7corejs3: true, + ie10: true, + edge12: true, + firefox2: true, + firefox31: true, + firefox40: false, + firefox52: true, + opera10_50: true, + chrome30: true, + safari3_1: true, + safari9: false, + safari10_1: true, + node0_12: true, + android4_0: true, + ios5_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: false, + rhino1_7_13: true, + }, + }, + { + name: 'arguments.caller removed', + category: '2017 misc', + significance: 'tiny', + spec: 'https://github.com/tc39/ecma262/pull/689', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller', + exec() { + /* + return (function () { + 'use strict'; + return !Object.getOwnPropertyDescriptor(arguments, 'caller'); + })(); + */ + }, + res: { + ie11: false, + edge16: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome56: true, + node8: true, + safari10_1: true, + duktape2_0: false, + duktape2_4: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'object rest/spread properties', + significance: 'medium', + category: '2018 features', + spec: 'https://github.com/tc39/proposal-object-rest-spread', + subtests: [ + { + name: 'object rest properties', + exec() { + /* + var { a, ...rest } = { a: 1, b: 2, c: 3 }; + return a === 1 && rest.a === void undefined && rest.b === 2 && rest.c === 3; + */ + }, + res: { + babel6corejs2: true, + closure: true, + closure20181028: { + val: false, + note_id: 'closure-object-assign', + note_html: 'Requires native support for Object.assign', + }, + closure20210906: true, + typescript2_1corejs2: true, + jsx: true, + ie11: false, + firefox2: false, + firefox55: true, + opera10_50: false, + chrome58: chrome.experimental, + chrome60: true, + safari11: false, + safari11_1: true, + safaritp: true, + webkit: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'object spread properties', + exec() { + /* + var spread = { b: 2, c: 3 }; + var O = { a: 1, ...spread }; + return O !== spread && (O.a + O.b + O.c) === 6; + */ + }, + res: { + babel6corejs2: true, + closure: true, + closure20190121: { + val: false, + note_id: 'closure-object-assign', + }, + closure20210906: true, + jsx: true, + ie11: false, + firefox2: false, + firefox55: true, + opera10_50: false, + chrome58: chrome.experimental, + chrome60: true, + typescript2_1corejs2: true, + safari11: false, + safari11_1: true, + safaritp: true, + webkit: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Promise.prototype.finally', + category: '2018 features', + significance: 'medium', + spec: 'https://github.com/tc39/proposal-promise-finally', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally', + subtests: [ + { + name: 'basic support', + exec() { + /* + var p1 = Promise.resolve("foo"); + var p2 = Promise.reject("bar"); + var score = 0; + function thenFn(result) { + score += (result === "foo"); + check(); + } + function catchFn(result) { + score += (result === "bar"); + check(); + } + function finallyFn() { + score += (arguments.length === 0); + check(); + } + p1.then(thenFn); + p1.finally(finallyFn); + p1.finally(function () { + // should return a new Promise + score += p1.finally() !== p1; + check(); + }); + p2.catch (catchFn); + p2.finally(finallyFn); + function check() { + if (score === 5) asyncTestPassed(); + } + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20180402: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge18: true, + firefox2: false, + firefox57: false, + firefox58: true, + opera10_50: false, + chrome61: chrome.promise, + chrome63: true, + safari11_1: true, + safaritp: true, + webkit: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: "don't change resolution value", + exec() { + /* + var score = 0; + function thenFn(result) { + score += (result === "foo"); + check(); + } + function catchFn(result) { + score += (result === "bar"); + check(); + } + function finallyFn() { + score++; + check(); + return Promise.resolve("foobar"); + } + Promise.resolve("foo").finally(finallyFn).then(thenFn); + Promise.reject("bar").finally(finallyFn).catch(catchFn); + function check() { + if (score === 4) asyncTestPassed(); + } + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20180402: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge18: true, + firefox2: false, + firefox57: false, + firefox58: true, + opera10_50: false, + chrome61: chrome.promise, + chrome63: true, + safari11_1: true, + safaritp: true, + webkit: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'change rejection value', + exec() { + /* + var score = 0; + Promise + .reject("foobar") + .finally(function () { + return Promise.reject("foo"); + }) + .catch (function (result) { + score += (result === "foo"); + check(); + return Promise.reject("foobar"); + }) + .finally(function () { + throw new Error('bar'); + }) + .catch (function (result) { + score += (result.message === "bar"); + check(); + }); + function check() { + if (score === 2) asyncTestPassed(); + } + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20180402: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge18: true, + firefox2: false, + firefox57: false, + firefox58: true, + opera10_50: false, + safari11_1: true, + safaritp: true, + chrome61: chrome.promise, + chrome63: true, + webkit: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'template literal revision', + spec: 'https://github.com/tc39/proposal-template-literal-revision', + category: '2018 misc', + significance: 'small', + exec() { + /* + function tag(strings, a) { + return strings[0] === void undefined + && strings.raw[0] === "\\01\\1\\xg\\xAg\\u0\\u0g\\u00g\\u000g\\u{g\\u{0\\u{110000}" + && strings[1] === "\0" + && strings.raw[1] === "\\0" + && a === 0; + } + return tag`\01\1\xg\xAg\u0\u0g\u00g\u000g\u{g\u{0\u{110000}${0}\0`; + */ + }, + res: { + babel7corejs3: true, + closure: false, + closure20181008: true, + closure20200315: false, + closure20200517: true, + ie11: false, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome59: chrome.harmony, + chrome62: true, + safari11: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 's (dotAll) flag for regular expressions', + spec: 'https://tc39.github.io/ecma262/#sec-get-regexp.prototype.dotAll', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/dotAll', + category: '2018 features', + significance: 'small', + exec() { + /* + const regex = /foo.bar/s; + return regex.test('foo\nbar'); + */ + }, + res: { + es6tr: null, + tr: null, + babel6corejs2: true, + closure: false, + jsx: null, + typescript1corejs2: null, + es6shim: null, + konq4_14: null, + ie7: null, + ie10: false, + firefox1: null, + firefox2: false, + firefox77: false, + firefox78: true, + opera10_50: false, + chrome1: null, + chrome60: chrome.harmony, + chrome62: true, + safari11_1: true, + safaritp: true, + webkit: true, + xs6: null, + jxa: null, + node0_10: null, + duktape2_0: false, + duktape2_2: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + android1_5: null, + ios4: null, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'RegExp named capture groups', + spec: 'https://github.com/tc39/proposal-regexp-named-groups', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges', + category: '2018 features', + significance: 'small', + exec() { + /* + var result = /(?\d{4})-(?\d{2})-(?\d{2})/.exec('2016-03-11'); + return result.groups.year === '2016' + && result.groups.month === '03' + && result.groups.day === '11' + && result[0] === '2016-03-11' + && result[1] === '2016' + && result[2] === '03' + && result[3] === '11'; + */ + }, + res: { + babel6corejs2: true, + ie11: false, + firefox2: false, + firefox77: false, + firefox78: true, + opera10_50: false, + chrome60: chrome.harmony, + chrome64: true, + safari11_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp Lookbehind Assertions', + spec: 'https://github.com/tc39/proposal-regexp-lookbehind', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Assertions', + category: '2018 features', + significance: 'small', + exec() { + /* + return /(?<=a)b/.test('ab') && /(? b'; + return eval('(' + str + ')') + '' === str; + */ + }, + res: { + node4: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome50: true, + safari10: true, + ie11: false, + edge13: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: '[native code]', + exec() { + /* + const NATIVE_EVAL_RE = /\bfunction\b[\s\S]*\beval\b[\s\S]*\([\s\S]*\)[\s\S]*\{[\s\S]*\[[\s\S]*\bnative\b[\s\S]+\bcode\b[\s\S]*\][\s\S]*\}/; + return NATIVE_EVAL_RE.test(eval + ''); + */ + }, + res: { + node4: true, + firefox2: false, + firefox10: true, + firefox45: true, + opera10_50: true, + chrome50: true, + safari3_1: true, + ie11: true, + edge13: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'class expression with implicit constructor', + exec() { + /* + var str = 'class A {}'; + return eval('(' + str + ')') + '' === str; + */ + }, + res: { + node4: true, + firefox2: false, + firefox55: true, + opera10_50: false, + chrome50: true, + safari10: true, + ie11: false, + edge14: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'class expression with explicit constructor', + exec() { + /* + var str = 'class /\x2A a \x2A/ A /\x2A b \x2A/ extends /\x2A c \x2A/ function B() {} /\x2A d \x2A/ { /\x2A e \x2A/ constructor /\x2A f \x2A/ ( /\x2A g \x2A/ ) /\x2A h \x2A/ { /\x2A i \x2A/ ; /\x2A j \x2A/ } /\x2A k \x2A/ m /\x2A l \x2A/ ( /\x2A m \x2A/ ) /\x2A n \x2A/ { /\x2A o \x2A/ } /\x2A p \x2A/ }'; + return eval('(/\x2A before \x2A/' + str + '/\x2A after \x2A/)') + '' === str; + */ + }, + res: { + node4: true, + firefox2: false, + firefox55: true, + opera10_50: false, + chrome50: true, + safari10: true, + ie11: false, + edge14: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'unicode escape sequences in identifiers', + exec() { + /* + var str = 'function \\u0061(\\u{62}, \\u0063) { \\u0062 = \\u{00063}; return b; }'; + return eval('(/\x2A before \x2A/' + str + '/\x2A after \x2A/)') + '' === str; + */ + }, + res: { + ie11: false, + firefox2: false, + firefox54: true, + opera10_50: false, + chrome59: chrome.harmony, + chrome66: true, + safari17: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'methods and computed property names', + exec() { + /* + var str = '[ /\x2A a \x2A/ "f" /\x2A b \x2A/ ] /\x2A c \x2A/ ( /\x2A d \x2A/ ) /\x2A e \x2A/ { /\x2A f \x2A/ }'; + return eval('({ /\x2A before \x2A/' + str + '/\x2A after \x2A/ }.f)') + '' === str; + */ + }, + res: { + ie11: false, + firefox2: false, + firefox54: true, + opera10_50: false, + chrome59: chrome.harmony, + chrome66: true, + safari17: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'JSON superset', + spec: 'https://github.com/tc39/proposal-json-superset', + category: '2019 misc', + significance: 'small', + subtests: [ + { + name: 'LINE SEPARATOR can appear in string literals', + exec() { + /* + return eval("'\u2028'") === "\u2028"; + */ + }, + res: { + closure: false, + closure20190215: true, + babel7corejs2: true, + ie11: false, + firefox2: false, + firefox61: false, + firefox62: true, + chrome65: false, + chrome66: true, + safari11: false, + safari12: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'PARAGRAPH SEPARATOR can appear in string literals', + exec() { + /* + return eval("'\u2029'") === "\u2029"; + */ + }, + res: { + closure: false, + closure20190215: true, + babel7corejs2: true, + ie11: false, + firefox2: false, + firefox61: false, + firefox62: true, + chrome65: false, + chrome66: true, + safari11: false, + safari12: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + ], + }, + { + name: 'Object.fromEntries', + significance: 'small', + spec: 'https://github.com/tc39/proposal-object-from-entries', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries', + category: '2019 features', + exec() { + /* + var object = Object.fromEntries(new Map([['foo', 42], ['bar', 23]])); + return object.foo === 42 && object.bar === 23; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + closure: false, + closure20190325: true, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox52: false, + firefox62: false, + firefox63: true, + safari12_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + chrome73: true, + chrome74: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'Well-formed JSON.stringify', + spec: 'https://github.com/tc39/proposal-well-formed-stringify', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Well-formed_JSON.stringify()', + category: '2019 misc', + significance: 'small', + exec() { + /* + return JSON.stringify('\uDF06\uD834') === "\"\\udf06\\ud834\"" + && JSON.stringify('\uDEAD') === "\"\\udead\""; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + edge16: false, + firefox10: false, + firefox52: false, + firefox63: false, + firefox64: true, + chrome70: false, + chrome71: false, + chrome72: true, + safari1: false, + safari12_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'string trimming', + category: '2019 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-string-left-right-trim', + subtests: [ + { + name: 'String.prototype.trimLeft', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimLeft', + exec() { + /* + return ' \t \n abc \t\n'.trimLeft() === 'abc \t\n'; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20190709: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox3_5: true, + firefox3_6: true, + firefox4: true, + chrome7: true, + opera10_10: false, + konq4_4: false, + konq4_9: true, + besen: false, + phantom1_9: true, + node0_12: true, + safari3: false, + safari4: true, + safari12: true, + webkit: true, + es7shim: true, + android4_0: true, + ios5_1: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.trimRight', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimRight', + exec() { + /* + return ' \t \n abc \t\n'.trimRight() === ' \t \n abc'; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20190709: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox3_5: true, + firefox3_6: true, + firefox4: true, + chrome7: true, + opera10_10: false, + konq4_4: false, + konq4_9: true, + besen: false, + phantom1_9: true, + node0_12: true, + safari3: false, + safari4: true, + safari12: true, + webkit: true, + es7shim: true, + android4_0: true, + ios5_1: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.trimStart', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimStart', + exec() { + /* + return ' \t \n abc \t\n'.trimStart() === 'abc \t\n'; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20190325: { + val: false, + note_id: 'closure-string-trimstart', + note_html: 'Requires native support for String.prototype.trimLeft.', + }, + closure20190709: true, + typescript1corejs2: typescript.corejs, + ie11: false, + firefox2: false, + firefox59: false, + firefox60: firefox.nightly, + firefox61: true, + chrome66: true, + opera10_50: false, + safari12: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.trimEnd', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd', + exec() { + /* + return ' \t \n abc \t\n'.trimEnd() === ' \t \n abc'; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20190325: { + val: false, + note_id: 'closure-string-trimend', + note_html: 'Requires native support for String.prototype.trimRight.', + }, + closure20190709: true, + typescript1corejs2: typescript.corejs, + ie11: false, + firefox2: false, + firefox59: false, + firefox60: firefox.nightly, + firefox61: true, + chrome66: true, + opera10_50: false, + safari12: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'Array.prototype.{flat, flatMap}', + category: '2019 features', + significance: 'medium', + spec: 'https://tc39.github.io/proposal-flatMap/', + links: [ + { + note_id: 'flatten-compat-issue', + note_html: + 'Name of Array.prototype.flatten() changed to Array.prototype.flat() due to web compatibility issues.', + }, + ], + subtests: [ + { + name: 'Array.prototype.flat', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat', + exec() { + /* + return [1, [2, 3], [4, [5, 6]]].flat().join('') === '12345,6'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + closure: false, + closure20190301: true, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox58: false, + firefox59: { + val: false, + note_id: 'ffox-flatten', + note_html: + 'Older Firefox Nightly builds support only the obsolete draft function name Array.prototype.flatten().', + }, + firefox62: true, + chrome69: true, + opera10_50: false, + safari12: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Array.prototype.flatMap', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap', + exec() { + /* + return [{a: 1, b: 2}, {a: 3, b: 4}].flatMap(function (it) { + return [it.a, it.b]; + }).join('') === '1234'; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20190301: true, + typescript1corejs2: typescript.corejs, + ie11: false, + firefox2: false, + firefox58: false, + firefox59: firefox.nightly, + firefox62: true, + chrome69: true, + opera10_50: false, + safari12: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'flat and flatMap in Array.prototype[@@unscopables]', + exec() { + /* + return Array.prototype[Symbol.unscopables].flat + && Array.prototype[Symbol.unscopables].flatMap; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox58: false, + firefox59: false, + firefox62: false, + firefox67: true, + chrome69: false, + chrome73: true, + chrome74: true, + opera10_50: false, + safari12: false, + safari13: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'String.prototype.matchAll', + category: '2020 features', + significance: 'small', + spec: 'https://github.com/tc39/String.prototype.matchAll', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + var iterator = '11a2bb'.matchAll(/(\d)(\D)/g); + if(iterator[Symbol.iterator]() !== iterator)return false; + var a = '', b = '', c = '', step; + while(!(step = iterator.next()).done) { + a += step.value[0]; + b += step.value[1]; + c += step.value[2]; + } + return a === '1a2b' + && b === '12' + && c === 'ab'; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: false, + closure20200101: true, + typescript1corejs2: typescript.corejs, + ie11: false, + firefox2: false, + firefox65: false, + firefox66: firefox.nightly, + firefox67: true, + chrome67: false, + chrome68: chrome.harmony, + chrome73: true, + chrome74: true, + opera10_50: false, + safari13: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + graalvm20: graalvm.es2020flag, + graalvm20_1: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'throws on non-global regex', + exec() { + /* + if (typeof String.prototype.matchAll !== 'function') return false; + try { + '11a2bb'.matchAll(/(\d)(\D)/); + } catch (e) { + return true; + } + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + closure: false, + closure20200101: true, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox60: false, + firefox72: false, + firefox73: true, + chrome67: false, + chrome68: false, + chrome73: false, + chrome74: false, + chrome80: true, + opera10_50: false, + safari13: false, + safari13_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: false, + graalvm20: graalvm.es2020flag, + graalvm20_1: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'BigInt', + category: '2020 features', + significance: 'medium', + spec: 'https://github.com/tc39/proposal-bigint', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + return (1n + 2n) === 3n; + */ + }, + res: { + ie11: false, + firefox10: false, + firefox45: false, + firefox66: false, + firefox67: firefox.bigint, + firefox68: true, + chrome67: true, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'constructor', + exec() { + /* + return BigInt("3") === 3n; + */ + }, + res: { + ie11: false, + firefox10: false, + firefox45: false, + firefox66: false, + firefox67: firefox.bigint, + firefox68: true, + chrome67: true, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'BigInt.asUintN', + exec() { + /* + return typeof BigInt.asUintN === 'function'; + */ + }, + res: { + ie11: false, + firefox10: false, + firefox45: false, + firefox66: false, + firefox67: firefox.bigint, + firefox68: true, + chrome67: true, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'BigInt.asIntN', + exec() { + /* + return typeof BigInt.asIntN === 'function'; + */ + }, + res: { + ie11: false, + firefox10: false, + firefox45: false, + firefox66: false, + firefox67: firefox.bigint, + firefox68: true, + chrome67: true, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'BigInt64Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new BigInt64Array(buffer); + view[0] = 0x8000000000000000n; + return view[0] === -0x8000000000000000n; + */ + }, + res: { + ie11: false, + firefox10: false, + firefox45: false, + firefox67: false, + firefox68: true, + chrome67: true, + safari15: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'BigUint64Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new BigUint64Array(buffer); + view[0] = 0x10000000000000000n; + return view[0] === 0n; + */ + }, + res: { + ie11: false, + firefox10: false, + firefox45: false, + firefox67: false, + firefox68: true, + chrome67: true, + safari15: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'DataView.prototype.getBigInt64', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setBigInt64(0, 1n); + return view.getBigInt64(0) === 1n; + */ + }, + res: { + ie11: false, + firefox10: false, + firefox45: false, + firefox66: false, + firefox67: firefox.bigint, + firefox68: true, + chrome67: true, + safari15: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'DataView.prototype.getBigUint64', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setBigUint64(0, 1n); + return view.getBigUint64(0) === 1n; + */ + }, + res: { + ie11: false, + firefox10: false, + firefox45: false, + firefox66: false, + firefox67: firefox.bigint, + firefox68: true, + chrome67: true, + safari15: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Promise.allSettled', + category: '2020 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-promise-allSettled', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled', + exec() { + /* + Promise.allSettled([ + Promise.resolve(1), + Promise.reject(2), + Promise.resolve(3) + ]).then(it => { + if ( + it.length === 3 && + it[0].status === 'fulfilled' && it[0].value === 1 && + it[1].status === 'rejected' && it[1].reason === 2 && + it[2].status === 'fulfilled' && it[2].value === 3 + ) asyncTestPassed(); + }); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + closure: false, + closure20191027: true, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox68: firefox.nightly, + firefox71: true, + chrome76: true, + safari13: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: false, + graalvm20: graalvm.es2020flag, + graalvm20_1: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'globalThis', + category: '2020 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-global', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis', + subtests: [ + { + name: '"globalThis" global property is global object', + exec() { + /* + var actualGlobal = Function ('return this')(); + actualGlobal.__system_global_test__ = 42; + return typeof globalThis === 'object' && globalThis && globalThis === actualGlobal && !globalThis.lacksGlobalThis && globalThis.__system_global_test__ === 42; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + closure: false, + closure20200101: true, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox53: false, + firefox65: true, + chrome70: chrome.experimental, + chrome71: true, + opera10_50: false, + safari10_1: false, + safari12_1: true, + safaritp: true, + node0_10: false, + node0_12: false, + node4: false, + node6: false, + node6_5: false, + node7: false, + node7_6: false, + node8: false, + node8_3: false, + node8_7: false, + duktape2_0: false, + duktape2_5: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: '"globalThis" global property has correct property descriptor', + exec() { + /* + var actualGlobal = Function ('return this')(); + if (typeof globalThis !== 'object') { return false; } + if (!('globalThis' in actualGlobal)) { return false; } + if (Object.prototype.propertyIsEnumerable.call(actualGlobal, 'globalThis')) { return false; } + + var descriptor = Object.getOwnPropertyDescriptor(actualGlobal, 'globalThis'); + return descriptor.value === actualGlobal && !descriptor.enumerable && descriptor.configurable && descriptor.writable; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + closure: false, + closure20200101: true, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox53: false, + firefox65: true, + chrome70: chrome.experimental, + chrome71: true, + opera10_50: false, + safari10_1: false, + safari12_1: true, + safaritp: true, + node0_10: false, + node0_12: false, + node4: false, + node6: false, + node6_5: false, + node7: false, + node7_6: false, + node8: false, + node8_3: false, + node8_7: false, + duktape2_0: false, + duktape2_5: true, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + ], + }, + { + name: 'optional chaining operator (?.)', + spec: 'https://github.com/tc39/proposal-optional-chaining', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining', + category: '2020 features', + significance: 'medium', + subtests: [ + { + name: 'optional property access', + exec() { + /* + var foo = { baz: 42 }; + var bar = null; + return foo?.baz === 42 && bar?.baz === void undefined; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20200927: true, + typescript3_7corejs3: true, + ie11: false, + firefox10: false, + firefox52: false, + firefox73: false, + firefox74: true, + chrome77: false, + chrome78: { + val: 'flagged', + note_id: 'chrome-optional-chaining', + note_html: 'The feature has to be enabled via --js-flags="--harmony-optional-chaining" flag', + }, + chrome80: true, + safari13_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: false, + graalvm20: graalvm.es2020flag, + graalvm20_1: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'optional bracket access', + exec() { + /* + var foo = { baz: 42 }; + var bar = null; + return foo?.['baz'] === 42 && bar?.['baz'] === void undefined; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20200927: true, + typescript3_7corejs3: true, + ie11: false, + firefox10: false, + firefox52: false, + firefox73: false, + firefox74: true, + chrome77: false, + chrome78: { val: 'flagged', note_id: 'chrome-optional-chaining' }, + chrome80: true, + safari13_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: false, + graalvm20: graalvm.es2020flag, + graalvm20_1: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'optional method call', + exec() { + /* + var foo = { baz: function () { return this.value; }, value: 42 }; + var bar = null; + return foo?.baz() === 42 && bar?.baz() === void undefined; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20200927: true, + typescript3_7corejs3: true, + ie11: false, + firefox10: false, + firefox52: false, + firefox73: false, + firefox74: true, + chrome77: false, + chrome78: { val: 'flagged', note_id: 'chrome-optional-chaining' }, + chrome80: true, + safari13_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: false, + graalvm20: graalvm.es2020flag, + graalvm20_1: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'optional function call', + exec() { + /* + var foo = { baz: function () { return 42; } }; + var bar = {}; + function baz() { return 42; }; + var n; + return foo.baz?.() === 42 && bar.baz?.() === void undefined && baz?.() === 42 && n?.() === void undefined; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20200927: true, + typescript3_7corejs3: true, + ie11: false, + firefox10: false, + firefox52: false, + firefox73: false, + firefox74: true, + chrome77: false, + chrome78: { val: 'flagged', note_id: 'chrome-optional-chaining' }, + chrome80: true, + safari13_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: false, + graalvm20: graalvm.es2020flag, + graalvm20_1: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'spread parameters after optional chaining', + exec() { + /* + var fn = null; + var n = null; + var o = {}; + + return fn?.(...[], 1) === void undefined && fn?.(...[], ...[]) === void undefined && o.method?.(...[], 1) === void undefined && n?.method(...[], 1) === void undefined; + */ + }, + res: { + babel7corejs3: true, + closure: false, + closure20200927: true, + ie11: false, + firefox10: false, + firefox52: false, + firefox73: false, + firefox74: true, + chrome77: false, + chrome80: false, + chrome89: false, + chrome90: false, + chrome91: true, + safari13_1: true, + safaritp: true, + duktape2_0: false, + graalvm21_3_3: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'nullish coalescing operator (??)', + spec: 'https://github.com/tc39/proposal-nullish-coalescing', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator', + category: '2020 features', + significance: 'small', + exec() { + /* + return (null ?? 42) === 42 && + (undefined ?? 42) === 42 && + (false ?? 42) === false && + ('' ?? 42) === '' && + (0 ?? 42) === 0 && + isNaN(NaN ?? 42); + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20200315: true, + typescript3_7corejs3: true, + ie11: false, + firefox10: false, + firefox52: false, + firefox72: true, + chrome77: false, + chrome78: { + val: 'flagged', + note_id: 'chrome-nullish', + note_html: 'The feature has to be enabled via --js-flags="--harmony-nullish" flag', + }, + chrome80: true, + safari13_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: false, + graalvm20: graalvm.es2020flag, + graalvm20_1: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'String.prototype.replaceAll', + significance: 'small', + spec: 'https://github.com/tc39/proposal-string-replace-all', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll', + category: '2021 features', + exec() { + /* + return 'q=query+string+parameters'.replaceAll('+', ' ') === 'q=query string parameters'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + closure: false, + closure20210808: true, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox52: false, + firefox71: false, + firefox72: firefox.nightly, + firefox77: true, + chrome77: false, + chrome80: chrome.stringPrototypeReplaceAll, + chrome85: true, + safari13_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: false, + graalvm20: graalvm.es2020flag, + graalvm20_1: graalvm.es2021flag, + graalvm21: true, + ios13_4: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Promise.any', + category: '2021 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-promise-any', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any', + subtests: [ + { + name: 'fulfillment', + exec() { + /* + Promise.any([ + Promise.reject(1), + Promise.resolve(2), + Promise.resolve(3) + ]).then(it => { + if (it === 2) asyncTestPassed(); + }); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + closure: false, + closure20210808: true, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox72: firefox.nightly, + firefox79: true, + chrome77: false, + chrome84: { + val: 'flagged', + note_id: 'chrome-promise-any', + note_html: + 'Available behind the --js-flags="--harmony-promise-any" flag in V8.', + }, + chrome85: true, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'AggregateError', + exec() { + /* + Promise.any([ + Promise.reject(1), + Promise.reject(2), + Promise.reject(3) + ]).catch (error => { + if (error instanceof AggregateError && error.errors.length === 3) asyncTestPassed(); + }); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + closure: false, + closure20210808: true, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox72: firefox.nightly, + firefox79: true, + chrome77: false, + chrome84: { + val: 'flagged', + note_id: 'chrome-promise-any', + note_html: + 'Available behind the --js-flags="--harmony-promise-any" flag in V8.', + }, + chrome85: true, + safari14: true, + safaritp: true, + duktape2_0: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + }, + }, + ], + }, + { + name: 'WeakReferences', + spec: 'https://github.com/tc39/proposal-weakrefs', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef', + category: '2021 features', + significance: 'large', + subtests: [ + { + name: 'WeakRef minimal support', + spec: 'https://github.com/tc39/proposal-weakrefs#weak-references', + exec() { + /* + var O = {}; + var weakref = new WeakRef(O); + return weakref.deref() === O; + */ + }, + res: { + ie11: false, + firefox2: false, + firefox74: { + val: 'flagged', + note_id: 'firefox-weakrefs', + note_html: + 'The feature has to be enabled via javascript.options.experimental.weakrefs setting under about:config.', + }, + firefox79: true, + opera10_50: false, + chrome65: false, + chrome74: { + val: 'flagged', + note_id: 'chrome-weakrefs', + note_html: + 'Available behind the --js-flags="--harmony-weak-refs --expose-gc" flag in V8.', + }, + chrome85: true, + safari13: false, + safari14_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: false, + graalvm20: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'FinalizationRegistry minimal support', + spec: 'https://github.com/tc39/proposal-weakrefs#finalizers', + exec() { + /* + var fr = new FinalizationRegistry(function () {}); + return Object.getPrototypeOf(fr) === FinalizationRegistry.prototype; + */ + }, + res: { + ie11: false, + firefox2: false, + firefox74: false, + firefox78: { val: 'flagged', note_id: 'firefox-weakrefs' }, + firefox79: true, + opera10_50: false, + chrome65: false, + chrome74: false, + chrome85: true, + safari14_1: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm19: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Logical Assignment', + category: '2021 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-logical-assignment/', + subtests: [ + { + name: '||= basic support', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR_assignment', + exec() { + /* + let a; + let b = 0; + let c = 1; + a ||= 2; + b ||= 2; + c ||= 2; + return a === 2 && b === 2 && c === 1; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + ie11: false, + firefox60: false, + firefox76: false, + firefox77: firefox.nightly, + firefox79: true, + chrome80: false, + chrome84: { + val: 'flagged', + note_id: 'chrome-logical-assignment', + note_html: + 'Available behind the --js-flags="--logical-assignment" flag in V8.', + }, + chrome85: true, + safari13: false, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '||= short-circuiting behaviour', + exec() { + /* + let a = 1; + let i = 1; + a ||= ++i; + return a === 1 && i === 1; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + ie11: false, + firefox60: false, + firefox76: false, + firefox77: firefox.nightly, + firefox79: true, + chrome80: false, + chrome84: { val: 'flagged', note_id: 'chrome-logical-assignment' }, + chrome85: true, + safari13: false, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '||= setter not unecessarily invoked', + exec() { + /* + let i = 1; + var obj = { get x() { return 1 }, set x(n) { i++; } }; + obj.x ||= 2; + return i === 1; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + ie11: false, + firefox60: false, + firefox76: false, + firefox77: firefox.nightly, + firefox79: true, + chrome80: false, + chrome84: { val: 'flagged', note_id: 'chrome-logical-assignment' }, + chrome85: true, + safari13: false, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '&&= basic support', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND_assignment', + exec() { + /* + let a; + let b = 0; + let c = 1; + a &&= 2; + b &&= 2; + c &&= 2; + return typeof a === 'undefined' && b === 0 && c === 2; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + ie11: false, + firefox60: false, + firefox76: false, + firefox77: firefox.nightly, + firefox79: true, + chrome80: false, + chrome84: { val: 'flagged', note_id: 'chrome-logical-assignment' }, + chrome85: true, + safari13: false, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '&&= short-circuiting behaviour', + exec() { + /* + let a; + let i = 1; + a &&= ++i; + return typeof a === 'undefined' && i === 1; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + ie11: false, + firefox60: false, + firefox76: false, + firefox77: firefox.nightly, + firefox79: true, + chrome80: false, + chrome84: { val: 'flagged', note_id: 'chrome-logical-assignment' }, + chrome85: true, + safari13: false, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '&&= setter not unecessarily invoked', + exec() { + /* + let i = 1; + var obj = { get x() { return }, set x(n) { i++; } }; + obj.x &&= 2; + return i === 1; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + ie11: false, + firefox60: false, + firefox76: false, + firefox77: firefox.nightly, + firefox79: true, + chrome80: false, + chrome84: { val: 'flagged', note_id: 'chrome-logical-assignment' }, + chrome85: true, + safari13: false, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '??= basic support', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment', + exec() { + /* + let a; + let b = 0; + let c = 1; + a ??= 2; + b ??= 2; + c ??= 2; + return a === 2 && b === 0 && c === 1; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + ie11: false, + firefox60: false, + firefox76: false, + firefox77: firefox.nightly, + firefox79: true, + chrome80: false, + chrome84: { val: 'flagged', note_id: 'chrome-logical-assignment' }, + chrome85: true, + safari13: false, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '??= short-circuiting behaviour', + exec() { + /* + let a = 1; + let i = 1; + a ??= ++i; + return a === 1 && i === 1; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + ie11: false, + firefox60: false, + firefox76: false, + firefox77: firefox.nightly, + firefox79: true, + chrome80: false, + chrome84: { val: 'flagged', note_id: 'chrome-logical-assignment' }, + chrome85: true, + safari13: false, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '??= setter not unecessarily invoked', + exec() { + /* + let i = 1; + var obj = { get x() { return 1 }, set x(n) { i++; } }; + obj.x ??= 2; + return i === 1; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + ie11: false, + firefox60: false, + firefox76: false, + firefox77: firefox.nightly, + firefox79: true, + chrome80: false, + chrome84: { val: 'flagged', note_id: 'chrome-logical-assignment' }, + chrome85: true, + safari13: false, + safari14: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + graalvm20_3: graalvm.es2021flag, + graalvm21: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'numeric separators', + spec: 'https://github.com/tc39/proposal-numeric-separator', + category: '2021 features', + significance: 'small', + exec() { + /* + return 1_000_000.000_001 === 1000000.000001 && + 0b1010_0001_1000_0101 === 0b1010000110000101; + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20210808: true, + typescript1corejs2: false, + typescript2_7corejs2: true, + ie11: false, + firefox2: false, + firefox10: false, + firefox67: false, + firefox68: firefox.nightly, + firefox70: true, + opera10_50: false, + chrome67: chrome.harmony, + chrome75: true, + safari13: true, + safaritp: true, + duktape2_0: false, + jerryscript2_3_0: false, + jerryscript2_4_0: true, + graalvm19: false, + graalvm20: graalvm.es2020flag, + graalvm20_1: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'instance class fields', + category: '2022 features', + significance: 'medium', + spec: 'https://github.com/tc39/proposal-class-fields', + subtests: [ + { + name: 'public instance class fields', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_elements#Public_instance_fields', + exec() { + /* + class C { + x = 'x'; + } + return new C().x === 'x'; + */ + }, + res: { + babel6corejs2: true, + tr: true, + typescript1corejs2: true, + ie11: false, + firefox2: false, + firefox67: firefox.classFields, + firefox69: true, + opera10_50: false, + chrome65: chrome.harmony, + chrome72: true, + safari14: true, + safaritp: true, + duktape2_0: false, + graalvm19: false, + graalvm20: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'private instance class fields basic support', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_elements#Private_instance_fields', + exec() { + /* + class C { + #x; + constructor(x) { + this.#x = x; + } + x() { + return this.#x; + } + } + return new C(42).x() === 42; + */ + }, + res: { + babel7corejs2: true, + ie11: false, + firefox2: false, + firefox67: firefox.privateClassFields, + firefox80: firefox.privateFields, + firefox90: true, + opera10_50: false, + chrome66: chrome.harmony, + chrome74: true, + safari14_1: true, + safaritp: true, + duktape2_0: false, + graalvm19: false, + graalvm20: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'private instance class fields initializers', + exec() { + /* + class C { + #x = 42; + x() { + return this.#x; + } + } + return new C().x() === 42; + */ + }, + res: { + babel7corejs2: true, + ie11: false, + firefox2: false, + firefox67: firefox.privateClassFields, + firefox80: firefox.privateFields, + firefox90: true, + opera10_50: false, + chrome66: chrome.harmony, + chrome74: true, + safari14_1: true, + safaritp: true, + duktape2_0: false, + graalvm19: false, + graalvm20: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'optional private instance class fields access', + exec() { + /* + class C { + #x = 42; + x(o = this) { + return o?.#x; + } + } + return new C().x() === 42 && new C().x(null) === void undefined; + */ + }, + res: { + babel7corejs2: true, + babel7corejs3: true, + ie11: false, + firefox2: false, + firefox80: firefox.privateFields, + firefox90: true, + chrome1: false, + chrome83: false, + chrome84: true, + safari1: false, + safari13_1: false, + safari14_1: true, + safaritp: true, + duktape2_0: false, + opera10_50: false, + graalvm20: false, + graalvm20_3: true, + typescript3_8corejs3: false, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'optional deep private instance class fields access', + exec() { + /* + class C { + #x = 42; + x(o = { p: this }) { + return o?.p.#x; + } + } + return new C().x() === 42 && new C().x(null) === void undefined; + */ + }, + res: { + babel7corejs2: true, + babel7corejs3: true, + ie11: false, + firefox2: false, + firefox74: firefox.privateClassFields, + firefox80: firefox.privateFields, + firefox90: true, + chrome1: false, + chrome78: { + val: 'flagged', + note_id: 'chrome-optional-chaining', + note_html: 'The feature has to be enabled via --js-flags="--harmony-optional-chaining" flag', + }, + chrome80: true, + safari1: false, + safari13_1: false, + safari14_1: true, + safaritp: true, + opera10_50: false, + duktape2_0: false, + graalvm20: false, + graalvm20_3: true, + typescript3_8corejs3: false, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed instance class fields', + exec() { + /* + class C { + ['x'] = 42; + } + return new C().x === 42; + */ + }, + res: { + babel7corejs2: true, + ie11: false, + firefox2: false, + firefox66: false, + firefox68: firefox.classFields, + firefox69: true, + opera10_50: false, + chrome73: true, + safari14: true, + safaritp: true, + duktape2_0: false, + graalvm19: false, + graalvm20: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'resolving identifier in parent scope', + exec() { + /* + { + let a = ["hello world"]; + class MyClass { + // The parenthesis below are required to trigger https://bugs.webkit.org/show_bug.cgi?id=236843 + c = a[(0)]; + } + return new MyClass().c === a[0]; + } + */ + }, + res: { + firefox122: true, + chrome74: true, + chrome124: true, + firefox69: true, + safari15: false, + safari16: true, + safari17: true, + safaritp: true, + }, + }, + ], + }, + { + name: 'static class fields', + category: '2022 features', + significance: 'medium', + spec: 'https://github.com/tc39/proposal-static-class-features/', + subtests: [ + { + name: 'public static class fields', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_elements#Public_static_fields', + exec() { + /* + class C { + static x = 'x'; + } + return C.x === 'x'; + */ + }, + res: { + babel6corejs2: true, + tr: true, + typescript1corejs2: true, + ie11: false, + firefox2: false, + firefox74: false, + firefox75: true, + opera10_50: false, + chrome71: chrome.harmony, + chrome72: true, + safari14_1: true, + safaritp: true, + duktape2_0: false, + graalvm19: false, + graalvm20: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'static class fields use [[Define]]', + exec() { + /* + return (class X { static name = "name"; }).name === 'name'; + */ + }, + res: { + ie11: false, + edge18: false, + chrome73: true, + chrome90: true, + chrome94: true, + chrome96: true, + chrome97: false, + chrome98: true, + firefox74: false, + firefox75: true, + firefox91: true, + firefox95: true, + firefox96: true, + opera10_50: false, + node11_0: false, + node12_0: true, + node12_5: true, + node12_9: true, + node12_11: true, + node13_0: true, + node13_2: true, + node14_0: true, + node14_5: true, + node14_6: true, + node15_0: true, + node16_0: true, + node16_9: true, + node16_11: true, + safari15: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_15: false, + }, + }, + { + name: 'private static class fields', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_elements#Private_static_fields', + exec() { + /* + class C { + static #x = 42; + x() { + return C.#x; + } + } + return new C().x() === 42; + */ + }, + res: { + babel7corejs2: true, + ie11: false, + firefox2: false, + firefox80: firefox.privateFields, + firefox90: true, + opera10_50: false, + chrome74: true, + safari14_1: true, + safaritp: true, + duktape2_0: false, + graalvm19: false, + graalvm20: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed static class fields', + exec() { + /* + class C { + static ['x'] = 42; + } + return C.x === 42; + */ + }, + res: { + babel7corejs2: true, + ie11: false, + firefox2: false, + firefox74: false, + firefox75: true, + opera10_50: false, + chrome73: true, + safari14_1: true, + safaritp: true, + duktape2_0: false, + graalvm19: false, + graalvm20: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'private class methods', + category: '2022 features', + significance: 'medium', + spec: 'https://github.com/tc39/proposal-private-methods', + subtests: [ + { + name: 'private instance methods', + exec() { + /* + class C { + #x() { return 42; } + x() { + return this.#x(); + } + } + return new C().x() === 42; + */ + }, + res: { + babel7corejs2: true, + ie11: false, + firefox60: false, + firefox68: false, + firefox75: false, + firefox81: { + val: 'flagged', + note_id: 'ff-private-instance-methods-and-accessors', + note_html: + 'The feature has to be enabled via javascript.options.experimental.private_fields and javascript.options.experimental.private_methods settings under about:config.', + }, + firefox90: true, + opera10_50: false, + chrome79: chrome.harmony, + chrome84: true, + duktape2_0: false, + safari13: false, + safari15: true, + safaritp: true, + graalvm20: false, + graalvm20_1: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'private static methods', + exec() { + /* + class C { + static #x() { return 42; } + x() { + return C.#x(); + } + } + return new C().x() === 42; + */ + }, + res: { + babel7corejs2: true, + ie11: false, + firefox60: false, + firefox68: false, + firefox75: false, + firefox82: { + val: 'flagged', + note_id: 'ff-private-instance-methods-and-accessors', + }, + firefox90: true, + opera10_50: false, + chrome79: chrome.harmony, + chrome84: true, + duktape2_0: false, + safari13: false, + safari15: true, + safaritp: true, + graalvm20: false, + graalvm20_1: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'private accessor properties', + exec() { + /* + var y = false; + class C { + get #x() { return 42; } + set #x(x) { y = x; } + x() { + this.#x = true; + return this.#x; + } + } + return new C().x() === 42 && y; + */ + }, + res: { + babel7corejs2: true, + ie11: false, + firefox60: false, + firefox68: false, + firefox75: false, + firefox81: { + val: 'flagged', + note_id: 'ff-private-instance-methods-and-accessors', + }, + firefox90: true, + opera10_50: false, + chrome79: chrome.harmony, + chrome84: true, + duktape2_0: false, + safari13: false, + safari15: true, + safaritp: true, + graalvm20: false, + graalvm20_1: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'private static accessor properties', + exec() { + /* + var y = false; + class C { + static get #x() { return 42; } + static set #x(x) { y = x; } + x() { + C.#x = true; + return C.#x; + } + } + return new C().x() === 42 && y; + */ + }, + res: { + babel7corejs2: true, + ie11: false, + firefox60: false, + firefox68: false, + firefox75: false, + firefox82: { + val: 'flagged', + note_id: 'ff-private-instance-methods-and-accessors', + }, + firefox90: true, + opera10_50: false, + chrome79: chrome.harmony, + chrome84: true, + duktape2_0: false, + safari13: false, + safari15: true, + safaritp: true, + graalvm20: false, + graalvm20_1: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Ergonomic brand checks for private fields', + category: '2022 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-private-fields-in-in', + exec() { + /* + class A { + #x; + static check(obj) { + return #x in obj; + } + } + return A.check(new A) && !A.check({}); + */ + }, + res: { + babel6corejs2: false, + babel7corejs2: true, + babel7corejs3: true, + chrome1: false, + chrome91: true, + edge18: false, + firefox2: false, + firefox90: true, + ie11: false, + opera10_50: false, + safari12: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: graalvm.esStagingFlag, + graalvm22_2: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.at() method on the built-in indexables', + category: '2022 features', + significance: 'tiny', + spec: 'https://github.com/tc39/proposal-relative-indexing-method/', + subtests: [ + { + name: 'Array.prototype.at()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at', + exec() { + /* + var arr = [1, 2, 3]; + return arr.at(0) === 1 + && arr.at(-3) === 1 + && arr.at(1) === 2 + && arr.at(-2) === 2 + && arr.at(2) === 3 + && arr.at(-1) === 3 + && arr.at(3) === undefined + && arr.at(-4) === undefined; + */ + }, + res: { + closure: false, + closure20220502: { + val: false, + note_id: 'closure-at-method', + note_html: 'Requires native support for Math.trunc', + }, + closure20220719: true, + ie11: false, + firefox68: false, + firefox85: firefox.nightly, + firefox90: true, + chrome85: false, + chrome92: true, + safari14_1: { + val: 'flagged', + note_id: 'safari-at-method', + note_html: 'The feature has to be enabled via jscOptions=--useAtMethod=true flag.', + }, + safari15_4: true, + safaritp: true, + duktape2_0: false, + babel7corejs3: babel.corejs, + typescript4corejs3: typescript.corejs, + graalvm21: graalvm.es2022flag, + graalvm21_3_3: graalvm.esStagingFlag, + graalvm22_2: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'String.prototype.at()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/at', + exec() { + /* + var str = 'abc'; + return str.at(0) === 'a' + && str.at(-3) === 'a' + && str.at(1) === 'b' + && str.at(-2) === 'b' + && str.at(2) === 'c' + && str.at(-1) === 'c' + && str.at(3) === undefined + && str.at(-4) === undefined; + */ + }, + res: { + closure: false, + closure20220502: { + val: false, + note_id: 'closure-at-method', + }, + closure20220719: true, + ie11: false, + firefox68: false, + firefox85: firefox.nightly, + firefox90: true, + chrome85: false, + chrome92: true, + safari14_1: { + val: 'flagged', + note_id: 'safari-at-method', + }, + safari15_4: true, + safaritp: true, + duktape2_0: false, + babel7corejs3: babel.corejs, + typescript4corejs3: typescript.corejs, + graalvm21: graalvm.es2022flag, + graalvm21_3_3: graalvm.esStagingFlag, + graalvm22_2: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: '%TypedArray%.prototype.at()', + exec() { + /* + return [ + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', + 'Uint32Array', + 'Float32Array', + 'Float64Array' + ].every(function (TypedArray) { + var Constructor = globalThis[TypedArray]; + if (typeof Constructor !== 'function') { + return false; + } + var arr = new Constructor([1, 2, 3]); + return arr.at(0) === 1 + && arr.at(-3) === 1 + && arr.at(1) === 2 + && arr.at(-2) === 2 + && arr.at(2) === 3 + && arr.at(-1) === 3 + && arr.at(3) === undefined + && arr.at(-4) === undefined; + }); + */ + }, + res: { + closure: false, + closure20220502: { + val: false, + note_id: 'closure-typed-array', + note_html: 'Requires native support for typed arrays', + }, + ie11: false, + firefox68: false, + firefox85: firefox.nightly, + firefox90: true, + chrome85: false, + chrome92: true, + safari14_1: { + val: 'flagged', + note_id: 'safari-at-method', + }, + safari15_4: true, + safaritp: true, + duktape2_0: false, + babel7corejs3: babel.corejs, + typescript4corejs3: typescript.corejs, + graalvm21: graalvm.es2022flag, + graalvm21_3_3: graalvm.esStagingFlag, + graalvm22_2: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'Object.hasOwn', + category: '2022 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-accessible-object-hasownproperty', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn', + subtests: [ + { + name: 'Basic functionality', + exec() { + /* + return Object.hasOwn({ x: 2 }, "x") === true; + */ + }, + res: { + babel7corejs3: babel.corejs, + closure20220719: true, + typescript3_2corejs3: typescript.corejs, + ie11: false, + chrome1: false, + chrome90: false, + chrome93: true, + edge18: false, + firefox2: false, + firefox90: false, + firefox91: firefox.nightly, + firefox92: true, + opera10_50: false, + safari12: false, + safari15_4: true, + safaritp: true, + duktape2_0: false, + graalvm21_3_3: graalvm.esStagingFlag, + graalvm22_2: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'ToObject called before ToPropertyKey', + exec() { + /* + var ok = !!Object.hasOwn; + try { + Object.hasOwn(null, { toString: function () { ok = false } }); + return false; + } catch (e) { + return ok; + } + */ + }, + res: { + babel7corejs3: babel.corejs, + closure20220719: true, + typescript3_2corejs3: typescript.corejs, + ie11: false, + chrome1: false, + chrome90: false, + chrome93: true, + edge18: false, + firefox2: false, + firefox90: false, + firefox91: firefox.nightly, + firefox92: true, + opera10_50: false, + safari12: false, + safari15_4: true, + safaritp: true, + duktape2_0: false, + graalvm21_3_3: graalvm.esStagingFlag, + graalvm22_2: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'Class static initialization blocks', + category: '2022 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-class-static-block', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Static_initialization_blocks', + exec() { + /* + let ok = false; + class A { + static { ok = true; } + } + return ok; + */ + }, + res: { + babel6corejs2: false, + babel7corejs2: true, + babel7corejs3: true, + chrome1: false, + chrome91: { + val: 'flagged', + note_id: 'ch-static-init-blocks', + note_html: 'The feature has to be enabled via harmony_class_static_blocks flag.', + }, + chrome94: true, + safari13: false, + edge18: false, + firefox2: false, + firefox87: false, + firefox90: { + val: 'flagged', + note_id: 'ff-static-init-blocks', + note_html: + 'The feature has to be enabled via javascript.options.experimental.class_static_blocks=true flag.', + }, + firefox93: true, + ie11: false, + opera10_50: false, + safari16_4: true, + duktape2_0: false, + graalvm21_3_3: graalvm.esStagingFlag, + graalvm22_2: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Error.cause property', + category: '2022 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-error-cause', + subtests: [ + { + name: 'Error has cause', + exec() { + /* + var error = new Error('error', { cause: 'cause' }) + return error.hasOwnProperty('cause') && error.cause === 'cause'; + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_14: false, + }, + }, + { + name: 'Error.prototype lacks cause', + exec() { + /* + return !('cause' in Error.prototype); + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: false, + chrome94: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + { + name: 'EvalError has cause', + exec() { + /* + var error = new EvalError('error', { cause: 'cause' }) + return error.hasOwnProperty('cause') && error.cause === 'cause'; + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_14: false, + }, + }, + { + name: 'EvalError.prototype lacks cause', + exec() { + /* + return !('cause' in EvalError.prototype); + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: false, + chrome94: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + { + name: 'RangeError has cause', + exec() { + /* + var error = new RangeError('error', { cause: 'cause' }) + return error.hasOwnProperty('cause') && error.cause === 'cause'; + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_14: false, + }, + }, + { + name: 'RangeError.prototype lacks cause', + exec() { + /* + return !('cause' in RangeError.prototype); + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: false, + chrome94: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + { + name: 'ReferenceError has cause', + exec() { + /* + var error = new ReferenceError('error', { cause: 'cause' }) + return error.hasOwnProperty('cause') && error.cause === 'cause'; + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_14: false, + }, + }, + { + name: 'ReferenceError.prototype lacks cause', + exec() { + /* + return !('cause' in ReferenceError.prototype); + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: false, + chrome94: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + { + name: 'SyntaxError has cause', + exec() { + /* + var error = new SyntaxError('error', { cause: 'cause' }) + return error.hasOwnProperty('cause') && error.cause === 'cause'; + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_14: false, + }, + }, + { + name: 'SyntaxError.prototype lacks cause', + exec() { + /* + return !('cause' in SyntaxError.prototype); + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: false, + chrome94: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + { + name: 'TypeError has cause', + exec() { + /* + var error = new TypeError('error', { cause: 'cause' }) + return error.hasOwnProperty('cause') && error.cause === 'cause'; + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_14: false, + }, + }, + { + name: 'TypeError.prototype lacks cause', + exec() { + /* + return !('cause' in TypeError.prototype); + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: false, + chrome94: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + { + name: 'URIError has cause', + exec() { + /* + var error = new URIError('error', { cause: 'cause' }) + return error.hasOwnProperty('cause') && error.cause === 'cause'; + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_14: false, + }, + }, + { + name: 'URIError.prototype lacks cause', + exec() { + /* + return !('cause' in URIError.prototype); + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: false, + chrome94: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + { + name: 'AggregateError has cause', + exec() { + /* + var error = new AggregateError([], 'error', { cause: 'cause' }) + return error.hasOwnProperty('cause') && error.cause === 'cause'; + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_14: false, + }, + }, + { + name: 'AggregateError.prototype lacks cause', + exec() { + /* + return !('cause' in AggregateError.prototype); + */ + }, + res: { + ie11: false, + chrome1: false, + chrome92: false, + chrome93: false, + chrome94: true, + edge90: false, + firefox45: false, + firefox90: false, + firefox91: true, + safari14: false, + safari15: true, + duktape2_0: false, + graalvm21_3_3: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_14: false, + }, + }, + ], + }, + { + name: 'RegExp Match Indices (`hasIndices` / `d` flag)', + category: '2022 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-regexp-match-indices', + subtests: [ + { + name: 'constructor supports it', + exec() { + /* + return new RegExp('a', 'd') instanceof RegExp; + */ + }, + res: { + ie11: false, + firefox68: false, + firefox78: false, + firefox91: true, + safari15: true, + chrome90: true, + graalvm21_3_3: graalvm.esStagingFlag, + graalvm22_2: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_15: false, + }, + }, + { + name: 'shows up in flags', + exec() { + /* + var expected = ['hasIndices']; + // Sorted alphabetically by shortname – "dgimsuy". + if ('global' in RegExp.prototype) expected.push('global'); + if ('ignoreCase' in RegExp.prototype) expected.push('ignoreCase'); + if ('multiline' in RegExp.prototype) expected.push('multiline'); + if ('dotAll' in RegExp.prototype) expected.push('dotAll'); + if ('unicode' in RegExp.prototype) expected.push('unicode'); + if ('sticky' in RegExp.prototype) expected.push('sticky'); + var actual = []; + var p = new Proxy({}, { get: function (o, k) { actual.push(k); return o[k]; }}); + Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(p); + if (expected.length !== actual.length) return false; + for (var i = 0; i < expected.length; i++) { + if (expected[i] !== actual[i]) return false; + } + return true; + */ + }, + res: { + ie11: false, + node16_0: false, + firefox68: false, + firefox78: false, + firefox91: true, + firefox116: false, + safari15: true, + chrome90: false, + graalvm21_3_3: graalvm.esStagingFlag, + graalvm22_2: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_15: false, + }, + }, + ], + }, + { + name: 'Array find from last', + category: '2023 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-array-find-from-last', + subtests: [ + { + name: 'Array.prototype.findLast', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findLast', + exec() { + /* + var arr = [{ x: 1 }, { x: 2 }, { x: 1 }, { x: 2 }]; + return arr.findLast(function (o) { return o.x === 1; }) === arr[2]; + */ + }, + res: { + babel7corejs3: babel.corejs, + typescript3_2corejs3: typescript.corejs, + ie11: false, + chrome1: false, + chrome90: false, + chrome96: false, + chrome97: true, + edge18: false, + firefox2: false, + firefox89: false, + firefox102: false, + firefox103: { + val: 'flagged', + note_id: 'firefox-arrayfindfromlast', + note_html: + 'The feature has to be enabled via javascript.options.experimental.array_find_last setting under about:config.', + }, + firefox104: true, + opera10_50: false, + safari12: false, + safari15_4: true, + safaritp: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: graalvm.esStagingFlag, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.findLastIndex', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findLastIndex', + exec() { + /* + var arr = [{ x: 1 }, { x: 2 }, { x: 1 }, { x: 2 }]; + return arr.findLastIndex(function (o) { return o.x === 1; }) === 2; + */ + }, + res: { + babel7corejs3: babel.corejs, + typescript3_2corejs3: typescript.corejs, + ie11: false, + chrome1: false, + chrome90: false, + chrome96: false, + chrome97: true, + edge18: false, + firefox2: false, + firefox89: false, + firefox102: false, + firefox103: { val: 'flagged', note_id: 'firefox-arrayfindfromlast' }, + firefox104: true, + opera10_50: false, + safari12: false, + safari15_4: true, + safaritp: true, + duktape2_0: false, + graalvm21_3_3: false, + graalvm22_2: graalvm.esStagingFlag, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Hashbang Grammar', + category: '2023 features', + significance: 'tiny', + spec: 'https://github.com/tc39/proposal-hashbang/', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Hashbang_comments', + exec() { + /* + try { + return !eval('#!/wash/your/hands'); + } catch (e) { + return false + } + */ + }, + res: { + chrome1: false, + chrome74: true, + firefox2: false, + firefox67: true, + ie11: false, + opera10_50: false, + edge18: false, + safari1: false, + safari13: false, + safari13_1: true, + duktape2_0: false, + graalvm19: false, + graalvm20_1: true, + babel7corejs3: false, + typescript3_2corejs3: false, + closure: false, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Change Array by copy', + category: '2023 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-change-array-by-copy', + subtests: [ + { + name: 'Array.prototype.toReversed()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toReversed', + exec() { + /* + var arr = [1, 2, 3]; + return arr.toReversed()[0] === 3 && arr[0] === 1; + */ + }, + res: { + babel7corejs3: babel.corejs, + typescript3_2corejs3: typescript.corejs, + ie11: false, + chrome94: false, + chrome109: false, + chrome110: true, + firefox45: false, + firefox95: { + val: 'flagged', + note_id: 'fx-change-array-by-copy', + note_html: 'The feature has to be enabled via --enable-change-array-by-copy flag', + }, + firefox115: true, + safari15_5: false, + safari16: true, + }, + }, + { + name: 'Array.prototype.toSorted()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSorted', + exec() { + /* + var arr = ['C', 'A', 'B']; + return arr.toSorted()[0] === 'A' && arr[0] === 'C'; + */ + }, + res: { + babel7corejs3: babel.corejs, + typescript3_2corejs3: typescript.corejs, + ie11: false, + chrome94: false, + chrome109: false, + chrome110: true, + firefox45: false, + firefox95: { val: 'flagged', note_id: 'fx-change-array-by-copy' }, + firefox115: true, + safari15_5: false, + safari16: true, + }, + }, + { + name: 'Array.prototype.toSpliced()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSpliced', + exec() { + /* + var arr = ['A', 'C']; + return arr.toSpliced(1, 0, 'B')[1] === 'B' && arr[1] === 'C'; + */ + }, + res: { + babel7corejs3: babel.corejs, + typescript3_2corejs3: typescript.corejs, + ie11: false, + chrome94: false, + chrome109: false, + chrome110: true, + firefox45: false, + firefox95: { val: 'flagged', note_id: 'fx-change-array-by-copy' }, + firefox115: true, + safari15_5: false, + safari16: true, + }, + }, + { + name: 'Array.prototype.with()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/with', + exec() { + /* + var arr = ['A', 'X', 'C']; + return arr.with(1, 'B')[1] === 'B' && arr[1] === 'X'; + */ + }, + res: { + babel7corejs3: babel.corejs, + typescript3_2corejs3: typescript.corejs, + ie11: false, + chrome94: false, + chrome109: false, + chrome110: true, + firefox45: false, + firefox95: { val: 'flagged', note_id: 'fx-change-array-by-copy' }, + firefox115: true, + safari15_5: false, + safari16: true, + }, + }, + { + name: 'TypedArray.prototype.toReversed()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/toReversed', + exec() { + /* + var arr = new Uint8Array([1, 2, 3]); + return arr.toReversed()[0] == 3 && arr[0] == 1; + */ + }, + res: { + ie11: false, + chrome94: false, + chrome109: false, + chrome110: true, + firefox45: false, + firefox95: { val: 'flagged', note_id: 'fx-change-array-by-copy' }, + firefox115: true, + safari15_5: false, + safari16: true, + }, + }, + { + name: 'TypedArray.prototype.toSorted()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/toSorted', + exec() { + /* + var arr = new Uint8Array([3, 1, 2]); + return arr.toSorted()[0] == 1 && arr[0] == 3; + */ + }, + res: { + ie11: false, + chrome94: false, + chrome109: false, + chrome110: true, + firefox45: false, + firefox95: { val: 'flagged', note_id: 'fx-change-array-by-copy' }, + firefox115: true, + safari15_5: false, + safari16: true, + }, + }, + { + name: 'TypedArray.prototype.with()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/with', + exec() { + /* + var arr = new Uint8Array([1, 0, 2]); + return arr.with(1, 2)[1] == 2 && arr[1] == 0; + */ + }, + res: { + ie11: false, + chrome94: false, + chrome109: false, + chrome110: true, + firefox45: false, + firefox95: { val: 'flagged', note_id: 'fx-change-array-by-copy' }, + firefox115: true, + safari15_5: false, + safari16: true, + }, + }, + ], + }, + { + name: 'RegExp `v` flag', + category: '2024 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-regexp-v-flag', + subtests: [ + { + name: 'set notations', + exec() { + /* + return /[\p{ASCII}&&\p{Decimal_Number}]/v.test("0") + && /[\p{Any}--[\x01-\u{10ffff}]]/v.test("\0") + */ + }, + res: { + chrome110: false, + chrome111: chrome.harmony, + chrome112: true, + firefox91: false, + firefox102: false, + firefox115: false, + firefox116: true, + ie11: false, + safari16_6: false, + safari17: true, + safaritp: true, + rhino1_7_15: false, + }, + }, + { + name: 'properties of Strings', + exec() { + /* + return /^\p{Emoji_Keycap_Sequence}$/v.test("*\uFE0F\u20E3") + && !/^\p{Emoji_Keycap_Sequence}$/v.test("*"); + */ + }, + res: { + chrome110: false, + chrome111: chrome.harmony, + chrome112: true, + firefox91: false, + firefox102: false, + firefox115: false, + firefox116: true, + ie11: false, + safari16_6: false, + safari17: true, + safaritp: true, + rhino1_7_15: false, + }, + }, + { + name: 'constructor supports it', + exec() { + /* + return new RegExp('a', 'v') instanceof RegExp; + */ + }, + res: { + chrome110: false, + chrome111: chrome.harmony, + chrome112: true, + firefox91: false, + firefox102: false, + firefox115: false, + firefox116: true, + ie11: false, + safari16_6: false, + safari17: true, + safaritp: true, + rhino1_7_15: false, + }, + }, + { + name: 'shows up in flags', + exec() { + /* + var flags = []; + var p = new Proxy({}, { get: function (o, k) { flags.push(k); return o[k]; }}); + Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(p); + return flags.indexOf("unicodeSets") !== -1; + */ + }, + res: { + chrome110: false, + chrome111: chrome.harmony, + chrome112: true, + firefox91: false, + firefox102: false, + firefox115: false, + firefox116: true, + ie11: false, + safari16_6: false, + safari17: true, + safaritp: true, + rhino1_7_15: false, + }, + }, + { + name: 'Unicode 15.1', + exec() { + /* + return /^\p{RGI_Emoji}$/v.test("🐦‍🔥"); + */ + }, + res: { + chrome117: false, + chrome118: false, + chrome124: false, + chrome125: true, + chrome126: true, + node20_0: false, + node21_0: false, + node22_0: true, + firefox115: false, + firefox117: false, + firefox118: false, + firefox133: false, + firefox134: true, + safaritp: false, + safari16_6: false, + safari18: true, + ie11: false, + duktape2_0: false, + jerryscript2_3_0: false, + hermes0_7_0: false, + rhino1_7_13: false, + }, + }, + { + name: 'Unicode 16.0', + exec() { + /* + return /^\p{RGI_Emoji}$/v.test("🇨🇶"); + */ + }, + res: { + ie11: false, + chrome128: false, + node22_0: false, + firefox115: false, + firefox130: false, + firefox133: false, + firefox134: true, + safari17_6: false, + }, + }, + ], + }, + { + name: 'ArrayBuffer.prototype.transfer', + category: '2024 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-arraybuffer-transfer', + subtests: [ + { + name: 'ArrayBuffer.prototype.transfer()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/transfer', + exec() { + /* + const buffer1 = new Uint8Array([1, 2]).buffer; + const buffer2 = buffer1.transfer(); + return buffer1.byteLength === 0 + && buffer2.byteLength === 2; + */ + }, + res: { + ie11: false, + firefox10: false, + firefox52: false, + firefox117: { + val: 'flagged', + note_id: 'firefox-arraybuffer', + note_html: + 'The feature has to be enabled via javascript.options.experimental.arraybuffer_transfer setting under about:config.', + }, + firefox122: true, + chrome70: false, + chrome114: true, + safari12: false, + safari17_4: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'ArrayBuffer.prototype.transferToFixedLength()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/transferToFixedLength', + exec() { + /* + const buffer1 = new Uint8Array([1, 2]).buffer; + const buffer2 = buffer1.transferToFixedLength(); + return buffer1.byteLength === 0 + && buffer2.byteLength === 2; + */ + }, + res: { + ie11: false, + firefox115: false, + firefox117: { + val: 'flagged', + note_id: 'firefox-arraybuffer', + }, + firefox122: true, + chrome114: true, + safari17_4: true, + }, + }, + { + name: 'ArrayBuffer.prototype.detached', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/detached', + exec() { + /* + const buffer1 = new Uint8Array([1, 2]).buffer; + const buffer2 = buffer1.transfer(); + return buffer1.detached && !buffer2.detached; + */ + }, + res: { + ie11: false, + firefox115: false, + firefox117: { + val: 'flagged', + note_id: 'firefox-arraybuffer', + }, + firefox122: true, + chrome114: true, + safari17_4: true, + }, + }, + ], + }, + { + name: 'Promise.withResolvers', + category: '2024 features', + significance: 'tiny', + spec: 'https://tc39.es/proposal-promise-with-resolvers/', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers', + exec() { + /* + var obj = Promise.withResolvers(); + return obj instanceof Object + && obj.promise instanceof Promise + && typeof obj.resolve === 'function' + && typeof obj.reject === 'function'; + */ + }, + res: { + ie11: false, + chrome119: true, + firefox115: false, + firefox121: true, + node22_0: true, + safari17_6: true, + safaritp: true, + }, + }, + { + name: 'Array Grouping', + category: '2024 features', + significance: 'small', + spec: 'https://github.com/tc39/proposal-array-grouping', + subtests: [ + { + name: 'Object.groupBy()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy', + exec() { + /* + const array = [1, 2, 3, 4]; + const obj = Object.groupBy(array, (num, index) => { + return num % 2 === 0 ? 'even': 'odd'; + }); + return !('toString' in obj) && obj.even[0] == 2 && obj.odd[0] == 1; + */ + }, + res: { + ie11: false, + chrome117: true, + firefox97: false, + firefox98: { + val: 'flagged', + note_id: 'ff-array-grouping', + note_html: + 'The feature is only available on Nightly builds, and has to be enabled via javascript.options.experimental.array_grouping setting under about:config.', + }, + firefox119: true, + safari17_4: true, + }, + }, + { + name: 'Map.groupBy()', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/groupBy', + exec() { + /* + const array = [1, 2, 3, 4]; + const odd = { odd: true }; + const even = { even: true }; + const map = Map.groupBy(array, (num, index) => { + return num % 2 === 0 ? even: odd; + }); + return map instanceof Map && map.get(even)[0] === 2 && map.get(odd)[0] === 1; + */ + }, + res: { + ie11: false, + chrome117: true, + firefox97: false, + firefox98: { + val: 'flagged', + note_id: 'ff-array-grouping', + }, + firefox119: true, + safari17_4: true, + }, + }, + ], + }, + { + name: 'Duplicate named capturing groups', + category: '2025 features', + significance: 'tiny', + spec: 'https://github.com/tc39/proposal-duplicate-named-capturing-groups', + exec() { + /* + return /(?[0-9]{4})-[0-9]{2}|[0-9]{2}-(?[0-9]{4})/.test("12-1995"); + */ + }, + res: { + chrome123: false, + chrome126: true, + deno1_42: false, + node21_0: false, + firefox115: false, + firefox128: false, + firefox129: true, + safari17_4: true, + safaritp: true, + ie11: false, + duktape2_0: false, + jerryscript2_3_0: false, + hermes0_7_0: false, + rhino1_7_13: false, + }, + }, + { + name: 'Set methods', + category: '2025 features', + significance: 'medium', + spec: 'https://github.com/tc39/proposal-set-methods', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#instance_methods', + subtests: [ + { + name: 'Set.prototype.intersection()', + exec() { + /* + var set = new Set([1, 2, 3]).intersection(new Set([2, 3, 4])); + return set.size === 2 + && set.has(2) + && set.has(3); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox117: false, + firefox118: { + val: 'flagged', + note_id: 'ff-new-set-methods', + note_html: + 'The feature has to be enabled via javascript.options.experimental.new_set_methods setting under about:config.', + }, + firefox127: true, + chrome77: false, + chrome122: true, + safari17: true, + duktape2_0: false, + graalvm19: false, + graalvm21_3_3: graalvm.newSetMethodsFlag, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Set.prototype.union()', + exec() { + /* + var set = new Set([1, 2]).union(new Set([2, 3])); + return set.size === 3 + && set.has(1) + && set.has(2) + && set.has(3); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox117: false, + firefox118: { + val: 'flagged', + note_id: 'ff-new-set-methods', + }, + firefox127: true, + chrome77: false, + chrome122: true, + safari17: true, + duktape2_0: false, + graalvm19: false, + graalvm21_3_3: graalvm.newSetMethodsFlag, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Set.prototype.difference()', + exec() { + /* + var set = new Set([1, 2, 3]).difference(new Set([3, 4])); + return set.size === 2 + && set.has(1) + && set.has(2); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox117: false, + firefox118: { + val: 'flagged', + note_id: 'ff-new-set-methods', + }, + firefox127: true, + chrome77: false, + chrome122: true, + safari17: true, + duktape2_0: false, + graalvm19: false, + graalvm21_3_3: graalvm.newSetMethodsFlag, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Set.prototype.symmetricDifference()', + exec() { + /* + var set = new Set([1, 2]).symmetricDifference(new Set([2, 3])); + return set.size === 2 + && set.has(1) + && set.has(3); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox117: false, + firefox118: { + val: 'flagged', + note_id: 'ff-new-set-methods', + }, + firefox127: true, + chrome77: false, + chrome122: true, + safari17: true, + duktape2_0: false, + graalvm19: false, + graalvm21_3_3: graalvm.newSetMethodsFlag, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Set.prototype.isDisjointFrom()', + exec() { + /* + return new Set([1, 2, 3]).isDisjointFrom(new Set([4, 5, 6])); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox117: false, + firefox118: { + val: 'flagged', + note_id: 'ff-new-set-methods', + }, + firefox127: true, + chrome77: false, + chrome122: true, + safari17: true, + duktape2_0: false, + graalvm19: false, + graalvm20_1: graalvm.es2021flag, + graalvm21_3_3: graalvm.newSetMethodsFlag, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Set.prototype.isSubsetOf()', + exec() { + /* + return new Set([1, 2, 3]).isSubsetOf(new Set([5, 4, 3, 2, 1])); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox117: false, + firefox118: { + val: 'flagged', + note_id: 'ff-new-set-methods', + }, + firefox127: true, + chrome77: false, + chrome122: true, + safari17: true, + duktape2_0: false, + graalvm19: false, + graalvm21_3_3: graalvm.newSetMethodsFlag, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Set.prototype.isSupersetOf()', + exec() { + /* + return new Set([5, 4, 3, 2, 1]).isSupersetOf(new Set([1, 2, 3])); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox2: false, + firefox117: false, + firefox118: { + val: 'flagged', + note_id: 'ff-new-set-methods', + }, + firefox127: true, + chrome77: false, + chrome122: true, + safari17: true, + duktape2_0: false, + graalvm19: false, + graalvm21_3_3: graalvm.newSetMethodsFlag, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'RegExp Pattern Modifiers', + category: '2025 features', + significance: 'medium', + spec: 'https://github.com/tc39/proposal-regexp-modifiers', + subtests: [ + { + name: 'i flag', + exec() { + /* + const regex = /^[a-z](?-i:[a-z])$/i; + return regex.test("ab") && regex.test("Ab") && !regex.test("aB"); + */ + }, + res: { + chrome121: false, + chrome122: chrome.harmony, + chrome124: chrome.harmony, + chrome125: true, + firefox127: false, + firefox129: false, + firefox130: { + val: 'flagged', + note_id: 'ff-regexp-modidiers', + note_html: + 'The feature has to be enabled via javascript.options.experimental.regexp_modifiers setting under about:config.', + }, + firefox132: true, + safari17_5: false, + }, + }, + { + name: 'm flag', + exec() { + /* + const regex = /^a|(?m:^b)/; + return regex.test("a") && regex.test("b") && regex.test("c\nb") && !regex.test("c\na"); + */ + }, + res: { + chrome121: false, + chrome122: chrome.harmony, + chrome124: chrome.harmony, + chrome125: true, + firefox127: false, + firefox129: false, + firefox130: { + val: 'flagged', + note_id: 'ff-regexp-modidiers', + }, + firefox132: true, + safari17_5: false, + }, + }, + { + name: 's flag', + exec() { + /* + const regex = /.(?-s:.)/s; + return regex.test("\na") && regex.test("aa") && !regex.test("\n\n"); + */ + }, + res: { + chrome121: false, + chrome122: chrome.harmony, + chrome124: chrome.harmony, + chrome125: true, + firefox127: false, + firefox129: false, + firefox130: { + val: 'flagged', + note_id: 'ff-regexp-modidiers', + }, + firefox132: true, + safari17_5: false, + }, + }, + ], + }, + { + name: 'Iterator Helpers', + category: '2025 features', + significance: 'large', + spec: 'https://github.com/tc39/proposal-iterator-helpers', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator#iterator_helpers', + subtests: [ + { + name: 'instanceof Iterator', + exec() { + /* + return [1, 2, 3].values() instanceof Iterator; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + note_html: + 'The feature is only available on Nightly builds, and has to be enabled via javascript.options.experimental.iterator_helpers setting under about:config.', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'extends Iterator', + exec() { + /* + class Class extends Iterator { } + const instance = new Class(); + return instance[Symbol.iterator]() === instance; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.from, iterable', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/from', + exec() { + /* + const iterator = Iterator.from([1, 2, 3]); + return 'next' in iterator + && iterator instanceof Iterator + && Array.from(iterator).join() === '1,2,3'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.from, iterator', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/from', + exec() { + /* + const iterator = Iterator.from({ + i: 0, + next() { + return { value: ++this.i, done: this.i > 3 }; + } + }); + return 'next' in iterator + && iterator instanceof Iterator + && Array.from(iterator).join() === '1,2,3'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.drop', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/drop', + exec() { + /* + return Array.from([1, 2, 3].values().drop(1)).join() === '2,3'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.every', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/every', + exec() { + /* + return [1, 2, 3].values().every(it => typeof it === 'number'); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.filter', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/filter', + exec() { + /* + return Array.from([1, 2, 3].values().filter(it => it % 2)).join() === '1,3'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.find', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/find', + exec() { + /* + return [1, 2, 3].values().find(it => it % 2) === 1; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.flatMap', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/flatMap', + exec() { + /* + return Array.from([1, 2, 3].values().flatMap(it => [it, 0])).join() === '1,0,2,0,3,0'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.forEach', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/forEach', + exec() { + /* + let result = ''; + [1, 2, 3].values().forEach(it => result += it); + return result === '123'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.map', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/map', + exec() { + /* + return Array.from([1, 2, 3].values().map(it => it * it)).join() === '1,4,9'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.reduce', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/reduce', + exec() { + /* + return [1, 2, 3].values().reduce((a, b) => a + b) === 6; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.some', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/some', + exec() { + /* + return [1, 2, 3].values().some(it => typeof it === 'number'); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.take', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/take', + exec() { + /* + return Array.from([1, 2, 3].values().take(2)).join() === '1,2'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype.toArray', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/toArray', + exec() { + /* + const array = [1, 2, 3].values().toArray(); + return Array.isArray(array) && array.join() === '1,2,3'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Iterator.prototype[@@toStringTag]', + exec() { + /* + return Iterator.prototype[Symbol.toStringTag] === 'Iterator'; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + firefox10: false, + firefox60: false, + firefox116: false, + firefox117: { + val: 'flagged', + note_id: 'ff-iterator-helpers', + }, + firefox131: true, + chrome77: false, + chrome126: true, + duktape2_0: false, + graalvm21_3_3: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Promise.try', + category: '2025 features', + significance: 'tiny', + spec: 'https://github.com/tc39/proposal-promise-try', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/try', + exec() { + /* + var called = false; + var argsMatch = false; + var p = Promise.try(function () { called = true; }) + var p2 = Promise.try(function () { + 'use strict'; + argsMatch = this === undefined && arguments.length === 2 && args[0] === p && args[1] === 2; + }, [p, 2]); + + return p instanceof Promise && called && argsMatch; + */ + }, + res: { + ie11: false, + chrome128: true, + firefox115: false, + firefox131: false, + firefox132: { + val: 'flagged', + note_id: 'ff-promise-try', + note_html: + 'The feature is only available on Nightly builds, and has to be enabled via javascript.options.experimental.promise_try setting under about:config.', + }, + firefox134: true, + node23: true, + }, + }, +] diff --git a/developer-extension/src/panel/components/tabs/diagnosticTab/data/es5.ts b/developer-extension/src/panel/components/tabs/diagnosticTab/data/es5.ts new file mode 100644 index 0000000000..c55923b722 --- /dev/null +++ b/developer-extension/src/panel/components/tabs/diagnosticTab/data/es5.ts @@ -0,0 +1,2498 @@ +/* eslint-disable */ +// @ts-nocheck + +const sparseNote = null +const hermes = {} + +export const data = [ + { + name: 'Object/array literal extensions', + significance: 'large', + subtests: [ + { + name: 'Getter accessors', + exec() { + /* + return ({ get x(){ return 1 } }).x === 1; + */ + }, + res: { + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Setter accessors', + exec() { + /* + var value = 0; + ({ set x(v){ value = v; } }).x = 1; + return value === 1; + */ + }, + res: { + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Trailing commas in object literals', + exec() { + /* + return { a: true, }.a === true; + */ + }, + res: { + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: null, + chrome7: true, + opera10_50: true, + opera12_10: true, + konq4_3: null, + besen: null, + rhino1_7_13: true, + ejs: null, + android4_0: null, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Trailing commas in array literals', + exec() { + /* + return [1,].length === 1; + */ + }, + res: { + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: null, + chrome7: true, + opera10_50: true, + opera12_10: true, + konq4_3: null, + besen: null, + rhino1_7_13: true, + ejs: null, + android4_0: null, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Reserved words as property names', + exec() { + /* + return ({ if: 1 }).if === 1; + */ + }, + res: { + ie9: true, + firefox2: true, + safari5_1: true, + chrome5: false, + chrome6: false, + chrome7: true, + chrome13: true, + chrome19: true, + chrome23: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + ], + separator: 'after', + }, + { + name: 'Object static methods', + significance: 'large', + subtests: [ + { + name: 'Object.create', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create', + exec() { + return typeof Object.create === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari4: true, + chrome5: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.defineProperty', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty', + exec() { + return typeof Object.defineProperty === 'function' + }, + res: { + ie8: { + val: true, + note_id: 'define-property-ie', + note_html: + 'In Internet Explorer 8 Object.defineProperty only accepts DOM objects ' + + '(MSDN reference).', + }, + ie9: true, + firefox2: false, + firefox4: true, + firefox21: true, + safari4: { + val: true, + note_id: 'define-property-webkit', + note_html: + 'In some versions of Safari 5, Object.defineProperty does not work with DOM objects.', + }, + safari5_1: true, + chrome5: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.defineProperties', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties', + exec() { + return typeof Object.defineProperties === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari4: true, + chrome5: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.getPrototypeOf', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf', + exec() { + return typeof Object.getPrototypeOf === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox3_5: true, + safari4: true, + chrome5: true, + opera10_50: false, + opera12: true, + konq4_3: false, + konq4_9: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.keys', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys', + exec() { + return typeof Object.keys === 'function' + }, + res: { + es5shim: true, + ie9: true, + firefox2: false, + firefox4: true, + safari4: true, + chrome5: true, + opera10_50: false, + opera12: true, + konq4_3: false, + konq4_9: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.seal', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal', + exec() { + return typeof Object.seal === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome6: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.freeze', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze', + exec() { + return typeof Object.freeze === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome6: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.preventExtensions', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions', + exec() { + return typeof Object.preventExtensions === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome6: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.isSealed', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed', + exec() { + return typeof Object.isSealed === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome6: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.isFrozen', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen', + exec() { + return typeof Object.isFrozen === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome6: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.isExtensible', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible', + exec() { + return typeof Object.isExtensible === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome6: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.getOwnPropertyDescriptor', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor', + exec() { + return typeof Object.getOwnPropertyDescriptor === 'function' + }, + res: { + ie7: false, + ie8: { + val: true, + note_id: 'get-own-property-descriptor-ie', + note_html: + 'In Internet Explorer 8 Object.getOwnPropertyDescriptor only accepts DOM objects ' + + '(MSDN reference).', + }, + ie9: true, + ie10: true, + firefox2: false, + firefox4: true, + safari4: true, + chrome5: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.getOwnPropertyNames', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames', + exec() { + return typeof Object.getOwnPropertyNames === 'function' + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari4: true, + chrome5: true, + opera10_50: false, + opera12: true, + konq4_3: false, + konq4_9: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + separator: 'after', + }, + ], + }, + { + name: 'Array methods', + significance: 'large', + subtests: [ + { + name: 'Array.isArray', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray', + exec() { + return typeof Array.isArray === 'function' + }, + res: { + es5shim: true, + ie9: true, + firefox2: false, + firefox4: true, + safari4: true, + chrome5: true, + opera10_50: true, + konq4_3: false, + konq4_9: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.indexOf', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf', + exec() { + return typeof Array.prototype.indexOf === 'function' + }, + res: { + es5shim: true, + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.lastIndexOf', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf', + exec() { + return typeof Array.prototype.lastIndexOf === 'function' + }, + res: { + es5shim: true, + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.every', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every', + exec() { + return typeof Array.prototype.every === 'function' + }, + res: { + es5shim: sparseNote, + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.some', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some', + exec() { + return typeof Array.prototype.some === 'function' + }, + res: { + es5shim: sparseNote, + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.forEach', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach', + exec() { + return typeof Array.prototype.forEach === 'function' + }, + res: { + es5shim: sparseNote, + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.map', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map', + exec() { + return typeof Array.prototype.map === 'function' + }, + res: { + es5shim: sparseNote, + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.filter', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter', + exec() { + return typeof Array.prototype.filter === 'function' + }, + res: { + es5shim: sparseNote, + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.reduce', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce', + exec() { + return typeof Array.prototype.reduce === 'function' + }, + res: { + es5shim: sparseNote, + ie9: true, + firefox2: false, + firefox3: true, + safari4: true, + chrome5: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.reduceRight', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight', + exec() { + return typeof Array.prototype.reduceRight === 'function' + }, + res: { + es5shim: sparseNote, + ie9: true, + firefox2: false, + firefox3: true, + safari4: true, + chrome5: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.sort: compareFn must be function or undefined', + exec() { + try { + ;[1, 2].sort(null) + return false + } catch (enull) {} + try { + ;[1, 2].sort(true) + return false + } catch (etrue) {} + try { + ;[1, 2].sort({}) + return false + } catch (eobj) {} + try { + ;[1, 2].sort([]) + return false + } catch (earr) {} + try { + ;[1, 2].sort(/a/g) + return false + } catch (eregex) {} + return true + }, + res: { + es5shim: true, + ie9: true, + firefox2: false, + firefox5: true, + safari1: false, + safari10_1: true, + safari11: false, + safari12: true, + safaritp: true, + chrome1: false, + chrome63: true, + opera10_10: null, + opera10_50: true, + konq4_3: null, + konq4_9: null, + konq4_13: null, + besen: null, + rhino1_7_13: true, + ejs: null, + android4_0: false, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.sort: compareFn may be explicit undefined', + exec() { + try { + const arr = [2, 1] + return arr.sort(undefined) === arr && arr[0] === 1 && arr[1] === 2 + } catch (e) { + return false + } + }, + res: { + es5shim: true, + ie9: true, + firefox2: false, + firefox4: true, + safari3_1: true, + chrome13: true, + opera10_10: null, + opera10_50: true, + konq4_3: null, + konq4_9: null, + konq4_13: null, + besen: null, + rhino1_7_13: true, + ejs: null, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Array.prototype.unshift: [].unshift(0) returns the unshifted count', + exec() { + return [].unshift(0) === 1 + }, + res: { + es5shim: true, + chrome15: true, + chrome101: true, + firefox3: true, + firefox100: true, + ie6: false, + ie7: false, + ie8: true, + ie11: true, + opera10_60: true, + opera11: true, + opera12_10: true, + opera12: true, + safari4: true, + safari15: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'String properties and methods', + significance: 'small', + subtests: [ + { + name: 'Property access on strings', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Character_access', + exec() { + return 'foobar'[3] === 'b' + }, + res: { + ie7: false, + ie8: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'String.prototype.split', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split', + exec() { + // all of these tests reflect bugs that es5-shim patches + return ( + typeof String.prototype.split === 'function' && + ''.split().length === 1 && + ''.split()[0] === '' && + ''.split(undefined).length === 1 && + ''.split(undefined)[0] === '' && + 'ab'.split().length === 1 && + 'ab'.split()[0] === 'ab' && + 'ab'.split(undefined).length === 1 && + 'ab'.split(undefined)[0] === 'ab' && + '0'.split(undefined, 0).length === 0 && + 'ab'.split(/(?:ab)*/).length === 2 && + '.'.split(/(.?)(.?)/).length === 4 && + 'tesst'.split(/(s)*/)[1] !== 't' && + 'test'.split(/(?:)/, -1).length === 4 && + ''.split(/.?/).length === 0 && + '.'.split(/()()/).length === 1 + ) + }, + res: { + chrome15: true, + chrome37: true, + edge15: true, + edge18: true, + edge80: true, + es5shim: true, + firefox3: false, + firefox3_6: false, + firefox4: false, + firefox5: true, + firefox10: true, + ie8: false, + ie9: true, + node0_4: true, + node0_6: true, + node0_8: false, + node0_10: false, + node0_12: true, + opera10_60: false, + opera11: true, + safari4: false, + safari5: false, + safari5_1: true, + safari13: true, + duktape2_0: true, + graalvm20_3: true, + jerryscript1_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'String.prototype.substr', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr', + exec() { + return '0b'.substr(-1) === 'b' + }, + res: { + es5shim: true, + ie6: false, + ie7: false, + ie8: false, + ie9: true, + chrome15: true, + firefox3: true, + opera11: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_15: true, + }, + }, + { + name: 'String.prototype.trim', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim', + exec() { + return typeof String.prototype.trim === 'function' + }, + res: { + es5shim: true, + ie9: true, + firefox2: false, + firefox3_5: true, + safari4: true, + chrome5: true, + opera10_50: true, + konq4_3: false, + konq4_9: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + separator: 'after', + }, + ], + }, + { + name: 'Date methods', + significance: 'small', + subtests: [ + { + name: 'Date.prototype.toISOString', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString', + exec() { + return typeof Date.prototype.toISOString === 'function' + }, + res: { + es5shim: true, + ie9: true, + firefox2: false, + firefox3_5: true, + safari4: true, + chrome5: true, + opera10_50: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: false, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Date.now', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now', + exec() { + return typeof Date.now === 'function' + }, + res: { + es5shim: true, + ie9: true, + firefox2: true, + safari4: true, + chrome5: true, + opera10_50: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Date.prototype.toJSON', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON', + exec() { + try { + return Date.prototype.toJSON.call(new Date(NaN)) === null + } catch (e) { + return false + } + }, + res: { + es5shim: true, + ie9: true, + firefox2: false, + firefox4: true, + safari10: true, + chrome5: true, + opera10_10: false, + opera10_50: false, + opera12: { + val: false, + note_id: 'Date.prototype.toJSON-OP11_60-OP11_64', + note_html: 'In Opera 11.60-11.64 Date.prototype.toJSON is undefined.', + }, + opera12_10: true, + konq4_3: true, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + ], + }, + { + name: 'Function.prototype.bind', + significance: 'medium', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind', + exec() { + return typeof Function.prototype.bind === 'function' + }, + res: { + es5shim: true, + ie9: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome7: true, + opera10_50: false, + opera12: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'JSON', + significance: 'medium', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON', + exec() { + return typeof JSON === 'object' + }, + res: { + ie7: false, + ie8: true, + ie9: true, + ie10: true, + firefox2: false, + firefox3_5: true, + safari4: true, + chrome5: true, + opera10_50: true, + konq4_3: false, + konq4_9: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + separator: 'after', + }, + { + name: 'Immutable globals', + significance: 'small', + subtests: [ + { + name: 'undefined', + exec() { + /* + undefined = 12345; + var result = typeof undefined === 'undefined'; + undefined = void 0; + return result; + */ + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari4: true, + chrome19: true, + chrome23: true, + opera10_50: false, + opera12: true, + konq4_3: false, + konq4_9: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: false, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'NaN', + exec() { + /* + NaN = false; + var result = typeof NaN === 'number'; + NaN = Math.sqrt(-1); + return result; + */ + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari4: true, + chrome19: true, + chrome23: true, + opera10_50: false, + opera12: true, + konq4_3: false, + konq4_9: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: false, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Infinity', + exec() { + /* + Infinity = false; + var result = typeof Infinity === 'number'; + Infinity = 1/0; + return result; + */ + }, + res: { + ie9: true, + firefox2: false, + firefox4: true, + safari4: true, + chrome19: true, + chrome23: true, + opera10_50: false, + opera12: true, + konq4_3: false, + konq4_9: true, + konq4_13: true, + besen: true, + rhino1_7_13: true, + ejs: false, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + ], + }, + { + name: 'Number methods', + significance: 'small', + subtests: [ + { + name: 'Number.prototype.toExponential rounds properly', + exec() { + return ( + (-6.9e-11).toExponential(4) === '-6.9000e-11' && // Edge <= 17 + (25).toExponential(0) === '3e+1' && // FF <= 86 + (1.255).toExponential(2) === '1.25e+0' + ) // IE <= 11 && Edge <= 14 + }, + res: { + ie6: false, + ie7: false, + ie8: false, + ie9: false, + ie10: false, + ie11: false, + chrome15: true, + firefox3: true, + firefox3_6: false, + firefox86: false, + firefox87: true, + opera10_10: true, + safari4: true, + edge13: false, + edge14: false, + edge15: false, + edge16: false, + edge17: false, + edge18: true, + edge80: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + { + name: 'Number.prototype.toExponential throws on ±Infinity fractionDigits', + exec() { + try { + ;(1).toExponential(Infinity) + ;(1).toExponential(-Infinity) + return false + } catch (e) { + return true + } + }, + res: { + ie6: false, + ie7: false, + ie8: false, + ie9: true, + ie10: true, + ie11: true, + chrome15: true, + firefox3: true, + opera10_10: true, + safari4: true, + edge15: true, + edge16: true, + edge17: true, + edge18: true, + edge80: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + { + name: 'Number.prototype.toExponential does not throw on edge cases', + exec() { + try { + NaN.toExponential(Infinity) + Infinity.toExponential(Infinity) + return true + } catch (e) { + return false + } + }, + res: { + chrome37: true, + firefox3: false, + firefox3_6: false, + firefox49: false, + firefox50: true, + ie6: true, + ie8: true, + edge12: true, + safari10: false, + safari11: true, + duktape2_0: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_14: true, + }, + }, + ], + }, + { + name: 'Miscellaneous', + significance: 'medium', + subtests: [ + { + name: 'Function.prototype.apply permits array-likes', + exec() { + try { + return function (a, b) { + return a === 1 && b === 2 + }.apply({}, { 0: 1, 1: 2, length: 2 }) + } catch (e) { + return false + } + }, + res: { + ie7: null, + ie9: true, + firefox2: false, + firefox4: true, + safari3_1: false, + safari5_1: true, + chrome5: false, + chrome13: true, + opera10_10: null, + opera10_50: true, + konq4_3: null, + besen: null, + rhino1_7_13: true, + ejs: null, + android4_0: null, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'parseInt ignores leading zeros', + exec() { + return parseInt('010') === 10 + }, + res: { + es5shim: true, + ie9: true, + firefox2: false, + firefox21: true, + safari6: true, + chrome23: true, + opera10_10: false, + opera10_50: false, + konq4_3: false, + konq4_9: false, + konq4_13: false, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_4: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Function "prototype" property is non-enumerable', + exec() { + /* + return !Function().propertyIsEnumerable('prototype'); + */ + }, + res: { + ie7: null, + ie9: true, + firefox2: false, + firefox3_6: true, + safari5_1: true, + chrome5: false, + chrome13: true, + opera10_10: null, + opera10_50: false, + opera12: true, + konq4_3: null, + besen: null, + rhino1_7_13: true, + ejs: null, + android4_0: null, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Arguments toStringTag is "Arguments"', + exec() { + /* + return (function(){ return Object.prototype.toString.call(arguments) === '[object Arguments]'; }()); + */ + }, + res: { + ie7: null, + ie9: true, + firefox2: false, + firefox4: true, + safari3_1: true, + chrome5: null, + chrome7: true, + chrome13: true, + opera10_10: null, + opera10_50: false, + opera12: true, + konq4_3: null, + besen: null, + rhino1_7_13: true, + ejs: null, + android4_0: null, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Zero-width chars in identifiers', + exec() { + /* + var _\u200c\u200d = true; + return _\u200c\u200d; + */ + }, + res: { + ie9: true, + firefox2: false, + firefox3_5: false, + firefox8: true, + firefox21: true, + safari6: true, + chrome19: true, + chrome23: true, + opera10_10: false, + opera10_50: false, + opera12_10: true, + konq4_3: false, + konq4_9: false, + konq4_13: false, + besen: true, + rhino1_7_13: true, + ejs: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Unreserved words', + exec() { + /* + var abstract, boolean, byte, char, double, final, float, goto, int, long, + native, short, synchronized, transient, volatile; + return true; + */ + }, + res: { + ie7: null, + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: false, + chrome13: true, + opera10_10: null, + opera10_50: true, + konq4_3: null, + besen: null, + rhino1_7_13: true, + ejs: null, + android4_0: null, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Enumerable properties can be shadowed by non-enumerables', + exec() { + /* + var result = true; + Object.prototype.length = 42; + for (var i in Function) { + if (i === 'length') { + result = false; + } + } + delete Object.prototype.length; + return result; + */ + }, + res: { + ie7: null, + ie9: false, + edge13: true, + firefox2: true, + safari3_1: false, + safari14_1: true, + safaritp: true, + chrome5: false, + chrome13: false, + chrome54: true, + opera10_10: null, + opera10_50: true, + konq4_3: null, + besen: null, + rhino1_7_13: false, + ejs: null, + android4_0: null, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: false, + jerryscript2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + { + name: 'Thrown functions have proper "this" values', + exec() { + /* + try { + throw function() { return !('a' in this); }; + } + catch(e) { + var a = true; + return e(); + } + */ + }, + res: { + ie7: null, + ie9: true, + firefox2: true, + safari3_1: true, + chrome5: true, + opera10_10: null, + opera10_50: true, + konq4_3: null, + besen: null, + rhino1_7_13: true, + ejs: null, + android4_0: null, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + ], + }, + { + name: 'Strict mode', + significance: 'large', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode', + subtests: [ + { + name: 'reserved words', + exec() { + /* + 'use strict'; + var words = 'implements,interface,let,package,private,protected,public,static,yield'.split(','); + for (var i = 0; i < 9; i+=1) { + try { eval('var ' + words[i]); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + } + return true; + */ + }, + res: { + ie10: true, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: hermes.evalStrictMode, + reactnative0_70_3: false, + rhino1_7_13: true, + }, + }, + { + name: '"this" is undefined in functions', + exec() { + /* + 'use strict'; + return this === void undefined && (function(){ return this === void undefined; }).call(); + */ + }, + res: { + ie10: { + val: true, + note_id: 'strict-mode-ie10', + note_html: 'IE10 PP2 fails this test.', + }, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"this" is not coerced to object in primitive methods', + exec() { + /* + 'use strict'; + return (function(){ return typeof this === 'string' }).call('') + && (function(){ return typeof this === 'number' }).call(1) + && (function(){ return typeof this === 'boolean' }).call(true); + */ + }, + res: { + ie10: true, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"this" is not coerced to object in primitive accessors', + exec() { + /* + 'use strict'; + + function test(Class, instance) { + Object.defineProperty(Class.prototype, 'test', { + get: function () { passed = passed && this === instance; }, + set: function () { passed = passed && this === instance; }, + configurable: true + }); + + var passed = true; + instance.test; + instance.test = 42; + return passed; + } + + return test(String, '') + && test(Number, 1) + && test(Boolean, true); + */ + }, + res: { + ie10: true, + firefox2: false, + firefox46: true, + safari6: true, + chrome13: true, + opera10_50: false, + opera12_10: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + graalvm19: true, + jerryscript1_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'legacy octal is a SyntaxError', + exec() { + /* + 'use strict'; + try { eval('010'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + try { eval('"\\010"'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + return true; + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: hermes.evalStrictMode, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'assignment to unresolvable identifiers is a ReferenceError', + exec() { + /* + 'use strict'; + try { eval('__i_dont_exist = 1'); } catch (err) { return err instanceof ReferenceError; } + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: hermes.evalStrictMode, + reactnative0_70_3: false, + rhino1_7_13: true, + }, + }, + { + name: 'assignment to eval or arguments is a SyntaxError', + exec() { + /* + 'use strict'; + try { eval('eval = 1'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + try { eval('arguments = 1'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + try { eval('eval++'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + try { eval('arguments++'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + return true; + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: hermes.evalStrictMode, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'assignment to non-writable properties is a TypeError', + exec() { + /* + 'use strict'; + try { Object.defineProperty({},"x",{ writable: false }).x = 1; return false; } catch (err) { if (!(err instanceof TypeError)) return false; } + try { Object.preventExtensions({}).x = 1; return false; } catch (err) { if (!(err instanceof TypeError)) return false; } + try { ({ get x(){ } }).x = 1; return false; } catch (err) { if (!(err instanceof TypeError)) return false; } + try { (function f() { f = 123; })(); return false; } catch (err) { if (!(err instanceof TypeError)) return false; } + return true; + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + graalvm19: true, + jerryscript1_0: false, + jerryscript2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'eval or arguments bindings is a SyntaxError', + exec() { + /* + 'use strict'; + try { eval('var eval'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + try { eval('var arguments'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + try { eval('(function(eval){})'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + try { eval('(function(arguments){})'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + try { eval('try{}catch(eval){}'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + try { eval('try{}catch(arguments){}'); return false; } catch (err) { if (!(err instanceof SyntaxError)) return false; } + return true; + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: hermes.evalStrictMode, + reactnative0_70_3: false, + rhino1_7_13: true, + }, + }, + { + name: 'arguments.caller removed or is a TypeError', + exec() { + /* + 'use strict'; + if ('caller' in arguments) { + try { arguments.caller; return false; } catch (err) { if (!(err instanceof TypeError)) return false; } + } + return true; + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari3_1: true, + chrome13: true, + opera10_50: true, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'arguments.callee is a TypeError', + exec() { + /* + 'use strict'; + try { arguments.callee; return false; } catch (err) { if (!(err instanceof TypeError)) return false; } + return true; + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '(function(){}).caller and (function(){}).arguments is a TypeError', + exec() { + /* + 'use strict'; + try { (function(){}).caller; return false; } catch (err) { if (!(err instanceof TypeError)) return false; } + try { (function(){}).arguments; return false; } catch (err) { if (!(err instanceof TypeError)) return false; } + return true; + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'arguments is unmapped', + exec() { + /* + 'use strict'; + return (function(x){ + x = 2; + return arguments[0] === 1; + })(1) && (function(x){ + arguments[0] = 2; + return x === 1; + })(1); + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: false, + }, + }, + { + name: "eval() can't create bindings", + exec() { + /* + 'use strict'; + try { eval('var __some_unique_variable;'); __some_unique_variable; } catch (err) { return err instanceof ReferenceError; } + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: hermes.evalLexicalScopeSuccess, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'deleting bindings is a SyntaxError', + exec() { + /* + 'use strict'; + try { eval('var x; delete x;'); } catch (err) { return err instanceof SyntaxError; } + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: hermes.evalStrictMode, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'deleting non-configurable properties is a TypeError', + exec() { + /* + 'use strict'; + try { delete Object.prototype; } catch (err) { return err instanceof TypeError; } + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '"with" is a SyntaxError', + exec() { + /* + 'use strict'; + try { eval('with({}){}'); } catch (err) { return err instanceof SyntaxError; } + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'repeated parameter names is a SyntaxError', + exec() { + /* + 'use strict'; + try { eval('function f(x, x) { }'); } catch (err) { return err instanceof SyntaxError; } + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + safari5_1: true, + chrome13: true, + opera10_50: false, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: hermes.evalStrictMode, + reactnative0_70_3: false, + rhino1_7_13: true, + }, + }, + { + name: 'function expressions with matching name and argument are valid', + exec() { + /* + var foo = function bar(bar) {'use strict'}; + return typeof foo === 'function'; + */ + }, + res: { + ie10: true, + firefox2: true, + safari3_1: true, + safari5_1: false, + safari10: true, + safari11: false, + safari11_1: true, + chrome13: true, + opera10_50: true, + opera12: true, + besen: true, + phantom1_9: true, + ejs: true, + ios7: true, + ios8: true, + ios9: true, + android4_1: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: false, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, +] diff --git a/developer-extension/src/panel/components/tabs/diagnosticTab/data/es6.ts b/developer-extension/src/panel/components/tabs/diagnosticTab/data/es6.ts new file mode 100644 index 0000000000..597b9a9977 --- /dev/null +++ b/developer-extension/src/panel/components/tabs/diagnosticTab/data/es6.ts @@ -0,0 +1,26030 @@ +/* eslint-disable */ +// @ts-nocheck + +const babel = {} +const typescript = {} +const chrome = {} +const edge = {} +const safari = {} +const graalvm = {} +const hermes = {} + +export const data = [ + { + name: 'proper tail calls (tail call optimisation)', + category: 'optimisation', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-tail-position-calls', + note_id: 'proper-tail-calls', + note_html: + '' + + 'The feature can be enabled with use strict and JavaScript flag "--harmony-tailcalls" ' + + 'in certain versions of Node.js. Since Node.js 8.2.1, the V8 flags ' + + '--harmony-tailcalls and --harmony-explicit-tailcalls ' + + 'have been removed. See: ' + + 'Chrome Platform Status, ' + + '' + + 'blog in JavaScript in Plain English, ' + + 'and V8 Dev Blog for details.', + subtests: [ + { + name: 'direct recursion', + exec() { + /* + "use strict"; + return (function f(n){ + if (n <= 0) { + return "foo"; + } + return f(n - 1); + }(1e6)) === "foo"; + */ + }, + res: { + tr: { + val: 'flagged', + note_id: 'tr-tco', + note_html: 'Requires the properTailCalls compile option.', + }, + babel6corejs2: false, + typescript1corejs2: typescript.fallthrough, + ie11: false, + firefox2: false, + opera10_50: false, + chrome51: chrome.harmony, + chrome58: chrome.tco, + chrome61: false, + safari10: true, + xs6: true, + duktape2_0: true, + graalvm19: false, + jerryscript2_0: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: false, + }, + }, + { + name: 'mutual recursion', + exec() { + /* + "use strict"; + function f(n){ + if (n <= 0) { + return "foo"; + } + return g(n - 1); + } + function g(n){ + if (n <= 0) { + return "bar"; + } + return f(n - 1); + } + return f(1e6) === "foo" && f(1e6+1) === "bar"; + */ + }, + res: { + tr: { val: 'flagged', note_id: 'tr-tco' }, + typescript1corejs2: typescript.fallthrough, + ie11: false, + firefox2: false, + opera10_50: false, + chrome51: chrome.harmony, + chrome58: chrome.tco, + chrome61: false, + safari10: true, + xs6: true, + duktape2_0: true, + graalvm19: false, + jerryscript2_0: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: false, + }, + }, + ], + }, + { + name: 'arrow functions', + category: 'functions', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-arrow-function-definitions', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions', + subtests: [ + { + name: '0 parameters', + exec() { + /* + return (() => 5)() === 5; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + ejs: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox22: true, + opera10_50: false, + chrome38: chrome.experimental, + chrome40: false, + chrome45: true, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '1 parameter, no brackets', + exec() { + /* + var b = x => x + "foo"; + return (b("fee fie foe ") === "fee fie foe foo"); + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + ejs: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox22: true, + opera10_50: false, + chrome38: chrome.experimental, + chrome40: false, + chrome45: true, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'multiple parameters', + exec() { + /* + var c = (v, w, x, y, z) => "" + v + w + x + y + z; + return (c(6, 5, 4, 3, 2) === "65432"); + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + ejs: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox22: true, + opera10_50: false, + chrome38: chrome.experimental, + chrome40: false, + chrome45: true, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'lexical "this" binding', + exec() { + /* + var d = { x : "bar", y : function() { return z => this.x + z; }}.y(); + var e = { x : "baz", y : d }; + return d("ley") === "barley" && e.y("ley") === "barley"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + ejs: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox22: true, + opera10_50: false, + chrome45: true, + safari10: true, + node4: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '"this" unchanged by call or apply', + exec() { + /* + var d = { x : "foo", y : function() { return () => this.x; }}; + var e = { x : "bar" }; + return d.y().call(e) === "foo" && d.y().apply(e) === "foo"; + */ + }, + res: { + tr: true, + closure: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox22: true, + opera10_50: false, + chrome45: true, + safari10: true, + node4: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: "can't be bound, can be curried", + exec() { + /* + var d = { x : "bar", y : function() { return z => this.x + z; }}; + var e = { x : "baz" }; + return d.y().bind(e, "ley")() === "barley"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + ejs: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox22: true, + opera10_50: false, + chrome45: true, + safari10: true, + node4: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'lexical "arguments" binding', + exec() { + /* + var f = (function() { return z => arguments[0]; }(5)); + return f(6) === 5; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox22: true, + firefox24: false, + firefox43: true, + opera10_50: false, + chrome45: true, + node4: true, + xs6: true, + safari10: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'no line break between params and =>', + exec() { + /* + return (() => { + try { Function("x\n => 2")(); } catch(e) { return true; } + })(); + */ + }, + res: { + babel6corejs2: true, + closure: true, + tr: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox39: true, + opera10_50: false, + safari10: true, + chrome45: true, + node4: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'correct precedence', + exec() { + /* + return (() => { + try { Function("0 || () => 2")(); } catch(e) { return true; } + })(); + */ + }, + res: { + closure: true, + tr: true, + ie11: false, + edge13: true, + firefox2: false, + firefox22: true, + opera10_50: false, + safari10: true, + chrome47: true, + node6: true, + node6_5: true, + xs6: false, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'no "prototype" property', + exec() { + /* + var a = () => 5; + return !a.hasOwnProperty("prototype"); + */ + }, + res: { + ie11: false, + edge13: true, + firefox2: false, + firefox22: true, + opera10_50: false, + chrome39: chrome.experimental, + chrome40: false, + chrome45: true, + safari10: true, + node4: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: true, + }, + }, + { + name: 'lexical "super" binding in constructors', + exec() { + /* + var received; + + class B { + constructor (arg) { + received = arg; + } + } + class C extends B { + constructor () { + var callSuper = () => super('foo'); + callSuper(); + } + } + return new C instanceof C && received === 'foo' + */ + }, + res: { + tr: true, + babel6corejs2: false, + closure: false, + es6tr: true, + jsx: true, + typescript1corejs2: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome45: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'lexical "super" binding in methods', + exec() { + /* + class B { + qux() { + return "quux"; + } + } + class C extends B { + baz() { + return x => super.qux(); + } + } + var arrow = new C().baz(); + return arrow() === "quux"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome45: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'lexical "new.target" binding', + exec() { + /* + function C() { + return x => new.target; + } + return new C()() === C && C()() === void undefined; + */ + }, + res: { + firefox2: false, + firefox41: true, + opera10_50: false, + chrome46: true, + ie11: false, + edge13: true, + node5: true, + xs6: true, + safari10: true, + duktape2_0: false, + duktape2_2: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'const', + category: 'bindings', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-let-and-const-declarations', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const', + subtests: [ + { + name: 'basic support', + exec() { + /* + const foo = 123; + return (foo === 123); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox3: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_4: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'is block-scoped', + exec() { + /* + const bar = 123; + { const bar = 456; } + return bar === 123; + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'scope shadow resolution', + exec() { + /* + try { + { const bar = 456; } + const bar = 123; + return bar === 123; + } catch(e) { + return false; + } + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox36: true, + chrome48: 'flagged', + chrome49: true, + node6: true, + node6_5: true, + safari10: false, + safari10_1: false, + safari11: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'cannot be in statements', + exec() { + /* + const bar = 1; + try { + Function("if(true) const baz = 1;")(); + } catch(e) { + return true; + } + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'redefining a const is an error', + exec() { + /* + const baz = 1; + try { + Function("const foo = 1; foo = 2;")(); + } catch(e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + closure: true, + ie11: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'for loop statement scope', + exec() { + /* + const baz = 1; + for(const baz = 0; false;) {} + return baz === 1; + */ + }, + res: { + tr: true, + ejs: true, + es6tr: true, + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox36: true, + opera10_50: false, + safari10: true, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'for-in loop iteration scope', + exec() { + /* + var scopes = []; + for(const i in { a:1, b:1 }) { + scopes.push(function(){ return i; }); + } + return (scopes[0]() === "a" && scopes[1]() === "b"); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + safari10: true, + ie11: false, + edge14: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'for-of loop iteration scope', + exec() { + /* + var scopes = []; + for(const i of ['a','b']) { + scopes.push(function(){ return i; }); + } + return (scopes[0]() === "a" && scopes[1]() === "b"); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + safari10: true, + ie11: false, + edge14: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'temporal dead zone', + exec() { + /* + var passed = (function(){ try { qux; } catch(e) { return true; }}()); + function fn() { passed &= qux === 456; } + const qux = 456; + fn(); + return passed; + */ + }, + res: { + babel6corejs2: babel.optional, + ie11: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + hermes0_12_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'basic support (strict mode)', + exec() { + /* + "use strict"; + const foo = 123; + return (foo === 123); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox3: true, + chrome5: chrome.experimental, + chrome41: true, + safari3_1: true, + safari5_1: false, + safari10: true, + opera10_50: true, + konq4_14: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'is block-scoped (strict mode)', + exec() { + /* + 'use strict'; + const bar = 123; + { const bar = 456; } + return bar === 123; + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + tr: true, + ejs: true, + closure: true, + chrome19: chrome.experimental, + chrome41: true, + ie11: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'scope shadow resolution (strict mode)', + exec() { + /* + 'use strict'; + try { + { const bar = 456; } + const bar = 123; + return bar === 123; + } catch(e) { + return false; + } + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + tr: true, + ejs: true, + closure: true, + chrome19: 'flagged', + chrome41: true, + ie11: true, + firefox2: false, + firefox36: true, + safari10: false, + safari10_1: false, + safari11: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'cannot be in statements (strict mode)', + exec() { + /* + 'use strict'; + const bar = 1; + try { + Function("'use strict'; if(true) const baz = 1;")(); + } catch(e) { + return true; + } + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + tr: true, + ejs: true, + closure: true, + chrome19: chrome.experimental, + chrome41: true, + ie11: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'redefining a const (strict mode)', + exec() { + /* + 'use strict'; + const baz = 1; + try { + Function("'use strict'; const foo = 1; foo = 2;")(); + } catch(e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + closure: true, + ie11: true, + firefox2: false, + firefox7: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome41: true, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'for loop statement scope (strict mode)', + exec() { + /* + 'use strict'; + const baz = 1; + for(const baz = 0; false;) {} + return baz === 1; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox36: true, + opera10_50: false, + chrome19: chrome.experimental, + chrome41: true, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'for-in loop iteration scope (strict mode)', + exec() { + /* + 'use strict'; + var scopes = []; + for(const i in { a:1, b:1 }) { + scopes.push(function(){ return i; }); + } + return (scopes[0]() === "a" && scopes[1]() === "b"); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + chrome40: chrome.experimental, + chrome41: true, + safari10: true, + ie11: false, + edge14: true, + firefox2: false, + firefox51: true, + opera10_50: false, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'for-of loop iteration scope (strict mode)', + exec() { + /* + 'use strict'; + var scopes = []; + for(const i of ['a','b']) { + scopes.push(function(){ return i; }); + } + return (scopes[0]() === "a" && scopes[1]() === "b"); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + safari10: true, + ie11: false, + edge14: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome40: chrome.experimental, + chrome41: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'temporal dead zone (strict mode)', + exec() { + /* + 'use strict'; + var passed = (function(){ try { qux; } catch(e) { return true; }}()); + function fn() { passed &= qux === 456; } + const qux = 456; + fn(); + return passed; + */ + }, + res: { + babel6corejs2: babel.optional, + ie11: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome19: chrome.experimental, + chrome41: true, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + hermes0_12_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'let', + category: 'bindings', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-let-and-const-declarations', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let', + subtests: [ + { + name: 'basic support', + exec() { + /* + let foo = 123; + return (foo === 123); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { + val: 'flagged', + note_id: 'fx-let', + note_html: + 'Available for code in a <script type="application/javascript;version=1.7"> (or version=1.8) tag.', + }, + firefox44: true, + opera10_50: false, + safari10: true, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'is block-scoped', + exec() { + /* + let bar = 123; + { let bar = 456; } + return bar === 123; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + opera10_50: false, + safari10: true, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'scope shadow resolution', + exec() { + /* + try { + { let bar = 456; } + let bar = 123; + return bar === 123; + } catch(e) { + return false; + } + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + safari10: false, + safari10_1: false, + safari11: true, + chrome48: 'flagged', + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'cannot be in statements', + exec() { + /* + let bar = 1; + try { + Function("if(true) let baz = 1;")(); + } catch(e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + opera10_50: false, + safari10: true, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'for loop statement scope', + exec() { + /* + let baz = 1; + for(let baz = 0; false;) {} + return baz === 1; + */ + }, + res: { + tr: true, + ejs: true, + es6tr: true, + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + opera10_50: false, + safari10: true, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'temporal dead zone', + exec() { + /* + var passed = (function(){ try { qux; } catch(e) { return true; }}()); + function fn() { passed &= qux === 456; } + let qux = 456; + fn(); + return passed; + */ + }, + res: { + babel6corejs2: babel.optional, + ie11: true, + firefox2: false, + firefox35: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + opera10_50: false, + safari10: true, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + hermes0_12_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'for/for-in loop iteration scope', + exec() { + /* + let scopes = []; + for(let i = 0; i < 2; i++) { + scopes.push(function(){ return i; }); + } + let passed = (scopes[0]() === 0 && scopes[1]() === 1); + + scopes = []; + for(let i in { a:1, b:1 }) { + scopes.push(function(){ return i; }); + } + passed &= (scopes[0]() === "a" && scopes[1]() === "b"); + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + safari10: true, + ie11: false, + edge14: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'for-in loop binding shadowing parameter', + exec() { + /* + try { + Function("function f(e) { for (let e in {}) e }"); + return true; + } catch(e) { + return false; + } + */ + }, + res: { + closure: true, + ie11: true, + edge14: true, + firefox2: false, + firefox3: false, + firefox3_6: false, + firefox4: true, + firefox5: true, + firefox10: true, + firefox20: true, + firefox30: true, + firefox40: true, + firefox44: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + safari10_1: false, + safari11: true, + node6: true, + duktape2_0: false, + jerryscript2_2_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'basic support (strict mode)', + exec() { + /* + 'use strict'; + let foo = 123; + return (foo === 123); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + chrome19: chrome.experimental, + chrome41: true, + node0_12: 'flagged', + node4: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + opera10_50: false, + safari10: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'is block-scoped (strict mode)', + exec() { + /* + 'use strict'; + let bar = 123; + { let bar = 456; } + return bar === 123; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + opera10_50: false, + chrome19: chrome.experimental, + chrome41: true, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'scope shadow resolution (strict mode)', + exec() { + /* + 'use strict'; + try { + { let bar = 456; } + let bar = 123; + return bar === 123; + } catch(e) { + return false; + } + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + chrome19: 'flagged', + chrome41: true, + safari10: false, + safari10_1: false, + safari11: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'cannot be in statements (strict mode)', + exec() { + /* + 'use strict'; + let bar = 1; + try { + Function("'use strict'; if(true) let baz = 1;")(); + } catch(e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + opera10_50: false, + safari10: true, + chrome19: chrome.experimental, + chrome41: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'for loop statement scope (strict mode)', + exec() { + /* + 'use strict'; + let baz = 1; + for(let baz = 0; false;) {} + return baz === 1; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + closure: true, + ie11: true, + firefox2: false, + firefox4: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + opera10_50: false, + chrome19: chrome.experimental, + chrome41: true, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'temporal dead zone (strict mode)', + exec() { + /* + 'use strict'; + var passed = (function(){ try { qux; } catch(e) { return true; }}()); + function fn() { passed &= qux === 456; } + let qux = 456; + fn(); + return passed; + */ + }, + res: { + babel6corejs2: babel.optional, + ie11: true, + firefox2: false, + firefox35: { val: 'flagged', note_id: 'fx-let' }, + firefox44: true, + opera10_50: false, + chrome19: chrome.experimental, + chrome41: true, + safari10: true, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + hermes0_12_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'for/for-in loop iteration scope (strict mode)', + exec() { + /* + 'use strict'; + let scopes = []; + for(let i = 0; i < 2; i++) { + scopes.push(function(){ return i; }); + } + let passed = (scopes[0]() === 0 && scopes[1]() === 1); + + scopes = []; + for(let i in { a:1, b:1 }) { + scopes.push(function(){ return i; }); + } + passed &= (scopes[0]() === "a" && scopes[1]() === "b"); + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + chrome37: chrome.experimental, + chrome41: true, + safari10: true, + ie11: false, + edge14: true, + firefox2: false, + firefox51: true, + opera10_50: false, + node0_12: 'flagged', + node4: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'for-in loop binding shadowing parameter (strict mode)', + exec() { + /* + try { + Function("'use strict'; function f(e) { for (let e in {}) e }"); + return true; + } catch(e) { + return false; + } + */ + }, + res: { + closure: true, + ie11: true, + edge14: true, + firefox2: false, + firefox3: false, + firefox3_6: false, + firefox4: true, + firefox5: true, + firefox10: true, + firefox20: true, + firefox30: true, + firefox40: true, + firefox44: true, + opera10_50: false, + chrome41: true, + safari10_1: false, + safari11: true, + node0_12: 'flagged', + node4: true, + duktape2_0: false, + jerryscript2_2_0: true, + graalvm19: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'default function parameters', + category: 'syntax', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-functiondeclarationinstantiation', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + return (function (a = 1, b = 2) { return a === 3 && b === 2; }(3)); + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + ejs: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox15: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + safari10: true, + ie11: false, + edge12: edge.experimental, + edge14: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'explicit undefined defers to the default', + exec() { + /* + return (function (a = 1, b = 2) { return a === 1 && b === 3; }(undefined, 3)); + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + ejs: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox18: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + safari10: true, + ie11: false, + edge12: edge.experimental, + edge14: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'defaults can refer to previous params', + exec() { + /* + return (function (a, b = a) { return b === 5; }(5)); + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + ejs: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox15: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + safari10: true, + ie11: false, + edge12: edge.experimental, + edge14: true, + xs6: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'arguments object interaction', + exec() { + /* + return (function (a = "baz", b = "qux", c = "quux") { + a = "corge"; + // The arguments object is not mapped to the + // parameters, even outside of strict mode. + return arguments.length === 2 + && arguments[0] === "foo" + && arguments[1] === "bar"; + }("foo", "bar")); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + safari10: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox43: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'temporal dead zone', + exec() { + /* + return (function(x = 1) { + try { + eval("(function(a=a){}())"); + return false; + } catch(e) {} + try { + eval("(function(a=b,b){}())"); + return false; + } catch(e) {} + return true; + }()); + */ + }, + res: { + babel6corejs2: false, + closure: true, + typescript1corejs2: true, + safari10: true, + ie11: false, + edge12: edge.experimental, + edge14: true, + firefox2: false, + firefox51: true, + opera10_50: false, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'separate scope', + exec() { + /* + return (function(a=function(){ + return typeof b === 'undefined'; + }){ + var b = 1; + return a(); + }()); + */ + }, + res: { + babel6corejs2: false, + closure: true, + safari10: true, + ie11: false, + edge12: edge.experimental, + edge14: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'new Function() support', + exec() { + /* + return new Function("a = 1", "b = 2", + "return a === 3 && b === 2;" + )(3); + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + safari10: true, + chrome48: chrome.experimental, + chrome49: true, + node6: true, + node6_5: true, + ie11: false, + edge12: edge.experimental, + edge14: true, + firefox2: false, + firefox53: true, + opera10_50: false, + xs6: true, + ejs: { val: false, note_id: 'ejs-no-function-ctor' }, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + jerryscript2_2_0: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'rest parameters', + category: 'syntax', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + return (function (foo, ...args) { + return args instanceof Array && args + "" === "bar,baz"; + }("foo", "bar", "baz")); + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + ejs: true, + closure: true, + jsx: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox15: true, + opera10_50: false, + chrome44: chrome.experimental, + chrome47: true, + node4: 'flagged', + node6: true, + node6_5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: "function 'length' property", + exec() { + /* + return function(a, ...b){}.length === 1 && function(...c){}.length === 0; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + closure20211107: true, + jsx: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox15: true, + opera10_50: false, + chrome44: chrome.experimental, + chrome47: true, + node4: 'flagged', + node6: true, + node6_5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'arguments object interaction', + exec() { + /* + return (function (foo, ...args) { + foo = "qux"; + // The arguments object is not mapped to the + // parameters, even outside of strict mode. + return arguments.length === 3 + && arguments[0] === "foo" + && arguments[1] === "bar" + && arguments[2] === "baz"; + }("foo", "bar", "baz")); + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + tr: true, + ejs: true, + chrome44: chrome.experimental, + chrome47: true, + ie11: false, + edge12: true, + node4: 'flagged', + node6: true, + node6_5: true, + firefox2: false, + firefox43: true, + opera10_50: false, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: "can't be used in setters", + exec() { + /* + return (function (...args) { + try { + eval("({set e(...args){}})"); + } catch(e) { + return true; + } + }()); + */ + }, + res: { + babel6corejs2: false, + tr: true, + ejs: true, + closure: true, + jsx: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + chrome47: true, + node4: 'flagged', + node6: true, + node6_5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'new Function() support', + exec() { + /* + return new Function("a", "...b", + "return b instanceof Array && a+b === 'foobar,baz';" + )('foo','bar','baz'); + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox15: true, + opera10_50: false, + chrome44: chrome.experimental, + chrome47: true, + node4: 'flagged', + node6: true, + node6_5: true, + xs6: true, + ejs: { val: false, note_id: 'ejs-no-function-ctor' }, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'spread syntax for iterable objects', + category: 'syntax', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-argument-lists-runtime-semantics-argumentlistevaluation', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator', + subtests: [ + { + name: 'with arrays, in function calls', + exec() { + /* + return Math.max(...[1, 2, 3]) === 3 + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox27: true, + opera10_50: false, + safari7_1: true, + chrome44: chrome.experimental, + chrome46: true, + node4: 'flagged', + node5: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with arrays, in array literals', + exec() { + /* + return [...[1, 2, 3]][2] === 3; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox16: true, + opera10_50: false, + safari7_1: true, + chrome46: true, + node4: 'flagged', + node5: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with sparse arrays, in function calls', + exec() { + /* + var a = Array(...[,,]); + return "0" in a && "1" in a && '' + a[0] + a[1] === "undefinedundefined"; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox27: true, + opera10_50: false, + safari7_1: true, + chrome44: chrome.experimental, + chrome46: true, + node4: 'flagged', + node5: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with sparse arrays, in array literals', + exec() { + /* + var a = [...[,,]]; + return "0" in a && "1" in a && '' + a[0] + a[1] === "undefinedundefined"; + */ + }, + res: { + tr: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox16: true, + opera10_50: false, + safari7_1: true, + chrome46: true, + node4: 'flagged', + node5: true, + ie11: false, + edge13: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with strings, in function calls', + exec() { + /* + return Math.max(..."1234") === 4; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome44: chrome.experimental, + chrome46: true, + node4: 'flagged', + node5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with strings, in array literals', + exec() { + /* + return ["a", ..."bcd", "e"][3] === "d"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox17: true, + opera10_50: false, + safari9: true, + chrome46: true, + node4: 'flagged', + node5: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with astral plane strings, in function calls', + exec() { + /* + return Array(..."𠮷𠮶")[0] === "𠮷"; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome44: chrome.experimental, + chrome46: true, + ie11: false, + edge12: true, + node4: 'flagged', + node5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with astral plane strings, in array literals', + exec() { + /* + return [..."𠮷𠮶"][0] === "𠮷"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox27: true, + opera10_50: false, + safari9: true, + ie11: false, + edge12: true, + chrome46: true, + node4: 'flagged', + node5: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generator instances, in calls', + exec() { + /* + var iterable = (function*(){ yield 1; yield 2; yield 3; }()); + return Math.max(...iterable) === 3; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + ejs: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome44: chrome.experimental, + chrome46: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + node4: 'flagged', + node5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generator instances, in arrays', + exec() { + /* + var iterable = (function*(){ yield "b"; yield "c"; yield "d"; }()); + return ["a", ...iterable, "e"][3] === "d"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome46: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + node4: 'flagged', + node5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generic iterables, in calls', + exec() { + /* + var iterable = global.__createIterableObject([1, 2, 3]); + return Math.max(...iterable) === 3; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + es6tr: { + val: true, + note_id: 'compiler-iterable', + note_html: + 'This compiler requires generic iterables have either a Symbol.iterator or non-standard "@@iterator" method.', + }, + ejs: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome44: chrome.experimental, + chrome46: true, + ie11: false, + edge12: true, + node4: 'flagged', + node5: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generic iterables, in arrays', + exec() { + /* + var iterable = global.__createIterableObject(["b", "c", "d"]); + return ["a", ...iterable, "e"][3] === "d"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + es6tr: { val: true, note_id: 'compiler-iterable' }, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome46: true, + node4: 'flagged', + node5: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with instances of iterables, in calls', + exec() { + /* + var iterable = global.__createIterableObject([1, 2, 3]); + return Math.max(...Object.create(iterable)) === 3; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + ejs: true, + es6tr: { val: true, note_id: 'compiler-iterable' }, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome44: chrome.experimental, + chrome46: true, + ie11: false, + edge12: true, + node4: 'flagged', + node5: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with instances of iterables, in arrays', + exec() { + /* + var iterable = global.__createIterableObject(["b", "c", "d"]); + return ["a", ...Object.create(iterable), "e"][3] === "d"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + ejs: true, + es6tr: { val: true, note_id: 'compiler-iterable' }, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome46: true, + safari9: true, + node4: 'flagged', + node5: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'spreading non-iterables is a runtime error', + exec() { + /* + try { + Math.max(...2); + } catch(e) { + return Math.max(...[1, 2, 3]) === 3; + } + */ + }, + res: { + tr: true, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.notDownlevelIteration, + closure20230228: true, + es6tr: true, + ie11: false, + edge12: true, + firefox2: false, + firefox27: true, + opera10_50: false, + safari7_1: true, + chrome44: chrome.experimental, + chrome46: true, + node4: 'flagged', + node5: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'class', + category: 'functions', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-class-definitions', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes', + subtests: [ + { + name: 'class statement', + exec() { + /* + class C {} + return typeof C === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + ejs: true, + jsx: true, + closure: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + typescript1corejs2: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'is block-scoped', + exec() { + /* + class C {} + var c1 = C; + { + class C {} + var c2 = C; + } + return C === c1; + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + jsx: true, + closure: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'class expression', + exec() { + /* + return typeof class C {} === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + closure: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'anonymous class', + exec() { + /* + return typeof class {} === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + closure: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'constructor', + exec() { + /* + class C { + constructor() { this.x = 1; } + } + return C.prototype.constructor === C + && new C().x === 1; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'prototype methods', + exec() { + /* + class C { + method() { return 2; } + } + return typeof C.prototype.method === "function" + && new C().method() === 2; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'string-keyed methods', + exec() { + /* + class C { + "foo bar"() { return 2; } + } + return typeof C.prototype["foo bar"] === "function" + && new C()["foo bar"]() === 2; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + ejs: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed prototype methods', + exec() { + /* + var foo = "method"; + class C { + [foo]() { return 2; } + } + return typeof C.prototype.method === "function" + && new C().method() === 2; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome45: 'strict', + chrome49: true, + node4: 'strict', + safari10: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'optional semicolons', + exec() { + /* + class C { + ; + method() { return 2; }; + method2() { return 2; } + method3() { return 2; }; + } + return typeof C.prototype.method === "function" + && typeof C.prototype.method2 === "function" + && typeof C.prototype.method3 === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'static methods', + exec() { + /* + class C { + static method() { return 3; } + } + return typeof C.method === "function" + && C.method() === 3; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed static methods', + exec() { + /* + var foo = "method"; + class C { + static [foo]() { return 3; } + } + return typeof C.method === "function" + && C.method() === 3; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome45: 'strict', + chrome49: true, + node4: 'strict', + safari10: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'accessor properties', + exec() { + /* + var baz = false; + class C { + get foo() { return "foo"; } + set bar(x) { baz = x; } + } + new C().bar = true; + return new C().foo === "foo" && baz; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + jsx: true, + es6tr: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed accessor properties', + exec() { + /* + var garply = "foo", grault = "bar", baz = false; + class C { + get [garply]() { return "foo"; } + set [grault](x) { baz = x; } + } + new C().bar = true; + return new C().foo === "foo" && baz; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome45: 'strict', + chrome49: true, + node4: 'strict', + safari10: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'static accessor properties', + exec() { + /* + var baz = false; + class C { + static get foo() { return "foo"; } + static set bar(x) { baz = x; } + } + C.bar = true; + return C.foo === "foo" && baz; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + jsx: true, + es6tr: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed static accessor properties', + exec() { + /* + var garply = "foo", grault = "bar", baz = false; + class C { + static get [garply]() { return "foo"; } + static set [grault](x) { baz = x; } + } + C.bar = true; + return C.foo === "foo" && baz; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure20200112: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome45: 'strict', + chrome49: true, + node4: 'strict', + safari10: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'class name is lexically scoped', + exec() { + /* + class C { + method() { return typeof C === "function"; } + } + var M = C.prototype.method; + C = void undefined; + return C === void undefined && M(); + */ + }, + res: { + tr: true, + babel6corejs2: true, + ejs: true, + typescript1corejs2: true, + es6tr: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari10: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed names, temporal dead zone', + exec() { + /* + try { + var B = class C { + [C](){} + } + } catch(e) { + return true; + } + */ + }, + res: { + typescript1corejs2: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome45: 'strict', + chrome49: true, + node4: 'strict', + safari10: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + hermes0_12_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: "methods aren't enumerable", + exec() { + /* + class C { + foo() {} + static bar() {} + } + return !C.prototype.propertyIsEnumerable("foo") && !C.propertyIsEnumerable("bar"); + */ + }, + res: { + babel6corejs2: true, + ejs: true, + jsx: true, + chrome42: 'strict', + chrome49: true, + safari9: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'implicit strict mode', + exec() { + /* + class C { + static method() { return this === void undefined; } + } + return (0,C.method)(); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'constructor requires new', + exec() { + /* + class C {} + try { + C(); + } + catch(e) { + return true; + } + */ + }, + res: { + babel6corejs2: true, + safari9: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'extends', + exec() { + /* + class B {} + class C extends B {} + return new C() instanceof B + && B.isPrototypeOf(C); + */ + }, + res: { + es6tr: { + val: false, + note_id: 'compiler-proto', + note_html: 'Requires native support for Object.prototype.__proto__', + }, + babel6corejs2: { val: false, note_id: 'compiler-proto' }, + tr: { val: false, note_id: 'compiler-proto' }, + typescript1corejs2: { + val: false, + note_id: 'typescript-extends', + note_html: + 'TypeScript transforms extends into code that copies static properties from the superclass (but uses the prototype chain for instance properties).', + }, + ejs: true, + closure: { + val: false, + note_id: 'compiled-extends', + note_html: + 'This compiler transforms extends into code that uses native Object.prototype.__proto__ or copies properties from the superclass, instead of using the prototype chain.', + }, + jsx: { val: false, note_id: 'compiled-extends' }, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'extends expressions', + exec() { + /* + var B; + class C extends (B = class {}) {} + return new C() instanceof B + && B.isPrototypeOf(C); + */ + }, + res: { + es6tr: { val: false, note_id: 'compiler-proto' }, + babel6corejs2: { val: false, note_id: 'compiler-proto' }, + tr: { val: false, note_id: 'compiler-proto' }, + typescript1corejs2: { + val: false, + note_id: 'typescript-extends', + }, + closure20180910: { + val: false, + note_id: 'compiled-extends', + }, + ejs: true, + jsx: { val: false, note_id: 'compiled-extends' }, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'extends null', + exec() { + /* + class C extends null { + constructor() { return Object.create(null); } + } + return Function.prototype.isPrototypeOf(C) + && Object.getPrototypeOf(C.prototype) === null; + */ + }, + res: { + babel6corejs2: false, + typescript1corejs2: true, + tr: true, + es6tr: true, + jsx: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'new.target', + exec() { + /* + var passed = false; + new function f() { + passed = new.target === f; + }(); + + class A { + constructor() { + passed &= new.target === B; + } + } + class B extends A {} + new B(); + return passed; + */ + }, + res: { + safari10: true, + chrome46: 'strict', + chrome49: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node5: 'strict', + xs6: true, + ejs: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'super', + category: 'functions', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-super-keyword', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super', + subtests: [ + { + name: 'statement in constructors', + exec() { + /* + var passed = false; + class B { + constructor(a) { passed = (a === "barbaz"); } + } + class C extends B { + constructor(a) { super("bar" + a); } + } + new C("baz"); + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: false, + jsx: true, + typescript1corejs2: true, + closure: true, + es6tr: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'expression in constructors', + exec() { + /* + class B { + constructor(a) { return ["foo" + a]; } + } + class C extends B { + constructor(a) { return super("bar" + a); } + } + return new C("baz")[0] === "foobarbaz"; + */ + }, + res: { + tr: true, + babel6corejs2: false, + jsx: true, + typescript1corejs2: true, + closure: true, + es6tr: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari10: true, + safari9: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'in methods, property access', + exec() { + /* + class B {} + B.prototype.qux = "foo"; + B.prototype.corge = "baz"; + class C extends B { + quux(a) { return super.qux + a + super["corge"]; } + } + C.prototype.qux = "garply"; + return new C().quux("bar") === "foobarbaz"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + jsx: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'in methods, method calls', + exec() { + /* + class B { + qux(a) { return "foo" + a; } + } + class C extends B { + qux(a) { return super.qux("bar" + a); } + } + return new C().qux("baz") === "foobarbaz"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + jsx: true, + typescript1corejs2: true, + closure: true, + es6tr: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'method calls use correct "this" binding', + exec() { + /* + class B { + qux(a) { return this.foo + a; } + } + class C extends B { + qux(a) { return super.qux("bar" + a); } + } + var obj = new C(); + obj.foo = "foo"; + return obj.qux("baz") === "foobarbaz"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + jsx: true, + typescript1corejs2: true, + closure: true, + es6tr: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'constructor calls use correct "new.target" binding', + exec() { + /* + var passed; + class B { + constructor() { passed = (new.target === C); } + } + class C extends B { + constructor() { super(); } + } + new C(); + return passed; + */ + }, + res: { + safari10: true, + chrome46: 'strict', + chrome49: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node5: 'strict', + xs6: true, + ejs: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'is statically bound', + exec() { + /* + class B { + qux() { return "bar"; } + } + class C extends B { + qux() { return super.qux() + this.corge; } + } + var obj = { + qux: C.prototype.qux, + corge: "ley" + }; + return obj.qux() === "barley"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure20180506: true, + jsx: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'super() invokes the correct constructor', + exec() { + /* + // checks that super() is *not* a synonym of super.constructor() + var passed; + class B { + constructor() { + passed = true; + } + }; + B.prototype.constructor = function () { + passed = false; + }; + class C extends B { }; + new C; + return passed; + */ + }, + res: { + closure: true, + node4: 'strict', + chrome41: 'strict', + chrome49: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + tr: true, + ejs: true, + jsx: true, + es6tr: true, + typescript1corejs2: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'object literal extensions', + category: 'syntax', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-object-initialiser', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#New_notations_in_ECMAScript_2015', + subtests: [ + { + name: 'computed properties', + exec() { + /* + var x = 'y'; + return ({ [x]: 1 }).y === 1; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + jsx: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + safari7_1: true, + opera10_50: false, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'shorthand properties', + exec() { + /* + var a = 7, b = 8, c = {a,b}; + return c.a === 7 && c.b === 8; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox33: true, + opera10_50: false, + chrome41: chrome.experimental, + chrome43: true, + node4: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'shorthand methods', + exec() { + /* + return ({ y() { return 2; } }).y() === 2; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: { + val: true, + note_id: 'ff-shorthand-methods', + note_html: + 'Firefox incorrectly produces an error in strict mode if the method is named "arguments", "eval", or "delete".', + }, + opera10_50: false, + chrome41: chrome.experimental, + chrome43: true, + node4: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'string-keyed shorthand methods', + exec() { + /* + return ({ "foo bar"() { return 4; } })["foo bar"]() === 4; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + es6tr: true, + jsx: true, + ejs: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome41: chrome.experimental, + chrome43: true, + node4: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'computed shorthand methods', + exec() { + /* + var x = 'y'; + return ({ [x](){ return 1 } }).y() === 1; + */ + }, + res: { + ie11: false, + edge12: true, + tr: true, + closure: true, + babel6corejs2: true, + ejs: true, + typescript1corejs2: true, + jsx: true, + es6tr: true, + firefox2: false, + firefox34: true, + opera10_50: false, + safari9: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed accessors', + exec() { + /* + var x = 'y', + valueSet, + obj = { + get [x] () { return 1 }, + set [x] (value) { valueSet = value } + }; + obj.y = 'foo'; + return obj.y === 1 && valueSet === 'foo'; + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + tr: true, + es6tr: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome44: true, + node4: true, + safari10: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'non-strict function semantics', + note_id: 'hoisted-block-functions', + note_html: + 'The 2015 version of the specification contains multiple bugs for hoisted block-level function declaration semantics, which these tests disregard.', + category: 'annex b', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-labelled-function-declarations', + subtests: [ + { + name: 'hoisted block-level function declaration', + exec() { + /* + // Note: only available outside of strict mode. + if (!this) return false; + var passed = f() === 1; + function f() { return 1; } + + passed &= typeof g === 'undefined'; + { function g() { return 1; } } + passed &= g() === 1; + + passed &= h() === 2; + { function h() { return 1; } } + function h() { return 2; } + passed &= h() === 1; + + return passed; + */ + }, + res: { + ie11: true, + firefox2: false, + firefox3_5: true, + rhino1_7_13: true, + chrome49: true, + jxa: true, + safari10: true, + opera10_50: false, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + { + name: 'labeled function statements', + exec() { + /* + // Note: only available outside of strict mode. + if (!this) return false; + + label: function foo() { return 2; } + return foo() === 2; + */ + }, + res: { + ie10: true, + firefox2: true, + chrome5: true, + safari4: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + { + name: 'function statements in if-statement clauses', + exec() { + /* + // Note: only available outside of strict mode. + if (!this) return false; + + if(true) function foo() { return 2; } + if(false) {} else function bar() { return 3; } + if(true) function baz() { return 4; } else {} + if(false) function qux() { return 5; } else function qux() { return 6; } + return foo() === 2 && bar() === 3 && baz() === 4 && qux() === 6; + */ + }, + res: { + ie10: true, + firefox2: true, + chrome5: true, + safari4: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + ], + }, + { + name: '__proto__ in object literals', + category: 'annex b', + significance: 'tiny', + note_id: 'proto-in-object-literals', + note_html: + 'Note that this is distinct from the existence or functionality of Object.prototype.__proto__.', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-__proto__-property-names-in-object-initializers', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto#Specifications', + subtests: [ + { + name: 'basic support', + exec() { + /* + return { __proto__ : [] } instanceof Array + && !({ __proto__ : null } instanceof Object); + */ + }, + res: { + ie11: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: false, + opera12_10: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'multiple __proto__ is an error', + exec() { + /* + try { + eval("({ __proto__ : [], __proto__: {} })"); + } + catch(e) { + return true; + } + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome42: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'not a computed property', + exec() { + /* + if (!({ __proto__ : [] } instanceof Array)) { + return false; + } + var a = "__proto__"; + return !({ [a] : [] } instanceof Array); + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + safari7_1: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'not a shorthand property', + exec() { + /* + if (!({ __proto__ : [] } instanceof Array)) { + return false; + } + var __proto__ = []; + return !({ __proto__ } instanceof Array); + */ + }, + res: { + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome42: true, + node4: true, + ie11: false, + edge13: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'not a shorthand method', + exec() { + /* + if (!({ __proto__ : [] } instanceof Array)) { + return false; + } + return !({ __proto__(){} } instanceof Function); + */ + }, + res: { + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome42: true, + node4: true, + ie11: false, + edge13: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'for..of loops', + category: 'syntax', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of', + subtests: [ + { + name: 'with arrays', + exec() { + /* + var arr = [5]; + for (var item of arr) + return item === 5; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + ejs: true, + jsx: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with sparse arrays', + exec() { + /* + var arr = [,,]; + var count = 0; + for (var item of arr) + count += (item === void undefined); + return count === 2; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + ejs: true, + jsx: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with strings', + exec() { + /* + var str = ""; + for (var item of "foo") + str += item; + return str === "foo"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + ejs: true, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox17: true, + opera10_50: false, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with astral plane strings', + exec() { + /* + var str = ""; + for (var item of "𠮷𠮶") + str += item + " "; + return str === "𠮷 𠮶 "; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with generator instances', + exec() { + /* + var result = ""; + var iterable = (function*(){ yield 1; yield 2; yield 3; }()); + for (var item of iterable) { + result += item; + } + return result === "123"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with generic iterables', + exec() { + /* + var result = ""; + var iterable = global.__createIterableObject([1, 2, 3]); + for (var item of iterable) { + result += item; + } + return result === "123"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.downlevelIteration, + es6tr: { val: true, note_id: 'compiler-iterable' }, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome21: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'with instances of generic iterables', + exec() { + /* + var result = ""; + var iterable = global.__createIterableObject([1, 2, 3]); + for (var item of Object.create(iterable)) { + result += item; + } + return result === "123"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + es6tr: { val: true, note_id: 'compiler-iterable' }, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome35: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'iterator closing, break', + exec() { + /* + var closed = false; + var iter = __createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + for (var it of iter) break; + return closed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + ie11: false, + edge15: true, + firefox2: false, + firefox53: true, + opera10_50: false, + safari9: true, + xs6: true, + chrome51: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'iterator closing, throw', + exec() { + /* + var closed = false; + var iter = __createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + try { + for (var it of iter) throw 0; + } catch(e){} + return closed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + ie11: false, + edge15: true, + firefox2: false, + firefox53: true, + opera10_50: false, + safari9: true, + xs6: true, + chrome51: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'generators', + category: 'functions', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + function * generator(){ + yield 5; yield 6; + }; + var iterator = generator(); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'generator function expressions', + exec() { + /* + var generator = function * (){ + yield 5; yield 6; + }; + var iterator = generator(); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'correct "this" binding', + exec() { + /* + function * generator(){ + yield this.x; yield this.y; + }; + var iterator = { g: generator, x: 5, y: 6 }.g(); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + closure20180319: false, + closure20180506: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'can\'t use "this" with new', + exec() { + /* + function * generator(){ + yield this.x; yield this.y; + }; + try { + (new generator()).next(); + } + catch (e) { + return true; + } + */ + }, + res: { + firefox2: false, + firefox43: true, + opera10_50: false, + chrome50: true, + node6: true, + node6_5: true, + ie11: false, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'sending', + exec() { + /* + var sent; + function * generator(){ + sent = [yield 5, yield 6]; + }; + var iterator = generator(); + iterator.next(); + iterator.next("foo"); + iterator.next("bar"); + return sent[0] === "foo" && sent[1] === "bar"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + ejs: true, + closure: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '%GeneratorPrototype%', + exec() { + /* + function * generatorFn(){} + var ownProto = Object.getPrototypeOf(generatorFn()); + var passed = ownProto === generatorFn.prototype; + + var sharedProto = Object.getPrototypeOf(ownProto); + passed &= sharedProto !== Object.prototype && + sharedProto === Object.getPrototypeOf(function*(){}.prototype) && + sharedProto.hasOwnProperty('next'); + + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '%GeneratorPrototype% prototype chain', + exec() { + /* + function * generatorFn(){} + var g = generatorFn(); + var ownProto = Object.getPrototypeOf(g); + var passed = ownProto === generatorFn.prototype; + + var sharedProto = Object.getPrototypeOf(ownProto); + var iterProto = Object.getPrototypeOf(sharedProto); + + passed &= iterProto.hasOwnProperty(Symbol.iterator) && + !sharedProto .hasOwnProperty(Symbol.iterator) && + !ownProto .hasOwnProperty(Symbol.iterator) && + g[Symbol.iterator]() === g; + + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome45: true, + node0_12: 'flagged', + node4: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '%GeneratorPrototype%.constructor', + exec() { + /* + function * g (){} + var iterator = new g.constructor("a","b","c","yield a; yield b; yield c;")(5,6,7); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === 7 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + + passed &= g.constructor === (function*(){}).constructor; + return passed; + */ + }, + res: { + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '%GeneratorPrototype%.throw', + exec() { + /* + var passed = false; + function * generator(){ + try { + yield 5; yield 6; + } catch(e) { + passed = (e === "foo"); + } + }; + var iterator = generator(); + iterator.next(); + iterator.throw("foo"); + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '%GeneratorPrototype%.return', + exec() { + /* + function * generator(){ + yield 5; yield 6; + }; + var iterator = generator(); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.return("quxquux"); + passed &= item.value === "quxquux" && item.done === true; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure20180319: true, + firefox2: false, + firefox38: true, + opera10_50: false, + ie11: false, + edge12: edge.experimental, + edge13: true, + chrome50: true, + node6: true, + node6_5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'yield operator precedence', + exec() { + /* + var passed; + function * generator(){ + passed = yield 0 ? true : false; + }; + var iterator = generator(); + iterator.next(); + iterator.next(true); + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'yield *, arrays', + exec() { + /* + var iterator = (function * generator() { + yield * [5, 6]; + }()); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome38: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'yield *, sparse arrays', + exec() { + /* + var iterator = (function * generator() { + yield * [,,]; + }()); + var item = iterator.next(); + var passed = item.value === void undefined && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome38: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'yield *, strings', + exec() { + /* + var iterator = (function * generator() { + yield * "56"; + }()); + var item = iterator.next(); + var passed = item.value === "5" && item.done === false; + item = iterator.next(); + passed &= item.value === "6" && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + tr: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome38: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'yield *, astral plane strings', + exec() { + /* + var iterator = (function * generator() { + yield * "𠮷𠮶"; + }()); + var item = iterator.next(); + var passed = item.value === "𠮷" && item.done === false; + item = iterator.next(); + passed &= item.value === "𠮶" && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + ejs: true, + tr: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome38: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'yield *, generator instances', + exec() { + /* + var iterator = (function * generator() { + yield * (function*(){ yield 5; yield 6; yield 7; }()); + }()); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === 7 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + ejs: true, + closure: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'yield *, generic iterables', + exec() { + /* + var iterator = (function * generator() { + yield * global.__createIterableObject([5, 6, 7]); + }()); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === 7 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + ejs: true, + closure: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'yield *, instances of iterables', + exec() { + /* + var iterator = (function * generator() { + yield * Object.create(__createIterableObject([5, 6, 7])); + }()); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === 7 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome35: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'yield * on non-iterables is a runtime error', + exec() { + /* + var iterator = (function * generator() { + yield * [5]; + }()); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + iterator = (function * generator() { + yield * 5; + }()); + try { + iterator.next(); + } catch (e) { + return passed; + } + */ + }, + res: { + tr: true, + babel6corejs2: false, + typescript1corejs2: false, + closure20230228: true, + firefox2: false, + firefox27: true, + opera10_50: false, + chrome35: chrome.experimental, + chrome39: true, + node0_12: 'flagged', + node4: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'yield *, iterator closing', + exec() { + /* + var closed = ''; + var iter = __createIterableObject([1, 2, 3], { + 'return': function(){ + closed += 'a'; + return {done: true}; + } + }); + var gen = (function* generator(){ + try { + yield *iter; + } finally { + closed += 'b'; + } + })(); + gen.next(); + gen['return'](); + return closed === 'ab'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure20180319: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome50: true, + node6: true, + node6_5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'yield *, iterator closing via throw()', + exec() { + /* + var closed = false; + var iter = global.__createIterableObject([1, 2, 3], { + 'throw': undefined, + 'return': function() { + closed = true; + return {done: true}; + } + }); + var gen = (function*(){ + try { + yield *iter; + } catch(e){} + })(); + gen.next(); + gen['throw'](); + return closed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + ie11: false, + edge13: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome50: true, + node6: true, + node6_5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'shorthand generator methods', + exec() { + /* + var o = { + * generator() { + yield 5; yield 6; + } + }; + var iterator = o.generator(); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + chrome41: chrome.experimental, + chrome42: true, + firefox2: false, + firefox34: true, + opera10_50: false, + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'string-keyed shorthand generator methods', + exec() { + /* + var o = { + * "foo bar"() { + yield 5; yield 6; + } + }; + var iterator = o["foo bar"](); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + chrome41: chrome.experimental, + chrome42: true, + firefox2: false, + firefox34: true, + opera10_50: false, + node4: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed shorthand generators', + exec() { + /* + var garply = "generator"; + var o = { + * [garply] () { + yield 5; yield 6; + } + }; + var iterator = o.generator(); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + firefox2: false, + firefox34: true, + opera10_50: false, + ejs: true, + chrome44: true, + ie11: false, + edge12: edge.experimental, + node4: true, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'shorthand generator methods, classes', + exec() { + /* + class C { + * generator() { + yield 5; yield 6; + } + }; + var iterator = new C().generator(); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'computed shorthand generators, classes', + exec() { + /* + var garply = "generator"; + class C { + * [garply] () { + yield 5; yield 6; + } + } + var iterator = new C().generator(); + var item = iterator.next(); + var passed = item.value === 5 && item.done === false; + item = iterator.next(); + passed &= item.value === 6 && item.done === false; + item = iterator.next(); + passed &= item.value === void undefined && item.done === true; + return passed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + closure: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + chrome45: 'strict', + chrome49: true, + node4: 'strict', + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: "shorthand generators can't be constructors", + exec() { + /* + class C { + * generator() { + yield 5; yield 6; + } + }; + try { + Function("class D { * constructor() { return {}; } }"); + } catch(e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.regenerator, + typescript1corejs2: typescript.downlevelIteration, + chrome41: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'prototype of bound functions', + category: 'misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-boundfunctioncreate', + subtests: [ + { + name: 'basic functions', + exec() { + /* + function correctProtoBound(proto) { + var f = function(){}; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(f, proto); + } else { + f.__proto__ = proto; + } + var boundF = Function.prototype.bind.call(f, null); + return Object.getPrototypeOf(boundF) === proto; + } + return correctProtoBound(Function.prototype) + && correctProtoBound({}) + && correctProtoBound(null); + */ + }, + res: { + chrome46: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node5: true, + xs6: true, + ejs: true, + safari10: true, + jxa: true, + duktape1_0: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'generator functions', + exec() { + /* + function correctProtoBound(proto) { + var f = function*(){}; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(f, proto); + } else { + f.__proto__ = proto; + } + var boundF = Function.prototype.bind.call(f, null); + return Object.getPrototypeOf(boundF) === proto; + } + return correctProtoBound(Function.prototype) + && correctProtoBound({}) + && correctProtoBound(null); + */ + }, + res: { + chrome46: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node5: true, + xs6: true, + ejs: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'arrow functions', + exec() { + /* + function correctProtoBound(proto) { + var f = ()=>5; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(f, proto); + } else { + f.__proto__ = proto; + } + var boundF = Function.prototype.bind.call(f, null); + return Object.getPrototypeOf(boundF) === proto; + } + return correctProtoBound(Function.prototype) + && correctProtoBound({}) + && correctProtoBound(null); + */ + }, + res: { + chrome46: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node5: true, + xs6: true, + ejs: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'classes', + exec() { + /* + function correctProtoBound(proto) { + class C {} + if (Object.setPrototypeOf) { + Object.setPrototypeOf(C, proto); + } else { + C.__proto__ = proto; + } + var boundF = Function.prototype.bind.call(C, null); + return Object.getPrototypeOf(boundF) === proto; + } + return correctProtoBound(Function.prototype) + && correctProtoBound({}) + && correctProtoBound(null); + */ + }, + res: { + chrome46: 'strict', + chrome49: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node5: 'strict', + xs6: true, + ejs: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'subclasses', + exec() { + /* + function correctProtoBound(superclass) { + class C extends superclass { + constructor() { + return Object.create(null); + } + } + var boundF = Function.prototype.bind.call(C, null); + return Object.getPrototypeOf(boundF) === Object.getPrototypeOf(C); + } + return correctProtoBound(function(){}) + && correctProtoBound(Array) + && correctProtoBound(null); + */ + }, + res: { + chrome46: 'strict', + chrome49: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node5: 'strict', + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'octal and binary literals', + category: 'syntax', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-literals-numeric-literals', + subtests: [ + { + name: 'octal literals', + exec() { + /* + return 0o10 === 8 && 0O10 === 8; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + ejs: true, + closure: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'binary literals', + exec() { + /* + return 0b10 === 2 && 0B10 === 2; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + ejs: true, + closure: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'octal supported by Number()', + exec() { + /* + return Number('0o1') === 1; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'binary supported by Number()', + exec() { + /* + return Number('0b1') === 1; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'template literals', + category: 'syntax', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-template-literals', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + var a = "ba", b = "QUX"; + return `foo bar + ${a + "z"} ${b.toLowerCase()}` === "foo bar\nbaz qux"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome41: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'toString conversion', + exec() { + /* + var a = { + toString: function() { return "foo"; }, + valueOf: function() { return "bar"; } + }; + return `${a}` === "foo"; + */ + }, + res: { + ejs: true, + closure: false, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome41: true, + safari9: true, + node4: true, + ie11: false, + edge13: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'tagged template literals', + exec() { + /* + var called = false; + function fn(parts, a, b) { + called = true; + return parts instanceof Array && + parts[0] === "foo" && + parts[1] === "bar\n" && + parts.raw[0] === "foo" && + parts.raw[1] === "bar\\n" && + a === 123 && + b === 456; + } + return fn `foo${123}bar\n${456}` && called; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + closure20200315: false, + closure20200517: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome41: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'passed array is frozen', + exec() { + /* + return (function(parts) { + return Object.isFrozen(parts) && Object.isFrozen(parts.raw); + }) `foo${0}bar${0}baz`; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: true, + closure: false, + es6tr: true, + jsx: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome41: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'line break normalisation', + /* For some reason, this .fromCharCode stuff is necessary instead of \r\n. */ + exec() { + /* + var cr = eval("`x" + String.fromCharCode(13) + "y`"); + var lf = eval("`x" + String.fromCharCode(10) + "y`"); + var crlf = eval("`x" + String.fromCharCode(13,10) + "y`"); + + return cr.length === 3 && lf.length === 3 && crlf.length === 3 + && cr[1] === lf[1] && lf[1] === crlf[1] && crlf[1] === '\n'; + */ + }, + res: { + tr: true, + babel6corejs2: true, + jsx: true, + ejs: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox34: true, + opera10_50: false, + ie11: false, + edge12: true, + chrome41: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'TemplateStrings call site caching', + exec() { + /* + // TemplateStrings caching was changed from per-contents to + // per-call-site. + // https://github.com/tc39/ecma262/pull/890 + function strings(array) { + return array; + } + function getStrings() { + return strings`foo`; + } + var original = getStrings(); + var other = strings`foo`; + return original === getStrings() && original !== other; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + closure20200315: false, + closure20200517: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome41: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'TemplateStrings permanent caching', + exec() { + /* + function strings(array) { + return array; + } + function getStrings() { + return strings`foo`; + } + var original = getStrings(); + var newed = new getStrings(); + return original === getStrings() && original === newed; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + closure20200315: false, + closure20200517: true, + typescript1corejs2: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome41: true, + safari9: true, + safari12: safari.templateStringsPermanentCaching, + safari13: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + ], + }, + { + name: 'RegExp "y" and "u" flags', + category: 'syntax', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-get-regexp.prototype.sticky', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Parameters', + subtests: [ + { + name: '"y" flag', + exec() { + /* + var re = new RegExp('\\w', 'y'); + re.exec('xy'); + return (re.exec('xy')[0] === 'y'); + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + firefox2: false, + firefox3: true, + opera10_50: false, + chrome39: chrome.experimental, + chrome40: false, + chrome49: true, + node6: true, + node6_5: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: '"y" flag, lastIndex', + exec() { + /* + var re = new RegExp('yy', 'y'); + re.lastIndex = 3; + var result = re.exec('xxxyyxx')[0]; + return result === 'yy' && re.lastIndex === 5; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + firefox2: false, + firefox3: true, + opera10_50: false, + chrome39: chrome.experimental, + chrome40: false, + chrome49: true, + node6: true, + node6_5: true, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: '"u" flag', + exec() { + /* + return "𠮷".match(/^.$/u)[0].length === 2; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + edge13: true, + firefox2: false, + firefox46: true, + opera10_50: false, + chrome50: true, + node6: true, + node6_5: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"u" flag, non-BMP Unicode characters', + exec() { + /* + return "𠮷x".match(/^.x$/u)[0].length === 3; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + edge13: true, + firefox2: false, + firefox46: true, + opera10_50: false, + chrome50: true, + node6: true, + node6_5: true, + safari10: null, + safari12: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"u" flag, Unicode code point escapes', + exec() { + /* + return "𝌆".match(/\u{1d306}/u)[0].length === 2; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + edge13: true, + firefox2: false, + firefox46: true, + opera10_50: false, + chrome50: true, + node6: true, + node6_5: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"u" flag, case folding', + exec() { + /* + return "ſ".match(/S/iu) && "S".match(/ſ/iu); + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge13: true, + firefox2: false, + firefox46: true, + opera10_50: false, + chrome50: true, + node6: true, + node6_5: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'typed arrays', + category: 'built-ins', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-typedarray-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray', + subtests: [ + { + name: 'Int8Array', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new Int8Array(buffer); view[0] = 0x80; + return view[0] === -0x80; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Uint8Array', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new Uint8Array(buffer); view[0] = 0x100; + return view[0] === 0; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Uint8ClampedArray', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new Uint8ClampedArray(buffer); view[0] = 0x100; + return view[0] === 0xFF; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: { + val: true, + note_id: 'ie-clampedarray', + note_html: + "A buggy implementation of Uint8ClampedArray on initial IE11 release has been fixed with the patch on KB2929437", + }, + edge12: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari6: true, + opera10_50: false, + opera12: true, + node0_12: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Int16Array', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new Int16Array(buffer); view[0] = 0x8000; + return view[0] === -0x8000; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Uint16Array', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new Uint16Array(buffer); view[0] = 0x10000; + return view[0] === 0; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Int32Array', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new Int32Array(buffer); view[0] = 0x80000000; + return view[0] === -0x80000000; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Uint32Array', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new Uint32Array(buffer); view[0] = 0x100000000; + return view[0] === 0; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Float32Array', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new Float32Array(buffer); view[0] = 0.1; + return view[0] === 0.10000000149011612; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Float64Array', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new Float64Array(buffer); view[0] = 0.1; + return view[0] === 0.1; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: false, + android4_1: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'DataView (Int8)', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setInt8 (0, 0x80); + return view.getInt8(0) === -0x80; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox15: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'DataView (Uint8)', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setUint8(0, 0x100); + return view.getUint8(0) === 0; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox15: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'DataView (Int16)', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setInt16(0, 0x8000); + return view.getInt16(0) === -0x8000; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox15: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'DataView (Uint16)', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setUint16(0, 0x10000); + return view.getUint16(0) === 0; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox15: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'DataView (Int32)', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setInt32(0, 0x80000000); + return view.getInt32(0) === -0x80000000; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox15: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'DataView (Uint32)', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setUint32(0, 0x100000000); + return view.getUint32(0) === 0; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox15: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'DataView (Float32)', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setFloat32(0, 0.1); + return view.getFloat32(0) === 0.10000000149011612; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox15: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'DataView (Float64)', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView', + exec() { + /* + var buffer = new ArrayBuffer(64); + var view = new DataView(buffer); + view.setFloat64(0, 0.1); + return view.getFloat64(0) === 0.1; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie10: true, + firefox2: false, + firefox15: true, + chrome5: true, + safari5_1: true, + opera10_50: false, + opera12: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape1_3: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'ArrayBuffer[Symbol.species]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/@@species', + exec() { + /* + return typeof ArrayBuffer[Symbol.species] === 'function'; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + xs6: true, + ejs: true, + safari10: true, + chrome50: chrome.experimental, + chrome51: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'constructors require new', + exec() { + /* + var buffer = new ArrayBuffer(64); + var constructors = [ + 'ArrayBuffer', + 'DataView', + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', + 'Uint32Array', + 'Float32Array', + 'Float64Array' + ]; + return constructors.every(function (constructor) { + try { + if (constructor in global) { + global[constructor](constructor === "ArrayBuffer" ? 64 : buffer); + } + return false; + } catch(e) { + return true; + } + }); + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + firefox2: false, + firefox44: true, + opera10_50: false, + ie11: false, + edge14: true, + chrome5: true, + safari10: true, + node0_12: true, + xs6: true, + jxa: true, + ejs: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'constructors accept generic iterables', + exec() { + /* + var constructors = [ + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', + 'Uint32Array', + 'Float32Array', + 'Float64Array' + ]; + for(var i = 0; i < constructors.length; i++){ + var arr = new global[constructors[i]](__createIterableObject([1, 2, 3])); + if(arr.length !== 3 || arr[0] !== 1 || arr[1] !== 2 || arr[2] !== 3)return false; + } + return true; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + chrome45: true, + ie11: false, + edge14: true, + node4: true, + safari10: true, + firefox2: false, + firefox52: true, + opera10_50: false, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'correct prototype chains', + exec() { + /* + var constructors = [ + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', + 'Uint32Array', + 'Float32Array', + 'Float64Array' + ]; + var constructor = Object.getPrototypeOf(Int8Array); + var prototype = Object.getPrototypeOf(Int8Array.prototype); + if(constructor === Function.prototype || prototype === Object.prototype)return false; + for(var i = 0; i < constructors.length; i+=1) { + if (!(constructors[i] in global + && Object.getPrototypeOf(global[constructors[i]]) === constructor + && Object.getPrototypeOf(global[constructors[i]].prototype) === prototype + && Object.getOwnPropertyNames(global[constructors[i]].prototype).sort() + '' + === "BYTES_PER_ELEMENT,constructor")) { + return false; + } + } + return true; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + firefox2: false, + firefox35: true, + opera10_50: false, + ie11: false, + edge12: true, + chrome51: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_1: true, + duktape2_5: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ].concat( + [ + // @@ jph + { + name: '.from', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/from', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.of', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/of', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.subarray', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: { + val: true, + note_id: 'ie-subarray', + note_html: + "This test depends on Uint8ClampedArray which has been introduced with KB2929437, so it fails on early IE11 builds.", + }, + edge12: true, + firefox2: false, + firefox4: true, + chrome5: true, + safari6: true, + opera10_50: false, + opera12: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '.prototype.join', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/join', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.indexOf', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/indexOf', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.lastIndexOf', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/lastIndexOf', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.slice', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.every', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/every', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.filter', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/filter', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.forEach', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/forEach', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.map', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/map', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.reduce', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/reduce', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.reduceRight', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/reduceRight', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.reverse', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/reverse', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.some', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/some', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.sort', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/sort', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox46: true, + opera10_50: false, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.copyWithin', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/copyWithin', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.find', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/find', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.findIndex', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/findIndex', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.fill', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/fill', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + chrome45: true, + node4: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.keys', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/keys', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + chrome38: true, + node0_12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.values', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/values', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + chrome38: true, + node0_12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ejs: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype.entries', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/entries', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + chrome38: true, + node0_12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '.prototype[Symbol.iterator]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/@@iterator', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + chrome38: true, + node0_12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + ejs: true, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '[Symbol.species]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/@@species', + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + xs6: true, + ejs: true, + chrome50: chrome.experimental, + chrome51: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ].map(function (m) { + const eqFn = ' === "function"' + const name = m.name + m.name = `%TypedArray%${name}` + // TODO: fix this eval + // m.exec = eval( + // `0,function(){/*\nreturn typeof ${[ + // 'Int8Array', + // 'Uint8Array', + // 'Uint8ClampedArray', + // 'Int16Array', + // 'Uint16Array', + // 'Int32Array', + // 'Uint32Array', + // 'Float32Array', + // 'Float64Array', + // ].join(`${name + eqFn} &&\n typeof `)}${name}${eqFn};\n*/}` + // ) + return m + }) + ), + }, + { + name: 'Map', + category: 'built-ins', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-map-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + var key = {}; + var map = new Map(); + + map.set(key, 123); + + return map.has(key) && map.get(key) === 123; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor arguments', + exec() { + /* + var key1 = {}; + var key2 = {}; + var map = new Map([[key1, 123], [key2, 456]]); + + return map.has(key1) && map.get(key1) === 123 && + map.has(key2) && map.get(key2) === 456; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor requires new', + exec() { + /* + new Map(); + try { + Map(); + return false; + } catch(e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: true, + chrome38: true, + safari9: true, + node4: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor accepts null', + exec() { + /* + new Map(null); + return true; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox10: false, + firefox17: false, + firefox37: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor invokes set', + exec() { + /* + var passed = false; + var _set = Map.prototype.set; + + Map.prototype.set = function(k, v) { + passed = true; + }; + + new Map([ [1, 2] ]); + Map.prototype.set = _set; + + return passed; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + chrome38: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'iterator closing', + exec() { + /* + var closed = false; + var iter = global.__createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + try { + new Map(iter); + } catch(e){} + return closed; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome51: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Map.prototype.set returns this', + exec() { + /* + var map = new Map(); + return map.set(0, 0) === map; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox33: true, + opera10_50: false, + chrome38: true, + safari7_1: true, + node0_12: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '-0 key converts to +0', + exec() { + /* + var map = new Map(); + map.set(-0, "foo"); + var k; + map.forEach(function (value, key) { + k = 1 / key; + }); + return k === Infinity && map.get(+0) === "foo"; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure20180506: true, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + opera10_50: false, + chrome39: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Map.prototype.size', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size', + exec() { + /* + var key = {}; + var map = new Map(); + + map.set(key, 123); + + return map.size === 1; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox19: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Map.prototype.delete', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete', + exec() { + /* + return typeof Map.prototype.delete === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Map.prototype.clear', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear', + exec() { + /* + return typeof Map.prototype.clear === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox19: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Map.prototype.forEach', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach', + exec() { + /* + return typeof Map.prototype.forEach === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome36: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Map.prototype.keys', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys', + exec() { + /* + return typeof Map.prototype.keys === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox20: true, + opera10_50: false, + safari7_1: true, + chrome37: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Map.prototype.values', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values', + exec() { + /* + return typeof Map.prototype.values === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox20: true, + opera10_50: false, + safari7_1: true, + chrome36: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Map.prototype.entries', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries', + exec() { + /* + return typeof Map.prototype.entries === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox20: true, + opera10_50: false, + safari7_1: true, + chrome36: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Map.prototype[Symbol.iterator]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@iterator', + exec() { + /* + return typeof Map.prototype[Symbol.iterator] === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome37: chrome.experimental, + chrome38: true, + safari9: true, + ie11: false, + edge12: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: "Map.prototype isn't an instance", + exec() { + /* + new Map(); + var obj = {}; + try { + Map.prototype.has(obj); + } + catch(e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Map iterator prototype chain', + exec() { + /* + // Iterator instance + var iterator = new Map()[Symbol.iterator](); + // %MapIteratorPrototype% + var proto1 = Object.getPrototypeOf(iterator); + // %IteratorPrototype% + var proto2 = Object.getPrototypeOf(proto1); + + return proto2.hasOwnProperty(Symbol.iterator) && + !proto1 .hasOwnProperty(Symbol.iterator) && + !iterator .hasOwnProperty(Symbol.iterator) && + iterator[Symbol.iterator]() === iterator; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + safari9: true, + chrome45: true, + node4: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Map[Symbol.species]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@species', + exec() { + /* + var prop = Object.getOwnPropertyDescriptor(Map, Symbol.species); + return 'get' in prop && Map[Symbol.species] === Map; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + firefox2: false, + firefox41: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + ie11: false, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'Set', + category: 'built-ins', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-set-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + var obj = {}; + var set = new Set(); + + set.add(123); + set.add(123); + + return set.has(123); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor arguments', + exec() { + /* + var obj1 = {}; + var obj2 = {}; + var set = new Set([obj1, obj2]); + + return set.has(obj1) && set.has(obj2); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor requires new', + exec() { + /* + new Set(); + try { + Set(); + return false; + } catch(e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: true, + chrome38: true, + safari9: true, + node4: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor accepts null', + exec() { + /* + new Set(null); + return true; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox37: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor invokes add', + exec() { + /* + var passed = false; + var _add = Set.prototype.add; + + Set.prototype.add = function(v) { + passed = true; + }; + + new Set([1]); + Set.prototype.add = _add; + + return passed; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + closure: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + chrome38: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'iterator closing', + exec() { + /* + var closed = false; + var iter = global.__createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + var add = Set.prototype.add; + Set.prototype.add = function(){ throw 0 }; + try { + new Set(iter); + } catch(e){} + Set.prototype.add = add; + return closed; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome51: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Set.prototype.add returns this', + exec() { + /* + var set = new Set(); + return set.add(0) === set; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox33: true, + opera10_50: false, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '-0 key converts to +0', + exec() { + /* + var set = new Set(); + set.add(-0); + var k; + set.forEach(function (value) { + k = 1 / value; + }); + return k === Infinity && set.has(+0); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure20180506: true, + es6shim: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + opera10_50: false, + chrome39: true, + safari9: true, + node0_12: 'flagged', + node4: true, + ejs: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Set.prototype.size', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/size', + exec() { + /* + var obj = {}; + var set = new Set(); + + set.add(123); + set.add(123); + set.add(456); + + return set.size === 2; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox19: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Set.prototype.delete', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete', + exec() { + /* + return typeof Set.prototype.delete === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Set.prototype.clear', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear', + exec() { + /* + return typeof Set.prototype.clear === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox19: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Set.prototype.forEach', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/forEach', + exec() { + /* + return typeof Set.prototype.forEach === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome36: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Set.prototype.keys', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/keys', + exec() { + /* + return typeof Set.prototype.keys === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox24: true, + opera10_50: false, + safari7_1: true, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Set.prototype.values', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/values', + exec() { + /* + return typeof Set.prototype.values === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox24: true, + opera10_50: false, + safari7_1: true, + chrome37: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Set.prototype.entries', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/entries', + exec() { + /* + return typeof Set.prototype.entries === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox24: true, + opera10_50: false, + safari7_1: true, + chrome37: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Set.prototype[Symbol.iterator]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/@@iterator', + exec() { + /* + return typeof Set.prototype[Symbol.iterator] === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + chrome51: true, + ejs: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome37: chrome.experimental, + chrome38: true, + safari9: true, + ie11: false, + edge12: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: "Set.prototype isn't an instance", + exec() { + /* + new Set(); + var obj = {}; + try { + Set.prototype.has(obj); + } + catch(e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: true, + firefox2: false, + firefox13: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Set iterator prototype chain', + exec() { + /* + // Iterator instance + var iterator = new Set()[Symbol.iterator](); + // %SetIteratorPrototype% + var proto1 = Object.getPrototypeOf(iterator); + // %IteratorPrototype% + var proto2 = Object.getPrototypeOf(proto1); + + return proto2.hasOwnProperty(Symbol.iterator) && + !proto1 .hasOwnProperty(Symbol.iterator) && + !iterator .hasOwnProperty(Symbol.iterator) && + iterator[Symbol.iterator]() === iterator; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + safari9: true, + chrome45: true, + node4: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Set[Symbol.species]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/@@species', + exec() { + /* + var prop = Object.getOwnPropertyDescriptor(Set, Symbol.species); + return 'get' in prop && Set[Symbol.species] === Set; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + chrome50: chrome.experimental, + chrome51: true, + firefox2: false, + firefox41: true, + opera10_50: false, + ie11: false, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'WeakMap', + category: 'built-ins', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-weakmap-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + var key = {}; + var weakmap = new WeakMap(); + + weakmap.set(key, 123); + + return weakmap.has(key) && weakmap.get(key) === 123; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox6: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome36: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor arguments', + exec() { + /* + var key1 = {}; + var key2 = {}; + var weakmap = new WeakMap([[key1, 123], [key2, 456]]); + + return weakmap.has(key1) && weakmap.get(key1) === 123 && + weakmap.has(key2) && weakmap.get(key2) === 456; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor requires new', + exec() { + /* + new WeakMap(); + try { + WeakMap(); + return false; + } catch(e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: true, + chrome36: true, + safari7_1: true, + node4: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor accepts null', + exec() { + /* + new WeakMap(null); + return true; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox10: true, + firefox17: true, + firefox37: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome36: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor invokes set', + exec() { + /* + var passed = false; + var _set = WeakMap.prototype.set; + + WeakMap.prototype.set = function(k, v) { + passed = true; + }; + + new WeakMap([ [{ }, 42] ]); + WeakMap.prototype.set = _set; + + return passed; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + chrome38: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'frozen objects as keys', + exec() { + /* + var f = Object.freeze({}); + var m = new WeakMap; + m.set(f, 42); + return m.get(f) === 42; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox6: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome36: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'iterator closing', + exec() { + /* + var closed = false; + var iter = global.__createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + try { + new WeakMap(iter); + } catch(e){} + return closed; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome51: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'WeakMap.prototype.set returns this', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/set#Return_value', + exec() { + /* + var weakmap = new WeakMap(); + var key = {}; + return weakmap.set(key, 0) === weakmap; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + chrome38: true, + firefox2: false, + firefox33: true, + opera10_50: false, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'WeakMap.prototype.delete', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/delete', + exec() { + /* + return typeof WeakMap.prototype.delete === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox6: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome36: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'no WeakMap.prototype.clear method', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/clear', + exec() { + /* + if (!("clear" in WeakMap.prototype)) { + return true; + } + var m = new WeakMap(); + var key = {}; + m.set(key, 2); + m.clear(); + return m.has(key); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + chrome43: true, + ie11: false, + edge12: true, + firefox2: false, + firefox6: true, + firefox20: false, + firefox46: true, + opera10_50: false, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '.has, .get and .delete methods accept primitives', + exec() { + /* + var m = new WeakMap; + return m.has(1) === false + && m.get(1) === void undefined + && m.delete(1) === false; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox38: true, + opera10_50: false, + chrome41: true, + safari9: true, + ejs: null, + xs6: null, + jxa: null, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: "WeakMap.prototype isn't an instance", + exec() { + /* + new WeakMap(); + var obj = {}; + try { + WeakMap.prototype.has(obj); + } + catch(e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: true, + firefox2: false, + firefox40: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome36: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'WeakSet', + category: 'built-ins', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-weakset-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + var obj1 = {}; + var weakset = new WeakSet(); + + weakset.add(obj1); + weakset.add(obj1); + + return weakset.has(obj1); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome36: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor arguments', + exec() { + /* + var obj1 = {}, obj2 = {}; + var weakset = new WeakSet([obj1, obj2]); + + return weakset.has(obj1) && weakset.has(obj2); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor requires new', + exec() { + /* + new WeakSet(); + try { + WeakSet(); + return false; + } catch(e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + firefox2: false, + firefox37: true, + opera10_50: false, + ie11: false, + edge12: true, + chrome36: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor accepts null', + exec() { + /* + new WeakSet(null); + return true; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome36: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'constructor invokes add', + exec() { + /* + var passed = false; + var _add = WeakSet.prototype.add; + + WeakSet.prototype.add = function(v) { + passed = true; + }; + + new WeakSet([ { } ]); + WeakSet.prototype.add = _add; + + return passed; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + chrome38: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'iterator closing', + exec() { + /* + var closed = false; + var iter = global.__createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + try { + new WeakSet(iter); + } catch(e){} + return closed; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome51: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'WeakSet.prototype.add returns this', + exec() { + /* + var weakset = new WeakSet(); + var obj = {}; + return weakset.add(obj) === weakset; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + chrome38: true, + safari9: true, + firefox2: false, + firefox34: true, + opera10_50: false, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'WeakSet.prototype.delete', + exec() { + /* + return typeof WeakSet.prototype.delete === "function"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome36: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'no WeakSet.prototype.clear method', + exec() { + /* + if (!("clear" in WeakSet.prototype)) { + return true; + } + var s = new WeakSet(); + var key = {}; + s.add(key); + s.clear(); + return s.has(key); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + chrome43: true, + safari9: true, + ie11: false, + edge12: true, + firefox2: false, + firefox46: true, + opera10_50: false, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: '.has and .delete methods accept primitives', + exec() { + /* + var s = new WeakSet; + return s.has(1) === false + && s.delete(1) === false; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome41: true, + safari9: true, + ejs: null, + xs6: null, + jxa: null, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: "WeakSet.prototype isn't an instance", + exec() { + /* + new WeakSet(); + var obj = {}; + try { + WeakSet.prototype.has(obj); + } + catch(e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome36: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'Proxy', + category: 'built-ins', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy', + note_id: 'proxy-enumerate', + note_html: + 'The 2015 version of the specification also specifies an "enumerate" handler, which was removed in the 2016 version.', + subtests: [ + { + name: 'constructor requires new', + exec() { + /* + new Proxy({}, {}); + try { + Proxy({}, {}); + return false; + } catch(e) { + return true; + } + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + firefox25: false, + firefox38: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'no "prototype" property', + exec() { + /* + new Proxy({}, {}); + return !Proxy.hasOwnProperty('prototype'); + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"get" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get', + exec() { + /* + var proxied = { }; + var proxy = new Proxy(proxied, { + get: function (t, k, r) { + return t === proxied && k === "foo" && r === proxy && 5; + } + }); + return proxy.foo === 5; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"get" handler, instances of proxies', + exec() { + /* + var proxied = { }; + var proxy = Object.create(new Proxy(proxied, { + get: function (t, k, r) { + return t === proxied && k === "foo" && r === proxy && 5; + } + })); + return proxy.foo === 5; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox18: { + val: false, + note_id: 'fx-proxy-get', + note_html: + 'Firefox 18 up to 37 doesn\'t allow a proxy\'s "get" handler to be triggered via the prototype chain, unless the proxied object does possess the named property (or the proxy\'s "has" handler reports it as present).', + }, + firefox2: false, + firefox38: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"get" handler invariants', + exec() { + /* + var passed = false; + var proxied = { }; + var proxy = new Proxy(proxied, { + get: function () { + passed = true; + return 4; + } + }); + // The value reported for a property must be the same as the value of the corresponding + // target object property if the target object property is a non-writable, + // non-configurable own data property. + Object.defineProperty(proxied, "foo", { value: 5, enumerable: true }); + try { + proxy.foo; + return false; + } + catch(e) {} + // The value reported for a property must be undefined if the corresponding target + // object property is a non-configurable own accessor property that has undefined + // as its [[Get]] attribute. + Object.defineProperty(proxied, "bar", + { set: function(){}, enumerable: true }); + try { + proxy.bar; + return false; + } + catch(e) {} + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"set" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/set', + exec() { + /* + var proxied = { }; + var passed = false; + var proxy = new Proxy(proxied, { + set: function (t, k, v, r) { + passed = t === proxied && k + v === "foobar" && r === proxy; + } + }); + proxy.foo = "bar"; + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"set" handler, instances of proxies', + exec() { + /* + var proxied = { }; + var passed = false; + var proxy = Object.create(new Proxy(proxied, { + set: function (t, k, v, r) { + passed = t === proxied && k + v === "foobar" && r === proxy; + } + })); + proxy.foo = "bar"; + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"set" handler invariants', + exec() { + /* + var passed = false; + new Proxy({},{}); + // Cannot change the value of a property to be different from the value of + // the corresponding target object if the corresponding target object + // property is a non-writable, non-configurable own data property. + var proxied = {}; + var proxy = new Proxy(proxied, { + set: function () { + passed = true; + return true; + } + }); + Object.defineProperty(proxied, "foo", { value: 2, enumerable: true }); + proxy.foo = 2; + try { + proxy.foo = 4; + return false; + } catch(e) {} + // Cannot set the value of a property if the corresponding target + // object property is a non-configurable own accessor property + // that has undefined as its [[Set]] attribute. + Object.defineProperty(proxied, "bar", + { get: function(){}, enumerable: true }); + try { + proxy.bar = 2; + return false; + } catch(e) {} + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"has" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/has', + exec() { + /* + var proxied = {}; + var passed = false; + "foo" in new Proxy(proxied, { + has: function (t, k) { + passed = t === proxied && k === "foo"; + } + }); + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"has" handler, instances of proxies', + exec() { + /* + var proxied = {}; + var passed = false; + "foo" in Object.create(new Proxy(proxied, { + has: function (t, k) { + passed = t === proxied && k === "foo"; + } + })); + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"has" handler invariants', + exec() { + /* + var passed = false; + new Proxy({},{}); + // A property cannot be reported as non-existent, if it exists as a + // non-configurable own property of the target object. + var proxied = {}; + var proxy = new Proxy(proxied, { + has: function () { + passed = true; + return false; + } + }); + Object.defineProperty(proxied, "foo", { value: 2, writable: true, enumerable: true }); + try { + 'foo' in proxy; + return false; + } catch(e) {} + // A property cannot be reported as non-existent, if it exists as an + // own property of the target object and the target object is not extensible. + proxied.bar = 2; + Object.preventExtensions(proxied); + try { + 'bar' in proxy; + return false; + } catch(e) {} + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"deleteProperty" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/deleteProperty', + exec() { + /* + var proxied = {}; + var passed = false; + delete new Proxy(proxied, { + deleteProperty: function (t, k) { + passed = t === proxied && k === "foo"; + } + }).foo; + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"deleteProperty" handler invariant', + exec() { + /* + var passed = false; + new Proxy({},{}); + // A property cannot be reported as deleted, if it exists as a non-configurable + // own property of the target object. + var proxied = {}; + Object.defineProperty(proxied, "foo", { value: 2, writable: true, enumerable: true }); + try { + delete new Proxy(proxied, { + deleteProperty: function () { + passed = true; + return true; + } + }).foo; + return false; + } catch(e) {} + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: '"getOwnPropertyDescriptor" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor', + exec() { + /* + var proxied = {}; + var fakeDesc = { value: "foo", configurable: true }; + var returnedDesc = Object.getOwnPropertyDescriptor( + new Proxy(proxied, { + getOwnPropertyDescriptor: function (t, k) { + return t === proxied && k === "foo" && fakeDesc; + } + }), + "foo" + ); + return (returnedDesc.value === fakeDesc.value + && returnedDesc.configurable === fakeDesc.configurable + && returnedDesc.writable === false + && returnedDesc.enumerable === false); + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: { + val: false, + note_id: 'fx-proxy-getown', + note_html: + 'From Firefox 18 up to 29, the getOwnPropertyDescriptor handler can only report non-existent properties if the proxy target is non-extensible rather than extensible', + }, + firefox23: { val: false, note_id: 'fx-proxy-getown' }, + firefox30: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"getOwnPropertyDescriptor" handler invariants', + exec() { + /* + var passed = false; + new Proxy({},{}); + // A property cannot be reported as non-existent, if it exists as a non-configurable + // own property of the target object. + var proxied = {}; + var proxy = new Proxy(proxied, { + getOwnPropertyDescriptor: function () { + passed = true; + return undefined; + } + }); + Object.defineProperty(proxied, "foo", { value: 2, writable: true, enumerable: true }); + try { + Object.getOwnPropertyDescriptor(proxy, "foo"); + return false; + } catch(e) {} + // A property cannot be reported as non-existent, if it exists as an own property + // of the target object and the target object is not extensible. + proxied.bar = 3; + Object.preventExtensions(proxied); + try { + Object.getOwnPropertyDescriptor(proxy, "bar"); + return false; + } catch(e) {} + // A property cannot be reported as existent, if it does not exists as an own property + // of the target object and the target object is not extensible. + try { + Object.getOwnPropertyDescriptor(new Proxy(proxied, { + getOwnPropertyDescriptor: function() { + return { value: 2, configurable: true, writable: true, enumerable: true }; + }}), "baz"); + return false; + } catch(e) {} + // A property cannot be reported as non-configurable, if it does not exists as an own + // property of the target object or if it exists as a configurable own property of + // the target object. + try { + Object.getOwnPropertyDescriptor(new Proxy({}, { + getOwnPropertyDescriptor: function() { + return { value: 2, configurable: false, writable: true, enumerable: true }; + }}), "baz"); + return false; + } catch(e) {} + try { + Object.getOwnPropertyDescriptor(new Proxy({baz:1}, { + getOwnPropertyDescriptor: function() { + return { value: 1, configurable: false, writable: true, enumerable: true }; + }}), "baz"); + return false; + } catch(e) {} + return passed; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox32: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"defineProperty" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/defineProperty', + exec() { + /* + var proxied = {}; + var passed = false; + Object.defineProperty( + new Proxy(proxied, { + defineProperty: function (t, k, d) { + passed = t === proxied && k === "foo" && d.value === 5; + return true; + } + }), + "foo", + { value: 5, configurable: true } + ); + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"defineProperty" handler invariants', + exec() { + /* + var passed = false; + new Proxy({},{}); + // A property cannot be added, if the target object is not extensible. + var proxied = Object.preventExtensions({}); + var proxy = new Proxy(proxied, { + defineProperty: function() { + passed = true; + return true; + } + }); + try { + Object.defineProperty(proxy, "foo", { value: 2 }); + return false; + } catch(e) {} + // A property cannot be non-configurable, unless there exists a corresponding + // non-configurable own property of the target object. + try { + Object.defineProperty( + new Proxy({ bar: true }, { + defineProperty: function () { + return true; + } + }), + "bar", + { value: 5, configurable: false, writable: true, enumerable: true } + ); + return false; + } catch(e) {} + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox32: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"getPrototypeOf" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getPrototypeOf', + exec() { + /* + var proxied = {}; + var fakeProto = {}; + var proxy = new Proxy(proxied, { + getPrototypeOf: function (t) { + return t === proxied && fakeProto; + } + }); + return Object.getPrototypeOf(proxy) === fakeProto; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"getPrototypeOf" handler invariant', + exec() { + /* + var passed = false; + new Proxy({},{}); + // If the target object is not extensible, [[GetPrototypeOf]] applied to the proxy object + // must return the same value as [[GetPrototypeOf]] applied to the proxy object's target object. + try { + Object.getPrototypeOf(new Proxy(Object.preventExtensions({}), { + getPrototypeOf: function () { + passed = true; + return {}; + } + })); + return false; + } catch(e) {} + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: '"setPrototypeOf" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/setPrototypeOf', + exec() { + /* + var proxied = {}; + var newProto = {}; + var passed = false; + Object.setPrototypeOf( + new Proxy(proxied, { + setPrototypeOf: function (t, p) { + passed = t === proxied && p === newProto; + return true; + } + }), + newProto + ); + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"setPrototypeOf" handler invariant', + exec() { + /* + var passed = false; + new Proxy({},{}); + Object.setPrototypeOf({},{}); + // If the target object is not extensible, the argument value must be the + // same as the result of [[GetPrototypeOf]] applied to target object. + try { + Object.setPrototypeOf( + new Proxy(Object.preventExtensions({}), { + setPrototypeOf: function () { + passed = true; + return true; + } + }),{}); + return false; + } catch(e) {} + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: '"isExtensible" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/isExtensible', + exec() { + /* + var proxied = {}; + var passed = false; + Object.isExtensible( + new Proxy(proxied, { + isExtensible: function (t) { + passed = t === proxied; return true; + } + }) + ); + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + firefox2: false, + firefox31: true, + opera10_50: false, + ie11: false, + edge12: true, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"isExtensible" handler invariant', + exec() { + /* + var passed = false; + new Proxy({},{}); + // [[IsExtensible]] applied to the proxy object must return the same value + // as [[IsExtensible]] applied to the proxy object's target object with the same argument. + try { + Object.isExtensible(new Proxy({}, { + isExtensible: function (t) { + passed = true; + return false; + } + })); + return false; + } catch(e) {} + try { + Object.isExtensible(new Proxy(Object.preventExtensions({}), { + isExtensible: function (t) { + return true; + } + })); + return false; + } catch(e) {} + return true; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + firefox2: false, + firefox31: true, + opera10_50: false, + ie11: false, + edge12: true, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"preventExtensions" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/preventExtensions', + exec() { + /* + var proxied = {}; + var passed = false; + Object.preventExtensions( + new Proxy(proxied, { + preventExtensions: function (t) { + passed = t === proxied; + return Object.preventExtensions(proxied); + } + }) + ); + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + firefox2: false, + firefox22: true, + opera10_50: false, + ie11: false, + edge12: true, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"preventExtensions" handler invariant', + exec() { + /* + var passed = false; + new Proxy({},{}); + // [[PreventExtensions]] applied to the proxy object only returns true + // if [[IsExtensible]] applied to the proxy object's target object is false. + try { + Object.preventExtensions(new Proxy({}, { + preventExtensions: function () { + passed = true; + return true; + } + })); + return false; + } catch(e) {} + return passed; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + firefox2: false, + firefox22: true, + opera10_50: false, + ie11: false, + edge12: true, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: '"ownKeys" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/ownKeys', + exec() { + /* + var proxied = {}; + var passed = false; + Object.keys( + new Proxy(proxied, { + ownKeys: function (t) { + passed = t === proxied; return []; + } + }) + ); + return passed; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + firefox2: false, + firefox18: { + val: false, + note_id: 'fx-proxy-ownkeys', + note_html: 'Available from Firefox 18 up to 33 as the draft standard keys handler', + }, + firefox23: { val: false, note_id: 'fx-proxy-ownkeys' }, + firefox33: true, + opera10_50: false, + ie11: false, + edge12: true, + xs6: true, + ejs: true, + chrome49: true, + safari10: true, + duktape1_0: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"ownKeys" handler invariant', + exec() { + /* + var passed = false; + new Proxy({},{}); + // The Type of each result List element is either String or Symbol. + try { + Object.keys(new Proxy({}, { + ownKeys: function () { + passed = true; + return [2]; + }})); + return false; + } catch(e) {} + // The result List must contain the keys of all non-configurable own properties of the target object. + var proxied = {}; + Object.defineProperty(proxied, "foo", { value: 2, writable: true, enumerable: true }); + try { + Object.keys(new Proxy(proxied, { + ownKeys: function () { + return []; + }})); + return false; + } catch(e) {} + // If the target object is not extensible, then the result List must contain all the keys + // of the own properties of the target object and no other values. + try { + Object.keys(new Proxy(Object.preventExtensions({b:1}), { + ownKeys: function () { + return ['a']; + }})); + return false; + } catch(e) {} + return passed; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + firefox2: false, + firefox18: { val: false, note_id: 'fx-proxy-ownkeys' }, + firefox42: true, + opera10_50: false, + ie11: false, + edge12: true, + xs6: true, + ejs: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: '"apply" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply', + exec() { + /* + var proxied = function(){}; + var passed = false; + var host = { + method: new Proxy(proxied, { + apply: function (t, thisArg, args) { + passed = t === proxied && thisArg === host && args + "" === "foo,bar"; + } + }) + }; + host.method("foo", "bar"); + return passed; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"apply" handler invariant', + exec() { + /* + var passed = false; + new Proxy(function(){}, { + apply: function () { passed = true; } + })(); + // A Proxy exotic object only has a [[Call]] internal method if the + // initial value of its [[ProxyTarget]] internal slot is an object + // that has a [[Call]] internal method. + try { + new Proxy({}, { + apply: function () {} + })(); + return false; + } catch(e) {} + return passed; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + chrome50: true, + xs6: true, + safari10: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"construct" handler', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/construct', + exec() { + /* + var proxied = function(){}; + var passed = false; + new new Proxy(proxied, { + construct: function (t, args) { + passed = t === proxied && args + "" === "foo,bar"; + return {}; + } + })("foo","bar"); + return passed; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: '"construct" handler invariants', + exec() { + /* + var passed = false; + new Proxy({},{}); + // A Proxy exotic object only has a [[Construct]] internal method if the + // initial value of its [[ProxyTarget]] internal slot is an object + // that has a [[Construct]] internal method. + try { + new new Proxy({}, { + construct: function (t, args) { + return {}; + } + })(); + return false; + } catch(e) {} + // The result of [[Construct]] must be an Object. + try { + new new Proxy(function(){}, { + construct: function (t, args) { + passed = true; + return 5; + } + })(); + return false; + } catch(e) {} + return passed; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox31: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Proxy.revocable', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/revocable', + exec() { + /* + var obj = Proxy.revocable({}, { get: function() { return 5; } }); + var passed = (obj.proxy.foo === 5); + obj.revoke(); + try { + obj.proxy.foo; + } catch(e) { + passed &= e instanceof TypeError; + } + return passed; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.isArray support', + exec() { + /* + return Array.isArray(new Proxy([], {})); + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + firefox2: false, + firefox18: true, + opera10_50: false, + ie11: false, + edge12: true, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + duktape2_5: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'JSON.stringify support', + exec() { + /* + return JSON.stringify(new Proxy(['foo'], {})) === '["foo"]'; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + firefox2: false, + firefox18: true, // a bug in FF18 + firefox21: false, + firefox40: true, + opera10_50: false, + ie11: false, + edge12: true, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + duktape2_5: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: "Proxy, internal 'get' calls", + category: 'misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get', + subtests: [ + { + name: 'ToPrimitive', + exec() { + /* + // ToPrimitive -> Get -> [[Get]] + var get = []; + var p = new Proxy({toString:Function()}, { get: function(o, k) { get.push(k); return o[k]; }}); + p + 3; + return get[0] === Symbol.toPrimitive && get.slice(1) + '' === "valueOf,toString"; + */ + }, + res: { + xs6: true, + ie11: false, + edge15: true, + firefox2: false, + firefox44: true, + opera10_50: false, + ejs: true, + chrome49: true, + safari10: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'CreateListFromArrayLike', + exec() { + /* + // CreateListFromArrayLike -> Get -> [[Get]] + var get = []; + var p = new Proxy({length:2, 0:0, 1:0}, { get: function(o, k) { get.push(k); return o[k]; }}); + Function.prototype.apply({}, p); + return get + '' === "length,0,1"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'instanceof operator', + exec() { + /* + // InstanceofOperator -> GetMethod -> GetV -> [[Get]] + // InstanceofOperator -> OrdinaryHasInstance -> Get -> [[Get]] + var get = []; + var p = new Proxy(Function(), { get: function(o, k) { get.push(k); return o[k]; }}); + ({}) instanceof p; + return get[0] === Symbol.hasInstance && get.slice(1) + '' === "prototype"; + */ + }, + res: { + ie11: false, + edge15: true, + firefox2: false, + firefox50: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'HasBinding', + exec() { + /* + // HasBinding -> Get -> [[Get]] + var get = []; + var p = new Proxy({foo:1}, { get: function(o, k) { get.push(k); return o[k]; }}); + p[Symbol.unscopables] = p; + with(p) { + typeof foo; + } + return get[0] === Symbol.unscopables && get.slice(1) + '' === "foo"; + */ + }, + res: { + xs6: true, + ejs: { val: false, note_id: 'ejs-no-with' }, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome49: true, + safari10: true, + ie11: false, + edge14: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'CreateDynamicFunction', + exec() { + /* + // CreateDynamicFunction -> GetPrototypeFromConstructor -> Get -> [[Get]] + var get = []; + var p = new Proxy(Function, { get: function(o, k) { get.push(k); return o[k]; }}); + new p; + return get + '' === "prototype"; + */ + }, + res: { + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'ClassDefinitionEvaluation', + exec() { + /* + // ClassDefinitionEvaluation -> Get -> [[Get]] + var get = []; + var p = new Proxy(Function(), { get: function(o, k) { get.push(k); return o[k]; }}); + class C extends p {} + return get + '' === "prototype"; + */ + }, + res: { + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'IteratorComplete, IteratorValue', + exec() { + /* + // IteratorComplete -> Get -> [[Get]] + // IteratorValue -> Get -> [[Get]] + var get = []; + var iterable = {}; + iterable[Symbol.iterator] = function() { + return { + next: function() { + return new Proxy({ value: 2, done: false }, { get: function(o, k) { get.push(k); return o[k]; }}); + } + }; + } + var i = 0; + for(var e of iterable) { + if (++i >= 2) break; + } + return get + '' === "done,value,done,value"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'ToPropertyDescriptor', + exec() { + /* + // ToPropertyDescriptor -> Get -> [[Get]] + var get = []; + var p = new Proxy({ + enumerable: true, configurable: true, value: true, + writable: true, get: Function(), set: Function() + }, { get: function(o, k) { get.push(k); return o[k]; }}); + try { + // This will throw, since it will have true for both "get" and "value", + // but not before performing a Get on every property. + Object.defineProperty({}, "foo", p); + } catch(e) { + return get + '' === "enumerable,configurable,value,writable,get,set"; + } + */ + }, + res: { + ejs: true, + firefox2: false, + firefox18: true, + opera10_50: false, + ie11: false, + edge13: true, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Object.assign', + exec() { + /* + // Object.assign -> Get -> [[Get]] + var get = []; + var p = new Proxy({foo:1, bar:2}, { get: function(o, k) { get.push(k); return o[k]; }}); + Object.assign({}, p); + return get + '' === "foo,bar"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Object.defineProperties', + exec() { + /* + // Object.defineProperties -> Get -> [[Get]] + var get = []; + var p = new Proxy({foo:{}, bar:{}}, { get: function(o, k) { get.push(k); return o[k]; }}); + Object.defineProperties({}, p); + return get + '' === "foo,bar"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Function.prototype.bind', + exec() { + /* + // Function.prototype.bind -> Get -> [[Get]] + var get = []; + var p = new Proxy(Function(), { get: function(o, k) { get.push(k); return o[k]; }}); + Function.prototype.bind.call(p); + return get + '' === "length,name"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Error.prototype.toString', + exec() { + /* + // Error.prototype.toString -> Get -> [[Get]] + var get = []; + var p = new Proxy({}, { get: function(o, k) { get.push(k); return o[k]; }}); + Error.prototype.toString.call(p); + return get + '' === "name,message"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'String.raw', + exec() { + /* + // String.raw -> Get -> [[Get]] + var get = []; + var raw = new Proxy({length: 2, 0: '', 1: ''}, { get: function(o, k) { get.push(k); return o[k]; }}); + var p = new Proxy({raw: raw}, { get: function(o, k) { get.push(k); return o[k]; }}); + String.raw(p); + return get + '' === "raw,length,0,1"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + xs6: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp constructor', + exec() { + /* + // RegExp -> Get -> [[Get]] + var get = []; + var re = { constructor: null }; + re[Symbol.match] = true; + var p = new Proxy(re, { get: function(o, k) { get.push(k); return o[k]; }}); + RegExp(p); + return get[0] === Symbol.match && get.slice(1) + '' === "constructor,source,flags"; + */ + }, + res: { + firefox2: false, + firefox40: true, + opera10_50: false, + ie11: false, + edge14: edge.experimental, + chrome50: true, + xs6: true, + ejs: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype.flags', + exec() { + /* + // RegExp.prototype.flags -> Get -> [[Get]] + var expected = []; + // Sorted alphabetically by shortname – "gimsuy". + if ('hasIndices' in RegExp.prototype) expected.push('hasIndices'); + if ('global' in RegExp.prototype) expected.push('global'); + if ('ignoreCase' in RegExp.prototype) expected.push('ignoreCase'); + if ('multiline' in RegExp.prototype) expected.push('multiline'); + if ('dotAll' in RegExp.prototype) expected.push('dotAll'); + if ('unicode' in RegExp.prototype) expected.push('unicode'); + if ('unicodeSets' in RegExp.prototype) expected.push('unicodeSets'); + if ('sticky' in RegExp.prototype) expected.push('sticky'); + + var actual = []; + var p = new Proxy({}, { get: function(o, k) { actual.push(k); return o[k]; }}); + Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(p); + if (expected.length !== actual.length) return false; + for (var i = 0; i < expected.length; i++) { + if (expected[i] !== actual[i]) return false; + } + return true; + */ + }, + res: { + firefox2: false, + firefox37: true, + firefox39: false, + firefox46: true, + opera10_50: false, + xs6: true, + chrome49: true, + ie11: false, + edge14: edge.experimental, + safari10: true, + duktape2_0: true, + graalvm19: true, + graalvm22_2: graalvm.es6flag, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype.test', + exec() { + /* + // RegExp.prototype.test -> RegExpExec -> Get -> [[Get]] + var get = []; + var p = new Proxy({ exec: function() { return null; } }, { get: function(o, k) { get.push(k); return o[k]; }}); + RegExp.prototype.test.call(p); + return get + '' === "exec"; + */ + }, + res: { + firefox2: false, + firefox46: true, + opera10_50: false, + ie11: false, + edge14: edge.experimental, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype.toString', + exec() { + /* + // RegExp.prototype.toString -> Get -> [[Get]] + var get = []; + var p = new Proxy({}, { get: function(o, k) { get.push(k); return o[k]; }}); + RegExp.prototype.toString.call(p); + return get + '' === "source,flags"; + */ + }, + res: { + firefox2: false, + firefox39: true, + opera10_50: false, + ie11: false, + edge14: edge.experimental, + chrome50: true, + xs6: null, + ejs: null, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype[Symbol.match]', + exec() { + /* + // RegExp.prototype[Symbol.match] -> Get -> [[Get]] + var get = []; + var p = new Proxy({ exec: function() { return null; } }, { get: function(o, k) { get.push(k); return o[k]; }}); + RegExp.prototype[Symbol.match].call(p); + p.global = true; + RegExp.prototype[Symbol.match].call(p); + var str = get + ''; + return str === "global,exec,global,unicode,exec" || str === 'flags,exec,flags,exec'; + */ + }, + res: { + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype[Symbol.replace]', + exec() { + /* + // RegExp.prototype[Symbol.replace] -> Get -> [[Get]] + var get = []; + var p = new Proxy({ exec: function() { return null; } }, { get: function(o, k) { get.push(k); return o[k]; }}); + RegExp.prototype[Symbol.replace].call(p); + p.global = true; + RegExp.prototype[Symbol.replace].call(p); + var str = get + ''; + return str === "global,exec,global,unicode,exec" || str === 'flags,exec,flags,exec'; + */ + }, + res: { + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype[Symbol.search]', + exec() { + /* + // RegExp.prototype[Symbol.search] -> Get -> [[Get]] + var get = []; + var p = new Proxy({ exec: function() { return null; } }, { get: function(o, k) { get.push(k); return o[k]; }}); + RegExp.prototype[Symbol.search].call(p); + return get + '' === "lastIndex,exec,lastIndex"; + */ + }, + note_id: 'regexp-prototype-symbolsearch', + note_html: + "The specification for this feature was updated after ES6 was published. This test reflects the updated spec, which is implemented by the latest browsers.", + res: { + ie11: false, + edge14: false, + firefox2: false, + firefox49: false, + firefox55: true, + opera10_50: false, + chrome51: false, + chrome56: true, + node8: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_4_0: true, + safari12: true, + safaritp: true, + webkit: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype[Symbol.split]', + exec() { + /* + // RegExp.prototype[Symbol.split] -> Get -> [[Get]] + var get = []; + var constructor = Function(); + constructor[Symbol.species] = Object; + var p = new Proxy({ constructor: constructor, flags: '', exec: function() { return null; } }, { get: function(o, k) { get.push(k); return o[k]; }}); + RegExp.prototype[Symbol.split].call(p, ""); + return get + '' === "constructor,flags,exec"; + */ + }, + res: { + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome51: true, + xs6: true, + ejs: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Array.from', + exec() { + /* + // Array.from -> Get -> [[Get]] + var get = []; + var p = new Proxy({length: 2, 0: '', 1: ''}, { get: function(o, k) { get.push(k); return o[k]; }}); + Array.from(p); + return get[0] === Symbol.iterator && get.slice(1) + '' === "length,0,1"; + */ + }, + res: { + ejs: true, + firefox2: false, + firefox36: true, + opera10_50: false, + ie11: false, + edge13: true, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.concat', + exec() { + /* + // Array.prototype.concat -> Get -> [[Get]] + var get = []; + var arr = [1]; + arr.constructor = void undefined; + var p = new Proxy(arr, { get: function(o, k) { get.push(k); return o[k]; }}); + Array.prototype.concat.call(p,p); + return get[0] === "constructor" + && get[1] === Symbol.isConcatSpreadable + && get[2] === "length" + && get[3] === "0" + && get[4] === get[1] && get[5] === get[2] && get[6] === get[3] + && get.length === 7; + */ + }, + res: { + ie11: false, + edge15: true, + chrome50: chrome.experimental, + chrome51: true, + firefox2: false, + firefox48: true, + opera10_50: false, + xs6: true, + ejs: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype iteration methods', + exec() { + /* + // Array.prototype methods -> Get -> [[Get]] + var methods = ['copyWithin', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', + 'indexOf', 'join', 'lastIndexOf', 'map', 'reduce', 'reduceRight', 'some']; + var get; + var p = new Proxy({length: 2, 0: '', 1: ''}, { get: function(o, k) { get.push(k); return o[k]; }}); + for(var i = 0; i < methods.length; i+=1) { + get = []; + Array.prototype[methods[i]].call(p, Function()); + if (get + '' !== ( + methods[i] === 'fill' ? "length" : + methods[i] === 'every' ? "length,0" : + methods[i] === 'lastIndexOf' || methods[i] === 'reduceRight' ? "length,1,0" : + "length,0,1" + )) { + return false; + } + } + return true; + */ + }, + res: { + firefox2: false, + firefox32: true, + opera10_50: false, + chrome51: true, + ie11: false, + edge12: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.pop', + exec() { + /* + // Array.prototype.pop -> Get -> [[Get]] + var get = []; + var p = new Proxy([0,1,2,3], { get: function(o, k) { get.push(k); return o[k]; }}); + Array.prototype.pop.call(p); + return get + '' === "length,3"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.reverse', + exec() { + /* + // Array.prototype.reverse -> Get -> [[Get]] + var get = []; + var p = new Proxy([0,,2,,4,,], { get: function(o, k) { get.push(k); return o[k]; }}); + Array.prototype.reverse.call(p); + return get + '' === "length,0,4,2"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.shift', + exec() { + /* + // Array.prototype.shift -> Get -> [[Get]] + var get = []; + var p = new Proxy([0,1,2,3], { get: function(o, k) { get.push(k); return o[k]; }}); + Array.prototype.shift.call(p); + return get + '' === "length,0,1,2,3"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.splice', + exec() { + /* + // Array.prototype.splice -> Get -> [[Get]] + var get = []; + var p = new Proxy([0,1,2,3], { get: function(o, k) { get.push(k); return o[k]; }}); + Array.prototype.splice.call(p,1,1); + Array.prototype.splice.call(p,1,0,1); + return get + '' === "length,constructor,1,2,3,length,constructor,2,1"; + */ + }, + res: { + closure: true, + ejs: true, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.toString', + exec() { + /* + // Array.prototype.toString -> Get -> [[Get]] + var get = []; + var p = new Proxy({ join:Function() }, { get: function(o, k) { get.push(k); return o[k]; }}); + Array.prototype.toString.call(p); + return get + '' === "join"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'JSON.stringify', + exec() { + /* + // JSON.stringify -> Get -> [[Get]] + var get = []; + var p = new Proxy({}, { get: function(o, k) { get.push(k); return o[k]; }}); + JSON.stringify(p); + return get + '' === "toJSON"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + xs6: true, + firefox2: false, + firefox18: true, + opera10_50: false, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Promise resolve functions', + exec() { + /* + // Promise resolve functions -> Get -> [[Get]] + var get = []; + var p = new Proxy({}, { get: function(o, k) { get.push(k); return o[k]; }}); + new Promise(function(resolve){ resolve(p); }); + return get + '' === "then"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'String.prototype.match', + exec() { + /* + // String.prototype.match -> Get -> [[Get]] + var get = []; + var proxied = {}; + proxied[Symbol.toPrimitive] = Function(); + var p = new Proxy(proxied, { get: function(o, k) { get.push(k); return o[k]; }}); + "".match(p); + return get[0] === Symbol.match && get[1] === Symbol.toPrimitive && get.length === 2; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'String.prototype.replace', + exec() { + /* + // String.prototype.replace functions -> Get -> [[Get]] + var get = []; + var proxied = {}; + proxied[Symbol.toPrimitive] = Function(); + var p = new Proxy(proxied, { get: function(o, k) { get.push(k); return o[k]; }}); + "".replace(p); + return get[0] === Symbol.replace && get[1] === Symbol.toPrimitive && get.length === 2; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome50: true, + xs6: true, + ejs: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'String.prototype.search', + exec() { + /* + // String.prototype.search functions -> Get -> [[Get]] + var get = []; + var proxied = {}; + proxied[Symbol.toPrimitive] = Function(); + var p = new Proxy(proxied, { get: function(o, k) { get.push(k); return o[k]; }}); + "".search(p); + return get[0] === Symbol.search && get[1] === Symbol.toPrimitive && get.length === 2; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'String.prototype.split', + exec() { + /* + // String.prototype.split functions -> Get -> [[Get]] + var get = []; + var proxied = {}; + proxied[Symbol.toPrimitive] = Function(); + var p = new Proxy(proxied, { get: function(o, k) { get.push(k); return o[k]; }}); + "".split(p); + return get[0] === Symbol.split && get[1] === Symbol.toPrimitive && get.length === 2; + */ + }, + res: { + ie11: false, + edge15: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome50: true, + xs6: true, + ejs: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Date.prototype.toJSON', + exec() { + /* + // Date.prototype.toJSON -> ToPrimitive -> Get -> [[Get]] + // Date.prototype.toJSON -> Invoke -> GetMethod -> GetV -> [[Get]] + var get = []; + var p = new Proxy({toString:Function(),toISOString:Function()}, { get: function(o, k) { get.push(k); return o[k]; }}); + Date.prototype.toJSON.call(p); + return get[0] === Symbol.toPrimitive && get.slice(1) + '' === "valueOf,toString,toISOString"; + */ + }, + res: { + xs6: true, + ie11: false, + edge15: true, + firefox2: false, + firefox44: true, + opera10_50: false, + chrome49: true, + safari10: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: "Proxy, internal 'set' calls", + category: 'misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/set', + subtests: [ + { + name: 'Object.assign', + exec() { + /* + // Object.assign -> Set -> [[Set]] + var set = []; + var p = new Proxy({}, { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + Object.assign(p, { foo: 1, bar: 2 }); + return set + '' === "foo,bar"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.from', + exec() { + /* + // Array.from -> Set -> [[Set]] + var set = []; + var p = new Proxy({}, { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + Array.from.call(function(){ return p; }, {length:2, 0:1, 1:2}); + return set + '' === "length"; + */ + }, + res: { + ie11: false, + edge12: true, + ejs: true, + firefox2: false, + firefox32: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.of', + exec() { + /* + // Array.from -> Set -> [[Set]] + var set = []; + var p = new Proxy({}, { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + Array.of.call(function(){ return p; }, 1, 2, 3); + return set + '' === "length"; + */ + }, + res: { + ie11: false, + edge12: true, + ejs: true, + firefox2: false, + firefox25: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.copyWithin', + exec() { + /* + // Array.prototype.copyWithin -> Set -> [[Set]] + var set = []; + var p = new Proxy([1,2,3,4,5,6], { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + p.copyWithin(0, 3); + return set + '' === "0,1,2"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.fill', + exec() { + /* + // Array.prototype.fill -> Set -> [[Set]] + var set = []; + var p = new Proxy([1,2,3,4,5,6], { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + p.fill(0, 3); + return set + '' === "3,4,5"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.pop', + exec() { + /* + // Array.prototype.pop -> Set -> [[Set]] + var set = []; + var p = new Proxy([], { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + p.pop(); + return set + '' === "length"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.push', + exec() { + /* + // Array.prototype.push -> Set -> [[Set]] + var set = []; + var p = new Proxy([], { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + p.push(0,0,0); + return set + '' === "0,1,2,length"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.reverse', + exec() { + /* + // Array.prototype.reverse -> Set -> [[Set]] + var set = []; + var p = new Proxy([0,0,0,,], { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + p.reverse(); + return set + '' === "3,1,2"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.shift', + exec() { + /* + // Array.prototype.shift -> Set -> [[Set]] + var set = []; + var p = new Proxy([0,0,,0], { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + p.shift(); + return set + '' === "0,2,length"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + firefox21: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.splice', + exec() { + /* + // Array.prototype.splice -> Set -> [[Set]] + var set = []; + var p = new Proxy([1,2,3], { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + p.splice(1,0,0); + return set + '' === "3,2,1,length"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + firefox21: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.unshift', + exec() { + /* + // Array.prototype.unshift -> Set -> [[Set]] + var set = []; + var p = new Proxy([0,0,,0], { set: function(o, k, v) { set.push(k); o[k] = v; return true; }}); + p.unshift(0,1); + return set + '' === "5,3,2,0,1,length"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + firefox21: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: "Proxy, internal 'defineProperty' calls", + category: 'misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/defineProperty', + subtests: [ + { + name: '[[Set]]', + exec() { + /* + // [[Set]] -> [[DefineOwnProperty]] + var def = []; + var p = new Proxy({foo:1, bar:2}, { defineProperty: function(o, v, desc) { def.push(v); Object.defineProperty(o, v, desc); return true; }}); + p.foo = 2; p.bar = 4; + return def + '' === "foo,bar"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + chrome49: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + hermes0_12_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'SetIntegrityLevel', + exec() { + /* + // SetIntegrityLevel -> DefinePropertyOrThrow -> [[DefineOwnProperty]] + var def = []; + var p = new Proxy({foo:1, bar:2}, { defineProperty: function(o, v, desc) { def.push(v); Object.defineProperty(o, v, desc); return true; }}); + Object.freeze(p); + return def + '' === "foo,bar"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: "Proxy, internal 'deleteProperty' calls", + category: 'misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/deleteProperty', + subtests: [ + { + name: 'Array.prototype.copyWithin', + exec() { + /* + // Array.prototype.copyWithin -> DeletePropertyOrThrow -> [[Delete]] + var del = []; + var p = new Proxy([0,0,0,,,,], { deleteProperty: function(o, v) { del.push(v); return delete o[v]; }}); + p.copyWithin(0,3); + return del + '' === "0,1,2"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.pop', + exec() { + /* + // Array.prototype.pop -> DeletePropertyOrThrow -> [[Delete]] + var del = []; + var p = new Proxy([0,0,0], { deleteProperty: function(o, v) { del.push(v); return delete o[v]; }}); + p.pop(); + return del + '' === "2"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + firefox21: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.reverse', + exec() { + /* + // Array.prototype.reverse -> DeletePropertyOrThrow -> [[Delete]] + var del = []; + var p = new Proxy([0,,2,,4,,], { deleteProperty: function(o, v) { del.push(v); return delete o[v]; }}); + p.reverse(); + return del + '' === "0,4,2"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + firefox21: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.shift', + exec() { + /* + // Array.prototype.shift -> DeletePropertyOrThrow -> [[Delete]] + var del = []; + var p = new Proxy([0,,0,,0,0], { deleteProperty: function(o, v) { del.push(v); return delete o[v]; }}); + p.shift(); + return del + '' === "0,2,5"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + firefox21: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.splice', + exec() { + /* + // Array.prototype.splice -> DeletePropertyOrThrow -> [[Delete]] + var del = []; + var p = new Proxy([0,0,0,0,,0], { deleteProperty: function(o, v) { del.push(v); return delete o[v]; }}); + p.splice(2,2,0); + return del + '' === "3,5"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + firefox21: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.unshift', + exec() { + /* + // Array.prototype.unshift -> DeletePropertyOrThrow -> [[Delete]] + var del = []; + var p = new Proxy([0,0,,0,,0], { deleteProperty: function(o, v) { del.push(v); return delete o[v]; }}); + p.unshift(0); + return del + '' === "5,3"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox18: true, + firefox21: false, + firefox40: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: "Proxy, internal 'getOwnPropertyDescriptor' calls", + category: 'misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor', + subtests: [ + { + name: '[[Set]]', + exec() { + /* + // [[Set]] -> [[GetOwnProperty]] + var gopd = []; + var p = new Proxy({}, + { getOwnPropertyDescriptor: function(o, v) { gopd.push(v); return Object.getOwnPropertyDescriptor(o, v); }}); + p.foo = 1; p.bar = 1; + return gopd + '' === "foo,bar"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox37: true, + opera10_50: false, + chrome49: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + hermes0_12_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Object.assign', + exec() { + /* + // Object.assign -> [[GetOwnProperty]] + var gopd = []; + var p = new Proxy({foo:1, bar:2}, + { getOwnPropertyDescriptor: function(o, v) { gopd.push(v); return Object.getOwnPropertyDescriptor(o, v); }}); + Object.assign({}, p); + return gopd + '' === "foo,bar"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Object.prototype.hasOwnProperty', + exec() { + /* + // Object.prototype.hasOwnProperty -> HasOwnProperty -> [[GetOwnProperty]] + var gopd = []; + var p = new Proxy({foo:1, bar:2}, + { getOwnPropertyDescriptor: function(o, v) { gopd.push(v); return Object.getOwnPropertyDescriptor(o, v); }}); + p.hasOwnProperty('garply'); + return gopd + '' === "garply"; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox33: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Function.prototype.bind', + exec() { + /* + // Function.prototype.bind -> HasOwnProperty -> [[GetOwnProperty]] + var gopd = []; + var p = new Proxy(Function(), + { getOwnPropertyDescriptor: function(o, v) { gopd.push(v); return Object.getOwnPropertyDescriptor(o, v); }}); + p.bind(); + return gopd + '' === "length"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: "Proxy, internal 'ownKeys' calls", + category: 'misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/ownKeys', + subtests: [ + { + name: 'SetIntegrityLevel', + exec() { + /* + // SetIntegrityLevel -> [[OwnPropertyKeys]] + var ownKeysCalled = 0; + var p = new Proxy({}, { ownKeys: function(o) { ownKeysCalled++; return Object.keys(o); }}); + Object.freeze(p); + return ownKeysCalled === 1; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox33: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'TestIntegrityLevel', + exec() { + /* + // TestIntegrityLevel -> [[OwnPropertyKeys]] + var ownKeysCalled = 0; + var p = new Proxy(Object.preventExtensions({}), { ownKeys: function(o) { ownKeysCalled++; return Object.keys(o); }}); + Object.isFrozen(p); + return ownKeysCalled === 1; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox33: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'SerializeJSONObject', + exec() { + /* + // SerializeJSONObject -> EnumerableOwnNames -> [[OwnPropertyKeys]] + var ownKeysCalled = 0; + var p = new Proxy({}, { ownKeys: function(o) { ownKeysCalled++; return Object.keys(o); }}); + JSON.stringify({a:p,b:p}); + return ownKeysCalled === 2; + */ + }, + res: { + ejs: true, + firefox2: false, + firefox33: true, + opera10_50: false, + ie11: false, + edge13: true, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Reflect', + category: 'built-ins', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-reflection', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect', + note_id: 'reflect-enumerate', + note_html: + 'The 2015 version of the specification also specifies Reflect.enumerate, which was removed in the 2016 version.', + subtests: [ + { + name: 'Reflect.get', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/get', + exec() { + /* + return Reflect.get({ qux: 987 }, "qux") === 987; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + firefox2: false, + firefox42: true, + opera10_50: false, + safari10: true, + xs6: true, + chrome49: true, + duktape1_0: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.set', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/set', + exec() { + /* + var obj = {}; + Reflect.set(obj, "quux", 654); + return obj.quux === 654; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape1_0: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.has', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/has', + exec() { + /* + return Reflect.has({ qux: 987 }, "qux"); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + duktape1_0: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.deleteProperty', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/deleteProperty', + exec() { + /* + var obj = { bar: 456 }; + Reflect.deleteProperty(obj, "bar"); + return !("bar" in obj); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + duktape1_0: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.getOwnPropertyDescriptor', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getOwnPropertyDescriptor', + exec() { + /* + var obj = { baz: 789 }; + var desc = Reflect.getOwnPropertyDescriptor(obj, "baz"); + return desc.value === 789 && + desc.configurable && desc.writable && desc.enumerable; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + firefox2: false, + firefox42: true, + opera10_50: false, + safari10: true, + xs6: true, + chrome49: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.defineProperty', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/defineProperty', + exec() { + /* + var obj = {}; + Reflect.defineProperty(obj, "foo", { value: 123 }); + return obj.foo === 123 && + Reflect.defineProperty(Object.freeze({}), "foo", { value: 123 }) === false; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + es6shim: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + ie11: false, + edge13: true, + xs6: true, + chrome49: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.getPrototypeOf', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getPrototypeOf', + exec() { + /* + return Reflect.getPrototypeOf([]) === Array.prototype; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.setPrototypeOf', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/setPrototypeOf', + exec() { + /* + var obj = {}; + Reflect.setPrototypeOf(obj, Array.prototype); + return obj instanceof Array; + */ + }, + res: { + babel6corejs2: { val: false, note_id: 'compiler-proto' }, + closure: { val: false, note_id: 'compiler-proto' }, + typescript1corejs2: { val: false, note_id: 'compiler-proto' }, + ejs: true, + ie11: false, + edge12: true, + es6shim: { val: false, note_id: 'compiler-proto' }, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.isExtensible', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/isExtensible', + exec() { + /* + return Reflect.isExtensible({}) && + !Reflect.isExtensible(Object.preventExtensions({})); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.preventExtensions', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/preventExtensions', + exec() { + /* + var obj = {}; + Reflect.preventExtensions(obj); + return !Object.isExtensible(obj); + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.ownKeys, string keys', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/ownKeys', + exec() { + /* + var obj = Object.create({ C: true }); + obj.A = true; + Object.defineProperty(obj, 'B', { value: true, enumerable: false }); + + return Reflect.ownKeys(obj).sort() + '' === "A,B"; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + duktape1_0: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.ownKeys, symbol keys', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/ownKeys', + exec() { + /* + var s1 = Symbol(), s2 = Symbol(), s3 = Symbol(); + var proto = {}; + proto[s1] = true; + var obj = Object.create(proto); + obj[s2] = true; + Object.defineProperty(obj, s3, { value: true, enumerable: false }); + + var keys = Reflect.ownKeys(obj); + return keys.indexOf(s2) >-1 && keys.indexOf(s3) >-1 && keys.length === 2; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + closure20190301: false, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + duktape1_0: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.apply', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/apply', + exec() { + /* + return Reflect.apply(Array.prototype.push, [1,2], [3,4,5]) === 5; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + es6shim: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.construct', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct', + exec() { + /* + return Reflect.construct(function(a, b, c) { + this.qux = a + b + c; + }, ["foo", "bar", "baz"]).qux === "foobarbaz"; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.construct sets new.target meta-property', + exec() { + /* + return Reflect.construct(function(a, b, c) { + if (new.target === Object) { + this.qux = a + b + c; + } + }, ["foo", "bar", "baz"], Object).qux === "foobarbaz"; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + firefox2: false, + firefox42: true, + opera10_50: false, + ie11: false, + edge13: true, + xs6: true, + ejs: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.construct creates instances from third argument', + exec() { + /* + function F(){} + var obj = Reflect.construct(function(){ this.y = 1; }, [], F); + return obj.y === 1 && obj instanceof F; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + closure: true, + es6shim: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge13: true, + firefox2: false, + firefox44: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.construct, Array subclassing', + exec() { + /* + function F(){} + var obj = Reflect.construct(Array, [], F); + obj[2] = 'foo'; + return obj.length === 3 && obj instanceof F; + */ + }, + res: { + ejs: null, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: null, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.construct, RegExp subclassing', + exec() { + /* + function F(){} + var obj = Reflect.construct(RegExp, ["baz","g"], F); + return RegExp.prototype.exec.call(obj, "foobarbaz")[0] === "baz" + && obj.lastIndex === 9 && obj instanceof F; + */ + }, + res: { + ejs: null, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + firefox46: false, + firefox49: true, + opera10_50: false, + xs6: null, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.construct, Function subclassing', + exec() { + /* + function F(){} + var obj = Reflect.construct(Function, ["return 2"], F); + return obj() === 2 && obj instanceof F; + */ + }, + res: { + ejs: null, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: null, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.construct, Promise subclassing', + exec() { + /* + function F(){} + var p1 = Reflect.construct(Promise,[function(resolve, reject) { resolve("foo"); }], F); + var p2 = Reflect.construct(Promise,[function(resolve, reject) { reject("quux"); }], F); + var score = +(p1 instanceof F && p2 instanceof F); + + function thenFn(result) { score += (result === "foo"); check(); } + function catchFn(result) { score += (result === "quux"); check(); } + function shouldNotRun(result) { score = -Infinity; } + + p1.then = p2.then = Promise.prototype.then; + p1.catch = p2.catch = Promise.prototype.catch; + + p1.then(thenFn, shouldNotRun); + p2.then(shouldNotRun, catchFn); + p1.catch(shouldNotRun); + p2.catch(catchFn); + + function check() { + if (score === 4) asyncTestPassed(); + } + */ + }, + res: { + ejs: null, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + xs6: null, + ie11: false, + edge13: true, + firefox2: false, + firefox42: true, + opera10_50: false, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'block-level function declaration', + category: 'bindings', + significance: 'small', + note_id: 'block-level-function', + note_html: + 'Note that prior to ES6, it was recommended that ES5 implementations forbid block-level declarations in strict mode.', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-functiondeclarationinstantiation', + exec() { + /* + 'use strict'; + if (f() !== 1) return false; + function f() { return 1; } + { + if (f() !== 2) return false; + function f() { return 2; } + if (f() !== 2) return false; + } + if (f() !== 1) return false; + return true; + */ + }, + res: { + babel6corejs2: true, + tr: true, + closure: true, + ie11: true, + firefox2: false, + firefox46: true, + opera10_50: false, + chrome21: chrome.experimental, + chrome41: true, + node0_12: 'flagged', + node4: true, + xs6: true, + safari10: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'destructuring, declarations', + category: 'syntax', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-destructuring-assignment', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment', + subtests: [ + { + name: 'with arrays', + exec() { + /* + var [a, , [b], c] = [5, null, [6]]; + return a === 5 && b === 6 && c === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with sparse arrays', + exec() { + /* + var [a, , b] = [,,,]; + return a === void undefined && b === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with strings', + exec() { + /* + var [a, b, c] = "ab"; + return a === "a" && b === "b" && c === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with astral plane strings', + exec() { + /* + var [c] = "𠮷𠮶"; + return c === "𠮷"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox34: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generator instances', + exec() { + /* + var [a, b, c] = (function*(){ yield 1; yield 2; }()); + return a === 1 && b === 2 && c === void undefined; + */ + }, + res: { + tr: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox34: true, + opera10_50: false, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + safari10: true, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generic iterables', + exec() { + /* + var [a, b, c] = global.__createIterableObject([1, 2]); + return a === 1 && b === 2 && c === void undefined; + */ + }, + res: { + tr: true, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + babel6corejs2: babel.corejs, + closure: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with instances of generic iterables', + exec() { + /* + var [a, b, c] = Object.create(global.__createIterableObject([1, 2])); + return a === 1 && b === 2 && c === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'iterator closing', + exec() { + /* + var closed = false; + var iter = global.__createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + var [a, b] = iter; + return closed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + ie11: false, + edge15: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome51: true, + node6_5: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'trailing commas in iterable patterns', + exec() { + /* + var [a,] = [1]; + return a === 1; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with objects', + exec() { + /* + var {c, x:d, e} = {c:7, x:8}; + return c === 7 && d === 8 && e === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: { + val: true, + note_id: 'ff11-object-destructuring', + note_html: + 'Firefox < 16 incorrectly treats ({f,g} = {f:9,g:10}) as assigning to global variables instead of locals.', + }, + firefox15: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'object destructuring with primitives', + exec() { + /* + var {toFixed} = 2; + var {slice} = ''; + return toFixed === Number.prototype.toFixed + && slice === String.prototype.slice; + */ + }, + res: { + tr: true, + babel6corejs2: true, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'trailing commas in object patterns', + exec() { + /* + var {a,} = {a:1}; + return a === 1; + */ + }, + res: { + tr: true, + babel6corejs2: true, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'throws on null and undefined', + exec() { + /* + try { + var {a} = null; + return false; + } catch(e) { + if (!(e instanceof TypeError)) + return false; + } + try { + var {b} = void undefined; + return false; + } catch(e) { + if (!(e instanceof TypeError)) + return false; + } + return true; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + ejs: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'computed properties', + exec() { + /* + var qux = "corge"; + var { [qux]: grault } = { corge: "garply" }; + return grault === "garply"; + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + tr: true, + es6tr: true, + firefox2: false, + firefox35: true, + opera10_50: false, + ie11: false, + edge13: edge.experimental, + edge14: true, + safari10: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'multiples in a single var statement', + exec() { + /* + var [a,b] = [5,6], {c,d} = {c:7,d:8}; + return a === 5 && b === 6 && c === 7 && d === 8; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'nested', + exec() { + /* + var [e, {x:f, g}] = [9, {x:10}]; + var {h, x:[i]} = {h:11, x:[12]}; + return e === 9 && f === 10 && g === void undefined + && h === 11 && i === 12; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'in for-in loop heads', + exec() { + /* + for(var [i, j, k] in { qux: 1 }) { + return i === "q" && j === "u" && k === "x"; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'in for-of loop heads', + exec() { + /* + for(var [i, j, k] of [[1,2,3]]) { + return i === 1 && j === 2 && k === 3; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + closure: true, + firefox2: false, + firefox13: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'in catch heads', + exec() { + /* + try { + throw [1,2]; + } catch([i,j]) { + try { + throw { k: 3, l: 4 }; + } catch({k, l}) { + return i === 1 && j === 2 && k === 3 && l === 4; + } + } + */ + }, + res: { + firefox2: false, + firefox3: true, + opera10_50: false, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + tr: true, + jsx: true, + closure: true, + chrome49: true, + node6: true, + node6_5: true, + ie11: false, + edge14: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.catchDestructuring, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'rest', + exec() { + /* + var [a, ...b] = [3, 4, 5]; + var [c, ...d] = [6]; + return a === 3 && b instanceof Array && (b + "") === "4,5" && + c === 6 && d instanceof Array && d.length === 0; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + jsx: true, + closure: true, + firefox2: false, + firefox34: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'defaults', + exec() { + /* + var {a = 1, b = 0, z:c = 3} = {b:2, z:undefined}; + var [d = 0, e = 5, f = 6] = [4,,undefined]; + return a === 1 && b === 2 && c === 3 + && d === 4 && e === 5 && f === 6; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + closure: true, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox47: true, + opera10_50: false, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'defaults, let temporal dead zone', + exec() { + /* + var {a, b = 2} = {a:1}; + try { + eval("let {c = c} = {};"); + return false; + } catch(e){} + try { + eval("let {c = d, d} = {d:1};"); + return false; + } catch(e){} + return a === 1 && b === 2; + */ + }, + res: { + babel6corejs2: babel.optional, + closure: true, + typescript1corejs2: true, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox47: true, + opera10_50: false, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + hermes0_12_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'destructuring, assignment', + category: 'syntax', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-destructuring-assignment', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment', + subtests: [ + { + name: 'with arrays', + exec() { + /* + var a,b,c; + [a, , [b], c] = [5, null, [6]]; + return a === 5 && b === 6 && c === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with sparse arrays', + exec() { + /* + var a, b; + [a, , b] = [,,,]; + return a === void undefined && b === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with strings', + exec() { + /* + var a,b,c; + [a, b, c] = "ab"; + return a === "a" && b === "b" && c === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with astral plane strings', + exec() { + /* + var c; + [c] = "𠮷𠮶"; + return c === "𠮷"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox34: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generator instances', + exec() { + /* + var a,b,c; + [a, b, c] = (function*(){ yield 1; yield 2; }()); + return a === 1 && b === 2 && c === void undefined; + */ + }, + res: { + tr: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox34: true, + opera10_50: false, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + safari10: true, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generic iterables', + exec() { + /* + var a,b,c; + [a, b, c] = global.__createIterableObject([1, 2]); + return a === 1 && b === 2 && c === void undefined; + */ + }, + res: { + tr: true, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + babel6corejs2: babel.corejs, + closure: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with instances of generic iterables', + exec() { + /* + var a,b,c; + [a, b, c] = Object.create(global.__createIterableObject([1, 2])); + return a === 1 && b === 2 && c === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'iterator closing', + exec() { + /* + var closed = false; + var iter = global.__createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + var a,b; + [a, b] = iter; + return closed; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + chrome51: true, + node6_5: true, + ie11: false, + edge15: true, + firefox2: false, + firefox53: true, + opera10_50: false, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'iterable destructuring expression', + exec() { + /* + var a, b, iterable = [1,2]; + return ([a, b] = iterable) === iterable; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: true, + es6tr: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'chained iterable destructuring', + exec() { + /* + var a,b,c,d; + [a,b] = [c,d] = [1,2]; + return a === 1 && b === 2 && c === 1 && d === 2; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: true, + es6tr: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'trailing commas in iterable patterns', + exec() { + /* + var a; + [a,] = [1]; + return a === 1; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with objects', + exec() { + /* + var c,d,e; + ({c, x:d, e} = {c:7, x:8}); + return c === 7 && d === 8 && e === void undefined; + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: { + val: false, + note_id: 'ff11-object-destructuring', + note_html: + 'Firefox < 16 incorrectly treats ({f,g} = {f:9,g:10}) as assigning to global variables instead of locals.', + }, + firefox15: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'object destructuring with primitives', + exec() { + /* + var toFixed, slice; + ({toFixed} = 2); + ({slice} = ''); + return toFixed === Number.prototype.toFixed + && slice === String.prototype.slice; + */ + }, + res: { + tr: true, + babel6corejs2: true, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + firefox3_5: false, + firefox15: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'trailing commas in object patterns', + exec() { + /* + var a; + ({a,} = {a:1}); + return a === 1; + */ + }, + res: { + tr: true, + babel6corejs2: true, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + firefox4: false, + firefox15: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'object destructuring expression', + exec() { + /* + var a, b, obj = { a:1, b:2 }; + return ({a,b} = obj) === obj; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + es6tr: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'parenthesised left-hand-side is a syntax error', + exec() { + /* + var a, b; + ({a,b} = {a:1,b:2}); + try { + eval("({a,b}) = {a:3,b:4};"); + } + catch(e) { + return a === 1 && b === 2; + } + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + safari7_1: true, + firefox2: false, + firefox41: true, + opera10_50: false, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'chained object destructuring', + exec() { + /* + var a,b,c,d; + ({a,b} = {c,d} = {a:1,b:2,c:3,d:4}); + return a === 1 && b === 2 && c === 3 && d === 4; + */ + }, + res: { + tr: true, + firefox2: false, + firefox3: true, + firefox3_5: false, + firefox15: true, + opera10_50: false, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + es6tr: true, + safari10: true, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'throws on null and undefined', + exec() { + /* + var a,b; + try { + ({a} = null); + return false; + } catch(e) { + if (!(e instanceof TypeError)) + return false; + } + try { + ({b} = void undefined); + return false; + } catch(e) { + if (!(e instanceof TypeError)) + return false; + } + return true; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + ejs: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'computed properties', + exec() { + /* + var grault, qux = "corge"; + ({ [qux]: grault } = { corge: "garply" }); + return grault === "garply"; + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + tr: true, + es6tr: true, + firefox2: false, + firefox34: true, + opera10_50: false, + ie11: false, + edge13: edge.experimental, + edge14: true, + safari10: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'nested', + exec() { + /* + var e,f,g,h,i; + [e, {x:f, g}] = [9, {x:10}]; + ({h, x:[i]} = {h:11, x:[12]}); + return e === 9 && f === 10 && g === void undefined + && h === 11 && i === 12; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + firefox3_5: false, + firefox4: false, + firefox15: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'rest', + exec() { + /* + var a,b,c,d; + [a, ...b] = [3, 4, 5]; + [c, ...d] = [6]; + return a === 3 && b instanceof Array && (b + "") === "4,5" && + c === 6 && d instanceof Array && d.length === 0; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + jsx: true, + closure: true, + firefox2: false, + firefox34: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'nested rest', + exec() { + /* + var a = [1, 2, 3], first, last; + [first, ...[a[2], last]] = a; + return first === 1 && last === 3 && (a + "") === "1,2,2"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox47: true, + opera10_50: false, + xs6: true, + safari10: true, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'empty patterns', + exec() { + /* + [] = [1,2]; + ({} = {a:1,b:2}); + return true; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'defaults', + exec() { + /* + var a,b,c,d,e,f; + ({a = 1, b = 0, z:c = 3} = {b:2, z:undefined}); + [d = 0, e = 5, f = 6] = [4,,undefined]; + return a === 1 && b === 2 && c === 3 + && d === 4 && e === 5 && f === 6; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + closure: true, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox47: true, + opera10_50: false, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'destructuring, parameters', + category: 'syntax', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-destructuring-assignment', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment', + subtests: [ + { + name: 'with arrays', + exec() { + /* + return function([a, , [b], c]) { + return a === 5 && b === 6 && c === void undefined; + }([5, null, [6]]); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with sparse arrays', + exec() { + /* + return function([a, , b]) { + return a === void undefined && b === void undefined; + }([,,,]); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with strings', + exec() { + /* + return function([a, b, c]) { + return a === "a" && b === "b" && c === void undefined; + }("ab"); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + es6tr: true, + jsx: true, + ejs: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with astral plane strings', + exec() { + /* + return function([c]) { + return c === "𠮷"; + }("𠮷𠮶"); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox34: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generator instances', + exec() { + /* + return function([a, b, c]) { + return a === 1 && b === 2 && c === void undefined; + }(function*(){ yield 1; yield 2; }()); + */ + }, + res: { + tr: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox34: true, + opera10_50: false, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + safari5_1: false, + safari10: true, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with generic iterables', + exec() { + /* + return function([a, b, c]) { + return a === 1 && b === 2 && c === void undefined; + }(global.__createIterableObject([1, 2])); + */ + }, + res: { + tr: true, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + babel6corejs2: babel.corejs, + closure: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'with instances of generic iterables', + exec() { + /* + return function([a, b, c]) { + return a === 1 && b === 2 && c === void undefined; + }(Object.create(global.__createIterableObject([1, 2]))); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + typescript1corejs2: typescript.downlevelIteration, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'iterator closing', + exec() { + /* + var closed = false; + var iter = global.__createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + (function([a,b]) {}(iter)); + return closed; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.downlevelIteration, + ie11: false, + edge15: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome51: true, + node6_5: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'trailing commas in iterable patterns', + exec() { + /* + return function([a,]) { + return a === 1; + }([1]); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + ejs: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'with objects', + exec() { + /* + return function({c, x:d, e}) { + return c === 7 && d === 8 && e === void undefined; + }({c:7, x:8}); + */ + }, + res: { + tr: true, + babel6corejs2: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: { + val: true, + note_id: 'ff11-object-destructuring', + note_html: + 'Firefox < 16 incorrectly treats ({f,g} = {f:9,g:10}) as assigning to global variables instead of locals.', + }, + firefox16: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'object destructuring with primitives', + exec() { + /* + return function({toFixed}, {slice}) { + return toFixed === Number.prototype.toFixed + && slice === String.prototype.slice; + }(2,''); + */ + }, + res: { + tr: true, + babel6corejs2: true, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'trailing commas in object patterns', + exec() { + /* + return function({a,}) { + return a === 1; + }({a:1}); + */ + }, + res: { + tr: true, + babel6corejs2: true, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'throws on null and undefined', + exec() { + /* + try { + (function({a}){}(null)); + return false; + } catch(e) {} + try { + (function({b}){}(undefined)); + return false; + } catch(e) {} + return true; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure: true, + ejs: true, + es6tr: true, + jsx: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'computed properties', + exec() { + /* + var qux = "corge"; + return function({ [qux]: grault }) { + return grault === "garply"; + }({ corge: "garply" }); + */ + }, + res: { + babel6corejs2: true, + typescript1corejs2: true, + closure: true, + tr: true, + es6tr: true, + firefox2: false, + firefox35: true, + opera10_50: false, + ie11: false, + edge13: edge.experimental, + edge14: true, + safari10: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'nested', + exec() { + /* + return function([e, {x:f, g}], {h, x:[i]}) { + return e === 9 && f === 10 && g === void undefined + && h === 11 && i === 12; + }([9, {x:10}],{h:11, x:[12]}); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: "'arguments' interaction", + exec() { + /* + return (function({a, x:b, y:e}, [c, d]) { + return arguments[0].a === 1 && arguments[0].x === 2 + && !("y" in arguments[0]) && arguments[1] + '' === "3,4"; + }({a:1, x:2}, [3, 4])); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + jsx: true, + closure: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + jxa: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'new Function() support', + exec() { + /* + return new Function("{a, x:b, y:e}","[c, d]", + "return a === 1 && b === 2 && c === 3 && " + + "d === 4 && e === void undefined;" + )({a:1, x:2}, [3, 4]); + */ + }, + res: { + safari7_1: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox53: true, + opera10_50: false, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: "in parameters, function 'length' property", + exec() { + /* + return function({a, b}, [c, d]){}.length === 2; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + jsx: true, + closure: true, + firefox2: false, + firefox3: true, + opera10_50: false, + safari7_1: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'rest', + exec() { + /* + return function([a, ...b], [c, ...d]) { + return a === 3 && b instanceof Array && (b + "") === "4,5" && + c === 6 && d instanceof Array && d.length === 0; + }([3, 4, 5], [6]); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + jsx: true, + closure: true, + firefox2: false, + firefox34: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'empty patterns', + exec() { + /* + return function ([],{}){ + return arguments[0] + '' === "3,4" && arguments[1].x === "foo"; + }([3,4],{x:"foo"}); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + es6tr: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + opera10_50: false, + safari9: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'defaults', + exec() { + /* + return (function({a = 1, b = 0, c = 3, x:d = 0, y:e = 5}, + [f = 6, g = 0, h = 8]) { + return a === 1 && b === 2 && c === 3 && d === 4 && + e === 5 && f === 6 && g === 7 && h === 8; + }({b:2, c:undefined, x:4},[, 7, undefined])); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: true, + es6tr: true, + closure: true, + safari10: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox47: true, + opera10_50: false, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'defaults, separate scope', + exec() { + /* + return (function({a=function(){ + return typeof b === 'undefined'; + }}){ + var b = 1; + return a(); + }({})); + */ + }, + res: { + babel6corejs2: false, + closure: true, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox51: true, + opera10_50: false, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'defaults, new Function() support', + exec() { + /* + return new Function("{a = 1, b = 0, c = 3, x:d = 0, y:e = 5}", + "return a === 1 && b === 2 && c === 3 && d === 4 && e === 5;" + )({b:2, c:undefined, x:4}); + */ + }, + res: { + safari10: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge13: edge.experimental, + edge14: true, + firefox2: false, + firefox53: true, + opera10_50: false, + xs6: true, + ejs: { val: false, note_id: 'ejs-no-function-ctor' }, + chrome49: true, + node6: true, + node6_5: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'aliased defaults, arrow function', + exec() { + /* + return ((a, {b: x = 0, c: y = 3}) => { + return a === 1 && x === 2 && y === 3; + })(1, {b: 2}); + */ + }, + res: { + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + tr: true, + ie11: false, + edge12: false, + edge15: true, + chrome47: chrome.experimental, + chrome49: true, + firefox50: false, + firefox52: true, + opera10_50: false, + node6: true, + node6_5: true, + node8: true, + safari9: false, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'shorthand defaults, arrow function', + exec() { + /* + return ((a, {b = 0, c = 3}) => { + return a === 1 && b === 2 && c === 3; + })(1, {b: 2}); + */ + }, + res: { + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + tr: true, + ie11: false, + edge15: false, + edge18: true, + chrome47: chrome.experimental, + chrome49: true, + firefox50: false, + firefox52: true, + opera10_50: false, + node6: true, + node6_5: true, + node8: true, + safari9: false, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'duplicate identifier', + exec() { + /* + try { + eval('var d = function d([d]) { return d };'); + if (d([true]) !== true) return false; + } catch (e) { + return !(e instanceof SyntaxError); + } + + try { + eval('var f = function f([id, id]) { return id }'); + return false; + } catch (e) { + return e instanceof SyntaxError; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + es6tr: true, + jsx: true, + closure: true, + typescript1corejs2: true, + firefox2: true, + safari11: false, + safari16_2: false, + safari16_3: true, + edge13: edge.experimental, + edge14: true, + xs6: true, + chrome49: true, + node6: true, + node6_5: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Promise', + category: 'built-ins', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise', + subtests: [ + { + name: 'basic functionality', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise', + exec() { + /* + var p1 = new Promise(function(resolve, reject) { resolve("foo"); }); + var p2 = new Promise(function(resolve, reject) { reject("quux"); }); + var score = 0; + + function thenFn(result) { score += (result === "foo"); check(); } + function catchFn(result) { score += (result === "quux"); check(); } + function shouldNotRun(result) { score = -Infinity; } + + p1.then(thenFn, shouldNotRun); + p2.then(shouldNotRun, catchFn); + p1.catch(shouldNotRun); + p2.catch(catchFn); + + p1.then(function() { + // Promise.prototype.then() should return a new Promise + score += p1.then() !== p1; + check(); + }); + + function check() { + if (score === 4) asyncTestPassed(); + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + opera10_50: false, + chrome33: true, + safari7_1: true, + node0_12: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'constructor requires new', + exec() { + /* + new Promise(function(){}); + try { + Promise(function(){}); + return false; + } catch(e) { + return true; + } + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + firefox2: false, + firefox30: true, + opera10_50: false, + ie11: false, + edge12: true, + chrome33: true, + node4: true, + safari10: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: "Promise.prototype isn't an instance", + exec() { + /* + new Promise(function(){}); + try { + Promise.prototype.then(function(){}); + } catch (e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + firefox31: false, + firefox45: true, + opera10_50: false, + chrome33: true, + safari7_1: true, + node0_12: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'Promise.all', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all', + exec() { + /* + var fulfills = Promise.all([ + new Promise(function(resolve) { setTimeout(resolve,2000,"foo"); }), + new Promise(function(resolve) { setTimeout(resolve,1000,"bar"); }) + ]); + var rejects = Promise.all([ + new Promise(function(_, reject) { setTimeout(reject, 2000,"baz"); }), + new Promise(function(_, reject) { setTimeout(reject, 1000,"qux"); }) + ]); + var score = 0; + fulfills.then(function(result) { score += (result + "" === "foo,bar"); check(); }); + rejects.catch(function(result) { score += (result === "qux"); check(); }); + + function check() { + if (score === 2) asyncTestPassed(); + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + opera10_50: false, + chrome33: true, + safari7_1: true, + node0_12: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Promise.all, generic iterables', + exec() { + /* + var fulfills = Promise.all(global.__createIterableObject([ + new Promise(function(resolve) { setTimeout(resolve,2000,"foo"); }), + new Promise(function(resolve) { setTimeout(resolve,1000,"bar"); }) + ])); + var rejects = Promise.all(global.__createIterableObject([ + new Promise(function(_, reject) { setTimeout(reject, 2000,"baz"); }), + new Promise(function(_, reject) { setTimeout(reject, 1000,"qux"); }) + ])); + var score = 0; + fulfills.then(function(result) { score += (result + "" === "foo,bar"); check(); }); + rejects.catch(function(result) { score += (result === "qux"); check(); }); + + function check() { + if (score === 2) asyncTestPassed(); + } + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + es6shim: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome43: true, + safari9: true, + node4: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Promise.race', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race', + exec() { + /* + var fulfills = Promise.race([ + new Promise(function(resolve) { setTimeout(resolve,1000,"foo"); }), + new Promise(function(_, reject) { setTimeout(reject, 2000,"bar"); }) + ]); + var rejects = Promise.race([ + new Promise(function(_, reject) { setTimeout(reject, 1000,"baz"); }), + new Promise(function(resolve) { setTimeout(resolve,2000,"qux"); }) + ]); + var score = 0; + fulfills.then(function(result) { score += (result === "foo"); check(); }); + rejects.catch(function(result) { score += (result === "baz"); check(); }); + + function check() { + if (score === 2) asyncTestPassed(); + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + opera10_50: false, + chrome33: true, + safari10: true, + safari7_1: true, + node0_12: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Promise.race, generic iterables', + exec() { + /* + var fulfills = Promise.race(global.__createIterableObject([ + new Promise(function(resolve) { setTimeout(resolve,1000,"foo"); }), + new Promise(function(_, reject) { setTimeout(reject, 2000,"bar"); }) + ])); + var rejects = Promise.race(global.__createIterableObject([ + new Promise(function(_, reject) { setTimeout(reject, 1000,"baz"); }), + new Promise(function(resolve) { setTimeout(resolve,2000,"qux"); }) + ])); + var score = 0; + fulfills.then(function(result) { score += (result === "foo"); check(); }); + rejects.catch(function(result) { score += (result === "baz"); check(); }); + + function check() { + if (score === 2) asyncTestPassed(); + } + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + es6shim: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome43: true, + safari9: true, + node4: true, + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Promise[Symbol.species]', + exec() { + /* + var prop = Object.getOwnPropertyDescriptor(Promise, Symbol.species); + return 'get' in prop && Promise[Symbol.species] === Promise; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + ], + }, + { + name: 'Object static methods', + category: 'built-in extensions', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-object-constructor', + subtests: [ + { + name: 'Object.assign', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign', + exec() { + /* + var o = Object.assign({a:true}, {b:true}, {c:true}); + return "a" in o && "b" in o && "c" in o; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + safari9: true, + chrome45: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.is', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is', + exec() { + /* + return typeof Object.is === 'function' && + Object.is(NaN, NaN) && + !Object.is(-0, 0); + */ + }, + res: { + tr: true, + ejs: true, + es6shim: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox22: true, + opera10_50: false, + chrome19: true, + safari9: true, + konq4_14: true, + node0_12: true, + android4_1: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.getOwnPropertySymbols', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols', + exec() { + /* + var o = {}; + var sym = Symbol(), sym2 = Symbol(), sym3 = Symbol(); + o[sym] = true; + o[sym2] = true; + o[sym3] = true; + var result = Object.getOwnPropertySymbols(o); + return result[0] === sym + && result[1] === sym2 + && result[2] === sym3; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + tr: true, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome34: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.setPrototypeOf', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf', + exec() { + /* + return Object.setPrototypeOf({}, Array.prototype) instanceof Array; + */ + }, + res: { + ejs: true, + babel6corejs2: { val: false, note_id: 'compiler-proto' }, + closure: { val: false, note_id: 'compiler-proto' }, + typescript1corejs2: { val: false, note_id: 'compiler-proto' }, + es6shim: { val: false, note_id: 'compiler-proto' }, + ie11: true, + firefox2: false, + firefox31: true, + opera10_50: false, + chrome34: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'Object static methods accept primitives', + category: 'misc', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-object-constructor', + subtests: [ + { + name: 'Object.getPrototypeOf', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf', + exec() { + /* + return Object.getPrototypeOf('a').constructor === String; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox3_5: true, + firefox4: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.getOwnPropertyDescriptor', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor', + exec() { + /* + return Object.getOwnPropertyDescriptor('a', 'foo') === void undefined; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.getOwnPropertyNames', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames', + exec() { + /* + var s = Object.getOwnPropertyNames('a'); + return s.length === 2 && + ((s[0] === 'length' && s[1] === '0') || (s[0] === '0' && s[1] === 'length')); + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox33: true, + opera10_50: false, + chrome40: true, + node4: true, + es6shim: true, + safari9: true, + chrome44: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.seal', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal', + exec() { + /* + return Object.seal('a') === 'a'; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.freeze', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze', + exec() { + /* + return Object.freeze('a') === 'a'; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.preventExtensions', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions', + exec() { + /* + return Object.preventExtensions('a') === 'a'; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.isSealed', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed', + exec() { + /* + return Object.isSealed('a') === true; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.isFrozen', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen', + exec() { + /* + return Object.isFrozen('a') === true; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.isExtensible', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible', + exec() { + /* + return Object.isExtensible('a') === false; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox35: true, + opera10_50: false, + safari9: true, + chrome44: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.keys', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys', + exec() { + /* + var s = Object.keys('a'); + return s.length === 1 && s[0] === '0'; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox35: true, + opera10_50: false, + chrome40: true, + safari9: true, + node4: true, + chrome44: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'Object.prototype.__proto__', + category: 'annex b', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-object.prototype.__proto__', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto', + subtests: [ + { + name: 'get prototype', + exec() { + /* + var A = function(){}; + return (new A()).__proto__ === A.prototype; + */ + }, + res: { + ie11: true, + firefox2: true, + chrome5: true, + deno1_0: false, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + ejs: true, + jxa: true, + duktape1_0: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'set prototype', + exec() { + /* + var o = {}; + o.__proto__ = Array.prototype; + return o instanceof Array; + */ + }, + res: { + ie11: true, + firefox2: true, + chrome5: true, + deno1_0: false, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'absent from Object.create(null)', + exec() { + /* + var o = Object.create(null), p = {}; + o.__proto__ = p; + return Object.getPrototypeOf(o) !== p; + */ + }, + res: { + ie11: true, + firefox2: false, + firefox4: true, + chrome30: true, + safari6: true, + opera10_50: false, + opera12_10: true, + node0_12: true, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'present in hasOwnProperty()', + exec() { + /* + return Object.prototype.hasOwnProperty('__proto__'); + */ + }, + res: { + konq4_14: true, + ie11: true, + firefox2: true, + chrome30: true, + deno1_0: false, + safari3_1: true, + opera10_50: false, + opera12_10: true, + node0_12: true, + xs6: true, + jxa: true, + android4_0: true, + android4_1: false, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'correct property descriptor', + exec() { + /* + var desc = Object.getOwnPropertyDescriptor(Object.prototype,"__proto__"); + var A = function(){}; + + return (desc + && "get" in desc + && "set" in desc + && desc.configurable + && !desc.enumerable); + */ + }, + res: { + ie11: true, + firefox2: false, + firefox17: true, + chrome30: true, + deno1_0: false, + safari6: true, + opera10_50: false, + opera12_10: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'present in Object.getOwnPropertyNames()', + exec() { + /* + return Object.getOwnPropertyNames(Object.prototype).indexOf('__proto__') > -1; + */ + }, + res: { + ie11: true, + firefox2: false, + firefox7: true, + firefox10: false, + firefox39: true, + chrome30: true, + deno1_0: false, + safari6: true, + opera10_50: false, + opera12_10: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'function "name" property', + category: 'built-in extensions', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-setfunctionname', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name', + subtests: [ + { + name: 'function statements', + exec() { + /* + function foo(){}; + return foo.name === 'foo' && + (function(){}).name === ''; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + firefox2: true, + chrome5: true, + safari4: true, + opera10_50: true, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + ie11: false, + edge12: true, + edge13: false, + edge14: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'function expressions', + exec() { + /* + return (function foo(){}).name === 'foo' && + (function(){}).name === ''; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + firefox2: true, + chrome5: true, + safari4: true, + opera10_50: true, + opera12: true, + konq4_14: true, + node0_12: true, + android4_0: true, + ie11: false, + edge12: true, + edge13: false, + edge14: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'new Function', + exec() { + /* + return (new Function).name === "anonymous"; + */ + }, + res: { + firefox2: true, + opera10_50: false, + ie11: false, + edge12: true, + safari4: true, + konq4_14: true, + android4_0: true, + android4_1: false, + chrome48: true, + node6: true, + node6_5: true, + xs6: true, + ejs: { val: false, note_id: 'ejs-no-function-ctor' }, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'bound functions', + exec() { + /* + function foo() {}; + return foo.bind({}).name === "bound foo" && + (function(){}).bind({}).name === "bound "; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox47: true, + opera10_50: false, + chrome45: true, + node4: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'variables (function)', + exec() { + /* + var foo = function() {}; + var bar = function baz() {}; + return foo.name === "foo" && bar.name === "baz"; + */ + }, + res: { + ie11: false, + edge12: edge.experimental, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + node6_5: true, + babel6corejs2: babel.corejs, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'object methods (function)', + exec() { + /* + var o = { foo: function(){}, bar: function baz(){}}; + o.qux = function(){}; + return o.foo.name === "foo" && + o.bar.name === "baz" && + o.qux.name === ""; + */ + }, + res: { + babel6corejs2: babel.corejs, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + node6_5: true, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'accessor properties', + exec() { + /* + var o = { get foo(){}, set foo(x){} }; + var descriptor = Object.getOwnPropertyDescriptor(o, "foo"); + return descriptor.get.name === "get foo" && + descriptor.set.name === "set foo"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + node6_5: true, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'shorthand methods', + exec() { + /* + var o = { foo(){} }; + return o.foo.name === "foo"; + */ + }, + res: { + babel6corejs2: babel.corejs, + firefox2: false, + firefox34: true, + opera10_50: false, + ie11: false, + edge12: edge.experimental, + edge13: true, + chrome41: chrome.experimental, + chrome42: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'shorthand methods (no lexical binding)', + exec() { + /* + var f = "foo"; + return ({f() { return f; }}).f() === "foo"; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + firefox2: false, + firefox34: true, + opera10_50: false, + ie11: false, + edge12: true, + chrome41: chrome.experimental, + chrome42: true, + node4: true, + xs6: true, + ejs: true, + jxa: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'symbol-keyed methods', + exec() { + /* + var sym1 = Symbol("foo"); + var sym2 = Symbol(); + var o = { + [sym1]: function(){}, + [sym2]: function(){} + }; + + return o[sym1].name === "[foo]" && + o[sym2].name === ""; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + node6_5: true, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'class statements', + exec() { + /* + class foo {}; + class bar { static name() {} }; + return foo.name === "foo" && + typeof bar.name === "function"; + */ + }, + res: { + babel6corejs2: { + val: false, + note_id: 'name-configurable', + note_html: 'Requires function "name" properties to be natively configurable', + }, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'class expressions', + exec() { + /* + return class foo {}.name === "foo" && + typeof class bar { static name() {} }.name === "function"; + */ + }, + res: { + babel6corejs2: { val: false, note_id: 'name-configurable' }, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'variables (class)', + exec() { + /* + var foo = class {}; + var bar = class baz {}; + var qux = class { static name() {} }; + return foo.name === "foo" && + bar.name === "baz" && + typeof qux.name === "function"; + */ + }, + res: { + babel6corejs2: { val: false, note_id: 'name-configurable' }, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + node6_5: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'object methods (class)', + exec() { + /* + var o = { foo: class {}, bar: class baz {}}; + o.qux = class {}; + return o.foo.name === "foo" && + o.bar.name === "baz" && + o.qux.name === ""; + */ + }, + res: { + babel6corejs2: false, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + node6_5: true, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'class prototype methods', + exec() { + /* + class C { foo(){} }; + return (new C).foo.name === "foo"; + */ + }, + res: { + babel6corejs2: babel.corejs, + ie11: false, + edge12: edge.experimental, + edge13: true, + edge14: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'class static methods', + exec() { + /* + class C { static foo(){} }; + return C.foo.name === "foo"; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari9: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: "isn't writable, is configurable", + exec() { + /* + var descriptor = Object.getOwnPropertyDescriptor(function f(){},"name"); + return descriptor.enumerable === false && + descriptor.writable === false && + descriptor.configurable === true; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox38: true, + opera10_50: false, + chrome43: true, + node4: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'String static methods', + category: 'built-in extensions', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-string-constructor', + subtests: [ + { + name: 'String.raw', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw', + exec() { + /* + return typeof String.raw === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure20211006: true, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome41: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'String.fromCodePoint', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint', + exec() { + /* + return typeof String.fromCodePoint === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + opera10_50: false, + chrome38: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'String.prototype methods', + category: 'built-in extensions', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-string-prototype-object', + subtests: [ + { + name: 'String.prototype.codePointAt', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt', + exec() { + /* + return typeof String.prototype.codePointAt === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + opera10_50: false, + chrome38: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.normalize', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize', + exec() { + /* + return typeof String.prototype.normalize === "function" + && "c\u0327\u0301".normalize("NFC") === "\u1e09" + && "\u1e09".normalize("NFD") === "c\u0327\u0301"; + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox31: true, + opera10_50: false, + chrome34: true, + chrome41: true, + node4: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.repeat', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat', + exec() { + /* + return typeof String.prototype.repeat === 'function' + && "foo".repeat(3) === "foofoofoo"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox24: true, + opera10_50: false, + safari9: true, + chrome30: chrome.experimental, + chrome41: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.startsWith', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith', + exec() { + /* + return typeof String.prototype.startsWith === 'function' + && "foobar".startsWith("foo"); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox17: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_1: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.startsWith throws on RegExp', + exec() { + /* + try { + "a".startsWith(/./); + } catch(e) { + return typeof String.prototype.startsWith === 'function'; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox17: false, + firefox29: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_1: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.endsWith', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith', + exec() { + /* + return typeof String.prototype.endsWith === 'function' + && "foobar".endsWith("bar"); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox17: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_1: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.endsWith throws on RegExp', + exec() { + /* + try { + "a".endsWith(/./); + } catch(e) { + return typeof String.prototype.endsWith === 'function'; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox29: true, + opera10_50: false, + chrome30: false, + chrome34: chrome.experimental, + chrome41: true, + safari9: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_1: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype.includes', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes', + exec() { + /* + return typeof String.prototype.includes === 'function' + && "foobar".includes("oba"); + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + firefox2: false, + firefox18: { + val: false, + note_id: 'string-contains', + note_html: 'Available as the draft standard String.prototype.contains', + }, + firefox40: true, + opera10_50: false, + chrome30: { val: false, note_id: 'string-contains' }, + chrome41: true, + safari9: true, + node0_12: { val: 'flagged', note_id: 'string-contains' }, + node4: true, + ie11: false, + edge12: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_1: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String.prototype[Symbol.iterator]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/@@iterator', + exec() { + /* + return typeof String.prototype[Symbol.iterator] === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome37: chrome.experimental, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'String iterator prototype chain', + exec() { + /* + // Iterator instance + var iterator = ''[Symbol.iterator](); + // %StringIteratorPrototype% + var proto1 = Object.getPrototypeOf(iterator); + // %IteratorPrototype% + var proto2 = Object.getPrototypeOf(proto1); + + return proto2.hasOwnProperty(Symbol.iterator) && + !proto1 .hasOwnProperty(Symbol.iterator) && + !iterator .hasOwnProperty(Symbol.iterator) && + iterator[Symbol.iterator]() === iterator; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + safari9: true, + chrome45: true, + node4: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'String.prototype HTML methods', + category: 'annex b', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-string.prototype.anchor', + subtests: [ + { + name: 'existence', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/prototype#HTML_wrapper_methods', + exec() { + /* + var i, names = ["anchor", "big", "bold", "fixed", "fontcolor", "fontsize", + "italics", "link", "small", "strike", "sub", "sup"]; + for (i = 0; i < names.length; i++) { + if (typeof String.prototype[names[i]] !== 'function') { + return false; + } + } + return true; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie10: true, + firefox2: false, + firefox3: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: false, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + { + name: "tags' names are lowercase", + exec() { + /* + var i, names = ["anchor", "big", "bold", "fixed", "fontcolor", "fontsize", + "italics", "link", "small", "strike", "sub", "sup"]; + for (i = 0; i < names.length; i++) { + if (""[names[i]]().toLowerCase() !== ""[names[i]]()) { + return false; + } + } + return true; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: false, + edge12: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: false, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + { + name: 'quotes in arguments are escaped', + exec() { + /* + var i, names = ["anchor", "fontcolor", "fontsize", "link"]; + for (i = 0; i < names.length; i++) { + if (""[names[i]]('"') !== ""[names[i]]('&' + 'quot;')) { + return false; + } + } + return true; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox17: true, + opera10_50: false, + chrome5: true, + safari6: true, + konq4_14: true, + node0_12: true, + android4_0: true, + xs6: false, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + ], + }, + { + name: 'Unicode code point escapes', + category: 'syntax', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-literals-string-literals', + subtests: [ + { + name: 'in strings', + exec() { + /* + return '\u{1d306}' === '\ud834\udf06'; + */ + }, + res: { + tr: true, + babel6corejs2: true, + typescript1corejs2: true, + es6tr: true, + ejs: true, + closure: true, + ie11: false, + edge12: true, + safari9: true, + chrome44: true, + firefox2: false, + firefox40: true, + opera10_50: false, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'in identifiers', + exec() { + /* + var \u{102C0} = 2; + return \u{102C0} === 2; + */ + }, + res: { + closure20200517: true, + ejs: true, + ie11: false, + edge12: true, + chrome44: true, + firefox2: false, + firefox53: true, + opera10_50: false, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_4_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'in property key definitions', + exec() { + /* + var o = { \u{102C0} : 2 }; + return o['\ud800\udec0'] === 2; + */ + }, + res: { + closure20200517: false, + ejs: true, + edge12: true, + chrome44: true, + firefox2: false, + firefox53: true, + opera10_50: false, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_4_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'in property key accesses', + exec() { + /* + var o = { '\ud800\udec0' : 2 }; + return o.\u{102C0} === 2; + */ + }, + res: { + closure20200517: false, + edge12: true, + chrome44: true, + firefox2: false, + firefox53: true, + opera10_50: false, + safari9: true, + node4: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_4_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'new.target', + category: 'syntax', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-built-in-function-objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new.target', + subtests: [ + { + name: 'in constructors', + exec() { + /* + var passed = false; + new function f() { + passed = (new.target === f); + }(); + (function() { + passed &= (new.target === void undefined); + }()); + return passed; + */ + }, + res: { + closure: false, + closure20200517: true, + firefox2: false, + firefox41: true, + opera10_50: false, + safari10: true, + chrome46: true, + ie11: false, + edge13: true, + node5: true, + xs6: true, + ejs: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'assignment is an early error', + exec() { + /* + var passed = false; + new function f() { + passed = (new.target === f); + }(); + + try { + Function("new.target = function(){};"); + } catch(e) { + return passed; + } + */ + }, + res: { + babel7corejs2: true, + closure: false, + closure20200517: true, + firefox2: false, + firefox41: true, + opera10_50: false, + chrome46: true, + ie11: false, + edge14: true, + node5: true, + xs6: true, + ejs: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Symbol', + category: 'built-ins', + significance: 'large', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-symbol-constructor', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + var object = {}; + var symbol = Symbol(); + var value = {}; + object[symbol] = value; + return object[symbol] === value; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome30: chrome.experimental, // Actually Chrome 29 + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'typeof support', + exec() { + /* + return typeof Symbol() === "symbol"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.fallthrough, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome30: chrome.experimental, // Actually Chrome 29 + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'symbol keys are hidden to pre-ES6 code', + exec() { + /* + var object = {}; + var symbol = Symbol(); + object[symbol] = 1; + + for (var x in object){} + var passed = !x; + + if (Object.keys && Object.getOwnPropertyNames) { + passed &= Object.keys(object).length === 0 + && Object.getOwnPropertyNames(object).length === 0; + } + + return passed; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome30: chrome.experimental, // Actually Chrome 29 + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object.defineProperty support', + exec() { + /* + var object = {}; + var symbol = Symbol(); + var value = {}; + + if (Object.defineProperty) { + Object.defineProperty(object, symbol, { value: value }); + return object[symbol] === value; + } + + return passed; + */ + }, + res: { + tr: true, + typescript1corejs2: typescript.corejs, + ejs: true, + babel6corejs2: babel.corejs, + closure: true, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome30: chrome.experimental, // Actually Chrome 29 + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'symbols inherit from Symbol.prototype', + exec() { + /* + var symbol = Symbol(); + var passed = symbol.foo === void undefined; + Symbol.prototype.foo = 2; + passed &= symbol.foo === 2; + delete Symbol.prototype.foo; + return passed; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome30: chrome.experimental, // Actually Chrome 29 + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'cannot coerce to string or number', + exec() { + /* + var symbol = Symbol(); + + try { + symbol + ""; + return false; + } + catch(e) {} + + try { + symbol + 0; + return false; + } catch(e) {} + + return true; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'can convert with String()', + exec() { + /* + return String(Symbol("foo")) === "Symbol(foo)"; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + chrome39: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'new Symbol() throws', + exec() { + /* + var symbol = Symbol(); + try { + new Symbol(); + } catch(e) { + return true; + } + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure20190301: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome35: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Object(symbol)', + exec() { + /* + var symbol = Symbol(); + var symbolObject = Object(symbol); + + return typeof symbolObject === "object" && + symbolObject instanceof Symbol && + symbolObject == symbol && // eslint-disable-line eqeqeq + symbolObject !== symbol && + symbolObject.valueOf() === symbol; + */ + }, + res: { + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome35: false, + chrome48: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_1: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'JSON.stringify ignores symbol primitives', + exec() { + /* + var object = { foo: Symbol() }; + object[Symbol()] = 1; + var array = [Symbol()]; + return JSON.stringify(object) === '{}' && JSON.stringify(array) === '[null]' && JSON.stringify(Symbol()) === void undefined; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge13: true, + es6shim: true, + firefox2: false, + firefox35: false, + firefox36: true, + firefox48: true, + opera10_50: false, + chrome35: chrome.experimental, + chrome38: true, + chrome49: true, + chrome52: true, + node0_12: true, + node4: true, + node6: true, + safari9: false, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'JSON.stringify ignores symbol objects', + exec() { + /* + var testSymbolObject = function (sym) { + var object = { foo: sym }; + try { + // some browsers throw a TypeError when setting symbol object keys. + // this isn't part of this test, so, ignore it if so. + object[sym] = 1; + } catch (e) {} // some browsers throw a TypeError when setting symbol object keys. + var array = [sym]; + return JSON.stringify(object) === '{"foo":{}}' && JSON.stringify(array) === '[{}]' && JSON.stringify(sym) === '{}'; + }; + var objSym = Object(Symbol()); + var symNoToJSON = Object(Symbol()); + Object.defineProperty(symNoToJSON, 'toJSON', { enumerable: false, value: null }); // ensure it overrides the prototype, but is not callable + return testSymbolObject(objSym) && testSymbolObject(symNoToJSON); + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge13: true, + es6shim: true, + firefox2: false, + firefox35: false, + firefox36: true, + firefox48: true, + opera10_50: false, + node0_12: false, + node4: false, + node6: true, + chrome38: false, + chrome48: false, + chrome49: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'global symbol registry', + exec() { + /* + var symbol = Symbol.for('foo'); + return Symbol.for('foo') === symbol && + Symbol.keyFor(symbol) === 'foo'; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome35: chrome.experimental, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'well-known symbols', + category: 'built-ins', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-well-known-symbols', + note_id: 'symbol-iterator-functionality', + note_html: + 'Functionality for Symbol.iterator is tested by the "generic iterators" subtests for ' + + 'the spread (...) operator, for..of loops, ' + + 'destructuring, yield *, ' + + 'and Array.from.', + subtests: [ + { + name: 'Symbol.hasInstance', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance', + exec() { + /* + var passed = false; + var obj = { foo: true }; + var C = function(){}; + Object.defineProperty(C, Symbol.hasInstance, { + value: function(inst) { passed = inst.foo; return false; } + }); + obj instanceof C; + return passed; + */ + }, + res: { + babel6corejs2: babel.optional, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge15: true, + chrome50: chrome.experimental, + chrome51: true, + firefox2: false, + firefox50: true, + opera10_50: false, + ejs: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.isConcatSpreadable, non-spreadable array', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/isConcatSpreadable', + exec() { + /* + var a = [], b = []; + b[Symbol.isConcatSpreadable] = false; + a = a.concat(b); + return a[0] === b; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + edge15: true, + ejs: true, + chrome48: true, + firefox2: false, + firefox48: true, + opera10_50: false, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Symbol.isConcatSpreadable, spreadable object with poisoned getter', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/isConcatSpreadable', + exec() { + /* + if (typeof Symbol !== 'function' || !Symbol.isConcatSpreadable) { + return null; + } + var spreadableHasPoisonedIndex = { length: Math.pow(2, 53) - 1 }; + spreadableHasPoisonedIndex[Symbol.isConcatSpreadable] = true; + Object.defineProperty(spreadableHasPoisonedIndex, 0, { + get: function () { throw new SyntaxError(); } + }); + try { + [].concat(spreadableHasPoisonedIndex); + return false; + } catch (e) { + return !!e && e.name === 'SyntaxError'; + } + */ + }, + res: { + chrome48: false, + chrome100: false, + chrome101: false, + safari5_1: false, + safari9: false, + safari12_1: false, + safari13: false, + safari14: true, + safari15: true, + firefox48: true, + firefox60: true, + firefox70: true, + firefox99: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_15: true, + }, + }, + { + name: 'Symbol.iterator, existence', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator', + exec() { + /* + return "iterator" in Symbol; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + edge14: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome37: chrome.experimental, + chrome38: true, + ejs: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Symbol.iterator, arguments object', + exec() { + /* + return (function() { + return typeof arguments[Symbol.iterator] === 'function' + && Object.hasOwnProperty.call(arguments, Symbol.iterator); + }()); + */ + }, + res: { + chrome37: chrome.experimental, + chrome38: true, + safari9: true, + firefox2: false, + firefox46: true, + opera10_50: false, + node0_12: false, + node4: true, + node5: true, + ie11: false, + edge12: true, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Symbol.species, existence', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/species', + exec() { + /* + return "species" in Symbol; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + firefox2: false, + firefox41: true, + opera10_50: false, + ie11: false, + edge13: true, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: true, + }, + }, + { + name: 'Symbol.species, Array.prototype.concat', + exec() { + /* + var obj = []; + obj.constructor = {}; + obj.constructor[Symbol.species] = function() { + return { foo: 1 }; + }; + return Array.prototype.concat.call(obj, []).foo === 1; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ejs: true, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.species, Array.prototype.filter', + exec() { + /* + var obj = []; + obj.constructor = {}; + obj.constructor[Symbol.species] = function() { + return { foo: 1 }; + }; + return Array.prototype.filter.call(obj, Boolean).foo === 1; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ejs: true, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.species, Array.prototype.map', + exec() { + /* + var obj = []; + obj.constructor = {}; + obj.constructor[Symbol.species] = function() { + return { foo: 1 }; + }; + return Array.prototype.map.call(obj, Boolean).foo === 1; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ejs: true, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.species, Array.prototype.slice', + exec() { + /* + var obj = []; + obj.constructor = {}; + obj.constructor[Symbol.species] = function() { + return { foo: 1 }; + }; + return Array.prototype.slice.call(obj, 0).foo === 1; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + ejs: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.species, Array.prototype.splice', + exec() { + /* + var obj = []; + obj.constructor = {}; + obj.constructor[Symbol.species] = function() { + return { foo: 1 }; + }; + return Array.prototype.splice.call(obj, 0).foo === 1; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ejs: true, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.species, RegExp.prototype[Symbol.split]', + exec() { + /* + var passed = false; + var obj = { constructor: {} }; + obj[Symbol.split] = RegExp.prototype[Symbol.split]; + obj.constructor[Symbol.species] = function() { + passed = true; + return /./; + }; + "".split(obj); + return passed; + */ + }, + res: { + babel6corejs2: false, + babel7corejs3: babel.corejs, + typescript1corejs2: typescript.fallthrough, + typescript3_2corejs3: typescript.corejs, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome51: true, + xs6: true, + ejs: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.species, Promise.prototype.then', + exec() { + /* + var promise = new Promise(function(resolve){ resolve(42); }); + var FakePromise1 = promise.constructor = function(exec){ exec(function(){}, function(){}); }; + var FakePromise2 = function(exec){ exec(function(){}, function(){}); }; + Object.defineProperty(FakePromise1, Symbol.species, {value: FakePromise2}); + return promise.then(function(){}) instanceof FakePromise2; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge13: false, + edge14: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: null, + ejs: null, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'Symbol.replace', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/replace', + exec() { + /* + var O = {}; + O[Symbol.replace] = function(){ + return 42; + }; + return ''.replace(O) === 42; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + chrome50: true, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.search', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/search', + exec() { + /* + var O = {}; + O[Symbol.search] = function(){ + return 42; + }; + return ''.search(O) === 42; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + chrome50: true, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.split', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/split', + exec() { + /* + var O = {}; + O[Symbol.split] = function(){ + return 42; + }; + return ''.split(O) === 42; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + chrome50: true, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.match', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/match', + exec() { + /* + var O = {}; + O[Symbol.match] = function(){ + return 42; + }; + return ''.match(O) === 42; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + chrome50: true, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.match, RegExp constructor', + exec() { + /* + var re = /./; + re[Symbol.match] = false; + var foo = {constructor: RegExp}; + foo[Symbol.match] = true; + return RegExp(re) !== re && RegExp(foo) === foo; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox40: true, + opera10_50: false, + chrome50: true, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.match, String.prototype.startsWith', + exec() { + /* + var re = /./; + try { + '/./'.startsWith(re); + } catch(e){ + re[Symbol.match] = false; + return '/./'.startsWith(re); + } + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + firefox2: false, + firefox40: true, + opera10_50: false, + ie11: false, + edge14: edge.experimental, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Symbol.match, String.prototype.endsWith', + exec() { + /* + var re = /./; + try { + '/./'.endsWith(re); + } catch(e){ + re[Symbol.match] = false; + return '/./'.endsWith(re); + } + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + firefox2: false, + firefox40: true, + opera10_50: false, + ie11: false, + edge14: edge.experimental, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Symbol.match, String.prototype.includes', + exec() { + /* + var re = /./; + try { + '/./'.includes(re); + } catch(e){ + re[Symbol.match] = false; + return '/./'.includes(re); + } + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + firefox2: false, + firefox40: true, + opera10_50: false, + ie11: false, + edge14: edge.experimental, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Symbol.toPrimitive', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive', + exec() { + /* + var a = {}, b = {}, c = {}; + var passed = 0; + a[Symbol.toPrimitive] = function(hint) { passed += hint === "number"; return 0; }; + b[Symbol.toPrimitive] = function(hint) { passed += hint === "string"; return 0; }; + c[Symbol.toPrimitive] = function(hint) { passed += hint === "default"; return 0; }; + + a >= 0; + b in {}; + c == 0; // eslint-disable-line eqeqeq + return passed === 3; + */ + }, + res: { + ejs: true, + typescript1corejs2: typescript.fallthrough, + ie11: false, + edge15: true, + firefox2: false, + firefox44: true, + opera10_50: false, + chrome47: true, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.toStringTag', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag', + exec() { + /* + var a = {}; + a[Symbol.toStringTag] = "foo"; + return (a + "") === "[object foo]"; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome40: chrome.experimental, + chrome49: true, + node4: 'flagged', + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.toStringTag affects existing built-ins', + exec() { + /* + var s = Symbol.toStringTag; + var passed = true; + [ + [Array.prototype, []], + [String.prototype, ''], + [arguments, arguments], + [Function.prototype, function(){}], + [Error.prototype, new Error()], + [Boolean.prototype, true], + [Number.prototype, 2], + [Date.prototype, new Date()], + [RegExp.prototype, /./] + ].forEach(function(pair){ + pair[0][s] = "foo"; + passed &= (Object.prototype.toString.call(pair[1]) === "[object foo]"); + delete pair[0][s]; + }); + return passed; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome40: chrome.experimental, + chrome49: true, + chrome55: false, + chrome57: true, + node4: 'flagged', + node8: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + duktape2_5: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.toStringTag, new built-ins', + exec() { + /* + var passed = true; + var s = Symbol.toStringTag; + [ + [String, "String Iterator"], + [Array, "Array Iterator"], + [Map, "Map Iterator"], + [Set, "Set Iterator"] + ].forEach(function(pair){ + var iterProto = Object.getPrototypeOf(new pair[0]()[Symbol.iterator]()); + passed = passed + && iterProto.hasOwnProperty(s) + && iterProto[s] === pair[1]; + }); + passed = passed + && Object.getPrototypeOf(function*(){})[s] === "GeneratorFunction" + && Object.getPrototypeOf(function*(){}())[s] === "Generator" + && Map.prototype[s] === "Map" + && Set.prototype[s] === "Set" + && ArrayBuffer.prototype[s] === "ArrayBuffer" + && DataView.prototype[s] === "DataView" + && Promise.prototype[s] === "Promise" + && Symbol.prototype[s] === "Symbol" + && typeof Object.getOwnPropertyDescriptor( + Object.getPrototypeOf(Int8Array).prototype, Symbol.toStringTag).get === "function"; + return passed; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome49: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Symbol.toStringTag, misc. built-ins', + exec() { + /* + var s = Symbol.toStringTag; + return Math[s] === "Math" + && JSON[s] === "JSON"; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox51: true, + opera10_50: false, + chrome40: chrome.experimental, + chrome49: true, + node4: 'flagged', + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Symbol.unscopables', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/unscopables', + exec() { + /* + var a = { foo: 1, bar: 2 }; + a[Symbol.unscopables] = { bar: true }; + with (a) { + return foo === 1 && typeof bar === "undefined"; + } + */ + }, + res: { + ie11: false, + edge12: true, + firefox2: false, + firefox48: true, + chrome38: true, + opera10_50: false, + safari9: true, + ejs: { + val: false, + note_id: 'ejs-no-with', + note_html: 'with is not supported in ejs', + }, + typescript1corejs2: typescript.fallthrough, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'RegExp.prototype properties', + category: 'built-in extensions', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-regexp.prototype', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/prototype', + subtests: [ + { + name: 'RegExp.prototype.flags', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags', + exec() { + /* + return /./igm.flags === "gim" && /./.flags === ""; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + es6shim: true, + firefox2: false, + firefox37: true, + opera10_50: false, + safari9: true, + xs6: true, + chrome48: chrome.experimental, + chrome49: true, + ie11: false, + edge14: edge.experimental, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'RegExp.prototype[Symbol.match]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@match', + exec() { + /* + return typeof RegExp.prototype[Symbol.match] === 'function'; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + chrome50: true, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'RegExp.prototype[Symbol.replace]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@replace', + exec() { + /* + return typeof RegExp.prototype[Symbol.replace] === 'function'; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + chrome50: true, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype[Symbol.split]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@split', + exec() { + /* + return typeof RegExp.prototype[Symbol.split] === 'function'; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + chrome50: true, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype[Symbol.search]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@search', + exec() { + /* + return typeof RegExp.prototype[Symbol.search] === 'function'; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + chrome50: true, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox49: true, + opera10_50: false, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'RegExp[Symbol.species]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@species', + exec() { + /* + var prop = Object.getOwnPropertyDescriptor(RegExp, Symbol.species); + return 'get' in prop && RegExp[Symbol.species] === RegExp; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge13: true, + firefox2: false, + firefox49: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + // As this one is Annex B, it is separate from the above. + { + name: 'RegExp.prototype.compile', + category: 'annex b', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-regexp.prototype.compile', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/compile', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + if (typeof RegExp.prototype.compile !== 'function') + return false + var rx = /a/; + rx.compile('b'); + return rx.test('b'); + */ + }, + res: { + ie10: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + { + name: 'returns this', + exec() { + /* + var rx = /a/; + return rx.compile('b') === rx; + */ + }, + res: { + ie10: true, + firefox2: true, + opera10_50: false, + chrome5: false, + chrome57: true, + safari5_1: false, + safari10: true, + konq4_14: null, + rhino1_7_13: true, + node0_12: false, + node8: true, + android4_0: false, + xs6: null, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + ], + }, + { + name: 'RegExp syntax extensions', + category: 'annex b', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns', + subtests: [ + { + name: 'hyphens in character sets', + exec() { + /* + return /[\w-_]/.exec("-")[0] === "-"; + */ + }, + res: { + ejs: true, + ie10: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'invalid character escapes', + exec() { + /* + return /\z/.exec("\\z")[0] === "z" + && /[\z]/.exec("[\\z]")[0] === "z"; + */ + }, + res: { + ie10: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'invalid control-character escapes', + exec() { + /* + return /\c2/.exec("\\c2")[0] === "\\c2"; + */ + }, + res: { + ie10: true, + firefox2: true, + chrome5: true, + safari4: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + { + name: 'invalid Unicode escapes', + exec() { + /* + return /\u1/.exec("u1")[0] === "u1" + && /[\u1]/.exec("u")[0] === "u"; + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + opera10_50: false, + chrome5: true, + safari3_1: true, + konq4_14: true, + rhino1_7_13: false, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'invalid hexadecimal escapes', + exec() { + /* + return /\x1/.exec("x1")[0] === "x1" + && /[\x1]/.exec("x")[0] === "x"; + */ + }, + res: { + ie10: true, + firefox2: false, + firefox4: true, + opera10_50: false, + chrome5: true, + safari3_1: true, + konq4_14: true, + rhino1_7_13: false, + node0_12: true, + android4_0: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'incomplete patterns and quantifiers', + exec() { + /* + return /x{1/.exec("x{1")[0] === "x{1" + && /x]1/.exec("x]1")[0] === "x]1"; + */ + }, + res: { + ejs: true, + ie10: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'octal escape sequences', + exec() { + /* + return /\041/.exec("!")[0] === "!" + && /[\041]/.exec("!")[0] === "!"; + */ + }, + res: { + ejs: true, + ie10: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'invalid backreferences become octal escapes', + exec() { + /* + return /\41/.exec("!")[0] === "!" + && /[\41]/.exec("!")[0] === "!"; + */ + }, + res: { + ejs: true, + ie10: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + ], + }, + { + name: 'Array static methods', + category: 'built-in extensions', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-array-constructor', + subtests: [ + { + name: 'Array.from, array-like objects', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Array_from_an_Array-like_object_(arguments)', + exec() { + /* + return Array.from({ 0: "foo", 1: "bar", length: 2 }) + '' === "foo,bar"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + es6shim: true, + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox32: true, + opera10_50: false, + safari9: true, + chrome45: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.from, generator instances', + exec() { + /* + var iterable = (function*(){ yield 1; yield 2; yield 3; }()); + return Array.from(iterable) + '' === "1,2,3"; + */ + }, + res: { + tr: true, + ejs: true, + babel6corejs2: true, + typescript1corejs2: typescript.fallthrough, + closure: true, + es6shim: true, + firefox2: false, + firefox32: true, + opera10_50: false, + chrome45: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + node4: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.from, generic iterables', + exec() { + /* + var iterable = global.__createIterableObject([1, 2, 3]); + return Array.from(iterable) + '' === "1,2,3"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + closure: true, + ie11: false, + edge12: true, + es6shim: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome45: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Array.from, instances of generic iterables', + exec() { + /* + var iterable = global.__createIterableObject([1, 2, 3]); + return Array.from(Object.create(iterable)) + '' === "1,2,3"; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + tr: true, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome45: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Array.from map function, array-like objects', + exec() { + /* + return Array.from({ 0: "foo", 1: "bar", length: 2 }, function(e, i) { + return e + this.baz + i; + }, { baz: "d" }) + '' === "food0,bard1"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure20180610: true, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox32: true, + opera10_50: false, + safari9: true, + chrome45: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.from map function, generator instances', + exec() { + /* + var iterable = (function*(){ yield "foo"; yield "bar"; yield "bal"; }()); + return Array.from(iterable, function(e, i) { + return e + this.baz + i; + }, { baz: "d" }) + '' === "food0,bard1,bald2"; + */ + }, + res: { + tr: true, + babel6corejs2: true, + closure20180610: true, + typescript1corejs2: typescript.fallthrough, + es6shim: true, + firefox2: false, + firefox32: true, + opera10_50: false, + chrome45: true, + ie11: false, + edge12: edge.experimental, + node4: true, + edge13: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.from map function, generic iterables', + exec() { + /* + var iterable = global.__createIterableObject(["foo", "bar", "bal"]); + return Array.from(iterable, function(e, i) { + return e + this.baz + i; + }, { baz: "d" }) + '' === "food0,bard1,bald2"; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure20180610: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + es6shim: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome45: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Array.from map function, instances of iterables', + exec() { + /* + var iterable = global.__createIterableObject(["foo", "bar", "bal"]); + return Array.from(Object.create(iterable), function(e, i) { + return e + this.baz + i; + }, { baz: "d" }) + '' === "food0,bard1,bald2"; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure20180610: true, + typescript1corejs2: typescript.corejs, + tr: true, + ie11: false, + edge12: true, + firefox2: false, + firefox36: true, + opera10_50: false, + safari9: true, + chrome45: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Array.from, iterator closing', + exec() { + /* + var closed = false; + var iter = global.__createIterableObject([1, 2, 3], { + 'return': function(){ closed = true; return {}; } + }); + try { + Array.from(iter, function() { throw 42 }); + } catch(e){} + return closed; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox36: true, + opera10_50: false, + chrome51: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Array.of', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/of', + exec() { + /* + return typeof Array.of === 'function' && + Array.of(2)[0] === 2; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome39: chrome.experimental, + chrome40: false, + chrome45: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array[Symbol.species]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/@@species', + exec() { + /* + var prop = Object.getOwnPropertyDescriptor(Array, Symbol.species); + return 'get' in prop && Array[Symbol.species] === Array; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'Array.prototype methods', + category: 'built-in extensions', + significance: 'medium', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-array-prototype-object', + subtests: [ + { + name: 'Array.prototype.copyWithin', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin', + exec() { + /* + return typeof Array.prototype.copyWithin === 'function'; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox32: true, + opera10_50: false, + safari9: true, + chrome45: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.prototype.find', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find', + exec() { + /* + return typeof Array.prototype.find === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome45: true, + safari7_1: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.prototype.findIndex', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex', + exec() { + /* + return typeof Array.prototype.findIndex === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome45: true, + safari7_1: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.prototype.fill', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill', + exec() { + /* + return typeof Array.prototype.fill === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox31: true, + opera10_50: false, + chrome36: chrome.experimental, + chrome45: true, + safari7_1: true, + node0_12: 'flagged', + node4: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.prototype.keys', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/keys', + exec() { + /* + return typeof Array.prototype.keys === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox28: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.prototype.values', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values', + exec() { + /* + return typeof Array.prototype.values === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + chrome51: true, + chrome52: { + val: false, + note_id: 'cr-array-prototype-values', + note_html: + 'The feature was disabled due to a compatibility issue.', + }, + chrome66: true, + safari9: true, + firefox2: false, + firefox17: { + val: false, + note_id: 'fx-array-prototype-iterator', + note_html: 'Available from Firefox 17 up to 27 as the non-standard Array.prototype.iterator', + }, + firefox27: { + val: false, + note_id: 'fx-array-prototype-iterator-2', + note_html: + 'Available from Firefox 27 up to 35 as the non-standard Array.prototype["@@iterator"]', + }, + firefox36: { + val: false, + note_id: 'fx-array-prototype-iterator-3', + note_html: 'Available from Firefox 36 up to 47 as Array.prototype[Symbol.iterator]', + }, + firefox48: true, + firefox49: { + val: false, + note_id: 'fx-array-prototype-values', + note_html: + 'The feature is enabled only in Firefox Nightly due to a compatibility issue.', + }, + firefox60: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome38: { val: false, note_id: 'fx-array-prototype-iterator-3' }, + node0_12: true, + node4: false, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.prototype.entries', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries', + exec() { + /* + return typeof Array.prototype.entries === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox28: true, + opera10_50: false, + chrome30: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array.prototype.splice', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice', + exec() { + /* + if ([0, 1, 2].splice(0).length !== 3) { + // IE <= 8 and other pre-ES6 engines fail this check + return false; + } + + var a = [1, 2]; + var result = a.splice(); + if (a.length !== 2 || result.length !== 0) { + // Safari 5.0 has this bug + return false; + } + + var obj = {}; + Array.prototype.splice.call(obj, 0, 0, 1); + if (obj.length !== 1) { + return false; + } + + var spliceWorksWithLargeSparseArrays = (function () { + // Per https://github.com/es-shims/es5-shim/issues/295 + // Safari 7/8 breaks with sparse arrays of size 1e5 or greater + var arr = new Array(1e5); + // note: the index MUST be 8 or larger or the test will false pass + arr[8] = 'x'; + arr.splice(1, 1); + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === 'x') { + return i === 7; + } + } + return false; + }()); + var spliceWorksWithSmallSparseArrays = (function () { + // Per https://github.com/es-shims/es5-shim/issues/295 + // Opera 12.15 breaks on this, no idea why. + var n = 256; + var arr = []; + arr[n] = 'a'; + arr.splice(n + 1, 0, 'b'); + return arr[n] === 'a'; + }()); + + return spliceWorksWithLargeSparseArrays && spliceWorksWithSmallSparseArrays; + */ + }, + res: { + ie8: false, + ie9: true, + ie11: true, + chrome15: false, + chrome16: true, + chrome18: true, + chrome20: true, + chrome40: true, + chrome50: true, + chrome101: true, + firefox3: null, + firefox13: true, + firefox15: true, + firefox20: true, + opera10_50: null, + opera12: false, + opera12_10: false, + safari4: false, + safari5: false, + safari5_1: true, + safari15: true, + graalvm21_3_3: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_15: true, + }, + }, + { + name: 'Array.prototype[Symbol.iterator]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/@@iterator', + exec() { + /* + return typeof Array.prototype[Symbol.iterator] === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + ejs: true, + ie11: false, + edge12: true, + safari9: true, + firefox2: false, + firefox17: { + val: false, + note_id: 'fx-array-prototype-iterator', + }, + firefox27: { + val: false, + note_id: 'fx-array-prototype-iterator-2', + }, + firefox36: true, + opera10_50: false, + chrome37: chrome.experimental, + chrome38: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Array iterator prototype chain', + exec() { + /* + // Iterator instance + var iterator = [][Symbol.iterator](); + // %ArrayIteratorPrototype% + var proto1 = Object.getPrototypeOf(iterator); + // %IteratorPrototype% + var proto2 = Object.getPrototypeOf(proto1); + + return proto2.hasOwnProperty(Symbol.iterator) && + !proto1 .hasOwnProperty(Symbol.iterator) && + !iterator .hasOwnProperty(Symbol.iterator) && + iterator[Symbol.iterator]() === iterator; + */ + }, + res: { + babel6corejs2: babel.corejs, + ejs: true, + typescript1corejs2: typescript.corejs, + safari9: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + chrome51: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype[Symbol.unscopables]', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/@@unscopables', + exec() { + /* + var unscopables = Array.prototype[Symbol.unscopables]; + if (!unscopables) { + return false; + } + var ns = "find,findIndex,fill,copyWithin,entries,keys,values".split(","); + for (var i = 0; i < ns.length; i++) { + if (Array.prototype[ns[i]] && !unscopables[ns[i]]) return false; + } + return true; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge12: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Number properties', + category: 'built-in extensions', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-isfinite-number', + subtests: [ + { + name: 'Number.isFinite', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite', + exec() { + /* + return typeof Number.isFinite === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox16: true, + opera10_50: false, + chrome19: true, + safari9: true, + konq4_14: true, + node0_12: true, + android4_1: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Number.isInteger', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger', + exec() { + /* + return typeof Number.isInteger === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox16: true, + opera10_50: false, + chrome34: true, + safari9: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Number.isSafeInteger', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger', + exec() { + /* + return typeof Number.isSafeInteger === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox32: true, + opera10_50: false, + chrome34: true, + safari9: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Number.isNaN', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN', + exec() { + /* + return typeof Number.isNaN === 'function'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox15: true, + opera10_50: false, + chrome19: true, + safari9: true, + konq4_14: true, + node0_12: true, + android4_1: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Number.parseFloat', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseFloat', + exec() { + /* + var actualGlobal = Function('return this')(); + return typeof Number.parseFloat === 'function' + && Number.parseFloat === actualGlobal.parseFloat; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + chrome34: true, + ie11: false, + edge12: true, + es6shim: true, + firefox25: true, + opera10_50: false, + node0_12: true, + safari9: true, + typescript1corejs2: typescript.corejs, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'Number.parseInt', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseInt', + exec() { + /* + var actualGlobal = Function('return this')(); + return typeof Number.parseInt === 'function' + && Number.parseInt === actualGlobal.parseInt; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + chrome34: true, + ie11: false, + edge12: true, + es6shim: true, + firefox25: true, + opera10_50: false, + node0_12: true, + safari9: true, + typescript1corejs2: typescript.corejs, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'Number.EPSILON', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON', + exec() { + /* + return typeof Number.EPSILON === 'number'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_14: true, + }, + }, + { + name: 'Number.MIN_SAFE_INTEGER', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER', + exec() { + /* + return typeof Number.MIN_SAFE_INTEGER === 'number'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox31: true, + opera10_50: false, + chrome34: true, + safari9: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + { + name: 'Number.MAX_SAFE_INTEGER', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER', + exec() { + /* + return typeof Number.MAX_SAFE_INTEGER === 'number'; + */ + }, + res: { + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox31: true, + opera10_50: false, + chrome34: true, + safari9: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }, + ], + }, + { + name: 'Math methods', + category: 'built-in extensions', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-math', + subtests: (function () { + const methods = { + clz32: { + ejs: true, + tr: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox31: true, + opera10_50: false, + chrome35: chrome.experimental, + chrome38: true, + safari9: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + imul: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox23: true, + opera10_50: false, + chrome21: { + val: true, + note_id: 'chromu-imul', + note_html: 'Available since Chrome 28', + }, + chrome30: true, + safari7: true, + safari10: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + sign: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome33: chrome.experimental, + chrome38: true, + safari9: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + log10: { + ejs: true, + babel6corejs2: babel.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + log2: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + log1p: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome35: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + expm1: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome35: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + cosh: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + sinh: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + tanh: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + acosh: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + asinh: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + atanh: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + trunc: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure: true, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome33: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + fround: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + closure20181125: { + val: false, + note_id: 'closure-mathfround', + note_html: 'Requires native support for Float32Array', + }, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox26: true, + opera10_50: false, + chrome35: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + cbrt: { + ejs: true, + babel6corejs2: babel.corejs, + closure: true, + typescript1corejs2: typescript.corejs, + tr: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox25: true, + opera10_50: false, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + } + const eqFn = ' === "function"' + return Object.keys(methods) + .map(function (m) { + return { + name: `Math.${m}`, + mdn: `https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/${m}`, + // TODO: fix this eval + // exec: eval(`0,function(){/*\n return typeof Math.${m}${eqFn};\n*/}`), + res: methods[m], + } + }) + .concat({ + name: 'Math.hypot', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/hypot', + exec() { + /* + return Math.hypot() === 0 && + Math.hypot(1) === 1 && + Math.hypot(9, 12, 20) === 25 && + Math.hypot(27, 36, 60, 100) === 125; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + closure20190215: true, + typescript1corejs2: typescript.corejs, + tr: true, + es6shim: true, + firefox2: false, + firefox27: true, + opera10_50: false, + ie11: false, + edge12: true, + chrome34: chrome.experimental, + chrome38: true, + safari7_1: true, + konq4_14: true, + node0_12: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: true, + }, + }) + })(), + }, + { + name: 'Date.prototype[Symbol.toPrimitive]', + category: 'built-in extensions', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive', + mdn: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/@@toPrimitive', + exec() { + /* + var tp = Date.prototype[Symbol.toPrimitive]; + return tp.call(Object(2), "number") === 2 + && tp.call(Object(2), "string") === "2" + && tp.call(Object(2), "default") === "2"; + */ + }, + res: { + ejs: true, + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge15: true, + firefox2: false, + firefox44: true, + opera10_50: false, + chrome47: true, + xs6: true, + safari10: true, + duktape2_0: false, + duktape2_3: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array is subclassable', + category: 'subclassing', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-array-constructor', + subtests: [ + { + name: 'length property (accessing)', + exec() { + /* + class C extends Array {} + var c = new C(); + var len1 = c.length; + c[2] = 'foo'; + var len2 = c.length; + return len1 === 0 && len2 === 3; + */ + }, + res: { + closure: false, + closure20200614: true, + node4: 'strict', + chrome43: 'strict', + chrome49: true, + safari9: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'length property (setting)', + exec() { + /* + class C extends Array {} + var c = new C(); + c[2] = 'foo'; + c.length = 1; + return c.length === 1 && !(2 in c); + */ + }, + res: { + closure: false, + closure20200614: true, + node4: 'strict', + chrome43: 'strict', + chrome49: true, + safari9: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'correct prototype chain', + exec() { + /* + class C extends Array {} + var c = new C(); + return c instanceof C && c instanceof Array && Object.getPrototypeOf(C) === Array; + */ + }, + res: { + babel6corejs2: { val: false, note_id: 'compiler-proto' }, + closure: false, + node4: 'strict', + chrome43: 'strict', + chrome49: true, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Array.isArray support', + exec() { + /* + class C extends Array {} + return Array.isArray(new C()); + */ + }, + res: { + closure: false, + closure20200614: true, + safari9: true, + chrome43: 'strict', + chrome49: true, + opera10_50: false, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.concat', + exec() { + /* + class C extends Array {} + var c = new C(); + return c.concat(1) instanceof C; + */ + }, + res: { + closure: false, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + ejs: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.filter', + exec() { + /* + class C extends Array {} + var c = new C(); + return c.filter(Boolean) instanceof C; + */ + }, + res: { + closure: false, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + ejs: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.map', + exec() { + /* + class C extends Array {} + var c = new C(); + return c.map(Boolean) instanceof C; + */ + }, + res: { + closure: false, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + ejs: true, + jxa: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.slice', + exec() { + /* + class C extends Array {} + var c = new C(); + c.push(2,4,6); + return c.slice(1,2) instanceof C; + */ + }, + res: { + closure: false, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + ejs: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Array.prototype.splice', + exec() { + /* + class C extends Array {} + var c = new C(); + c.push(2,4,6); + return c.splice(1,2) instanceof C; + */ + }, + res: { + closure: false, + ie11: false, + edge13: true, + firefox2: false, + firefox48: true, + opera10_50: false, + chrome50: chrome.experimental, + chrome51: true, + xs6: true, + ejs: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Array.from', + exec() { + /* + class C extends Array {} + return C.from({ length: 0 }) instanceof C; + */ + }, + res: { + tr: { val: false, note_id: 'compiler-proto' }, + babel6corejs2: { val: false, note_id: 'compiler-proto' }, + closure: false, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + ejs: true, + chrome45: 'strict', + chrome49: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Array.of', + exec() { + /* + class C extends Array {} + return C.of(0) instanceof C; + */ + }, + res: { + tr: { val: false, note_id: 'compiler-proto' }, + babel6corejs2: { val: false, note_id: 'compiler-proto' }, + closure: false, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + chrome45: 'strict', + chrome49: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'RegExp is subclassable', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-regexp-constructor', + category: 'subclassing', + significance: 'tiny', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + class R extends RegExp {} + var r = new R("baz","g"); + return r.global && r.source === "baz"; + */ + }, + res: { + closure: false, + closure20200614: true, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + safari9: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'correct prototype chain', + exec() { + /* + class R extends RegExp {} + var r = new R("baz","g"); + return r instanceof R && r instanceof RegExp && Object.getPrototypeOf(R) === RegExp; + */ + }, + res: { + babel6corejs2: { val: false, note_id: 'compiler-proto' }, + closure: false, + node4: 'strict', + chrome43: 'strict', + chrome49: true, + typescript1corejs2: false, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + safari10: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype.exec', + exec() { + /* + class R extends RegExp {} + var r = new R("baz","g"); + return r.exec("foobarbaz")[0] === "baz" && r.lastIndex === 9; + */ + }, + res: { + closure: false, + closure20200614: true, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + safari9: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node5: 'strict', + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype.test', + exec() { + /* + class R extends RegExp {} + var r = new R("baz"); + return r.test("foobarbaz"); + */ + }, + res: { + closure: false, + closure20200614: true, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + safari9: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + node5: 'strict', + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Function is subclassable', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-function-constructor', + category: 'subclassing', + significance: 'tiny', + subtests: [ + { + name: 'can be called', + exec() { + /* + class C extends Function {} + var c = new C("return 'foo';"); + return c() === 'foo'; + */ + }, + res: { + closure: false, + closure20200614: true, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'correct prototype chain', + exec() { + /* + class C extends Function {} + var c = new C("return 'foo';"); + return c instanceof C && c instanceof Function && Object.getPrototypeOf(C) === Function; + */ + }, + res: { + babel6corejs2: { val: false, note_id: 'compiler-proto' }, + closure: false, + typescript1corejs2: false, + ie11: false, + edge12: edge.experimental, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + chrome48: chrome.experimental, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'can be used with "new"', + exec() { + /* + class C extends Function {} + var c = new C("this.bar = 2;"); + c.prototype.baz = 3; + return new c().bar === 2 && new c().baz === 3; + */ + }, + res: { + closure: false, + closure20200614: true, + typescript1corejs2: false, + chrome43: 'strict', + chrome48: false, + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Function.prototype.call', + exec() { + /* + class C extends Function {} + var c = new C("x", "return this.bar + x;"); + return c.call({bar:1}, 2) === 3; + */ + }, + res: { + closure: false, + closure20200614: true, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Function.prototype.apply', + exec() { + /* + class C extends Function {} + var c = new C("x", "return this.bar + x;"); + return c.apply({bar:1}, [2]) === 3; + */ + }, + res: { + closure: false, + closure20200614: true, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Function.prototype.bind', + exec() { + /* + class C extends Function {} + var c = new C("x", "y", "return this.bar + x + y;").bind({bar:1}, 2); + return c(6) === 9 && c instanceof C; + */ + }, + res: { + closure: false, + closure20200614: true, + typescript1corejs2: false, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + chrome48: chrome.experimental, + chrome49: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Promise is subclassable', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-function-constructor', + category: 'subclassing', + significance: 'small', + subtests: [ + { + name: 'basic functionality', + exec() { + /* + class P extends Promise {} + var p1 = new P(function(resolve, reject) { resolve("foo"); }); + var p2 = new P(function(resolve, reject) { reject("quux"); }); + var score = +(p1 instanceof P); + + function thenFn(result) { score += (result === "foo"); check(); } + function catchFn(result) { score += (result === "quux"); check(); } + function shouldNotRun(result) { score = -Infinity; } + + p1.then(thenFn, shouldNotRun); + p2.then(shouldNotRun, catchFn); + p1.catch(shouldNotRun); + p2.catch(catchFn); + + p1.then(function() { + // P.prototype.then() should return a new P + score += p1.then() instanceof P && p1.then() !== p1; + check(); + }); + + function check() { + if (score === 5) asyncTestPassed(); + } + */ + }, + res: { + closure: false, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari10: true, + node5: 'strict', + xs6: true, + ejs: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'correct prototype chain', + exec() { + /* + class C extends Promise {} + var c = new C(function(resolve, reject) { resolve("foo"); }); + return c instanceof C && c instanceof Promise && Object.getPrototypeOf(C) === Promise; + */ + }, + res: { + closure: false, + closure20200614: true, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari10: true, + node5: 'strict', + xs6: true, + ejs: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Promise.all', + exec() { + /* + class P extends Promise {} + var fulfills = P.all([ + new Promise(function(resolve) { setTimeout(resolve,2000,"foo"); }), + new Promise(function(resolve) { setTimeout(resolve,1000,"bar"); }) + ]); + var rejects = P.all([ + new Promise(function(_, reject) { setTimeout(reject, 2000,"baz"); }), + new Promise(function(_, reject) { setTimeout(reject, 1000,"qux"); }) + ]); + var score = +(fulfills instanceof P); + fulfills.then(function(result) { score += (result + "" === "foo,bar"); check(); }); + rejects.catch(function(result) { score += (result === "qux"); check(); }); + + function check() { + if (score === 3) asyncTestPassed(); + } + */ + }, + res: { + closure: false, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari10: true, + node5: 'strict', + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Promise.race', + exec() { + /* + class P extends Promise {} + var fulfills = P.race([ + new Promise(function(resolve) { setTimeout(resolve,1000,"foo"); }), + new Promise(function(_, reject) { setTimeout(reject, 2000,"bar"); }) + ]); + var rejects = P.race([ + new Promise(function(_, reject) { setTimeout(reject, 1000,"baz"); }), + new Promise(function(resolve) { setTimeout(resolve,2000,"qux"); }) + ]); + var score = +(fulfills instanceof P); + fulfills.then(function(result) { score += (result === "foo"); check(); }); + rejects.catch(function(result) { score += (result === "baz"); check(); }); + + function check() { + if (score === 3) asyncTestPassed(); + } + */ + }, + res: { + closure: false, + typescript1corejs2: false, + chrome43: 'strict', + chrome49: true, + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + safari10: true, + node5: 'strict', + xs6: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'miscellaneous subclassables', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-boolean-constructor', + category: 'subclassing', + significance: 'tiny', + subtests: [ + { + name: 'Boolean is subclassable', + exec() { + /* + class C extends Boolean {} + var c = new C(true); + return c instanceof Boolean + && c instanceof C + && c == true; // eslint-disable-line eqeqeq + */ + }, + res: { + closure: false, + safari10: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Number is subclassable', + exec() { + /* + class C extends Number {} + var c = new C(6); + return c instanceof Number + && c instanceof C + && +c === 6; + */ + }, + res: { + closure: false, + safari10: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'String is subclassable', + exec() { + /* + class C extends String {} + var c = new C("golly"); + return c instanceof String + && c instanceof C + && c + '' === "golly" + && c[0] === "g" + && c.length === 5; + */ + }, + res: { + closure: false, + safari10: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Error is subclassable', + exec() { + /* + class C extends Error {} + var c = new C(); + return c instanceof Error + && c instanceof C + && Object.prototype.toString.call(c) === "[object Error]"; + */ + }, + res: { + closure: false, + safari10: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Map is subclassable', + exec() { + /* + var key = {}; + class M extends Map {} + var map = new M(); + + map.set(key, 123); + + return map instanceof M && map.has(key) && map.get(key) === 123; + */ + }, + res: { + closure: false, + closure20200614: true, + safari10: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Set is subclassable', + exec() { + /* + var obj = {}; + class S extends Set {} + var set = new S(); + + set.add(123); + set.add(123); + + return set instanceof S && set.has(123); + */ + }, + res: { + closure: false, + closure20200614: true, + safari10: true, + chrome43: 'strict', + chrome49: true, + node4: 'strict', + ie11: false, + edge13: true, + firefox2: false, + firefox45: true, + opera10_50: false, + xs6: true, + ejs: true, + jxa: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: hermes.class, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'own property order', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys', + category: 'misc', + significance: 'tiny', + subtests: [ + { + name: 'Object.keys', + exec() { + /* + var obj = { + // Non-negative integer names appear first in value order + 2: true, + 0: true, + 1: true, + // Other string names appear in source order + ' ': true, + // Non-negative integers are sorted above other names + 9: true, + D: true, + B: true, + // Negative integers are treated as other names + '-1': true + }; + // Other string names are added in order of creation + obj.A = true; + // Non-negative integer names, conversely, ignore order of creation + obj[3] = true; + // Having a total of 20+ properties doesn't affect property order + "EFGHIJKLMNOPQRSTUVWXYZ".split('').forEach(function(key){ + obj[key] = true; + }); + // Object.defineProperty doesn't affect the above rules + Object.defineProperty(obj, 'C', { value: true, enumerable: true }); + Object.defineProperty(obj, '4', { value: true, enumerable: true }); + // Deleting and reinserting a property doesn't preserve its position + delete obj[2]; + obj[2] = true; + + var forInOrder = ''; + for(var key in obj)forInOrder += key; + + return Object.keys(obj).join('') === forInOrder; + */ + }, + res: { + ie10: true, + chrome5: true, + firefox2: false, + firefox4: true, + node0_12: true, + opera10_50: false, + opera12: true, + safari4: true, + android4_0: true, + xs6: true, + phantom1_9: true, + ejs: false, + konq4_14: null, + rhino1_7_13: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'Object.getOwnPropertyNames', + exec() { + /* + var obj = { + 2: true, + 0: true, + 1: true, + ' ': true, + 9: true, + D: true, + B: true, + '-1': true + }; + obj.A = true; + obj[3] = true; + "EFGHIJKLMNOPQRSTUVWXYZ".split('').forEach(function(key){ + obj[key] = true; + }); + Object.defineProperty(obj, 'C', { value: true, enumerable: true }); + Object.defineProperty(obj, '4', { value: true, enumerable: true }); + delete obj[2]; + obj[2] = true; + + return Object.getOwnPropertyNames(obj).join('') === "012349 DB-1AEFGHIJKLMNOPQRSTUVWXYZC"; + */ + }, + res: { + ie10: { val: true, note_id: 'ie_property_order' }, + firefox2: false, + firefox44: true, + opera10_50: false, + opera12: true, + safari7_1: true, + xs6: true, + chrome49: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Object.assign', + exec() { + /* + var result = ''; + var target = {}; + + "012349 DBACEFGHIJKLMNOPQRST".split('').concat(-1).forEach(function(key){ + Object.defineProperty(target, key, { + set: function(){ + result += key; + } + }) + }); + + var obj = {2: 2, 0: 0, 1: 1, ' ': ' ', 9: 9, D: 'D', B: 'B', '-1': '-1'}; + Object.defineProperty(obj, 'A', {value: 'A', enumerable: true}); + Object.defineProperty(obj, '3', {value: '3', enumerable: true}); + Object.defineProperty(obj, 'C', {value: 'C', enumerable: true}); + Object.defineProperty(obj, '4', {value: '4', enumerable: true}); + delete obj[2]; + obj[2] = true; + + "EFGHIJKLMNOPQRST".split('').forEach(function(key){ + obj[key] = key; + }); + + Object.assign(target, obj); + + return result === "012349 DB-1ACEFGHIJKLMNOPQRST"; + */ + }, + res: { + ie11: false, + edge12: { val: true, note_id: 'ie_property_order' }, + firefox2: false, + firefox44: true, + opera10_50: false, + safari9: true, + xs6: true, + chrome49: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'JSON.stringify', + exec() { + /* + var obj = { + 2: true, + 0: true, + 1: true, + ' ': true, + 9: true, + D: true, + B: true, + '-1': true + }; + obj.A = true; + obj[3] = true; + "EFGHIJKLMNOPQRSTUVWXYZ".split('').forEach(function(key){ + obj[key] = true; + }); + Object.defineProperty(obj, 'C', { value: true, enumerable: true }); + Object.defineProperty(obj, '4', { value: true, enumerable: true }); + delete obj[2]; + obj[2] = true; + + return JSON.stringify(obj) === + '{"0":true,"1":true,"2":true,"3":true,"4":true,"9":true," ":true,"D":true,"B":true,"-1":true,"A":true,"E":true,"F":true,"G":true,"H":true,"I":true,"J":true,"K":true,"L":true,"M":true,"N":true,"O":true,"P":true,"Q":true,"R":true,"S":true,"T":true,"U":true,"V":true,"W":true,"X":true,"Y":true,"Z":true,"C":true}'; + */ + }, + res: { + ie10: { val: true, note_id: 'ie_property_order' }, + firefox2: false, + firefox44: true, + ejs: true, + chrome5: true, + node0_12: true, + opera10_50: false, + opera12: true, + safari7: true, + safari10: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'JSON.parse', + exec() { + /* + var result = ''; + JSON.parse( + '{"0":true,"1":true,"2":true,"3":true,"4":true,"9":true," ":true,"D":true,"B":true,"-1":true,"E":true,"F":true,"G":true,"H":true,"I":true,"J":true,"K":true,"L":true,"A":true,"C":true}', + function reviver(k,v) { + result += k; + return v; + } + ); + return result === "012349 DB-1EFGHIJKLAC"; + */ + }, + res: { + ie10: { + val: true, + note_id: 'ie_property_order', + note_html: + 'Unlike other engines, Chakra sorts properties removed by delete, then recreated by assignment, to their original creation positions, not their latest positions.', + }, + firefox2: false, + firefox3_5: true, + firefox4: true, + chrome5: true, + node0_12: true, + opera10_50: true, + opera12: true, + safari4: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'Reflect.ownKeys, string key order', + exec() { + /* + var obj = { + 2: true, + 0: true, + 1: true, + ' ': true, + 9: true, + D: true, + B: true, + '-1': true + }; + obj.A = true; + obj[3] = true; + "EFGHIJKLMNOPQRSTUVWXYZ".split('').forEach(function(key){ + obj[key] = true; + }); + Object.defineProperty(obj, 'C', { value: true, enumerable: true }); + Object.defineProperty(obj, '4', { value: true, enumerable: true }); + delete obj[2]; + obj[2] = true; + + return Reflect.ownKeys(obj).join('') === "012349 DB-1AEFGHIJKLMNOPQRSTUVWXYZC"; + */ + }, + res: { + babel6corejs2: { + val: false, + note_id: 'forin-order', + note_html: 'This uses native for-in enumeration order, rather than the correct order.', + }, + closure: { val: false, note_id: 'forin-order' }, + typescript1corejs2: { val: false, note_id: 'forin-order' }, + es6shim: { val: false, note_id: 'forin-order' }, + firefox2: false, + firefox44: true, + opera10_50: false, + ie11: false, + edge12: true, + safari10: true, + xs6: true, + ejs: true, + chrome49: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'Reflect.ownKeys, symbol key order', + exec() { + /* + var sym1 = Symbol(), sym2 = Symbol(), sym3 = Symbol(); + var obj = { + 1: true, + A: true + }; + obj.B = true; + obj[sym1] = true; + obj[2] = true; + obj[sym2] = true; + Object.defineProperty(obj, 'C', { value: true, enumerable: true }); + Object.defineProperty(obj, sym3,{ value: true, enumerable: true }); + Object.defineProperty(obj, 'D', { value: true, enumerable: true }); + + var result = Reflect.ownKeys(obj); + var l = result.length; + return result[l-3] === sym1 && result[l-2] === sym2 && result[l-1] === sym3; + */ + }, + res: { + babel6corejs2: babel.corejs, + closure: true, + closure20190301: false, + typescript1corejs2: typescript.corejs, + es6shim: true, + ie11: false, + edge12: true, + safari10: true, + firefox2: false, + firefox42: true, + opera10_50: false, + xs6: true, + ejs: true, + chrome49: true, + duktape2_0: false, + duktape2_2: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'Updated identifier syntax', + category: 'misc', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-names-and-keywords', + subtests: [ + { + name: 'var ⸯ;', + exec() { + /* + try { + eval('var ⸯ'); + } catch(e) { + return true; + } + */ + }, + res: { + es6tr: null, + tr: null, + babel6corejs2: null, + closure: false, + jsx: null, + typescript1corejs2: null, + es6shim: null, + konq4_14: null, + ie7: null, + ie10: false, + ie11: true, + edge14: true, + firefox1: null, + firefox2: false, + firefox52: true, + opera10_50: false, + chrome1: null, + chrome58: true, + safari1: false, + safari12_1: true, + safaritp: true, + rhino1_7_13: false, + xs6: null, + jxa: null, + node0_10: null, + duktape2_0: false, + android1_5: null, + ios4: null, + graalvm19: true, + jerryscript1_0: true, + jerryscript2_0: false, + jerryscript2_4_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + }, + }, + { + name: 'var 𐋀;', + exec() { + /* + var 𐋀; + return true; + */ + }, + res: { + es6tr: null, + tr: null, + babel6corejs2: null, + closure: false, + jsx: null, + typescript1corejs2: null, + es6shim: null, + konq4_14: null, + ie7: null, + ie10: false, + edge12: null, + edge14: true, + firefox1: null, + firefox2: false, + firefox52: true, + opera10_50: false, + chrome1: null, + chrome58: true, + safari1: false, + safari14: true, + webkit: false, + rhino1_7_13: false, + xs6: null, + jxa: null, + node0_10: null, + duktape2_0: false, + android1_5: null, + ios4: null, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_4_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_15: true, + }, + }, + { + name: 'no escaped reserved words as identifiers', + exec() { + /* + var \u0061; + try { + eval('var v\\u0061r'); + } catch(e) { + return true; + } + */ + }, + res: { + es6tr: true, + tr: true, + babel6corejs2: true, + closure: true, + jsx: true, + typescript1corejs2: true, + es6shim: null, + konq4_14: null, + ie7: null, + ie10: true, + firefox1: null, + firefox2: false, + firefox10: true, + opera10_50: false, + opera12_10: true, + chrome1: null, + chrome49: true, + safari1: null, + safari9: true, + rhino1_7_13: false, + xs6: true, + jxa: true, + node0_10: null, + duktape2_0: false, + android1_5: null, + ios4: null, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_15: true, + }, + }, + ], + }, + { + name: 'miscellaneous', + category: 'misc', + significance: 'small', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-additions-and-changes-that-introduce-incompatibilities-with-prior-editions', + subtests: [ + { + name: 'duplicate property names in strict mode', + exec() { + /* + 'use strict'; + return this === void undefined && ({ a:1, a:1 }).a === 1; + */ + }, + res: { + ejs: true, + ie11: false, + edge12: true, + firefox2: false, + firefox34: true, + opera10_50: false, + chrome42: true, + safari9: true, + node4: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'no semicolon needed after do-while', + exec() { + /* + do {} while (false) return true; + */ + }, + res: { + ejs: true, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + ie10: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'no assignments allowed in for-in head in strict mode', + exec() { + /* + 'use strict'; + try { + eval('for (var i = 0 in {}) {}'); + } + catch(e) { + return true; + } + */ + }, + res: { + ejs: true, + babel6corejs2: true, + closure: true, + typescript1corejs2: true, + ie11: false, + edge15: true, + firefox2: false, + firefox52: true, + opera10_50: false, + chrome45: true, + safari9: true, + xs6: true, + jxa: true, + duktape2_0: false, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: "accessors aren't constructors", + exec() { + /* + var f = (Object.getOwnPropertyDescriptor({get a(){}}, 'a')).get; + try { + new f; + } catch(e) { + return true; + } + */ + }, + res: { + ie11: false, + edge12: true, + chrome42: true, + node4: true, + firefox2: false, + firefox41: true, + opera10_50: false, + safari10: true, + xs6: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + reactnative0_70_3: false, + rhino1_7_13: false, + }, + }, + { + name: 'Invalid Date', + exec() { + /* + return new Date(NaN) + "" === "Invalid Date"; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + es6shim: true, + ejs: true, + ie10: true, + firefox2: true, + chrome5: true, + safari3_1: true, + opera10_50: true, + opera12: true, + konq4_14: true, + rhino1_7_13: true, + node0_12: true, + android4_0: true, + xs6: true, + jxa: true, + duktape2_0: true, + nashorn1_8: true, + nashorn9: true, + nashorn10: true, + graalvm19: true, + jerryscript1_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + }, + }, + { + name: 'RegExp constructor can alter flags', + exec() { + /* + return new RegExp(/./im, "g").global === true; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ejs: true, + es6shim: true, + ie11: false, + edge12: true, + firefox2: false, + firefox39: true, + opera10_50: false, + xs6: true, + chrome49: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: 'RegExp.prototype.toString generic and uses "flags" property', + exec() { + /* + return RegExp.prototype.toString.call({source: 'foo', flags: 'bar'}) === '/foo/bar'; + */ + }, + res: { + babel6corejs2: babel.corejs, + typescript1corejs2: typescript.corejs, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox39: true, + opera10_50: false, + chrome50: true, + ejs: null, + xs6: null, + jxa: true, + safari10: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_2_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + rhino1_7_15: true, + }, + }, + { + name: 'built-in prototypes are not instances', + exec() { + /* + try { + RegExp.prototype.exec(); return false; + } catch(e) {} + try { + Date.prototype.valueOf(); return false; + } catch(e) {} + + if (![Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError].every(function (E) { + return Object.prototype.toString.call(E.prototype) === '[object Object]'; + })) { + return false; + } + + return true; + */ + }, + res: { + xs6: false, + jxa: true, + ie11: false, + edge14: edge.experimental, + firefox2: false, + firefox53: true, + opera10_50: false, + chrome50: true, + safari10: true, + duktape2_0: false, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: false, + hermes0_12_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + { + name: "function 'length' is configurable", + exec() { + /* + var fn = function(a, b) {}; + + var desc = Object.getOwnPropertyDescriptor(fn, "length"); + if (desc.configurable) { + Object.defineProperty(fn, "length", { value: 1 }); + return fn.length === 1; + } + + return false; + */ + }, + res: { + firefox2: false, + firefox37: true, + opera10_50: false, + chrome43: true, + ie11: false, + edge12: true, + node4: true, + xs6: true, + safari10: true, + jxa: true, + duktape2_0: true, + graalvm19: true, + jerryscript2_0: false, + jerryscript2_3_0: true, + hermes0_7_0: true, + reactnative0_70_3: true, + rhino1_7_13: false, + }, + }, + ], + }, + { + name: 'HTML-style comments', + category: 'annex b', + significance: 'tiny', + spec: 'http://www.ecma-international.org/ecma-262/6.0/#sec-html-like-comments', + exec() { + /* + --> A comment +