넥사크로 스튜디오 옵션에서 [Script > Version] 항목값을 "ES6"로 설정했을때 17.1.3.400 미만 버전에서아래 목록의 코드는 스크립트 편집 또는 Generate 시 정상적으로 동작하지 않을 수 있습니다.
아래 목록 분류는 ECMAScript compatibility tables 목록을 사용했습니다.
https://kangax.github.io/compat-table/es6/
https://github.com/kangax/compat-table
17.1.3.100 이후 버전에 순차적으로 정상 동작을 지원하고 있습니다.
항목 제목 옆에 버전 표시가 있으면 해당 버전부터는 스튜디오에서 정상적으로 처리하는 항목입니다.
Modules, Array.prototype.values 는 넥사크로 스튜디오 지원 여부와 상관없이 NRE에서 지원하지 않습니다.
Modules
https://262.ecma-international.org/6.0/#sec-modules
https://262.ecma-international.org/6.0/#sec-imports
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
Array.prototype.values
https://262.ecma-international.org/6.0/#sec-array.prototype.values
syntax
default function parameters (17.1.3.200)
Feature name | example |
---|---|
defaults can refer to previous params | trace( (function (a, b = a) { return b === 5; }(5)) ); |
separate scope | trace( (function(a=function(){ return typeof b === 'undefined'; }){ var b = 1; return a(); }()) ); |
rest parameters (17.1.3.300)
Feature name | example |
---|---|
basic functionality | trace( (function (foo, ...args) { return args instanceof Array && args + " === "bar,baz"; }("foo", "bar", "baz")) ); |
function 'length' property | trace( function(a, ...b){}.length === 1 && function(...c){}.length === 0 ); |
arguments object interaction | trace( (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")) ); |
can't be used in setters | trace( (function (...args) { try { eval("({set e(...args){}})"); } catch(e) { return true; }}()) ); |
spread syntax for iterable objects (17.1.3.400)
Feature name | example |
---|---|
with arrays, in function calls | trace( Math.max(...[1, 2, 3]) === 3 ); |
with arrays, in array literals | trace( [...[1, 2, 3]][2] === 3 ); |
with sparse arrays, in function calls | var a = Array(...[,,]); trace( "0" in a && "1" in a && '' + a[0] + a[1] === "undefinedundefined" ); |
with sparse arrays, in array literals | var b = [...[,,]]; trace( "0" in b && "1" in b && '' + b[0] + b[1] === "undefinedundefined" ); |
with strings, in function calls | trace( Math.max(..."1234") === 4 ); |
with strings, in array literals | trace( ["a", ..."bcd", "e"][3] === "d" ); |
with astral plane strings, in function calls | trace( Array(..."𠮷𠮶")[0] === "𠮷" ); |
with astral plane strings, in array literals | trace( [..."𠮷𠮶"][0] === "𠮷" ); |
spreading non-iterables is a runtime error | try { Math.max(...2); } catch(e) { return Math.max(...[1, 2, 3]) === 3; } |
with generator instances, in calls | var iterable = (function*(){ yield 1; yield 2; yield 3; }()); trace( Math.max(...iterable) === 3 ); |
with generator instances, in arrays | var iterablee = (function*(){ yield "b"; yield "c"; yield "d"; }()); return ["a", ...iterablee, "e"][3] === "d"; |
object literal extensions MDN (17.1.3.400)
Feature name | example |
---|---|
computed properties | var xx = 'yyy'; return ({ [xx]: 1 }).yyy === 1; |
string-keyed shorthand methods | return ({ "foo bar"() { return 4; } })["foo bar"]() === 4; |
computed shorthand methods | var xxxxx = 'y'; return ({ [xxxxx](){ return 1 } }).y() === 1; |
computed accessors | var xtr = 'y', valueSet, obj = { get [xtr] () { return 1 }, set [xtr] (value) { valueSet = value } }; obj.y = 'foo'; return obj.y === 1 && valueSet === 'foo'; |
for..of loops (17.1.3.400)
Feature name | example |
---|---|
with arrays | var arr = [5]; for (var item of arr) return item === 5; |
with sparse arrays | var aarr = [,,]; var count = 0; for (var item of aarr) count += (item === void undefined); return count === 2; |
with strings | var str = ""; for (var item of "foo") str += item; return str === "foo"; |
with astral plane strings | var strr = ""; for (var item of "𠮷𠮶") strr += item + " "; return strr === "𠮷 𠮶 "; |
with generator instances | var resultt = ""; var iterablee = (function*(){ yield 1; yield 2; yield 3; }()); for (var item of iterablee) { resultt += item; } trace( resultt === "123" ); |
with generic iterables | var ressult = ""; var itterable = global.__createIterableObject([1, 2, 3]); for (var item of itterable) { ressult += item; } trace( result === "123" ); |
with instances of generic iterables | trace( "5-7.with instances of generic iterables" ); var resuult = ""; var iteraable = global.__createIterableObject([1, 2, 3]); for (var item of Object.create(iteraable)) { resuult += item; } trace( result === "123" ); |
iterator closing, break | var closed = false; var iter = __createIterableObject([1, 2, 3], { 'return': function(){ closed = true; return {}; } }); for (var it of iter) break; trace( closed ); |
iterator closing, throw | trace( "5-9. iterator closing, throw" ); var closedd = false; var iterr = __createIterableObject([1, 2, 3], { 'return': function(){ closedd = true; return {}; } }); try { for (var it of iterr) throw 0; } catch(e){} trace( closedd ); |
object literal extensions (17.1.3.300)
Feature name | example |
---|---|
octal literals | trace( 0o10 === 8 && 0O10 === 8 ); |
binary literals | trace( 0b10 === 2 && 0B10 === 2 ); |
template literals (17.1.3.300)
Feature name | example |
---|---|
basic functionality | var a = "ba", b = "QUX"; trace ( `foo bar ${a + "z"} ${b.toLowerCase()}` === "foo bar\nbaz qux" ); |
tagged template literals | var callled = false; function fnn(parts, a, b) { callled = 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; } trace( fnn foo${123}bar\n${456} && callled ); |
passed array is frozen | trace( (function(parts) { return Object.isFrozen(parts) && Object.isFrozen(parts.raw); }) foo${0}bar${0}baz ); |
TemplateStrings call site caching | function strings(array) { return array; } function getStrings() { return stringsfoo; } var original = getStrings(); var other = stringsfoo; trace( original === getStrings() && original !== other ); |
TemplateStrings permanent caching | function strings(array) { return array; } function getStrings() { return stringsfoo; } var ooriginal = getStrings(); var newed = new getStrings(); trace( ooriginal === getStrings() && ooriginal === newed ); |
destructuring, declarations (17.1.3.400)
Feature name | example |
---|---|
with arrays | trace( "9-1. with arrays" ); var [a, , [b], c] = [5, null, [6]]; trace( a === 5 && b === 6 && c === void undefined ); |
with sparse arrays | var [a, , b] = [,,,]; trace( a === void undefined && b === void undefined ); |
computed properties | var qux = "corge"; var { [qux]: grault } = { corge: "garply" }; trace( grault === "garply" ); |
multiples in a single var statement | var [a,b] = [5,6], {c,d} = {c:7,d:8}; trace( a === 5 && b === 6 && c === 7 && d === 8 ); |
nested | var [e, {x:f, g}] = [9, {x:10}]; var {h, x:[i]} = {h:11, x:[12]}; trace( e === 9 && f === 10 && g === void undefined && h === 11 && i === 12 ); |
in for-in loop heads | for(var [i, j, k] in { qux: 1 }) { trace( i === "q" && j === "u" && k === "x" ); } |
in catch heads | try { throw [1,2]; } catch([i,j]) { try { throw { k: 3, l: 4 }; } catch({k, l}) { trace( i === 1 && j === 2 && k === 3 && l === 4 ); } } |
defaults | var {a = 1, b = 0, z:c = 3} = {b:2, z:undefined}; var [d = 0, e = 5, f = 6] = [4,,undefined]; trace( a === 1 && b === 2 && c === 3 && d === 4 && e === 5 && f === 6 ); |
defaults, let temporal dead zone | var {a, b = 2} = {a:1}; try { eval("let {c = c} = {};"); trace( false ); } catch(e){} try { eval("let {c = d, d} = {d:1};"); trace( false ); } catch(e){} trace( a === 1 && b === 2 ); |
with generator instances | var [a, b, c] = (function*(){ yield 1; yield 2; }()); trace( a === 1 && b === 2 && c === void undefined ); |
destructuring, assignment (17.1.3.400)
Feature name | example |
---|---|
with objects | var cg,dg,eg; ({cg, x:dg, eg} = {cg:7, x:8}); trace( cg === 7 && dg === 8 && eg === void undefined ); |
object destructuring with primitives | var toFixed, slice; ({toFixed} = 2); ({slice} = ''); trace( toFixed === Number.prototype.toFixed && slice === String.prototype.slice ); |
trailing commas in object patterns | var am; ({am,} = {am:1}); trace( am === 1 ); |
throws on null and undefined | var aadd,bdd; try { ({aadd} = null); trace( false ); } catch(e) { if (!(e instanceof TypeError)) trace( false ); } try { ({bdd} = void undefined); trace( false ); } catch(e) { if (!(e instanceof TypeError)) trace( false ); } trace( true ); |
computed properties | var grault, qux = "corge"; ({ [qux]: grault } = { corge: "garply" }); trace( grault === "garply" ); |
nested | var ec,fc,gc,hc,ic; [ec, {x:fc, gc}] = [9, {x:10}]; ({hc, x:[i]} = {hc:11, x:[12]}); trace( ec === 9 && fc === 10 && gc === void undefined && hc === 11 && ic === 12 ); |
defaults | var aff,bff,cff,dff,eff,fff; ({aff = 1, bff = 0, z:cff = 3} = {bff:2, z:undefined}); [dff = 0, eff = 5, fff = 6] = [4,,undefined]; trace( aff === 1 && bff === 2 && cff === 3 && dff === 4 && eff === 5 && fff === 6 ); |
with generator instances | var a,b,c; [a, b, c] = (function*(){ yield 1; yield 2; }()); trace ( a === 1 && b === 2 && c === void undefined ); |
destructuring, parameter (17.1.3.400)
Feature name | example |
---|---|
with arrays | trace( function([afg, , [bfg], cfg]) { return afg === 5 && bfg === 6 && cfg === void undefined; }([5, null, [6]])) ); |
with sparse arrays | trace( function([awt, , bwt]) { return awt === void undefined && bwt === void undefined; }([,,,]) ); |
with strings | trace( function([xva, xvb, xvc]) { return xva === "a" && xvb === "b" && xvc === void undefined; }("ab") ); |
with astral plane strings | tace( function([cy]) { return cy === "𠮷"; }("𠮷𠮶") ); |
with generic iterables | trace( function([aui, bui, cui]) { return aui === 1 && bui === 2 && cui === void undefined; }(global.__createIterableObject([1, 2])) ); |
with instances of generic iterables | trace( function([acd, bcd, ccd]) { return acd === 1 && bcd === 2 && ccd === void undefined; }(Object.create(global.__createIterableObject([1, 2]))) ); |
iterator closing | var closedrt = false; var iterrt = global.__createIterableObject([1, 2, 3], { 'return': function(){ closedrt = true; return {}; } }); (function([ahh,bhh]) {}(iterrt)); trace( closedrt ); |
trailing commas in iterable patterns | trace( function([aiu,]) { return aiu === 1; }([1]) ); |
with objects | trace( function({cja, x:dja, eja}) { return cja === 7 && dja === 8 && eja === void undefined; }({cja:7, x:8}) ); |
object destructuring with primitives | trace( function({toFixed}, {slice}) { return toFixed === Number.prototype.toFixed && slice === String.prototype.slice; }(2,'') ); |
trailing commas in object patterns | trace( function({ave,}) { return ave === 1; }({ave:1}) ); |
computed properties | var qux = "corge"; trace( function({ [qux]: grault }) { return grault === "garply"; }({ corge: "garply" }) ); |
nested | trace( function([ear, {x:far, gar}], {har, x:[i]}) { return ear === 9 && far === 10 && gar === void undefined && har === 11 && iar === 12; }([9, {x:10}],{har:11, x:[12]}) ); |
'arguments' interaction | trace( (function({ajn, x:bjn, y:ejn}, [cjn, djn]) { return arguments[0].ajn === 1 && arguments[0].x === 2 && !("y" in arguments[0]) && arguments[1] + '' === "3,4"; }({ajn:1, x:2}, [3, 4])) ); |
in parameters, function 'length' property | trace( function({gha, ghb}, [ghc, ghd]){}.length === 2 ); |
rest | trace( function([sfa, ...sfb], [sfc, ...sfd]) { return sfa === 3 && sfb instanceof Array && (sfb + "") === "4,5" && sfc === 6 && sfd instanceof Array && sfd.length === 0; }([3, 4, 5], [6]) ); |
empty patterns | trace( function ([],{}){ return arguments[0] + '' === "3,4" && arguments[1].x === "foo"; }([3,4],{x:"foo"}) ); |
defaults | trace( (function({aon = 1, bon = 0, con = 3, x:don = 0, y:eon = 5}, [f = 6, g = 0, h = 8]) { return aon === 1 && bon === 2 && con === 3 && don === 4 && eon === 5 && fon === 6 && gon === 7 && hon === 8; }({bon:2, con:undefined, x:4},[, 7, undefined])) ); |
defaults, separate scope | trace( (function({anm=function(){ return typeof bnm === 'undefined'; }}){ var bnm = 1; return anm(); }({})) ); |
aliased defaults, arrow functions | trace( ((afw, {b: xfw = 0, c: yfw = 3}) => { return afw === 1 && xfw === 2 && yfw === 3; })(1, {b: 2}) ); |
shorthand defaults, arrow function | trace( ((amv, {bmv = 0, cmv = 3}) => { return amv === 1 && bmv === 2 && cmv === 3; })(1, {bmv: 2}) ); |
with generator instances | trace( function([awd, bwd, cwd]) { return awd === 1 && bwd === 2 && cwd === void undefined; }(function*(){ yield 1; yield 2; }()) ); |
Unicode code point escapes (17.1.3.400)
Feature name | example |
---|---|
in identifiers | var \u{102C0} = 2; trace( \u{102C0} === 2 ); |
in property key definitions | var o = { \u{102C0} : 2 }; trace( o['\ud800\udec0'] === 2 ); |
in property key accesses | var og = { '\ud800\udec0' : 2 }; trace( og.\u{102C0} === 2 ); |
new.target (17.1.3.400)
Feature name | example |
---|---|
in constructors | var passeds = false; new function fu() { passeds = (new.target === fu); }(); (function() { passeds &= (new.target === void undefined); }()); return passeds; |
assignment is an early error | var passede = false; new function ft() { passede = (new.target === ft); }(); try { Function("new.target = function(){};"); } catch(e) { return passede; } |
Bindings
const (17.1.3.400)
Feature name | example |
---|---|
is block-scoped | const barr = 123; { const barr = 456; } trace( barr === 123 ); |
scope shadow resolution | try { { const bare = 456; } const bare = 123; trace( bare === 123 ); } catch(e) { trace( false ); } |
for loop statement scope | const bazf = 1; for(const bazf = 0; false;) {} trace( bazf === 1 ); |
for-in loop iteration scope | var scopesoy = []; for(const i in { a:1, b:1 }) { scopesoy.push(function(){ return i; }); } trace( (scopes[0]() === "a" && scopes[1]() === "b") ); |
is block-scoped (strict mode) | use strict'; const baruy = 123; { const baruy = 456; } trace( baruy === 123 ); |
scope shadow resolution (strict mode) | use strict'; try { { const barim = 456; } const barim = 123; trace( barim === 123 ); } catch(e) { trace( false ); } |
for loop statement scope (strict mode) | use strict'; const bazzf = 1; for(const bazzf = 0; false;) {} trace( bazzf === 1 ); |
for-in loop iteration scope (strict mode) | use strict'; var scopeszg = []; for(const i in { a:1, b:1 }) { scopeszg.push(function(){ return i; }); } trace( (scopes[0]() === "a" && scopes[1]() === "b") ); |
for-of loop iteration scope | var scopesgf = []; for(const i of ['a','b']) { scopesgf.push(function(){ return i; }); } trace( (scopesgf[0]() === "a" && scopesgf[1]() === "b") ); |
for-of loop iteration scope (strict mode) | 'use strict'; var scopeskj = []; for(const i of ['a','b']) { scopeskj.push(function(){ return i; }); } trace( (scopes[0]() === "a" && scopes[1]() === "b") ); |
Functions
arrow functions (17.1.3.400)
Feature name | example |
---|---|
0 parameters | trace( (() => 5)() === 5 ); |
this' unchanged by call or apply | var dgbn = { xgbn : "foo", ygbn : function() { return () => this.xgbn; }}; var egbn = { xgbn : "bar" }; trace( dgbn.ygbn().call(e) === "foo" && dgbn.ygbn().apply(e) === "foo" ); |
no line break between params and => | trace( (() => { try { Function("x\n => 2")(); } catch(e) { trace( true ); } })() ); |
correct precedence | trace( (() => { try { Function("0 || () => 2")(); } catch(e) { trace( true ); } })() ); |
lexical 'super' binding in methods | class B { qux() { return "quux"; } } class C extends B { baz() { return x => super.qux(); } } var arrow = new C().baz(); trace("lexical 'super' binding in methods : " + ( arrow() === "quux" ) ); |
lexical 'new.target' binding | function CT() { trac x => new.target; } trace( new CT()() === CT && CT()() === void undefined ); |
class (17.1.3.400)
Feature name | example |
---|---|
class statement | class CY {} trace( typeof CY === "function" ); |
is block-scoped | class CU {} var c1 = CU; { class CU {} var c2 = CU; } trace( CU === c1 ); |
class expression | trace( typeof class TC {} === "function" ); |
anonymous class | trace( typeof class {} === "function" ); |
constructor | class CWR { constructor() { this.x = 1; } } trace( CWR.prototype.constructor === CWR && new CWR().x === 1 ); |
prototype methods | class CYU { method() { return 2; } } trace( typeof CYU.prototype.method === "function" && new CYU().method() === 2 ); |
string-keyed methods | class CUI { "foo bar"() { return 2; } } trace( typeof CUI.prototype["foo bar"] === "function" && new CUI()["foo bar"]() === 2 ); |
computed prototype methods | var foo = "method"; class CKJ { [foo]() { trace( 2 ); } } trace( typeof CKJ.prototype.method === "function" && new CKJ().method() === 2 ); |
static methods | class CGB { static method() { return 3; } } return typeof CGB.method === "function" && CGB.method() === 3; |
computed static methods | var foo = "method"; class CCD { static [foo]() { return 3; } } trace( typeof CCD.method === "function" && CCD.method() === 3 ); |
computed accessor properties | var garply = "foo", grault = "bar", baz = false; class CPC { get [garply]() { return "foo"; } set [grault](x) { baz = x; } } new CPC().bar = true; trace( new CPC().foo === "foo" && baz ); |
class name is lexically scoped | class CDI { method() { return typeof C === "function"; } } var MT = CDI.prototype.method; CDI = void undefined; trace( CDI === void undefined && MT() ); |
computed names, temporal dead zone | try { var BTY = class CTY { [CTY](){} } } catch(e) { trace( true ); } |
methods aren't enumerable | class COO { foo() {} static bar() {} } trace( !COO.prototype.propertyIsEnumerable("foo") && !COO.propertyIsEnumerable("bar") ); |
constructor requires new | class CJN {} try { CJN(); } catch(e) { trace( true ); } |
extends | class BFW {} class CFW extends BFW {} trace( new CFW() instanceof BFW && BFW.isPrototypeOf(CFW) ); |
extends expressions | var BOIU; class COIU extends (BOIU = class {}) {} trace( new COIU() instanceof BOIU && BOIU.isPrototypeOf(COIU) ); |
extends null | class CSDF extends null { constructor() { return Object.create(null); } } trace( Function.prototype.isPrototypeOf(CSDF) && Object.getPrototypeOf(CSDF.prototype) === null ); |
accessor properties | var baz = false; class CFO { get foo() { return "foo"; } set bar(x) { baz = x; } } new CFO().bar = true; trace( new CFO().foo === "foo" && baz ); |
static accessor properties | var garply = "foo", grault = "bar", baz = false; class CRF { static get [garply]() { return "foo"; } static set [grault](x) { baz = x; } } CRF.bar = true; trace( CRF.foo === "foo" && baz ); |
implicit strict mode | class COP { static method() { return this === void undefined; } } trace( (0,COP.method)() ); |
new.target | var passedsdfg = false; new function fsdfg() { passedsdfg = new.targetsdfg === fsdfg; }(); class ASDFG { constructor() { passedsdfg &= new.target === BSDFG; } } class BSDFG extends ASDFG {} new BSDFG(); trace( passedsdfg ); |
super (17.1.3.400)
Feature name | example |
---|---|
in methods, property access | class BJRI {} BJRI.prototype.qux = "foo"; BJRI.prototype.corge = "baz"; class CJRI extends BJRI { quux(a) { return super.qux + a + super["corge"]; } } CJRI.prototype.qux = "garply"; trace( new CJRI().quux("bar") === "foobarbaz" ); |
in methods, method calls | class BKOP { qux(a) { return "foo" + a; } } class CKOP extends BKOP { qux(a) { return super.qux("bar" + a); } } trace( new CKOP().qux("baz") === "foobarbaz" ); |
method calls use correct 'this' binding | class BCIW { qux(a) { return this.foo + a; } } class CCIW extends BCIW { qux(a) { return super.qux("bar" + a); } } var obj = new CCIW(); obj.foo = "foo"; trace( obj.qux("baz") === "foobarbaz" ); |
constructor calls use correct 'new.target' binding | var passed; class BXCV { constructor() { passed = (new.target === CXCV); } } class CXCV extends BXCV { constructor() { super(); } } new CXCV(); trace( passed ); |
is statically bound | class BHPW { qux() { return "bar"; } } class CHPW extends BHPW { qux() { return super.qux() + this.corge; } } var obj = { qux: CHPW.prototype.qux, corge: "ley" }; trace( obj.qux() === "barley" ); |
super() invokes the correct constructor | var passed; class BSPE { constructor() { passed = true; } }; BSPE.prototype.constructor = function () { passed = false; }; class CSPE extends BSPE { }; new CSPE; trace( passed ); |
generators (17.1.3.400)
Feature name | example |
---|---|
basic functionality | function * generator(){ yield 5; yield 6; }; var iteratorabc = generator(); var itemabc = iterator.next(); var passedabc = itemabc.value === 5 && itemabc.done === false; itemabc = iteratorabc.next(); passedabc &= itemabc.value === 6 && itemabc.done === false; itemabc = iteratorabc.next(); passedabc &= itemabc.value === void undefined && itemabc.done === true; trace( passedabc ); |
generator function expressions | var generatorefb = function * (){ yield 5; yield 6; }; var iteratorefb = generatorefb(); var itemefb = iteratorefb.next(); var passedefb = itemefb.value === 5 && itemefb.done === false; itemefb = iteratorefb.next(); passedefb &= itemefb.value === 6 && itemefb.done === false; itemefb = iteratorefb.next(); passedefb &= itemefb.value === void undefined && itemefb.done === true; trace( passedefb ); |
correct 'this' binding | function * generatorr(){ yield this.x; yield this.y; }; var iteratorvg = { g: generatorr, x: 5, y: 6 }.g(); var itemvg = iteratorvg.next(); var passedvg = itemvg.value === 5 && itemvg.done === false; itemvg = iteratorvg.next(); passedvg &= itemvg.value === 6 && itemvg.done === false; itemvg = iteratorvg.next(); passedvg &= itemvg.value === void undefined && itemvg.done === true; trace( passedvg ); |
can't use 'this' with new | function * generatorviq(){ yield this.x; yield this.y; }; try { (new generatorviq()).next(); } catch (e) { trace( true ); } |
sending | var sentkwp; function * generatorkwp(){ sent = [yield 5, yield 6]; }; var iteratorkwp = generatorkwp(); iteratorkwp.next(); iteratorkwp.next("foo"); iteratorkwp.next("bar"); trace( sent[0] === "foo" && sent[1] === "bar" ); |
%GeneratorPrototype% | function * generatorFnjp(){} var ownProtojp = Object.getPrototypeOf(generatorFn()); var passedjp = ownProtojp === generatorFnjp.prototype; var sharedProtojp = Object.getPrototypeOf(ownProto); passedjp &= sharedProtojp !== Object.prototype && sharedProtojp === Object.getPrototypeOf(function*(){}.prototype) && sharedProtojp.hasOwnProperty('next'); trace( passedjp ); |
%GeneratorPrototype% prototype chain | function * generatorFnlg(){} var glg = generatorFnlg(); var ownProtolg = Object.getPrototypeOf(g); var passedlg = ownProtolg === generatorFnlg.prototype; var sharedProtolg = Object.getPrototypeOf(ownProto); var iterProtolg = Object.getPrototypeOf(sharedProto); passedlg &= iterProtolg.hasOwnProperty(Symbol.iterator) && !sharedProtolg .hasOwnProperty(Symbol.iterator) && !ownProtolg .hasOwnProperty(Symbol.iterator) && g[Symbol.iterator]() === g; trace( passedlg ); |
%GeneratorPrototype%.constructor | function * ggs (){} var iteratorgs = new ggs.constructor("a","b","c","yield a; yield b; yield c;")(5,6,7); var itemgs = iteratorgs.next(); var passedgs = item.value === 5 && itemgs.done === false; itemgs = iteratorgs.next(); passedgs &= itemgs.value === 6 && itemgs.done === false; itemgs = iteratorgs.next(); passedgs &= item.value === 7 && itemgs.done === false; itemgs = iteratorgs.next(); passedgs &= itemgs.value === void undefined && itemgs.done === true; passedgs &= ggs.constructor === (function*(){}).constructor; trace( passedgs ); |
%GeneratorPrototype%.throw | var passedjkl = false; function * generatorjkl(){ try { yield 5; yield 6; } catch(e) { passedjkl = (e === "foo"); } }; var iteratorjkl = generatorjkl(); iteratorjkl.next(); iteratorjkl.throw("foo"); trace( passedjkl ); |
%GeneratorPrototype%.return | function * generatorbpq(){ yield 5; yield 6; }; var iteratorbpq = generatorbpq(); var itembpq = iteratorbpq.next(); var passedbpq = itembpq.value === 5 && itembpq.done === false; itembpq = iteratorbpq.return("quxquux"); passedbpq &= itembpq.value === "quxquux" && itembpq.done === true; itembpq = iteratorbpq.next(); passedbpq &= itembpq.value === void undefined && itembpq.done === true; trace( passedbpq ); |
yield operator precedence | var passedpvh; function * generatorpvh(){ passed = yield 0 ? true : false; }; var iteratorpvh = generatorpvh(); iteratorpvh.next(); iteratorpvh.next(true); trace( passed ); |
yield *, arrays | var iteratorqks = (function * generatorqks() { yield * [5, 6]; }()); var itemqks = iteratorqks.next(); var passedqks = itemqks.value === 5 && itemqks.done === false; itemqks = iteratorqks.next(); passedqks &= itemqks.value === 6 && itemqks.done === false; itemqks = iteratorqks.next(); passedqks &= itemqks.value === void undefined && itemqks.done === true; trace( passedqks ); |
yield *, sparse arrays | var iteratoryyy = (function * generatoryyy() { yield * [,,]; }()); var itemyyy = iteratoryyy.next(); var passedyyy = itemyyy.value === void undefined && itemyyy.done === false; itemyyy = iteratoryyy.next(); passedyyy &= itemyyy.value === void undefined && itemyyy.done === false; itemyyy = iteratoryyy.next(); passedyyy &= itemyyy.value === void undefined && itemyyy.done === true; trace( passedyyy ); |
yield *, strings | var iteratorooo = (function * generatorooo() { yield * "56"; }()); var itemooo = iteratorooo.next(); var passedooo = itemooo.value === "5" && itemooo.done === false; itemooo = iteratorooo.next(); passedooo &= itemooo.value === "6" && itemooo.done === false; itemooo = iteratorooo.next(); passedooo &= itemooo.value === void undefined && itemooo.done === true; trace( passedooo ); |
yield *, astral plane strings | var iteratorwer = (function * generatorwer() { yield * "𠮷𠮶"; }()); var itemwer = iteratorwer.next(); var passedwer = itemwer.value === "𠮷" && itemwer.done === false; itemwer = iteratorwer.next(); passedwer &= itemwer.value === "𠮶" && itemwer.done === false; itemwer = iteratorwer.next(); passedwer &= itemwer.value === void undefined && itemwer.done === true; trace( passedwer ); |
yield *, generator instances | var iteratorwmp = (function * generatorwmp() { yield * (function*(){ yield 5; yield 6; yield 7; }()); }()); var itemwmp = iteratorwmp.next(); var passedwmp = itemwmp.value === 5 && itemwmp.done === false; itemwmp = iteratorwmp.next(); passedwmp &= itemwmp.value === 6 && itemwmp.done === false; itemwmp = iteratorwmp.next(); passedwmp &= itemwmp.value === 7 && itemwmp.done === false; itemwmp = iteratorwmp.next(); passedwmp &= itemwmp.value === void undefined && itemwmp.done === true; trace( passedwmp ); |
yield *, generic iterables | var iteratorxkp = (function * generatorxkp() { yield * global.__createIterableObject([5, 6, 7]); }()); var itemxkp = iteratorxkp.next(); var passedxkp = itemxkp.value === 5 && itemxkp.done === false; itemxkp = iteratorxkp.next(); passedxkp &= itemxkp.value === 6 && itemxkp.done === false; itemxkp = iteratorxkp.next(); passedxkp &= itemxkp.value === 7 && itemxkp.done === false; itemxkp = iteratorxkp.next(); passedxkp &= itemxkp.value === void undefined && itemxkp.done === true; trace( passedxkp ); |
yield *, instances of iterables | var iteratoruqb = (function * generatoruqb() { yield * Object.create(__createIterableObject([5, 6, 7])); }()); var itemuqb = iteratoruqb.next(); var passeduqb = itemuqb.value === 5 && itemuqb.done === false; itemuqb = iteratoruqb.next(); passeduqb &= itemuqb.value === 6 && itemuqb.done === false; itemuqb = iteratoruqb.next(); passeduqb &= itemuqb.value === 7 && itemuqb.done === false; itemuqb = iteratoruqb.next(); passeduqb &= itemuqb.value === void undefined && itemuqb.done === true; trace( passeduqb ); |
yield * on non-iterables is a runtime error | var iterator78 = (function * generator78() { yield * [5]; }()); var item78 = iterator78.next(); var passed78 = item78.value === 5 && item78.done === false; iterator78 = (function * generator78() { yield * 5; }()); try { iterator78.next(); } catch (e) { trace( passed78 ); } |
yield *, iterator closing | var closed12 = ''; var iter12 = __createIterableObject([1, 2, 3], { 'return': function(){ closed12 += 'a'; trace( {done: true} ); } }); var gen12 = (function* generator12(){ try { yield *iter; } finally { closed12 += 'b'; } })(); gen12.next(); gen12['return'](); trace( closed12 === 'ab' ); |
yield *, iterator closing via throw() | var closed6 = false; var iter6 = global.__createIterableObject([1, 2, 3], { 'throw': undefined, 'return': function() { closed6 = true; trace( {done: true} ); } }); var gen6 = (function*(){ try { yield *iter; } catch(e){} })(); gen6.next(); gen6['throw'](); trace( closed6 ); |
shorthand generator methods | var o59 = { * generator59() { yield 5; yield 6; }, }; var iterator59 = o.generator59(); var item59 = iterator59.next(); var passed59 = item59.value === 5 && item59.done === false; item59 = iterator59.next(); passed59 &= item59.value === 6 && item59.done === false; item59 = iterator59.next(); passed59 &= item59.value === void undefined && item59.done === true; trace( passed59 ); |
string-keyed shorthand generator methods | var o80 = { * "foo bar"() { yield 5; yield 6; }, }; var iterator80 = o80["foo bar"](); var item80 = iterator80.next(); var passed80 = item80.value === 5 && item80.done === false; item80 = iterator80.next(); passed80 &= item80.value === 6 && item80.done === false; item = iterator.next(); passed80 &= item80.value === void undefined && item80.done === true; trace( passed80 ); |
computed shorthand generators | var garply46 = "generator46"; var o46 = { * [garply46] () { yield 5; yield 6; }, }; var iterator46 = o.generator46(); var item46 = iterator46.next(); var passed46 = item46.value === 5 && item46.done === false; item46 = iterator46.next(); passed46 &= item46.value === 6 && item46.done === false; item46 = iterator46.next(); passed46 &= item46.value === void undefined && item46.done === true; trace( passed46 ); |
shorthand generator methods, classes | class C44 { * generator44() { yield 5; yield 6; } }; var iterator44 = new C44().generator44(); var item44 = iterator44.next(); var passed44 = item44.value === 5 && item44.done === false; item44 = iterator44.next(); passed44 &= item44.value === 6 && item44.done === false; item44 = iterator44.next(); passed44 &= item44.value === void undefined && item44.done === true; trace( passed44 ); |
computed shorthand generators, classes | var garplydpbb = "generatordpbb"; class Cdpbb { * [garplydpbb] () { yield 5; yield 6; } } var iteratordpbb = new C().generatordpbb(); var itemdpbb = iteratordpbb.next(); var passeddpbb = itemdpbb.value === 5 && itemdpbb.done === false; itemdpbb = iteratordpbb.next(); passeddpbb &= itemdpbb.value === 6 && itemdpbb.done === false; itemdpbb = iteratordpbb.next(); passeddpbb &= itemdpbb.value === void undefined && itemdpbb.done === true; trace( passeddpbb ); |
shorthand generators can't be constructors | class C612 { * generator612() { yield 5; yield 6; } }; try { Function("class D612 { * constructor() { return {}; } }"); } catch(e) { trace( true ); } |
Built-ins
Reflect (17.1.3.400)
Feature name | example |
---|---|
Reflect.construct sets new.target meta-property | return Reflect.construct(function(a, b, c) { if (new.target === Object) { this.qux = a + b + c; } }, ["foo", "bar", "baz"], Object).qux === "foobarbaz"; |
well-known symbols (17.1.3.400)
Feature name | example |
---|---|
Symbol.species, RegExp.prototype[Symbol.split] | 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; |
Symbol.toStringTag affects existing built-ins | 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; |
Symbol.toStringTag, new built-ins | 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; |
Built-in extensions
function "name" property (17.1.3.400)
Feature name | example |
---|---|
shorthand methods (no lexical binding) | var f = "foo"; return ({f() { return f; }}).f() === "foo"; |
symbol-keyed methods | var sym1 = Symbol("foo"); var sym2 = Symbol(); var o = { [sym1]: function(){}, [sym2]: function(){} }; return o[sym1].name === "[foo]" && o[sym2].name === ""; |
class statements | class foo {}; class bar { static name() {} }; return foo.name === "foo" && typeof bar.name === "function"; |
class expressions | return class foo {}.name === "foo" && typeof class bar { static name() {} }.name === "function"; |
variables (class) | var foo = class {}; var bar = class baz {}; var qux = class { static name() {} }; return foo.name === "foo" && bar.name === "baz" && typeof qux.name === "function"; |
object methods (class) | var o = { foo: class {}, bar: class baz {}}; o.qux = class {}; return o.foo.name === "foo" && o.bar.name === "baz" && o.qux.name === ""; |
class static methods | class C { static foo(){} }; return C.foo.name === "foo"; |
Misc
Proxy, internal 'get' calls (17.1.3.400)
Feature name | example |
---|---|
IteratorComplete, IteratorValue | // 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"; |
miscellaneous (17.1.3.400)
Feature name | example |
---|---|
no semicolon needed after do-while | do {} while (false) return true; |
Annex b
String.prototype HTML methods (17.1.3.400)
Feature name | example |
---|---|
existence | 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; |
tags' names are lowercase | 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; |
quotes in arguments are escaped | var i, names = ["anchor", "fontcolor", "fontsize", "link"]; for (i = 0; i < names.length; i++) { if (""[names[i]]('"') !== ""[names[i]]('&' + 'quot;')) { return false; } } return true; |
RegExp syntax extensions (17.1.3.400)
Feature name | example |
---|---|
hyphens in character sets | return /[\w-_]/.exec("-")[0] === "-"; |
invalid character escapes | return /\z/.exec("\\z")[0] === "z" && /[\z]/.exec("[\\z]")[0] === "z"; |
invalid control-character escapes | return /\c2/.exec("\\c2")[0] === "\\c2"; |
invalid Unicode escapes | return /\u1/.exec("u1")[0] === "u1" && /[\u1]/.exec("u")[0] === "u"; |
invalid hexadecimal escapes | return /\x1/.exec("x1")[0] === "x1" && /[\x1]/.exec("x")[0] === "x"; |
incomplete patterns and quantifiers | return /x{1/.exec("x{1")[0] === "x{1" && /x]1/.exec("x]1")[0] === "x]1"; |
octal escape sequences | return /\041/.exec("!")[0] === "!" && /[\041]/.exec("!")[0] === "!"; |
invalid backreferences become octal escapes | return /\41/.exec("!")[0] === "!" && /[\41]/.exec("!")[0] === "!"; |
HTML-style comments (17.1.3.400)
Feature name | example |
---|---|
HTML-style comments | "--> A comment <!-- Another comment var a = 3; <!-- Another comment return a === 3;" var a = 3; return a === 3;"--> |