넥사크로 스튜디오 옵션에서 [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;"--> |