mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-02 00:25:34 +08:00
Lower static Array fill/copyWithin and position coercion (#457)
* Coerce static Array slice and splice positions * Lower static Array fill and copyWithin with Test262 assertions
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
import { BOOL, F64, type IrExpr, type IrStmt, type IrType, type SrcLoc } from "../../ir/ir.js";
|
||||
import { numLit, varRef } from "../../ir/build.js";
|
||||
import { typeKey } from "../type-mapper.js";
|
||||
import type { Lowerer } from "./lowerer.js";
|
||||
import { arrayValueStore } from "./array-values.js";
|
||||
|
||||
const add = (left: IrExpr, right: IrExpr, loc: SrcLoc): IrExpr => ({ kind: "bin", op: "+", left, right, type: F64, loc });
|
||||
const sub = (left: IrExpr, right: IrExpr, loc: SrcLoc): IrExpr => ({ kind: "bin", op: "-", left, right, type: F64, loc });
|
||||
const lt = (left: IrExpr, right: IrExpr, loc: SrcLoc): IrExpr => ({ kind: "bin", op: "<", left, right, type: BOOL, loc });
|
||||
const eq = (left: IrExpr, right: IrExpr, loc: SrcLoc): IrExpr => ({ kind: "bin", op: "===", left, right, type: BOOL, loc });
|
||||
const math = (fn: "min" | "max" | "trunc", args: IrExpr[], loc: SrcLoc): IrExpr => ({ kind: "libCall", fn: `math.${fn}`, args, type: F64, loc });
|
||||
const lengthOf = (arr: IrExpr, loc: SrcLoc): IrExpr => ({ kind: "arrIntrinsic", method: "length", receiver: arr, args: [], type: F64, loc });
|
||||
|
||||
function relativeIndex(position: IrExpr, length: IrExpr, loc: SrcLoc): IrExpr {
|
||||
const integer: IrExpr = {
|
||||
kind: "ternary",
|
||||
cond: { kind: "libCall", fn: "num.isNaN", args: [position], type: BOOL, loc },
|
||||
then: numLit(0, loc),
|
||||
else_: math("trunc", [position], loc),
|
||||
type: F64,
|
||||
loc,
|
||||
};
|
||||
return {
|
||||
kind: "ternary",
|
||||
cond: lt(integer, numLit(0, loc), loc),
|
||||
then: math("max", [add(length, integer, loc), numLit(0, loc)], loc),
|
||||
else_: math("min", [integer, length], loc),
|
||||
type: F64,
|
||||
loc,
|
||||
};
|
||||
}
|
||||
|
||||
export function lowerArrayFill(
|
||||
lowerer: Lowerer,
|
||||
receiver: IrExpr,
|
||||
value: IrExpr | null,
|
||||
writeUndefined: boolean,
|
||||
start: IrExpr,
|
||||
end: IrExpr,
|
||||
arrType: IrType & { kind: "array" },
|
||||
loc: SrcLoc,
|
||||
): IrExpr {
|
||||
const valueType = writeUndefined ? F64 : value!.type;
|
||||
const key = "indexed:fill:" + typeKey(arrType.elem) + ":" + typeKey(valueType) + ":" + writeUndefined;
|
||||
let name = lowerer.arrHofHelpers.get(key);
|
||||
if (!name) {
|
||||
name = "%arr.fill." + lowerer.arrHofHelpers.size;
|
||||
lowerer.arrHofHelpers.set(key, name);
|
||||
const a = varRef("a.0", arrType, loc);
|
||||
const n = varRef("n.0", F64, loc);
|
||||
const i = varRef("i.0", F64, loc);
|
||||
const body: IrStmt[] = writeUndefined
|
||||
? [{ kind: "arraySetUndefined", arr: a, index: i, loc }]
|
||||
: [arrayValueStore(lowerer, a, i, varRef("v.0", valueType, loc), arrType.elem, loc)];
|
||||
lowerer.liftedFns.push({
|
||||
name,
|
||||
params: [
|
||||
{ localId: "a.0", name: "a", type: arrType },
|
||||
{ localId: "v.0", name: "v", type: valueType },
|
||||
{ localId: "start.0", name: "start", type: F64 },
|
||||
{ localId: "end.0", name: "end", type: F64 },
|
||||
],
|
||||
returnType: arrType,
|
||||
locals: [
|
||||
{ id: "a.0", name: "a", type: arrType, mutable: true },
|
||||
{ id: "v.0", name: "v", type: valueType, mutable: false },
|
||||
{ id: "start.0", name: "start", type: F64, mutable: false },
|
||||
{ id: "end.0", name: "end", type: F64, mutable: false },
|
||||
{ id: "n.0", name: "n", type: F64, mutable: false },
|
||||
{ id: "from.0", name: "from", type: F64, mutable: false },
|
||||
{ id: "until.0", name: "until", type: F64, mutable: false },
|
||||
{ id: "i.0", name: "i", type: F64, mutable: true },
|
||||
],
|
||||
body: [
|
||||
{ kind: "varDecl", localId: "n.0", init: lengthOf(a, loc), loc },
|
||||
{ kind: "varDecl", localId: "from.0", init: relativeIndex(varRef("start.0", F64, loc), n, loc), loc },
|
||||
{ kind: "varDecl", localId: "until.0", init: relativeIndex(varRef("end.0", F64, loc), n, loc), loc },
|
||||
{
|
||||
kind: "for",
|
||||
init: { kind: "varDecl", localId: "i.0", init: varRef("from.0", F64, loc), loc },
|
||||
cond: lt(i, varRef("until.0", F64, loc), loc),
|
||||
update: { kind: "assign", localId: "i.0", value: add(i, numLit(1, loc), loc), loc },
|
||||
body,
|
||||
loc,
|
||||
},
|
||||
{ kind: "return", value: a, loc },
|
||||
],
|
||||
loc,
|
||||
});
|
||||
}
|
||||
const valueArg: IrExpr = value && writeUndefined
|
||||
? { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: value, loc }], result: numLit(0, loc), type: F64, loc }
|
||||
: value ?? numLit(0, loc);
|
||||
return { kind: "call", callee: name, args: [receiver, valueArg, start, end], type: arrType, loc };
|
||||
}
|
||||
|
||||
export function lowerArrayCopyWithin(
|
||||
lowerer: Lowerer,
|
||||
receiver: IrExpr,
|
||||
target: IrExpr,
|
||||
start: IrExpr,
|
||||
end: IrExpr,
|
||||
arrType: IrType & { kind: "array" },
|
||||
loc: SrcLoc,
|
||||
): IrExpr {
|
||||
const key = "indexed:copyWithin:" + typeKey(arrType.elem);
|
||||
let name = lowerer.arrHofHelpers.get(key);
|
||||
if (!name) {
|
||||
name = "%arr.copyWithin." + lowerer.arrHofHelpers.size;
|
||||
lowerer.arrHofHelpers.set(key, name);
|
||||
const a = varRef("a.0", arrType, loc);
|
||||
const n = varRef("n.0", F64, loc);
|
||||
const dst = varRef("targetIndex.0", F64, loc);
|
||||
const src = varRef("startIndex.0", F64, loc);
|
||||
const last = varRef("endIndex.0", F64, loc);
|
||||
const remaining = varRef("count.0", F64, loc);
|
||||
const step = varRef("direction.0", F64, loc);
|
||||
const from = varRef("from.0", F64, loc);
|
||||
const to = varRef("to.0", F64, loc);
|
||||
const state = varRef("state.0", F64, loc);
|
||||
const backwards: IrExpr = {
|
||||
kind: "logical", op: "&&", left: lt(src, dst, loc),
|
||||
right: lt(dst, add(src, remaining, loc), loc), type: BOOL, loc,
|
||||
};
|
||||
const offset: IrExpr = {
|
||||
kind: "ternary", cond: lt(step, numLit(0, loc), loc),
|
||||
then: sub(remaining, numLit(1, loc), loc), else_: numLit(0, loc), type: F64, loc,
|
||||
};
|
||||
lowerer.liftedFns.push({
|
||||
name,
|
||||
params: [
|
||||
{ localId: "a.0", name: "a", type: arrType },
|
||||
{ localId: "target.0", name: "target", type: F64 },
|
||||
{ localId: "start.0", name: "start", type: F64 },
|
||||
{ localId: "end.0", name: "end", type: F64 },
|
||||
],
|
||||
returnType: arrType,
|
||||
locals: [
|
||||
{ id: "a.0", name: "a", type: arrType, mutable: true },
|
||||
{ id: "target.0", name: "target", type: F64, mutable: false },
|
||||
{ id: "start.0", name: "start", type: F64, mutable: false },
|
||||
{ id: "end.0", name: "end", type: F64, mutable: false },
|
||||
{ id: "n.0", name: "n", type: F64, mutable: false },
|
||||
{ id: "targetIndex.0", name: "targetIndex", type: F64, mutable: false },
|
||||
{ id: "startIndex.0", name: "startIndex", type: F64, mutable: false },
|
||||
{ id: "endIndex.0", name: "endIndex", type: F64, mutable: false },
|
||||
{ id: "count.0", name: "count", type: F64, mutable: true },
|
||||
{ id: "direction.0", name: "direction", type: F64, mutable: false },
|
||||
{ id: "from.0", name: "from", type: F64, mutable: true },
|
||||
{ id: "to.0", name: "to", type: F64, mutable: true },
|
||||
{ id: "state.0", name: "state", type: F64, mutable: false },
|
||||
{ id: "value.0", name: "value", type: arrType.elem, mutable: false },
|
||||
],
|
||||
body: [
|
||||
{ kind: "varDecl", localId: "n.0", init: lengthOf(a, loc), loc },
|
||||
{ kind: "varDecl", localId: "targetIndex.0", init: relativeIndex(varRef("target.0", F64, loc), n, loc), loc },
|
||||
{ kind: "varDecl", localId: "startIndex.0", init: relativeIndex(varRef("start.0", F64, loc), n, loc), loc },
|
||||
{ kind: "varDecl", localId: "endIndex.0", init: relativeIndex(varRef("end.0", F64, loc), n, loc), loc },
|
||||
{
|
||||
kind: "varDecl", localId: "count.0",
|
||||
init: {
|
||||
kind: "ternary", cond: eq(src, dst, loc), then: numLit(0, loc),
|
||||
else_: math("min", [math("max", [sub(last, src, loc), numLit(0, loc)], loc), sub(n, dst, loc)], loc),
|
||||
type: F64, loc,
|
||||
}, loc,
|
||||
},
|
||||
{ kind: "varDecl", localId: "direction.0", init: { kind: "ternary", cond: backwards, then: numLit(-1, loc), else_: numLit(1, loc), type: F64, loc }, loc },
|
||||
{ kind: "varDecl", localId: "from.0", init: add(src, offset, loc), loc },
|
||||
{ kind: "varDecl", localId: "to.0", init: add(dst, offset, loc), loc },
|
||||
{
|
||||
kind: "while", cond: lt(numLit(0, loc), remaining, loc),
|
||||
body: [
|
||||
{ kind: "varDecl", localId: "state.0", init: { kind: "arrayState", arr: a, index: from, type: F64, loc }, loc },
|
||||
{
|
||||
kind: "if", cond: eq(state, numLit(0, loc), loc),
|
||||
then: [{ kind: "arrayDelete", arr: a, index: to, loc }],
|
||||
else_: [{
|
||||
kind: "if", cond: eq(state, numLit(2, loc), loc),
|
||||
then: [{ kind: "arraySetUndefined", arr: a, index: to, loc }],
|
||||
else_: [
|
||||
{ kind: "varDecl", localId: "value.0", init: { kind: "arrayGet", arr: a, index: from, type: arrType.elem, loc }, loc },
|
||||
{ kind: "arraySet", arr: a, index: to, value: varRef("value.0", arrType.elem, loc), loc },
|
||||
], loc,
|
||||
}], loc,
|
||||
},
|
||||
{ kind: "assign", localId: "from.0", value: add(from, step, loc), loc },
|
||||
{ kind: "assign", localId: "to.0", value: add(to, step, loc), loc },
|
||||
{ kind: "assign", localId: "count.0", value: sub(remaining, numLit(1, loc), loc), loc },
|
||||
], loc,
|
||||
},
|
||||
{ kind: "return", value: a, loc },
|
||||
],
|
||||
loc,
|
||||
});
|
||||
}
|
||||
return { kind: "call", callee: name, args: [receiver, target, start, end], type: arrType, loc };
|
||||
}
|
||||
@@ -17,7 +17,8 @@ import { arrayIndexPresent, arrayValueRead, arrayValueStore, arrayValueType, cur
|
||||
import { typeKey } from "../type-mapper.js";
|
||||
import { WidthLift } from "./lowerer.js";
|
||||
import { boolLit, countedFor, numLit, varRef } from "../../ir/build.js";
|
||||
import { lowerOptionalArgument, lowerPositionArgument, positionNumber } from "./optional-arguments.js";
|
||||
import { lowerPositionArgument, positionNumber } from "./optional-arguments.js";
|
||||
import { lowerArrayCopyWithin, lowerArrayFill } from "./array-indexed-mutation.js";
|
||||
|
||||
function primitivePositionType(lowerer: Lowerer, type: IrType): boolean {
|
||||
if (type.kind === "union") {
|
||||
@@ -27,6 +28,30 @@ function primitivePositionType(lowerer: Lowerer, type: IrType): boolean {
|
||||
type.kind === "nullT" || type.kind === "undefinedT";
|
||||
}
|
||||
|
||||
function lowerArrayPosition(
|
||||
lowerer: Lowerer,
|
||||
node: ts.Expression | undefined,
|
||||
defaultValue: IrExpr,
|
||||
subject: string,
|
||||
): IrExpr {
|
||||
if (!node) return defaultValue;
|
||||
if (ts.isSpreadElement(node)) lowerer.noLowering(`${subject} with a spread argument`, node);
|
||||
const value = lowerPositionArgument(lowerer, node, defaultValue);
|
||||
if (!primitivePositionType(lowerer, value.type)) {
|
||||
lowerer.noLowering(`${subject} of '${lowerer.fmt(value.type)}' values`, node);
|
||||
}
|
||||
const loc = locOf(node);
|
||||
const local = lowerer.declareHiddenLocal("%arrayPosition", value.type);
|
||||
const ref = varRef(local.id, value.type, loc);
|
||||
return {
|
||||
kind: "seqExpr",
|
||||
stmts: [{ kind: "varDecl", localId: local.id, init: value, loc }],
|
||||
result: positionNumber(lowerer, ref, defaultValue, node, subject),
|
||||
type: F64,
|
||||
loc,
|
||||
};
|
||||
}
|
||||
|
||||
/** Build the argument array for a mutating/copying operation while keeping
|
||||
* the receiver's scalar payload ABI. A missing read is represented as the
|
||||
* present UNDEFINED state in this temporary, so push/unshift and toSpliced
|
||||
@@ -212,6 +237,41 @@ function fenceProducedArrayElem(lowerer: Lowerer, node: ts.Node, producer: strin
|
||||
loc,
|
||||
};
|
||||
}
|
||||
if (name === "fill") {
|
||||
if (call.arguments.length > 3 || call.arguments.some(ts.isSpreadElement)) {
|
||||
lowerer.noLowering(`.fill with ${call.arguments.length} arguments`, call);
|
||||
}
|
||||
const value = call.arguments[0] ? lowerer.lowerExpr(call.arguments[0]) : null;
|
||||
if (value && (value.type.kind === "dyn" || value.type.kind === "jsval") &&
|
||||
isRefCounted(elem) && elem.kind !== "string" && !typeEquals(value.type, elem)) {
|
||||
lowerer.noLowering(".fill of a checked-dynamic reference into a static array", call.arguments[0]!);
|
||||
}
|
||||
const writeUndefined = value === null || value.type.kind === "undefinedT";
|
||||
return lowerArrayFill(
|
||||
lowerer,
|
||||
lowerer.lowerExpr(access.expression),
|
||||
value,
|
||||
writeUndefined,
|
||||
lowerArrayPosition(lowerer, call.arguments[1], numLit(0, loc), "array fill start"),
|
||||
lowerArrayPosition(lowerer, call.arguments[2], numLit(Infinity, loc), "array fill end"),
|
||||
receiverIr,
|
||||
loc,
|
||||
);
|
||||
}
|
||||
if (name === "copyWithin") {
|
||||
if (call.arguments.length > 3 || call.arguments.some(ts.isSpreadElement)) {
|
||||
lowerer.noLowering(`.copyWithin with ${call.arguments.length} arguments`, call);
|
||||
}
|
||||
return lowerArrayCopyWithin(
|
||||
lowerer,
|
||||
lowerer.lowerExpr(access.expression),
|
||||
lowerArrayPosition(lowerer, call.arguments[0], numLit(0, loc), "array copyWithin target"),
|
||||
lowerArrayPosition(lowerer, call.arguments[1], numLit(0, loc), "array copyWithin start"),
|
||||
lowerArrayPosition(lowerer, call.arguments[2], numLit(Infinity, loc), "array copyWithin end"),
|
||||
receiverIr,
|
||||
loc,
|
||||
);
|
||||
}
|
||||
if (name === "with") {
|
||||
if (call.arguments.length !== 2 || call.arguments.some(ts.isSpreadElement)) {
|
||||
lowerer.noLowering(`.with with ${call.arguments.length} arguments`, call);
|
||||
@@ -287,26 +347,13 @@ function fenceProducedArrayElem(lowerer: Lowerer, node: ts.Node, producer: strin
|
||||
lowerer.unsupported("SC1090", call, "spread arguments to Array.toSpliced");
|
||||
}
|
||||
const receiver = lowerer.lowerExpr(access.expression);
|
||||
const start = call.arguments[0]
|
||||
? lowerer.lowerExprExpecting(call.arguments[0], F64)
|
||||
: { kind: "numLit" as const, value: 0, type: F64, loc };
|
||||
const deleteCountDefault: IrExpr = {
|
||||
kind: "numLit",
|
||||
value: NaN,
|
||||
type: F64,
|
||||
loc,
|
||||
};
|
||||
const deleteCount =
|
||||
call.arguments.length === 0
|
||||
? { kind: "numLit" as const, value: 0, type: F64, loc }
|
||||
: call.arguments[1]
|
||||
? lowerOptionalArgument(
|
||||
lowerer,
|
||||
call.arguments[1],
|
||||
F64,
|
||||
deleteCountDefault,
|
||||
)
|
||||
: { kind: "numLit" as const, value: Infinity, type: F64, loc };
|
||||
const start = lowerArrayPosition(lowerer, call.arguments[0], numLit(0, loc), "array toSpliced start");
|
||||
const deleteCount = lowerArrayPosition(
|
||||
lowerer,
|
||||
call.arguments[1],
|
||||
numLit(call.arguments.length === 1 ? Infinity : 0, loc),
|
||||
"array toSpliced deleteCount",
|
||||
);
|
||||
const itemNodes = call.arguments.slice(2);
|
||||
const itemProbes = itemNodes.map((arg) => tryLowerExpression(lowerer, arg));
|
||||
const statefulItems = itemProbes.some((probe) =>
|
||||
@@ -339,7 +386,7 @@ function fenceProducedArrayElem(lowerer: Lowerer, node: ts.Node, producer: strin
|
||||
const arity = {
|
||||
push: [0, Number.MAX_SAFE_INTEGER], unshift: [0, Number.MAX_SAFE_INTEGER], pop: [0, 0], indexOf: [1, 2], lastIndexOf: [1, 2], includes: [0, 2], join: [1, 1],
|
||||
concat: [0, Number.MAX_SAFE_INTEGER],
|
||||
slice: [0, 2], shift: [0, 0], splice: [1, 2], at: [0, 1],
|
||||
slice: [0, 2], shift: [0, 0], splice: [0, 2], at: [0, 1],
|
||||
map: [1, 1], filter: [1, 1], forEach: [1, 1], find: [1, 1], findIndex: [1, 1], some: [1, 1],
|
||||
findLast: [1, 1], findLastIndex: [1, 1],
|
||||
every: [1, 1], flatMap: [1, 1], reduce: [1, 2], reduceRight: [1, 2],
|
||||
@@ -522,30 +569,19 @@ function fenceProducedArrayElem(lowerer: Lowerer, node: ts.Node, producer: strin
|
||||
return { kind: "call", callee: helper, args: [receiver, ...args], type: receiverIr, loc };
|
||||
}
|
||||
if (name === "slice") {
|
||||
// `a.slice(start?, end?)` — a fresh shallow copy of the index range,
|
||||
// JS-exact index handling (ToIntegerOrInfinity, negatives from the
|
||||
// end, clamping; omitted args are omitted from the IR — the backend
|
||||
// fills 0 / +Infinity, the string-slice convention). Ref elements
|
||||
// are RETAINED into the copy: the same references, exactly JS's
|
||||
// shallow copy. Every element kind slices — the receiver's own type
|
||||
// is the result type.
|
||||
const receiver = lowerer.lowerExpr(access.expression);
|
||||
const args = call.arguments.map((a) => lowerer.lowerExpr(a));
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i]!.type.kind !== "f64") lowerer.badType(call.arguments[i]!, lowerer.typeOf(call.arguments[i]!));
|
||||
}
|
||||
const args = [
|
||||
lowerArrayPosition(lowerer, call.arguments[0], numLit(0, loc), "array slice start"),
|
||||
lowerArrayPosition(lowerer, call.arguments[1], numLit(Infinity, loc), "array slice end"),
|
||||
];
|
||||
return { kind: "arrIntrinsic", method: "slice", receiver, args, type: receiverIr, loc };
|
||||
}
|
||||
if (name === "splice") {
|
||||
// The REMOVAL forms: splice(start) and splice(start, deleteCount) —
|
||||
// Node-exact relative/clamped indices, the removed elements back in
|
||||
// order (their ownership moves out of the receiver). Insertion
|
||||
// (3+ args) fenced by arity above.
|
||||
const receiver = lowerer.lowerExpr(access.expression);
|
||||
const args = call.arguments.map((a) => lowerer.lowerExpr(a));
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i]!.type.kind !== "f64") lowerer.badType(call.arguments[i]!, lowerer.typeOf(call.arguments[i]!));
|
||||
}
|
||||
const args = [
|
||||
lowerArrayPosition(lowerer, call.arguments[0], numLit(0, loc), "array splice start"),
|
||||
lowerArrayPosition(lowerer, call.arguments[1], numLit(call.arguments.length === 1 ? Infinity : 0, loc), "array splice deleteCount"),
|
||||
];
|
||||
return { kind: "arrIntrinsic", method: "splice", receiver, args, type: receiverIr, loc };
|
||||
}
|
||||
if (name === "shift") {
|
||||
|
||||
@@ -300,6 +300,8 @@ export const ARRAY_METHODS = new Set([
|
||||
"unshift",
|
||||
"pop",
|
||||
"reverse",
|
||||
"fill",
|
||||
"copyWithin",
|
||||
"concat",
|
||||
"map",
|
||||
"filter",
|
||||
|
||||
@@ -2116,12 +2116,24 @@
|
||||
"name": "Array.prototype.concat",
|
||||
"status": "static"
|
||||
},
|
||||
{
|
||||
"id": "stdlib.array.copyWithin",
|
||||
"kind": "stdlib",
|
||||
"name": "Array.prototype.copyWithin",
|
||||
"status": "static"
|
||||
},
|
||||
{
|
||||
"id": "stdlib.array.every",
|
||||
"kind": "stdlib",
|
||||
"name": "Array.prototype.every",
|
||||
"status": "static"
|
||||
},
|
||||
{
|
||||
"id": "stdlib.array.fill",
|
||||
"kind": "stdlib",
|
||||
"name": "Array.prototype.fill",
|
||||
"status": "static"
|
||||
},
|
||||
{
|
||||
"id": "stdlib.array.filter",
|
||||
"kind": "stdlib",
|
||||
|
||||
@@ -7057,6 +7057,24 @@
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/3044-array-slice-splice-positions.js": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/3044-array-slice-splice-positions.js"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/3045-array-indexed-mutation.js": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/3045-array-indexed-mutation.js"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/3046-array-indexed-ref-identity.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/3046-array-indexed-ref-identity.ts"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/305-truthiness.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/305-truthiness.ts"
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
const source = [10, 20, 30, 40];
|
||||
|
||||
console.log("slice", JSON.stringify(source.slice("1", "3")), JSON.stringify(source.slice(true, null)));
|
||||
console.log("slice-default", JSON.stringify(source.slice()), JSON.stringify(source.slice(undefined, undefined)));
|
||||
console.log("slice-range", JSON.stringify(source.slice("-2", Infinity)), JSON.stringify(source.slice(NaN, false)));
|
||||
|
||||
const sliceOrder = [];
|
||||
const sliceResult = (() => {
|
||||
sliceOrder.push("receiver");
|
||||
return source;
|
||||
})().slice(void sliceOrder.push("start"), void sliceOrder.push("end"));
|
||||
console.log("slice-effects", JSON.stringify(sliceResult), sliceOrder.join(","));
|
||||
|
||||
const selectedStart = source.length === 4 ? "1" : undefined;
|
||||
const absentStart = source.length === 3 ? "1" : undefined;
|
||||
console.log("slice-union", JSON.stringify(source.slice(selectedStart)), JSON.stringify(source.slice(absentStart)));
|
||||
|
||||
const spliceSource = [10, 20, 30, 40];
|
||||
console.log("splice-no-args", JSON.stringify(spliceSource.splice()), JSON.stringify(spliceSource));
|
||||
console.log("splice-one-arg", JSON.stringify(spliceSource.splice("2")), JSON.stringify(spliceSource));
|
||||
console.log("splice-undefined-count", JSON.stringify(spliceSource.splice("0", undefined)), JSON.stringify(spliceSource));
|
||||
console.log("splice-undefined-start", JSON.stringify(spliceSource.splice(undefined)), JSON.stringify(spliceSource));
|
||||
|
||||
const spliceMore = [10, 20, 30, 40, 50];
|
||||
console.log("splice-coerce", JSON.stringify(spliceMore.splice(true, "2")), JSON.stringify(spliceMore));
|
||||
console.log("splice-null", JSON.stringify(spliceMore.splice(null, false)), JSON.stringify(spliceMore));
|
||||
const selectedCount = source.length === 4 ? "2" : undefined;
|
||||
const absentCount = source.length === 3 ? "2" : undefined;
|
||||
const spliceUnion = [10, 20, 30, 40];
|
||||
console.log("splice-union", JSON.stringify(spliceUnion.splice(1, selectedCount)), JSON.stringify(spliceUnion));
|
||||
console.log("splice-union-undefined", JSON.stringify(spliceUnion.splice(0, absentCount)), JSON.stringify(spliceUnion));
|
||||
const spliceOrder = [];
|
||||
const spliceResult = spliceMore.splice(void spliceOrder.push("start"), void spliceOrder.push("count"));
|
||||
console.log("splice-effects", JSON.stringify(spliceResult), JSON.stringify(spliceMore), spliceOrder.join(","));
|
||||
|
||||
console.log("toSpliced", JSON.stringify(source.toSpliced("1", "2")), JSON.stringify(source.toSpliced(false, true, 99)));
|
||||
console.log("toSpliced-default", JSON.stringify(source.toSpliced()), JSON.stringify(source.toSpliced("2")));
|
||||
console.log("toSpliced-undefined", JSON.stringify(source.toSpliced(undefined, undefined, 99)));
|
||||
console.log("toSpliced-union", JSON.stringify(source.toSpliced(1, selectedCount)), JSON.stringify(source.toSpliced(1, absentCount)));
|
||||
const copyOrder = [];
|
||||
const copied = source.toSpliced(void copyOrder.push("start"), void copyOrder.push("count"), (() => {
|
||||
copyOrder.push("item");
|
||||
return 99;
|
||||
})());
|
||||
console.log("toSpliced-effects", JSON.stringify(copied), copyOrder.join(","), JSON.stringify(source));
|
||||
@@ -0,0 +1,53 @@
|
||||
/** @param {number[]} a */
|
||||
function describe(a) {
|
||||
return JSON.stringify(a);
|
||||
}
|
||||
|
||||
const filled = [0, 1, 2, 3];
|
||||
console.log("fill", filled.fill(9, "1", "3") === filled, describe(filled));
|
||||
console.log("fill-default", describe([0, 1].fill()), describe([0, 1].fill(8, undefined, undefined)));
|
||||
console.log("fill-coerce", describe([0, 1, 2, 3].fill(9, true, null)), describe([0, 1, 2, 3].fill(9, NaN, Infinity)));
|
||||
console.log("fill-negative", describe([0, 1, 2, 3].fill(8, -3, -1)), describe([0, 1].fill(8, -Infinity, 1)));
|
||||
console.log("fill-empty", describe([0, 1, 2].fill(8, 2, 1)));
|
||||
/** @type {number[]} */
|
||||
const sparse = [];
|
||||
sparse.length = 4;
|
||||
sparse[3] = 7;
|
||||
console.log("fill-hole", describe(sparse.fill(5, 1, 3)), 0 in sparse, 1 in sparse, 2 in sparse);
|
||||
const optional = [1];
|
||||
const absent = optional[9];
|
||||
console.log("fill-missing-read", describe([0, 1].fill(absent)));
|
||||
|
||||
const forward = [0, 1, 2, 3, 4];
|
||||
console.log("copy-forward", forward.copyWithin(0, 2) === forward, describe(forward));
|
||||
const backward = [0, 1, 2, 3, 4];
|
||||
console.log("copy-backward", backward.copyWithin(1, 0, 4) === backward, describe(backward));
|
||||
console.log("copy-default", describe([0, 1, 2].copyWithin()), describe([0, 1, 2].copyWithin(undefined, 1, undefined)));
|
||||
console.log("copy-negative", describe([0, 1, 2, 3].copyWithin(-2, -4, -1)));
|
||||
console.log("copy-coerce", describe([0, 1, 2, 3].copyWithin("1", true, "3.8")));
|
||||
console.log("copy-bounds", describe([0, 1, 2].copyWithin(99, 0)), describe([0, 1, 2].copyWithin(0, -Infinity, Infinity)));
|
||||
/** @type {number[]} */
|
||||
const holes = [0, , 2, , 4];
|
||||
console.log("copy-holes-forward", describe(holes.copyWithin(0, 1, 4)), 0 in holes, 1 in holes, 2 in holes, 3 in holes);
|
||||
/** @type {number[]} */
|
||||
const holesBack = [, 1, , 3, 4];
|
||||
console.log("copy-holes-backward", describe(holesBack.copyWithin(1, 0, 4)), 0 in holesBack, 1 in holesBack, 2 in holesBack, 3 in holesBack);
|
||||
const missing = [10, 20];
|
||||
missing[1] = missing[9];
|
||||
console.log("copy-undefined", describe(missing.copyWithin(0, 1)), 0 in missing);
|
||||
|
||||
const effects = [];
|
||||
const effectTarget = [0, 1, 2];
|
||||
const fillReturn = (() => { effects.push("receiver"); return effectTarget; })().fill(
|
||||
(() => { effects.push("value"); return 8; })(),
|
||||
(() => { effects.push("start"); return "1"; })(),
|
||||
(() => { effects.push("end"); return 3; })(),
|
||||
);
|
||||
console.log("fill-order", effects.join(","), fillReturn === effectTarget, describe(effectTarget));
|
||||
const copyEffects = [];
|
||||
const copyReturn = (() => { copyEffects.push("receiver"); return effectTarget; })().copyWithin(
|
||||
(() => { copyEffects.push("target"); return "0"; })(),
|
||||
(() => { copyEffects.push("start"); return 1; })(),
|
||||
(() => { copyEffects.push("end"); return "3"; })(),
|
||||
);
|
||||
console.log("copy-order", copyEffects.join(","), copyReturn === effectTarget, describe(effectTarget));
|
||||
@@ -0,0 +1,13 @@
|
||||
type Item = { label: string };
|
||||
|
||||
const fillValue: Item = { label: "same" };
|
||||
const filled: Item[] = [{ label: "first" }, { label: "second" }, { label: "third" }];
|
||||
console.log("fill-return", filled.fill(fillValue, 1) === filled);
|
||||
fillValue.label = "updated";
|
||||
console.log("fill-shared", JSON.stringify(filled));
|
||||
|
||||
const source: Item = { label: "first" };
|
||||
const copied: Item[] = [source, { label: "second" }, { label: "third" }];
|
||||
console.log("copy-return", copied.copyWithin(1, 0, 2) === copied);
|
||||
source.label = "updated";
|
||||
console.log("copy-shared", JSON.stringify(copied));
|
||||
@@ -50,6 +50,13 @@ test("unsupported execution requirements and assertion reflection remain exclusi
|
||||
expect(exclusion(text, metadata(text), "sloppy")).toBe("execution:sloppy");
|
||||
});
|
||||
|
||||
test("the compareArray include only admits the implemented assertion form", () => {
|
||||
const accepted = source("includes: [compareArray.js]", "assert.compareArray([1, NaN], [1, NaN]);");
|
||||
expect(exclusion(accepted, metadata(accepted), "strict")).toBeUndefined();
|
||||
const globalHelper = source("includes: [compareArray.js]", "compareArray([1], [1]);");
|
||||
expect(exclusion(globalHelper, metadata(globalHelper), "strict")).toBe("harness:compareArray-surface");
|
||||
});
|
||||
|
||||
test("the adapter retains the test body without a function or try/catch wrapper", () => {
|
||||
const body = source("description: lexical", "const x = 1;\nassert.sameValue(x, 1);");
|
||||
const result = prepare(body);
|
||||
|
||||
@@ -51,6 +51,10 @@ assert.notSameValue(1, "1");
|
||||
{ name: "wrong SameValue", status: "fail", source: "assert.sameValue(1, 2);" },
|
||||
{ name: "signed zero mismatch", status: "fail", source: "assert.sameValue(0, -0);" },
|
||||
{ name: "NaN is the same value", status: "fail", source: "assert.notSameValue(NaN, NaN);" },
|
||||
{ name: "scalar array contents", status: "pass", source: "assert.compareArray([1, NaN, -0, undefined], [1, NaN, -0, undefined]);" },
|
||||
{ name: "array length mismatch", status: "fail", source: "assert.compareArray([1], [1, 2]);" },
|
||||
{ name: "array element mismatch", status: "fail", source: "assert.compareArray([1, 2], [1, 3]);" },
|
||||
{ name: "array signed zero mismatch", status: "fail", source: "assert.compareArray([0], [-0]);" },
|
||||
{ name: "assert requires true, not truthiness", status: "fail", source: "assert(1);" },
|
||||
];
|
||||
|
||||
@@ -78,4 +82,18 @@ describe(`Test262 host assertion contract${shardSuffix()}`, () => {
|
||||
expect(result, JSON.stringify(result)).toMatchObject({ status: "harness-refusal", reason: "reference-assertion" });
|
||||
});
|
||||
}
|
||||
|
||||
test("array element identity assertions are refused", async () => {
|
||||
const source = "const value = {}; try { assert.compareArray([value], [value]); } catch { }";
|
||||
expect(() => runUpstream(source)).not.toThrow();
|
||||
const result = await runSource(source, { sanitize });
|
||||
expect(result, JSON.stringify(result)).toMatchObject({ status: "harness-refusal", reason: "reference-assertion" });
|
||||
});
|
||||
|
||||
test("array-like objects remain outside the adapter", async () => {
|
||||
const source = "try { assert.compareArray({ 0: 1, length: 1 }, [1]); } catch { }";
|
||||
expect(() => runUpstream(source)).not.toThrow();
|
||||
const result = await runSource(source, { sanitize });
|
||||
expect(result, JSON.stringify(result)).toMatchObject({ status: "harness-refusal", reason: "reference-assertion" });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,9 +30,9 @@ Pass the resulting directory as `--root` and use `--filter` to survey an API fam
|
||||
|
||||
The current profile is `static-strict-scalar-adapter-v1`. It selects synchronous, positive strict-script variants and adapts each script to a standalone module. Preparation adds a strict directive, imports the host assertions, appends a completion marker, and leaves the upstream test body unchanged. Each program executes in a fresh native process. Conservative syntax checks reject known global-script dependencies, but do not establish that every module adaptation preserves the original script's semantics. Reports are local investigation artifacts, not published compatibility assessments.
|
||||
|
||||
The unmodified upstream assertion helper currently reaches scriptc's JavaScript function-expando refusal. Test262 explicitly permits host implementations of harness functions in its [interpretation rules](https://github.com/tc39/test262/blob/7ab7fafa0003f73fc85c1b95d88094d33f7eb8bd/INTERPRETING.md#host-defined-functions). `harness.ts` supplies `assert`, `assert.sameValue`, `assert.notSameValue`, and `Test262Error`. Scalar SameValue uses the statically compiled `node:assert/strict` implementation. Contract tests compare it with the original Test262 helpers under Node using cases for NaN, signed zero, null/undefined, differing primitive types, failed assertions, and premature termination.
|
||||
The unmodified upstream assertion helper currently reaches scriptc's JavaScript function-expando refusal. Test262 explicitly permits host implementations of harness functions in its [interpretation rules](https://github.com/tc39/test262/blob/7ab7fafa0003f73fc85c1b95d88094d33f7eb8bd/INTERPRETING.md#host-defined-functions). `harness.ts` supplies `assert`, `assert.sameValue`, `assert.notSameValue`, `assert.compareArray`, and `Test262Error`. Scalar SameValue and scalar array-element comparisons use the statically compiled `node:assert/strict` implementation. Contract tests compare successful and failing assertions with the original Test262 helpers under Node, including NaN, signed zero, null/undefined, differing primitive types, and premature termination.
|
||||
|
||||
Reference-equality assertions terminate with a distinct harness-refusal result: conversion at a native function boundary can copy references, so this adapter cannot faithfully compare every object, array, or function identity. Tests cannot catch this refusal and accidentally pass. Assertion aliases, mutation, reflection, additional assertion methods, and all `includes` helpers are excluded until explicitly implemented and tested.
|
||||
Reference-equality assertions terminate with a distinct harness-refusal result: conversion at a native function boundary can copy references, so this adapter cannot faithfully compare every object, array, or function identity. Tests cannot catch this refusal and accidentally pass. Sparse array comparisons are not yet handled faithfully across that boundary. Assertion aliases, mutation, reflection, additional assertion methods, and `includes` helpers other than `compareArray.js` remain excluded.
|
||||
|
||||
Sloppy variants, raw tests, modules, asynchronous completion, agents, and negative tests are currently excluded. Parse, resolution, and runtime negative phases retain their distinct reasons; arbitrary compiler errors never satisfy a negative expectation. `$262`, dynamic evaluation, observable script-global state, and other unsupported host requirements are excluded as well. The runtime and compiler continue to enforce their existing refusal boundaries for admitted source.
|
||||
|
||||
|
||||
@@ -39,4 +39,24 @@ export namespace assert {
|
||||
throw new Test262Error(message);
|
||||
}
|
||||
}
|
||||
|
||||
export function compareArray(actual: unknown, expected: unknown, message = "Expected matching array contents"): void {
|
||||
if (!Array.isArray(actual) || !Array.isArray(expected)) {
|
||||
scalar(actual);
|
||||
scalar(expected);
|
||||
throw new Test262Error(message);
|
||||
}
|
||||
if (actual.length !== expected.length) throw new Test262Error(message);
|
||||
for (let i = 0; i < actual.length; i++) {
|
||||
const left: unknown = i in actual ? actual[i] : undefined;
|
||||
const right: unknown = i in expected ? expected[i] : undefined;
|
||||
scalar(left);
|
||||
scalar(right);
|
||||
try {
|
||||
nodeAssert.strictEqual(left, right);
|
||||
} catch {
|
||||
throw new Test262Error(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,8 @@ export function exclusion(source, meta, variant) {
|
||||
if (meta.negative) return `negative-phase:${meta.negative.phase}`;
|
||||
if (meta.flags.includes("async")) return "execution:async";
|
||||
if (meta.flags.some((flag) => flag.startsWith("CanBlock"))) return "host:agents";
|
||||
if (meta.includes.length) return `harness-includes:${meta.includes.join(",")}`;
|
||||
const unsupportedIncludes = meta.includes.filter((name) => name !== "compareArray.js");
|
||||
if (unsupportedIncludes.length) return `harness-includes:${unsupportedIncludes.join(",")}`;
|
||||
const sf = ts.createSourceFile("test.js", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
|
||||
let reason;
|
||||
const forbidden = new Set(["$262", "$DONE", "$DONOTEVALUATE", "globalThis", "eval", "Function", "print", "process", "require", "arguments"]);
|
||||
@@ -106,10 +107,13 @@ export function exclusion(source, meta, variant) {
|
||||
if (ts.isCallExpression(parent) && parent.expression === node) {
|
||||
// assert(value, message)
|
||||
} else if (ts.isPropertyAccessExpression(parent) && parent.expression === node &&
|
||||
["sameValue", "notSameValue"].includes(parent.name.text) &&
|
||||
["sameValue", "notSameValue", "compareArray"].includes(parent.name.text) &&
|
||||
ts.isCallExpression(parent.parent) && parent.parent.expression === parent) {
|
||||
// Supported assertion calls; aliases, mutations, and reflection stay out.
|
||||
} else reason = "harness:assert-surface";
|
||||
} else if (meta.includes.includes("compareArray.js") && ts.isIdentifier(node) && node.text === "compareArray" &&
|
||||
!(ts.isPropertyAccessExpression(node.parent) && node.parent.name === node && ts.isIdentifier(node.parent.expression) && node.parent.expression.text === "assert")) {
|
||||
reason = "harness:compareArray-surface";
|
||||
} else if (ts.isIdentifier(node) && node.text === "Test262Error") {
|
||||
if (!ts.isNewExpression(node.parent) || node.parent.expression !== node) reason = "harness:Test262Error-surface";
|
||||
}
|
||||
|
||||
@@ -10,6 +10,18 @@
|
||||
"test/built-ins/Array/prototype/at/returns-item.js",
|
||||
"test/built-ins/Array/prototype/at/returns-undefined-for-holes-in-sparse-arrays.js",
|
||||
"test/built-ins/Array/prototype/at/returns-undefined-for-out-of-range-index.js",
|
||||
"test/built-ins/Array/prototype/copyWithin/coerced-values-end.js",
|
||||
"test/built-ins/Array/prototype/copyWithin/coerced-values-start.js",
|
||||
"test/built-ins/Array/prototype/copyWithin/negative-end.js",
|
||||
"test/built-ins/Array/prototype/copyWithin/negative-start.js",
|
||||
"test/built-ins/Array/prototype/copyWithin/negative-target.js",
|
||||
"test/built-ins/Array/prototype/copyWithin/non-negative-out-of-bounds-target-and-start.js",
|
||||
"test/built-ins/Array/prototype/copyWithin/non-negative-target-and-start.js",
|
||||
"test/built-ins/Array/prototype/copyWithin/non-negative-target-start-and-end.js",
|
||||
"test/built-ins/Array/prototype/copyWithin/undefined-end.js",
|
||||
"test/built-ins/Array/prototype/fill/coerced-indexes.js",
|
||||
"test/built-ins/Array/prototype/fill/fill-values-relative-end.js",
|
||||
"test/built-ins/Array/prototype/fill/fill-values-relative-start.js",
|
||||
"test/built-ins/Array/prototype/includes/no-arg.js",
|
||||
"test/built-ins/Array/prototype/indexOf/15.4.4.14-4-1.js",
|
||||
"test/built-ins/Array/prototype/indexOf/15.4.4.14-5-13.js",
|
||||
@@ -42,6 +54,8 @@
|
||||
"test/built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-6.js",
|
||||
"test/built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-7.js",
|
||||
"test/built-ins/Array/prototype/lastIndexOf/fromindex-zero-conversion.js",
|
||||
"test/built-ins/Array/prototype/splice/15.4.4.12-9-a-1.js",
|
||||
"test/built-ins/Array/prototype/splice/called_with_one_argument.js",
|
||||
"test/built-ins/BigInt/prototype/toString/default-radix.js",
|
||||
"test/built-ins/Math/abs/S15.8.2.1_A1.js",
|
||||
"test/built-ins/Math/abs/S15.8.2.1_A2.js",
|
||||
@@ -163,6 +177,18 @@
|
||||
"test/built-ins/Array/prototype/at/returns-item.js": "793b0f4a94ccf54a1e43813b3fde39d8e1f216cde9e22be674ecefd6a46e8e63",
|
||||
"test/built-ins/Array/prototype/at/returns-undefined-for-holes-in-sparse-arrays.js": "32d020ce560af714f8c429f6d168507797304f72ef340f31c725c925e38d3969",
|
||||
"test/built-ins/Array/prototype/at/returns-undefined-for-out-of-range-index.js": "ad51fad4e5e759ba996c59306e49bfd355f4c9afc6f0ba4bc90a768f57e3ff63",
|
||||
"test/built-ins/Array/prototype/copyWithin/coerced-values-end.js": "bb14f53816c619c6d21886f99fa64b9afb0223af50e2fb1c7a3cc3bee7708862",
|
||||
"test/built-ins/Array/prototype/copyWithin/coerced-values-start.js": "82f01c1dedf206d935030520aa5c1ba5a7adc439f86b0e1f1c9ae9cd7bb0577f",
|
||||
"test/built-ins/Array/prototype/copyWithin/negative-end.js": "bf4eda932254d7bab04164ee0eb26492feadd3fcb74b01bb2baee77cb76ba17c",
|
||||
"test/built-ins/Array/prototype/copyWithin/negative-start.js": "c2231097edb3ef50da00d9e882ad6b8fb28c41d50985332869315999043a463b",
|
||||
"test/built-ins/Array/prototype/copyWithin/negative-target.js": "c0716a622c7427667129ddd32b3abc9a42d5975974cc521eb1208cf24e3a4940",
|
||||
"test/built-ins/Array/prototype/copyWithin/non-negative-out-of-bounds-target-and-start.js": "10aa7748761388033a832d4f93a364cb96df60fa68e1fa0006394b1cd747ae4c",
|
||||
"test/built-ins/Array/prototype/copyWithin/non-negative-target-and-start.js": "5791c024bbc5de9631a11857822b41bd4be622175fa957523c93bb15068271a7",
|
||||
"test/built-ins/Array/prototype/copyWithin/non-negative-target-start-and-end.js": "05f846e32ef19b3d36f807b717450a1fdad89193e7a93ea807607c1209f938c2",
|
||||
"test/built-ins/Array/prototype/copyWithin/undefined-end.js": "88c1354b0cfce33c1f6a9dd5ca3c4186fda612b0b21f6aedbac710f43bdad18b",
|
||||
"test/built-ins/Array/prototype/fill/coerced-indexes.js": "e5ea8d3c667d1aee2c009ec11bbc5969f81eddffd9b5a95c0ccc4211e94d83bc",
|
||||
"test/built-ins/Array/prototype/fill/fill-values-relative-end.js": "a99a40ef2166f7cc368c675779edc5b3150c52089857caba3b1151a135c4b9b5",
|
||||
"test/built-ins/Array/prototype/fill/fill-values-relative-start.js": "68ea96909caf42da6632d84dd8112d44c53a5ff731339ae2c4f8587be8239192",
|
||||
"test/built-ins/Array/prototype/includes/no-arg.js": "e38e7db529094b08ac13cc8a53cdbf59b5b2537711922af9bf8b1178f615e511",
|
||||
"test/built-ins/Array/prototype/indexOf/15.4.4.14-4-1.js": "ef762d69cbdf878821a6f998064590c2c19aa9e3db297968a5db02a6f5cd455a",
|
||||
"test/built-ins/Array/prototype/indexOf/15.4.4.14-5-13.js": "3c1ebd36e0e4657c42abbb76a707546a7b46ad954d3e569a84b796695d10da02",
|
||||
@@ -195,6 +221,8 @@
|
||||
"test/built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-6.js": "d389d03867aef471519b23d75bf6b24e68038a91de9f4489ac0d08da9f393bbb",
|
||||
"test/built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-7.js": "5afb53c527ddb49da7a505af67cd59ad49d8b47d5af9280ed0e5578672a94c40",
|
||||
"test/built-ins/Array/prototype/lastIndexOf/fromindex-zero-conversion.js": "8231b818adf4123a4e5c9b65206b0b72984894b825319da669b99f820c75f963",
|
||||
"test/built-ins/Array/prototype/splice/15.4.4.12-9-a-1.js": "6e6cd215339a848aef80163023c1201e9c502af76d4dcc62915bf6f868d9523a",
|
||||
"test/built-ins/Array/prototype/splice/called_with_one_argument.js": "719fd6f8bf400aacefa5a0499b69495384e831668463d42960ff44d399f9f74e",
|
||||
"test/built-ins/BigInt/prototype/toString/default-radix.js": "d901ef7e3fab5b8c528cb60a12c80145a6c5b7fbd02f829fe657259eddbe711a",
|
||||
"test/built-ins/Math/abs/S15.8.2.1_A1.js": "c5b508cdc6130c8670e8ac6d822ca93e5dbead7566543cb65b793602b7203d7c",
|
||||
"test/built-ins/Math/abs/S15.8.2.1_A2.js": "a625e117f7858319c2ff25b959539266a6f29473925bb47ad5d8bbfe88e7b31e",
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.copywithin
|
||||
description: >
|
||||
end argument is coerced to an integer values.
|
||||
info: |
|
||||
22.1.3.3 Array.prototype.copyWithin (target, start [ , end ] )
|
||||
|
||||
...
|
||||
11. If end is undefined, let relativeEnd be len; else let relativeEnd be
|
||||
ToInteger(end).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, 0, null), [0, 1, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(1, 0, null) must return [0, 1, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, 0, NaN), [0, 1, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(1, 0, NaN) must return [0, 1, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, 0, false), [0, 1, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(1, 0, false) must return [0, 1, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, 0, true), [0, 0, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(1, 0, true) must return [0, 0, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, 0, '-2'), [0, 0, 1, 3],
|
||||
'[0, 1, 2, 3].copyWithin(1, 0, "-2") must return [0, 0, 1, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, 0, -2.5), [0, 0, 1, 3],
|
||||
'[0, 1, 2, 3].copyWithin(1, 0, -2.5) must return [0, 0, 1, 3]'
|
||||
);
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.copywithin
|
||||
description: >
|
||||
start argument is coerced to an integer value.
|
||||
info: |
|
||||
22.1.3.3 Array.prototype.copyWithin (target, start [ , end ] )
|
||||
|
||||
...
|
||||
8. Let relativeStart be ToInteger(start).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, undefined), [0, 0, 1, 2],
|
||||
'[0, 1, 2, 3].copyWithin(1, undefined) must return [0, 0, 1, 2]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, false), [0, 0, 1, 2],
|
||||
'[0, 1, 2, 3].copyWithin(1, false) must return [0, 0, 1, 2]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, NaN), [0, 0, 1, 2],
|
||||
'[0, 1, 2, 3].copyWithin(1, NaN) must return [0, 0, 1, 2]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, null), [0, 0, 1, 2],
|
||||
'[0, 1, 2, 3].copyWithin(1, null) must return [0, 0, 1, 2]'
|
||||
);
|
||||
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, true), [1, 2, 3, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, true) must return [1, 2, 3, 3]'
|
||||
);
|
||||
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, '1'), [1, 2, 3, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, "1") must return [1, 2, 3, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, 0.5), [0, 0, 1, 2],
|
||||
'[0, 1, 2, 3].copyWithin(1, 0.5) must return [0, 0, 1, 2]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, 1.5), [1, 2, 3, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, 1.5) must return [1, 2, 3, 3]'
|
||||
);
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.copywithin
|
||||
description: >
|
||||
Set values with negative end argument.
|
||||
info: |
|
||||
22.1.3.3 Array.prototype.copyWithin (target, start [ , end ] )
|
||||
|
||||
...
|
||||
11. If end is undefined, let relativeEnd be len; else let relativeEnd be
|
||||
ToInteger(end).
|
||||
12. ReturnIfAbrupt(relativeEnd).
|
||||
13. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let
|
||||
final be min(relativeEnd, len).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, 1, -1), [1, 2, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, 1, -1) must return [1, 2, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(2, 0, -1), [0, 1, 0, 1, 2],
|
||||
'[0, 1, 2, 3, 4].copyWithin(2, 0, -1) must return [0, 1, 0, 1, 2]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(1, 2, -2), [0, 2, 2, 3, 4],
|
||||
'[0, 1, 2, 3, 4].copyWithin(1, 2, -2) must return [0, 2, 2, 3, 4]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, -2, -1), [2, 1, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, -2, -1) must return [2, 1, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(2, -2, -1), [0, 1, 3, 3, 4],
|
||||
'[0, 1, 2, 3, 4].copyWithin(2, -2, -1) must return [0, 1, 3, 3, 4]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(-3, -2, -1), [0, 2, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(-3, -2, -1) must return [0, 2, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(-2, -3, -1), [0, 1, 2, 2, 3],
|
||||
'[0, 1, 2, 3, 4].copyWithin(-2, -3, -1) must return [0, 1, 2, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(-5, -2, -1), [3, 1, 2, 3, 4],
|
||||
'[0, 1, 2, 3, 4].copyWithin(-5, -2, -1) must return [3, 1, 2, 3, 4]'
|
||||
);
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.copywithin
|
||||
description: >
|
||||
Set values with negative start argument.
|
||||
info: |
|
||||
22.1.3.3 Array.prototype.copyWithin (target, start [ , end ] )
|
||||
|
||||
...
|
||||
10. If relativeStart < 0, let from be max((len + relativeStart),0); else let
|
||||
from be min(relativeStart, len).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, -1), [3, 1, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, -1) must return [3, 1, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(2, -2), [0, 1, 3, 4, 4],
|
||||
'[0, 1, 2, 3, 4].copyWithin(2, -2) must return [0, 1, 3, 4, 4]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(1, -2), [0, 3, 4, 3, 4],
|
||||
'[0, 1, 2, 3, 4].copyWithin(1, -2) must return [0, 3, 4, 3, 4]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(-1, -2), [0, 1, 2, 2],
|
||||
'[0, 1, 2, 3].copyWithin(-1, -2) must return [0, 1, 2, 2]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(-2, -3), [0, 1, 2, 2, 3],
|
||||
'[0, 1, 2, 3, 4].copyWithin(-2, -3) must return [0, 1, 2, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(-5, -2), [3, 4, 2, 3, 4],
|
||||
'[0, 1, 2, 3, 4].copyWithin(-5, -2) must return [3, 4, 2, 3, 4]'
|
||||
);
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.copywithin
|
||||
description: >
|
||||
Set values with negative target argument.
|
||||
info: |
|
||||
22.1.3.3 Array.prototype.copyWithin (target, start [ , end ] )
|
||||
|
||||
...
|
||||
7. If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to
|
||||
be min(relativeTarget, len).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(-1, 0), [0, 1, 2, 0],
|
||||
'[0, 1, 2, 3].copyWithin(-1, 0) must return [0, 1, 2, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4].copyWithin(-2, 2), [0, 1, 2, 2, 3],
|
||||
'[0, 1, 2, 3, 4].copyWithin(-2, 2) must return [0, 1, 2, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(-1, 2), [0, 1, 2, 2],
|
||||
'[0, 1, 2, 3].copyWithin(-1, 2) must return [0, 1, 2, 2]'
|
||||
);
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.copywithin
|
||||
description: >
|
||||
Max values of target and start positions are this.length.
|
||||
info: |
|
||||
22.1.3.3 Array.prototype.copyWithin (target, start [ , end ] )
|
||||
|
||||
...
|
||||
7. If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to
|
||||
be min(relativeTarget, len).
|
||||
...
|
||||
10. If relativeStart < 0, let from be max((len + relativeStart),0); else let
|
||||
from be min(relativeStart, len).
|
||||
11. If end is undefined, let relativeEnd be len; else let relativeEnd be
|
||||
ToInteger(end).
|
||||
...
|
||||
14. Let count be min(final-from, len-to).
|
||||
15. If from<to and to<from+count
|
||||
...
|
||||
16. Else,
|
||||
a. Let direction = 1.
|
||||
17. Repeat, while count > 0
|
||||
...
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(6, 0), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(6, 0) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(7, 0), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(7, 0) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(Infinity, 0), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(Infinity, 0) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(6, 2), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(6, 2) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(7, 2), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(7, 2) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(Infinity, 2), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(Infinity, 2) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(0, 6), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(0, 6) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(0, 7), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(0, 7) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(0, Infinity), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(0, Infinity) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(2, 6), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(2, 6) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(1, 7), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(1, 7) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(3, Infinity), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(3, Infinity) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(6, 6), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(6, 6) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(10, 10), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(10, 10) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(Infinity, Infinity), [0, 1, 2, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(Infinity, Infinity) must return [0, 1, 2, 3, 4, 5]'
|
||||
);
|
||||
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.copywithin
|
||||
description: >
|
||||
Copy values with non-negative target and start positions.
|
||||
info: |
|
||||
22.1.3.3 Array.prototype.copyWithin (target, start [ , end ] )
|
||||
|
||||
...
|
||||
7. If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to
|
||||
be min(relativeTarget, len).
|
||||
...
|
||||
10. If relativeStart < 0, let from be max((len + relativeStart),0); else let
|
||||
from be min(relativeStart, len).
|
||||
11. If end is undefined, let relativeEnd be len; else let relativeEnd be
|
||||
ToInteger(end).
|
||||
...
|
||||
14. Let count be min(final-from, len-to).
|
||||
15. If from<to and to<from+count
|
||||
...
|
||||
16. Else,
|
||||
a. Let direction = 1.
|
||||
17. Repeat, while count > 0
|
||||
...
|
||||
a. If fromPresent is true, then
|
||||
i. Let fromVal be Get(O, fromKey).
|
||||
...
|
||||
iii. Let setStatus be Set(O, toKey, fromVal, true).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray(
|
||||
['a', 'b', 'c', 'd', 'e', 'f'].copyWithin(0, 0),
|
||||
['a', 'b', 'c', 'd', 'e', 'f']
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
['a', 'b', 'c', 'd', 'e', 'f'].copyWithin(0, 2),
|
||||
['c', 'd', 'e', 'f', 'e', 'f']
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
['a', 'b', 'c', 'd', 'e', 'f'].copyWithin(3, 0),
|
||||
['a', 'b', 'c', 'a', 'b', 'c']
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(1, 4),
|
||||
[0, 4, 5, 3, 4, 5]
|
||||
);
|
||||
Vendored
+70
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.copywithin
|
||||
description: >
|
||||
Copy values with non-negative target, start and end positions.
|
||||
info: |
|
||||
22.1.3.3 Array.prototype.copyWithin (target, start [ , end ] )
|
||||
|
||||
...
|
||||
7. If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to
|
||||
be min(relativeTarget, len).
|
||||
...
|
||||
10. If relativeStart < 0, let from be max((len + relativeStart),0); else let
|
||||
from be min(relativeStart, len).
|
||||
11. If end is undefined, let relativeEnd be len; else let relativeEnd be
|
||||
ToInteger(end).
|
||||
...
|
||||
14. Let count be min(final-from, len-to).
|
||||
15. If from<to and to<from+count
|
||||
a. Let direction be -1.
|
||||
b. Let from be from + count -1.
|
||||
c. Let to be to + count -1.
|
||||
16. Else,
|
||||
a. Let direction = 1.
|
||||
17. Repeat, while count > 0
|
||||
...
|
||||
a. If fromPresent is true, then
|
||||
i. Let fromVal be Get(O, fromKey).
|
||||
...
|
||||
iii. Let setStatus be Set(O, toKey, fromVal, true).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, 0, 0), [0, 1, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, 0, 0) must return [0, 1, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, 0, 2), [0, 1, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, 0, 2) must return [0, 1, 2, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, 1, 2), [1, 1, 2, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, 1, 2) must return [1, 1, 2, 3]'
|
||||
);
|
||||
|
||||
/*
|
||||
* 15. If from<to and to<from+count
|
||||
* a. Let direction be -1.
|
||||
* b. Let from be from + count -1.
|
||||
* c. Let to be to + count -1.
|
||||
*
|
||||
* 0 < 1, 1 < 0 + 2
|
||||
* direction = -1
|
||||
* from = 0 + 2 - 1
|
||||
* to = 1 + 2 - 1
|
||||
*/
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(1, 0, 2), [0, 0, 1, 3],
|
||||
'[0, 1, 2, 3].copyWithin(1, 0, 2) must return [0, 0, 1, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3, 4, 5].copyWithin(1, 3, 5), [0, 3, 4, 3, 4, 5],
|
||||
'[0, 1, 2, 3, 4, 5].copyWithin(1, 3, 5) must return [0, 3, 4, 3, 4, 5]'
|
||||
);
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.copywithin
|
||||
description: >
|
||||
If `end` is undefined, set final position to `this.length`.
|
||||
info: |
|
||||
22.1.3.3 Array.prototype.copyWithin (target, start [ , end ] )
|
||||
|
||||
...
|
||||
11. If end is undefined, let relativeEnd be len; else let relativeEnd be
|
||||
ToInteger(end).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, 1, undefined), [1, 2, 3, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, 1, undefined) must return [1, 2, 3, 3]'
|
||||
);
|
||||
|
||||
assert.compareArray(
|
||||
[0, 1, 2, 3].copyWithin(0, 1), [1, 2, 3, 3],
|
||||
'[0, 1, 2, 3].copyWithin(0, 1) must return [1, 2, 3, 3]'
|
||||
);
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.fill
|
||||
description: >
|
||||
Fills elements from coerced to Integer `start` and `end` values
|
||||
info: |
|
||||
Array.prototype.fill ( _value_ [ , _start_ [ , _end_ ] ] )
|
||||
|
||||
3. Let _relativeStart_ be ? ToIntegerOrInfinity(_start_).
|
||||
4. If _relativeStart_ = -∞, let _k_ be 0.
|
||||
5. Else if _relativeStart_ < 0, let _k_ be max(_len_ + _relativeStart_, 0).
|
||||
|
||||
7. If _end_ is *undefined*, let _relativeEnd_ be _len_; else let _relativeEnd_ be ? ToIntegerOrInfinity(_end_).
|
||||
8. If _relativeEnd_ = -∞, let _final_ be 0.
|
||||
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray([0, 0].fill(1, undefined), [1, 1],
|
||||
'[0, 0].fill(1, undefined) must return [1, 1]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, 0, undefined), [1, 1],
|
||||
'[0, 0].fill(1, 0, undefined) must return [1, 1]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, null), [1, 1],
|
||||
'[0, 0].fill(1, null) must return [1, 1]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, 0, null), [0, 0],
|
||||
'[0, 0].fill(1, 0, null) must return [0, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, true), [0, 1],
|
||||
'[0, 0].fill(1, true) must return [0, 1]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, 0, true), [1, 0],
|
||||
'[0, 0].fill(1, 0, true) must return [1, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, false), [1, 1],
|
||||
'[0, 0].fill(1, false) must return [1, 1]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, 0, false), [0, 0],
|
||||
'[0, 0].fill(1, 0, false) must return [0, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, NaN), [1, 1],
|
||||
'[0, 0].fill(1, NaN) must return [1, 1]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, 0, NaN), [0, 0],
|
||||
'[0, 0].fill(1, 0, NaN) must return [0, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, '1'), [0, 1],
|
||||
'[0, 0].fill(1, "1") must return [0, 1]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, 0, '1'), [1, 0],
|
||||
'[0, 0].fill(1, 0, "1") must return [1, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, 1.5), [0, 1],
|
||||
'[0, 0].fill(1, 1.5) must return [0, 1]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, 0, 1.5), [1, 0],
|
||||
'[0, 0].fill(1, 0, 1.5) must return [1, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, Number.NEGATIVE_INFINITY, 1), [1, 0],
|
||||
'[0, 0].fill(1, Number.NEGATIVE_INFINITY, 1) must return [1, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0].fill(1, 0, Number.NEGATIVE_INFINITY), [0, 0],
|
||||
'[0, 0].fill(1, 0, Number.NEGATIVE_INFINITY) must return [0, 0]'
|
||||
);
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.fill
|
||||
description: >
|
||||
Fills all the elements from a with a custom start index.
|
||||
info: |
|
||||
22.1.3.6 Array.prototype.fill (value [ , start [ , end ] ] )
|
||||
|
||||
...
|
||||
8. If end is undefined, let relativeEnd be len; else let relativeEnd be
|
||||
ToInteger(end).
|
||||
9. ReturnIfAbrupt(relativeEnd).
|
||||
10. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let
|
||||
final be min(relativeEnd, len).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray([0, 0, 0].fill(8, 0, 1), [8, 0, 0],
|
||||
'[0, 0, 0].fill(8, 0, 1) must return [8, 0, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0, 0].fill(8, 0, -1), [8, 8, 0],
|
||||
'[0, 0, 0].fill(8, 0, -1) must return [8, 8, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0, 0].fill(8, 0, 5), [8, 8, 8],
|
||||
'[0, 0, 0].fill(8, 0, 5) must return [8, 8, 8]'
|
||||
);
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.fill
|
||||
description: >
|
||||
Fills all the elements from a with a custom start index.
|
||||
info: |
|
||||
22.1.3.6 Array.prototype.fill (value [ , start [ , end ] ] )
|
||||
|
||||
...
|
||||
7. If relativeStart < 0, let k be max((len + relativeStart),0); else let k be
|
||||
min(relativeStart, len).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
assert.compareArray([0, 0, 0].fill(8, 1), [0, 8, 8],
|
||||
'[0, 0, 0].fill(8, 1) must return [0, 8, 8]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0, 0].fill(8, 4), [0, 0, 0],
|
||||
'[0, 0, 0].fill(8, 4) must return [0, 0, 0]'
|
||||
);
|
||||
|
||||
assert.compareArray([0, 0, 0].fill(8, -1), [0, 0, 8],
|
||||
'[0, 0, 0].fill(8, -1) must return [0, 0, 8]'
|
||||
);
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-array.prototype.splice
|
||||
description: >
|
||||
Array.prototype.splice - 'from' is the result of
|
||||
ToString(actualStart+k) in an Array
|
||||
---*/
|
||||
|
||||
var arrObj = [1, 2, 3];
|
||||
var newArrObj = arrObj.splice(-2, 1);
|
||||
|
||||
assert.sameValue(newArrObj.length, 1, 'newArrObj.length');
|
||||
assert.sameValue(newArrObj[0], 2, 'newArrObj[0]');
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2015 André Bargull. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
description: Array.prototype.splice deletes length-start elements when called with one argument
|
||||
info: |
|
||||
22.1.3.25 Array.prototype.splice (start, deleteCount , ...items )
|
||||
|
||||
...
|
||||
9. Else if the number of actual arguments is 1, then
|
||||
a. Let insertCount be 0.
|
||||
b. Let actualDeleteCount be len – actualStart.
|
||||
esid: sec-array.prototype.splice
|
||||
---*/
|
||||
|
||||
var array = ["first", "second", "third"];
|
||||
|
||||
var result = array.splice(1);
|
||||
|
||||
assert.sameValue(array.length, 1, "array length updated");
|
||||
assert.sameValue(array[0], "first", "array[0] unchanged");
|
||||
|
||||
assert.sameValue(result.length, 2, "result array length correct");
|
||||
assert.sameValue(result[0], "second", "result[0] correct");
|
||||
assert.sameValue(result[1], "third", "result[1] correct");
|
||||
Reference in New Issue
Block a user