Skip to content

Commit

Permalink
Bug 1931350: Add initial implementation for the Iterator Sequencing p…
Browse files Browse the repository at this point in the history
…roposal. r=mgaudet

Test PR: tc39/test262#4326

Differential Revision: https://phabricator.services.mozilla.com/D229014
  • Loading branch information
anba committed Nov 27, 2024
1 parent f971ea6 commit 737856a
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 4 deletions.
81 changes: 77 additions & 4 deletions js/src/builtin/Iterator.js
Original file line number Diff line number Diff line change
Expand Up @@ -974,11 +974,84 @@ function IteratorFind(predicate) {
}
}


#ifdef NIGHTLY_BUILD
/**
/**
* Iterator.concat ( ...items )
*
* https://tc39.es/proposal-iterator-sequencing/
*/
function IteratorConcat() {
// Step 1.
//
// Stored in reversed order to simplify removing processed items.
var index = ArgumentsLength() * 2;
var iterables = std_Array(index);

// Step 2.
for (var i = 0; i < ArgumentsLength(); i++) {
var item = GetArgument(i);

// Step 2.a.
if (!IsObject(item)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, typeof item);
}

// Step 2.b. (Inlined GetMethod)
var method = item[GetBuiltinSymbol("iterator")];

// Step 2.c.
if (!IsCallable(method)) {
ThrowTypeError(JSMSG_NOT_ITERABLE, ToSource(item));
}

// Step 2.d.
DefineDataProperty(iterables, --index, item);
DefineDataProperty(iterables, --index, method);
}
assert(index === 0, "all items stored");

// Steps 3-5.
var result = NewIteratorHelper();
var generator = IteratorConcatGenerator(iterables);
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_GENERATOR_SLOT,
generator
);

// Step 6.
return result;
}

/**
* Iterator.concat ( ...items )
*
* https://tc39.es/proposal-iterator-sequencing/
*/
function* IteratorConcatGenerator(iterables) {
assert(IsArray(iterables), "iterables is an array");
assert(iterables.length % 2 === 0, "iterables contains pairs (item, method)");

// Step 3.a.
for (var i = iterables.length; i > 0; ) {
var item = iterables[--i];
var method = iterables[--i];

// Remove processed items to avoid keeping them alive.
iterables.length -= 2;

// Steps 3.a.i-v.
for (var innerValue of allowContentIterWith(item, method)) {
// Steps 3.a.v.1-3. (Implicit through for-of loop)

yield innerValue;
}
}
}

/**
* Iterator.zip (iterables [, options])
*
*
* https://tc39.es/proposal-joint-iteration/#sec-iterator.zip
*/
function IteratorZip(predicate) {
Expand All @@ -993,4 +1066,4 @@ function IteratorZip(predicate) {
function IteratorZipKeyed(predicate) {
return false;
}
#endif
#endif
1 change: 1 addition & 0 deletions js/src/vm/CommonPropertyNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
MACRO_(compact, "compact") \
MACRO_(compactDisplay, "compactDisplay") \
MACRO_(compare, "compare") \
MACRO_(concat, "concat") \
MACRO_(configurable, "configurable") \
MACRO_(const_, "const") \
MACRO_(constrain, "constrain") \
Expand Down
1 change: 1 addition & 0 deletions js/src/vm/Iteration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,7 @@ void js::AssertDenseElementsNotIterated(NativeObject* obj) {
static const JSFunctionSpec iterator_static_methods[] = {
JS_SELF_HOSTED_FN("from", "IteratorFrom", 1, 0),
#ifdef NIGHTLY_BUILD
JS_SELF_HOSTED_FN("concat", "IteratorConcat", 0, 0),
JS_SELF_HOSTED_FN("range", "IteratorRange", 1, 0),
JS_SELF_HOSTED_FN("zip", "IteratorZip", 1, 0),
JS_SELF_HOSTED_FN("zipKeyed", "IteratorZipKeyed", 1, 0),
Expand Down
9 changes: 9 additions & 0 deletions js/src/vm/JSObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2339,6 +2339,15 @@ JS_PUBLIC_API bool js::ShouldIgnorePropertyDefinition(JSContext* cx,
return true;
}

// It's gently surprising that this is JSProto_Function, but the trick
// to realize is that this is a -constructor function-, not a function
// on the prototype; and the proto of the constructor is JSProto_Function.
if (key == JSProto_Function &&
!JS::Prefs::experimental_iterator_sequencing() &&
id == NameToId(cx->names().concat)) {
return true;
}

if (key == JSProto_Atomics && !JS::Prefs::experimental_atomics_pause() &&
id == NameToId(cx->names().pause)) {
return true;
Expand Down

0 comments on commit 737856a

Please sign in to comment.