diff --git a/INTERPRETING.md b/INTERPRETING.md index 7904eb7109..54e5418008 100644 --- a/INTERPRETING.md +++ b/INTERPRETING.md @@ -64,16 +64,16 @@ properties of the global scope prior to test execution. 6. Return Completion(status). - **`global`** - a reference to the global object on which `$262` was initially defined - - **`uncallableAndIsHTMLDDA`** - a function that returns an object *`obj`* for - which [Call](https://tc39.github.io/ecma262/#sec-call)(*`obj`*, *any value*, «») - throws a `TypeError`. (The value of [IsCallable]()(*`obj`*) is unspecified: - a callable *`obj`* that throws a `TypeError` or an uncallable *`obj`* works - equally well.) In hosts supporting the - [IsHTMLDDA](https://tc39.github.io/ecma262/#sec-IsHTMLDDA-internal-slot) - internal slot, *`obj`* must also have such a slot. (These highly specific - behaviors are entirely motivated by the very few tests that use this. Read - them for an explanation.) Tests that use this function should be marked as - using the `uncallableAndIsHTMLDDA` feature. + - **`IsHTMLDDA`** - (present only in implementations that can provide it) an + object that 1) has an [[IsHTMLDDA]] internal slot, and 2) when called with + no arguments or with the single argument `""` returns `null`. Use this + property to test that ECMAScript algorithms aren't mis-implemented to treat + `document.all` as being `undefined` or of type Undefined (instead of + Object). (The peculiar second requirement permits testing algorithms when + they also call `document.all` with such arguments, so that testing for + correct behavior requires knowing how the call behaves. This is rarely + necessary.) Tests using this function must be tagged with the `IsHTMLDDA` + feature so that only hosts supporting this property will run them. - **`agent`** - an ordinary object with the following properties: - **`start`** - a function that takes a script source string and runs the script in a concurrent agent. Will block until that agent is diff --git a/features.txt b/features.txt index ce2e3b4595..f3072571d7 100644 --- a/features.txt +++ b/features.txt @@ -124,4 +124,4 @@ WeakSet # language features, exposed through global-environment functions on the $262 # object, go here. -uncallableAndIsHTMLDDA +IsHTMLDDA diff --git a/test/annexB/language/expressions/yield/star-iterable-return-emulates-undefined-throws-when-called.js b/test/annexB/language/expressions/yield/star-iterable-return-emulates-undefined-throws-when-called.js index 04aa29987a..272e180527 100644 --- a/test/annexB/language/expressions/yield/star-iterable-return-emulates-undefined-throws-when-called.js +++ b/test/annexB/language/expressions/yield/star-iterable-return-emulates-undefined-throws-when-called.js @@ -2,18 +2,19 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: sec-generator-function-definitions-runtime-semantics-evaluation +esid: sec-generator-function-definitions-runtime-semantics-evaluation description: > If .return is an object emulating `undefined` (e.g. `document.all` in browsers), it shouldn't be treated as if it were actually `undefined` by the yield* operator. -features: [generators, uncallableAndIsHTMLDDA] +features: [generators, IsHTMLDDA] ---*/ +var IsHTMLDDA = $262.IsHTMLDDA; var iter = { [Symbol.iterator]() { return this; }, next() { return {}; }, - return: $262.uncallableAndIsHTMLDDA(), + return: IsHTMLDDA, }; var outer = (function*() { yield* iter; })(); @@ -21,11 +22,10 @@ var outer = (function*() { yield* iter; })(); outer.next(); assert.throws(TypeError, function() { - // This code is expected to throw a TypeError because `iter.return` throws a - // TypeError when invoked with `iter` as `this` and no arguments provided. - // It's irrelevant that in hosts that support the [[IsHTMLDDA]] internal slot, - // this object has that slot: `.return` behavior is skipped only if - // that property is exactly the value `undefined`, not a value loosely equal - // to it. - outer.return(); + // `IsHTMLDDA` is called here with `iter` as `this` and `emptyString` as the + // sole argument, and it's specified to return `null` under these conditions. + // As `iter`'s iteration isn't ending because of a throw, the iteration + // protocol will then throw a `TypeError` because `null` isn't an object. + var emptyString = ""; + outer.return(emptyString); }); diff --git a/test/annexB/language/statements/for-await-of/iterator-close-return-emulates-undefined-throws-when-called.js b/test/annexB/language/statements/for-await-of/iterator-close-return-emulates-undefined-throws-when-called.js index 77c4847ecb..9c730c4b36 100644 --- a/test/annexB/language/statements/for-await-of/iterator-close-return-emulates-undefined-throws-when-called.js +++ b/test/annexB/language/statements/for-await-of/iterator-close-return-emulates-undefined-throws-when-called.js @@ -7,19 +7,23 @@ description: > `GetIterator(obj, ~async~)` must attempt to call `obj[@@asyncIterator]` when that value is an object with an [[IsHTMLDDA]] internal slot, not act as if the value were `undefined`. -features: [async-iteration, uncallableAndIsHTMLDDA] +features: [async-iteration, IsHTMLDDA] flags: [async] ---*/ async function f() { - var fakeIter = { - [Symbol.asyncIterator]: $262.uncallableAndIsHTMLDDA(), + var IsHTMLDDA = $262.IsHTMLDDA; + var iter = { + [Symbol.asyncIterator]: IsHTMLDDA, get [Symbol.iterator]() { throw new Test262Error("shouldn't touch Symbol.iterator"); }, }; - for await (var x of fakeIter) + // `IsHTMLDDA` is called here with `iter` as `this` and no arguments, and it's + // expected to return `null` under these conditions. Then the iteration + // protocol throws a `TypeError` because `null` isn't an object. + for await (var x of iter) return "for-await-of body shouldn't be reached"; return "should have failed earlier"; @@ -28,7 +32,8 @@ async function f() { f().then($DONE, function (e) { assert.sameValue(e.constructor, TypeError, - "expected TypeError from calling " + - "uncallableAndIsHTMLDDA() value: " + e); + "expected TypeError because " + + "`iter[Symbol.asyncIterator]() returned a " + + "non-object: " + e); }) .then($DONE, $DONE); diff --git a/test/annexB/language/statements/for-of/iterator-close-return-emulates-undefined-throws-when-called.js b/test/annexB/language/statements/for-of/iterator-close-return-emulates-undefined-throws-when-called.js index a7fc382be4..feb95f5111 100644 --- a/test/annexB/language/statements/for-of/iterator-close-return-emulates-undefined-throws-when-called.js +++ b/test/annexB/language/statements/for-of/iterator-close-return-emulates-undefined-throws-when-called.js @@ -2,26 +2,24 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: sec-iteratorclose +esid: sec-iteratorclose description: > If .return is an object emulating `undefined` (e.g. `document.all` in browsers), it shouldn't be treated as if it were actually `undefined`. -features: [generators, uncallableAndIsHTMLDDA] +features: [generators, IsHTMLDDA] ---*/ +var IsHTMLDDA = $262.IsHTMLDDA; var iter = { [Symbol.iterator]() { return this; }, next() { return {}; }, - return: $262.uncallableAndIsHTMLDDA(), + return: IsHTMLDDA, }; assert.throws(TypeError, function() { - // This code is expected to throw a TypeError because `iter.return` throws a - // TypeError when invoked with `iter` as `this` and no arguments provided. - // It's irrelevant that in hosts that support the [[IsHTMLDDA]] internal slot, - // this object has that slot: `.return` behavior is skipped only if - // that property is exactly the value `undefined`, not a value loosely equal - // to it. + // `IsHTMLDDA` is called here with `iter` as `this` and no arguments, and it's + // specified to return `null` under these conditions. Then the iteration + // protocol throws a `TypeError` because `null` isn't an object. for (var x of iter) break; });