부록 A.넥사크로 스튜디오 ES6 버전 별 미지원 현황

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

A.1syntax

A.1.1default 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();
         }()) );

A.1.2rest 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;
         }}()) );

A.1.3spread 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";

A.1.4object 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';

A.1.5for..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 );

A.1.6object literal extensions (17.1.3.300)

Feature name

example

octal literals

trace( 0o10 === 8 && 0O10 === 8 );

binary literals

trace( 0b10 === 2 && 0B10 === 2 );

A.1.7template 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 );

A.1.8destructuring, 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 );

A.1.9destructuring, 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 );

A.1.10destructuring, 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; }()) );

A.1.11Unicode 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 );

A.1.12new.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;
         }

A.2Bindings

A.2.1const (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") );

A.3Functions

A.3.1arrow 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 );

A.3.2class (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 );

A.3.3super (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 );

A.3.4generators (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 );
         }

A.4Built-ins

A.4.1Reflect (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";

A.4.2well-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;

A.5Built-in extensions

A.5.1function "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";

A.6Misc

A.6.1Proxy, 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";

A.6.2miscellaneous (17.1.3.400)

Feature name

example

no semicolon needed after do-while

do {} while (false) return true;

A.7Annex b

A.7.1String.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;

A.7.2RegExp 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] === "!";

A.7.3HTML-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;"-->