Skip to content

Commit

Permalink
Iterator is not constructible from the active function object (work…
Browse files Browse the repository at this point in the history
…s as an abstract class)
  • Loading branch information
zloirock committed Jul 26, 2023
1 parent 7ce3606 commit 19ff49d
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 11 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Expand Up @@ -9,8 +9,9 @@
- [`Set` methods stage 3 proposal](https://github.com/tc39/proposal-set-methods), July 2023 TC39 meeting updates::
- Throw on negative `Set` sizes, [proposal-set-methods/88](https://github.com/tc39/proposal-set-methods/pull/88)
- Removed `IsCallable` check in `GetKeysIterator`, [proposal-set-methods/101](https://github.com/tc39/proposal-set-methods/pull/101)
- [Iterator Helpers stage 3 proposal](https://github.com/tc39/proposal-iterator-helpers), July 2023 TC39 meeting updates::
- Avoid creating observable `String` wrapper objects, [proposal-iterator-helpers/281](https://github.com/tc39/proposal-iterator-helpers/pull/281)
- [Iterator Helpers stage 3 proposal](https://github.com/tc39/proposal-iterator-helpers):
- Avoid creating observable `String` wrapper objects, July 2023 TC39 meeting update, [proposal-iterator-helpers/281](https://github.com/tc39/proposal-iterator-helpers/pull/281)
- `Iterator` is not constructible from the active function object (works as an abstract class)
- Async explicit resource management:
- Built-ins:
- `Symbol.asyncDispose`
Expand Down
4 changes: 4 additions & 0 deletions packages/core-js/modules/esnext.async-iterator.constructor.js
@@ -1,6 +1,7 @@
'use strict';
var $ = require('../internals/export');
var anInstance = require('../internals/an-instance');
var getPrototypeOf = require('../internals/object-get-prototype-of');
var createNonEnumerableProperty = require('../internals/create-non-enumerable-property');
var hasOwn = require('../internals/has-own-property');
var wellKnownSymbol = require('../internals/well-known-symbol');
Expand All @@ -9,8 +10,11 @@ var IS_PURE = require('../internals/is-pure');

var TO_STRING_TAG = wellKnownSymbol('toStringTag');

var $TypeError = TypeError;

var AsyncIteratorConstructor = function AsyncIterator() {
anInstance(this, AsyncIteratorPrototype);
if (getPrototypeOf(this) === AsyncIteratorPrototype) throw $TypeError('Abstract class AsyncIterator not directly constructable');
};

AsyncIteratorConstructor.prototype = AsyncIteratorPrototype;
Expand Down
3 changes: 3 additions & 0 deletions packages/core-js/modules/esnext.iterator.constructor.js
Expand Up @@ -3,6 +3,7 @@ var $ = require('../internals/export');
var global = require('../internals/global');
var anInstance = require('../internals/an-instance');
var isCallable = require('../internals/is-callable');
var getPrototypeOf = require('../internals/object-get-prototype-of');
var createNonEnumerableProperty = require('../internals/create-non-enumerable-property');
var fails = require('../internals/fails');
var hasOwn = require('../internals/has-own-property');
Expand All @@ -12,6 +13,7 @@ var IS_PURE = require('../internals/is-pure');

var TO_STRING_TAG = wellKnownSymbol('toStringTag');

var $TypeError = TypeError;
var NativeIterator = global.Iterator;

// FF56- have non-standard global helper `Iterator`
Expand All @@ -23,6 +25,7 @@ var FORCED = IS_PURE

var IteratorConstructor = function Iterator() {
anInstance(this, IteratorPrototype);
if (getPrototypeOf(this) === IteratorPrototype) throw $TypeError('Abstract class Iterator not directly constructable');
};

if (!hasOwn(IteratorPrototype, TO_STRING_TAG)) {
Expand Down
9 changes: 8 additions & 1 deletion tests/unit-global/esnext.async-iterator.constructor.js
@@ -1,3 +1,5 @@
import { nativeSubclass } from '../helpers/helpers';

const { getPrototypeOf } = Object;

QUnit.test('AsyncIterator', assert => {
Expand All @@ -22,7 +24,12 @@ QUnit.test('AsyncIterator', assert => {
assert.true(AsyncIterator.from([1, 2, 3]) instanceof AsyncIterator, 'Async From Proxy');
assert.true(AsyncIterator.from([1, 2, 3]).drop(1) instanceof AsyncIterator, 'Async Drop Proxy');

assert.true(new AsyncIterator() instanceof AsyncIterator, 'constructor');
if (nativeSubclass) {
const Sub = nativeSubclass(AsyncIterator);
assert.true(new Sub() instanceof AsyncIterator, 'abstract constructor');
}

assert.throws(() => new AsyncIterator(), 'direct constructor throws');
assert.throws(() => AsyncIterator(), 'throws w/o `new`');
});

Expand Down
4 changes: 2 additions & 2 deletions tests/unit-global/esnext.async-iterator.from.js
@@ -1,4 +1,4 @@
const { assign } = Object;
const { assign, create } = Object;

QUnit.test('AsyncIterator.from', assert => {
const { from } = AsyncIterator;
Expand All @@ -13,7 +13,7 @@ QUnit.test('AsyncIterator.from', assert => {

assert.true(AsyncIterator.from([]) instanceof AsyncIterator, 'proxy, iterable');

const asyncIterator = assign(new AsyncIterator(), {
const asyncIterator = assign(create(AsyncIterator.prototype), {
next: () => { /* empty */ },
});

Expand Down
9 changes: 7 additions & 2 deletions tests/unit-global/esnext.iterator.constructor.js
@@ -1,4 +1,4 @@
import { createIterator } from '../helpers/helpers';
import { createIterator, nativeSubclass } from '../helpers/helpers';

const { getPrototypeOf } = Object;

Expand Down Expand Up @@ -28,7 +28,12 @@ QUnit.test('Iterator', assert => {
assert.true(Iterator.from(createIterator([1, 2, 3])) instanceof Iterator, 'From Proxy');
assert.true([].values().drop(1) instanceof Iterator, 'Drop Proxy');

assert.true(new Iterator() instanceof Iterator, 'constructor');
if (nativeSubclass) {
const Sub = nativeSubclass(Iterator);
assert.true(new Sub() instanceof Iterator, 'abstract constructor');
}

assert.throws(() => new Iterator(), 'direct constructor throws');
assert.throws(() => Iterator(), 'throws w/o `new`');
});

Expand Down
9 changes: 8 additions & 1 deletion tests/unit-pure/esnext.async-iterator.constructor.js
@@ -1,3 +1,5 @@
import { nativeSubclass } from '../helpers/helpers';

import Symbol from 'core-js-pure/es/symbol';

import AsyncIterator from 'core-js-pure/actual/async-iterator';
Expand All @@ -9,7 +11,12 @@ QUnit.test('AsyncIterator', assert => {
assert.true(AsyncIterator.from([1, 2, 3]) instanceof AsyncIterator, 'Async From Proxy');
assert.true(AsyncIterator.from([1, 2, 3]).drop(1) instanceof AsyncIterator, 'Async Drop Proxy');

assert.true(new AsyncIterator() instanceof AsyncIterator, 'constructor');
if (nativeSubclass) {
const Sub = nativeSubclass(AsyncIterator);
assert.true(new Sub() instanceof AsyncIterator, 'abstract constructor');
}

assert.throws(() => new AsyncIterator(), 'direct constructor throws');
assert.throws(() => AsyncIterator(), 'throws w/o `new`');
});

Expand Down
3 changes: 2 additions & 1 deletion tests/unit-pure/esnext.async-iterator.from.js
@@ -1,5 +1,6 @@
import Promise from 'core-js-pure/es/promise';
import assign from 'core-js-pure/es/object/assign';
import create from 'core-js-pure/es/object/create';
import values from 'core-js-pure/es/array/values';
import AsyncIterator from 'core-js-pure/actual/async-iterator';

Expand All @@ -13,7 +14,7 @@ QUnit.test('AsyncIterator.from', assert => {

assert.true(AsyncIterator.from([]) instanceof AsyncIterator, 'proxy, iterable');

const asyncIterator = assign(new AsyncIterator(), {
const asyncIterator = assign(create(AsyncIterator.prototype), {
next: () => { /* empty */ },
});

Expand Down
9 changes: 7 additions & 2 deletions tests/unit-pure/esnext.iterator.constructor.js
@@ -1,4 +1,4 @@
import { createIterator } from '../helpers/helpers';
import { createIterator, nativeSubclass } from '../helpers/helpers';

import Symbol from 'core-js-pure/es/symbol';
import Iterator from 'core-js-pure/actual/iterator';
Expand All @@ -9,7 +9,12 @@ QUnit.test('Iterator', assert => {

assert.true(Iterator.from(createIterator([1, 2, 3])) instanceof Iterator, 'From Proxy');

assert.true(new Iterator() instanceof Iterator, 'constructor');
if (nativeSubclass) {
const Sub = nativeSubclass(Iterator);
assert.true(new Sub() instanceof Iterator, 'abstract constructor');
}

assert.throws(() => new Iterator(), 'direct constructor throws');
assert.throws(() => Iterator(), 'throws w/o `new`');
});

Expand Down

0 comments on commit 19ff49d

Please sign in to comment.