Implement Array.prototype.with (#45)

This commit is contained in:
Ben Noordhuis 2023-11-11 23:35:46 +01:00 committed by GitHub
parent a19b07af37
commit 15f798db27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 36 deletions

View file

@ -35936,6 +35936,80 @@ static JSValue js_array_at(JSContext *ctx, JSValueConst this_val,
return ret;
}
static JSValue js_array_with(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
JSValue arr, obj, ret, *arrp, *pval;
JSObject *p;
int64_t i, len, idx;
uint32_t count32;
ret = JS_EXCEPTION;
arr = JS_UNDEFINED;
obj = JS_ToObject(ctx, this_val);
if (js_get_length64(ctx, &len, obj))
goto exception;
if (len > UINT32_MAX) {
JS_ThrowRangeError(ctx, "invalid array length");
goto exception;
}
if (JS_ToInt64Sat(ctx, &idx, argv[0]))
goto exception;
if (idx < 0)
idx = len + idx;
if (idx < 0 || idx >= len) {
JS_ThrowRangeError(ctx, "invalid array index: %" PRId64, idx);
goto exception;
}
arr = JS_NewArray(ctx);
if (JS_IsException(arr))
goto exception;
p = JS_VALUE_GET_OBJ(arr);
if (expand_fast_array(ctx, p, len) < 0)
goto exception;
p->u.array.count = len;
i = 0;
pval = p->u.array.u.values;
if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
for (; i < idx; i++, pval++)
*pval = JS_DupValue(ctx, arrp[i]);
*pval = JS_DupValue(ctx, argv[1]);
for (i++, pval++; i < len; i++, pval++)
*pval = JS_DupValue(ctx, arrp[i]);
} else {
for (; i < idx; i++, pval++)
if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
goto fill_and_fail;
*pval = JS_DupValue(ctx, argv[1]);
for (i++, pval++; i < len; i++, pval++) {
if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) {
fill_and_fail:
for (; i < len; i++, pval++)
*pval = JS_UNDEFINED;
goto exception;
}
}
}
if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
goto exception;
ret = arr;
arr = JS_UNDEFINED;
exception:
JS_FreeValue(ctx, arr);
JS_FreeValue(ctx, obj);
return ret;
}
static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@ -37432,6 +37506,7 @@ static const JSCFunctionListEntry js_iterator_proto_funcs[] = {
static const JSCFunctionListEntry js_array_proto_funcs[] = {
JS_CFUNC_DEF("at", 1, js_array_at ),
JS_CFUNC_DEF("with", 2, js_array_with ),
JS_CFUNC_DEF("concat", 1, js_array_concat ),
JS_CFUNC_MAGIC_DEF("every", 1, js_array_every, special_every ),
JS_CFUNC_MAGIC_DEF("some", 1, js_array_every, special_some ),

View file

@ -59,42 +59,6 @@ test262/test/built-ins/Array/prototype/toSpliced/this-value-boolean.js:18: TypeE
test262/test/built-ins/Array/prototype/toSpliced/this-value-boolean.js:18: strict mode: TypeError: cannot read property 'call' of undefined
test262/test/built-ins/Array/prototype/toSpliced/unmodified.js:13: TypeError: not a function
test262/test/built-ins/Array/prototype/toSpliced/unmodified.js:13: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/frozen-this-value.js:13: TypeError: not a function
test262/test/built-ins/Array/prototype/with/frozen-this-value.js:13: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/holes-not-preserved.js:27: TypeError: not a function
test262/test/built-ins/Array/prototype/with/holes-not-preserved.js:27: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/ignores-species.js:21: TypeError: not a function
test262/test/built-ins/Array/prototype/with/ignores-species.js:21: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/immutable.js:13: TypeError: not a function
test262/test/built-ins/Array/prototype/with/immutable.js:13: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/index-bigger-or-eq-than-length.js:21: Test262Error: Expected a RangeError but got a TypeError
test262/test/built-ins/Array/prototype/with/index-bigger-or-eq-than-length.js:21: strict mode: Test262Error: Expected a RangeError but got a TypeError
test262/test/built-ins/Array/prototype/with/index-casted-to-number.js:23: TypeError: not a function
test262/test/built-ins/Array/prototype/with/index-casted-to-number.js:23: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/index-negative.js:23: TypeError: not a function
test262/test/built-ins/Array/prototype/with/index-negative.js:23: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/index-smaller-than-minus-length.js:21: TypeError: not a function
test262/test/built-ins/Array/prototype/with/index-smaller-than-minus-length.js:21: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/length-decreased-while-iterating.js:32: TypeError: not a function
test262/test/built-ins/Array/prototype/with/length-decreased-while-iterating.js:32: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/length-exceeding-array-length-limit.js:26: Test262Error: Expected a RangeError but got a TypeError
test262/test/built-ins/Array/prototype/with/length-exceeding-array-length-limit.js:26: strict mode: Test262Error: Expected a RangeError but got a TypeError
test262/test/built-ins/Array/prototype/with/length-increased-while-iterating.js:32: TypeError: not a function
test262/test/built-ins/Array/prototype/with/length-increased-while-iterating.js:32: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/length-tolength.js:19: TypeError: cannot read property 'call' of undefined
test262/test/built-ins/Array/prototype/with/length-tolength.js:19: strict mode: TypeError: cannot read property 'call' of undefined
test262/test/built-ins/Array/prototype/with/metadata/length.js:30: TypeError: cannot convert to object
test262/test/built-ins/Array/prototype/with/metadata/length.js:30: strict mode: TypeError: cannot convert to object
test262/test/built-ins/Array/prototype/with/metadata/name.js:28: TypeError: cannot convert to object
test262/test/built-ins/Array/prototype/with/metadata/name.js:28: strict mode: TypeError: cannot convert to object
test262/test/built-ins/Array/prototype/with/metadata/property-descriptor.js:18: Test262Error: typeof Expected SameValue(«undefined», «function») to be true
test262/test/built-ins/Array/prototype/with/metadata/property-descriptor.js:18: strict mode: Test262Error: typeof Expected SameValue(«undefined», «function») to be true
test262/test/built-ins/Array/prototype/with/no-get-replaced-index.js:29: TypeError: not a function
test262/test/built-ins/Array/prototype/with/no-get-replaced-index.js:29: strict mode: TypeError: not a function
test262/test/built-ins/Array/prototype/with/not-a-constructor.js:30: Test262Error: isConstructor invoked with a non-function value
test262/test/built-ins/Array/prototype/with/not-a-constructor.js:30: strict mode: Test262Error: isConstructor invoked with a non-function value
test262/test/built-ins/Array/prototype/with/this-value-boolean.js:22: TypeError: cannot read property 'call' of undefined
test262/test/built-ins/Array/prototype/with/this-value-boolean.js:22: strict mode: TypeError: cannot read property 'call' of undefined
test262/test/built-ins/AsyncGeneratorPrototype/return/return-state-completed-broken-promise.js:53: TypeError: $DONE() not called
test262/test/built-ins/AsyncGeneratorPrototype/return/return-state-completed-broken-promise.js:53: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncGeneratorPrototype/return/return-suspendedStart-broken-promise.js:34: TypeError: $DONE() not called