Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,174 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var { ...x } = { a: 1 };
assertEquals({ a: 1 }, x);
var { ...x } = { a: 1, b: 1 };
assertEquals({ a: 1, b: 1 }, x);
var { x, ...x } = { a: 1, b: 1 };
assertEquals({ a: 1, b: 1 }, x);
var { x = {}, ...x } = { a: 1, b: 1 };
assertEquals({ a: 1, b: 1 }, x);
var { y, ...x } = { y: 1, a: 1 };
assertEquals({ a: 1 }, x);
assertEquals(1, y);
var { z, y, ...x } = { z:1, y: 1, a: 1, b: 1 };
assertEquals({ a: 1, b:1 }, x);
assertEquals(1, y);
assertEquals(1, z);
({ a, ...b } = { a: 1, b: 2 });
assertEquals(1, a);
assertEquals({ b: 2 }, b);
var { ...x } = {};
assertEquals({}, x);
var key = "b";
var { [key]: y, ...x } = { b: 1, a: 1 };
assertEquals({ a: 1 }, x);
assertEquals(1, y);
var key = 1;
var { [key++]: y, ...x } = { 1: 1, a: 1 };
assertEquals({ a: 1 }, x);
assertEquals(key, 2);
assertEquals(1, y);
var key = '1';
var {[key]: y, ...x} = {1: 1, a: 1};
assertEquals({a: 1}, x);
assertEquals(1, y);
function example({a, ...rest}, { b = rest }) {
assertEquals(1, a);
assertEquals({ b: 2, c: 3}, rest);
assertEquals({ b: 2, c: 3}, b);
};
example({ a: 1, b: 2, c: 3}, { b: undefined });
var x = { a: 3 };
var y = {
set a(val) { assertUnreachable(); },
...x,
};
assertEquals(y.a, 3);
var {...y} = {
get a() {
return 1
}
};
assertEquals({a: 1}, y);
var x = {
get a() { throw new Error(); },
};
assertThrows(() => { var { ...y } = x });
var p = new Proxy({}, {
ownKeys() { throw new Error(); }
});
assertThrows(() => { var { ...y } = p });
var p = new Proxy({}, {
ownKeys() { [1]; },
get() { throw new Error(); }
});
assertThrows(() => { var { ...y } = p });
var p = new Proxy({}, {
ownKeys() { [1]; },
getOwnPropertyDescriptor() { throw new Error(); }
});
assertThrows(() => { var { ...y } = p });
var z = { b: 1};
var p = new Proxy(z, {
ownKeys() { return Object.keys(z); },
get(_, prop) { return z[prop]; },
getOwnPropertyDescriptor(_, prop) {
return Object.getOwnPropertyDescriptor(z, prop);
},
});
var { ...y } = p;
assertEquals(z, y);
var z = { 1: 1, 2: 2, 3: 3 };
var p = new Proxy(z, {
ownKeys() { return ['1', '2']; },
getOwnPropertyDescriptor(_, prop) {
return Object.getOwnPropertyDescriptor(z, prop);
},
});
var { 1: x, ...y } = p;
assertEquals(1, x);
assertEquals({ 2: 2 }, y);
var z = { b: 1}
var { ...y } = { ...z} ;
assertEquals(z, y);
var count = 0;
class Foo {
constructor(x) { this.x = x; }
toString() { count++; return this.x.toString(); }
}
var f = new Foo(1);
var { [f] : x, ...y } = { 1: 1, 2: 2}
assertEquals(1, count);
assertEquals({2: 2}, y);
var { 1: x, 2: y, ...z } = { 1: 1, 2: 2, 3:3 };
assertEquals(1, x);
assertEquals(2, y);
assertEquals({ 3: 3 }, z);
var { 1.5: x, 2: y, ...z } = { 1.5: 1, 2: 2, 3:3 };
assertEquals(1, x);
assertEquals(2, y);
assertEquals({ 3: 3 }, z);
(({x, ...z}) => { assertEquals({y: 1}, z); })({ x: 1, y: 1});
var [...{...z}] = [{ x: 1}];
assertEquals({ 0: { x: 1} }, z);
var x = {};
({ ...x.f } = { a: 1 });
assertEquals(x.f, { a: 1 });
var x = [];
({ ...x[0] } = { a: 1 });
assertEquals(x[0], {a: 1});
var {4294967297: y, ...x} = {4294967297: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);
var obj = {
[Symbol.toPrimitive]() {
return 1;
}
};
var {[obj]: y, ...x} = {1: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);
var {[null]: y, ...x} = {null: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);
var {[true]: y, ...x} = {true: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);
var {[false]: y, ...x} = {false: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);

View File

@ -0,0 +1,160 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var x = {a: 1};
var y = { ...x};
assertEquals(x, y);
assertEquals({}, y = { ...{} } );
assertEquals({}, y = { ...undefined });
assertEquals({}, y = { ...null });
assertEquals({}, y = { ...1 });
assertEquals({}, y = { ...1n });
assertEquals({}, y = { ...NaN });
assertEquals({}, y = { ...false });
assertEquals({}, y = { ...true });
assertEquals({}, y = { ...Symbol() });
assertEquals({0: 'f', 1: 'o', 2: 'o'}, y = { ...'foo' });
assertEquals({0: 0, 1: 1}, y = { ...[0, 1] });
assertEquals({}, { ...new Proxy({}, {}) });
assertEquals({a: 2}, y = { ...x, a: 2 });
assertEquals({a: 1, b: 1}, y = { ...x, b: 1 });
assertEquals({a: 1}, y = { a: 2, ...x });
assertEquals({a: 1, b: 1}, y = { a:2, ...x, b: 1 });
assertEquals({a: 3}, y = { a: 2, ...x, a: 3 });
var z = { b: 1}
assertEquals({a: 1, b: 1}, y = { ...x, ...z });
assertEquals({a: 1, b: 1}, y = { a: 2, ...x, ...z });
assertEquals({a: 1, b: 1}, y = { b: 2, ...z, ...x });
assertEquals({a: 1, b: 1}, y = { a: 1, ...x, b: 2, ...z });
assertEquals({a: 1, b: 2}, y = { a: 1, ...x, ...z, b: 2 });
assertEquals({a: 2, b: 2}, y = { ...x, ...z, a:2, b: 2 });
var x = {}
Object.defineProperty(x, 'a', {
enumerable: false,
configurable: false,
writable: false,
value: 1
});
assertEquals({}, { ...x });
var x = {}
Object.defineProperty(x, 'a', {
enumerable: true,
configurable: false,
writable: false,
value: 1
});
var y = { ...x };
var prop = Object.getOwnPropertyDescriptor(y, 'a');
assertEquals(prop.value, 1);
assertTrue(prop.enumerable);
assertTrue(prop.configurable);
assertTrue(prop.writable);
var x = { __proto__: z }
assertEquals({}, { ...x });
var x = {
get a() { return 1; },
set a(_) { assertUnreachable("setter called"); },
};
assertEquals({ a: 1 }, y = { ...x });
var x = {
method() { return 1; },
};
assertEquals(x, y = { ...x });
var x = {
*gen() { return {value: 1, done: true} ; },
};
assertEquals(x, y = { ...x });
var x = {
get a() { throw new Error(); },
};
assertThrows(() => { y = { ...x } });
var p = new Proxy({}, {
ownKeys() { throw new Error(); }
});
assertThrows(() => { y = { ...p } });
var p = new Proxy({}, {
ownKeys() { [1]; },
get() { throw new Error(); }
});
assertThrows(() => { y = { ...p } });
var p = new Proxy({}, {
ownKeys() { [1]; },
getOwnPropertyDescriptor() { throw new Error(); }
});
assertThrows(() => { y = { ...p } });
var p = new Proxy(z, {
ownKeys() { return Object.keys(z); },
get(_, prop) { return z[prop]; },
getOwnPropertyDescriptor(_, prop) {
return Object.getOwnPropertyDescriptor(z, prop);
},
});
assertEquals(z, y = { ...p });
var x = { a:1 };
assertEquals(x, y = { set a(_) { throw new Error(); }, ...x });
var prop = Object.getOwnPropertyDescriptor(y, 'a');
assertEquals(prop.value, 1);
assertFalse("set" in prop);
assertTrue(prop.enumerable);
assertTrue(prop.configurable);
assertTrue(prop.writable);
var x = { a:2 };
assertEquals(x, y = { get a() { throw new Error(); }, ...x });
var prop = Object.getOwnPropertyDescriptor(y, 'a');
assertEquals(prop.value, 2);
assertFalse("get" in prop);
assertTrue(prop.enumerable);
assertTrue(prop.configurable);
assertTrue(prop.writable);
var x = { a:3 };
assertEquals(x, y = {
get a() {
throw new Error();
},
set a(_) {
throw new Error();
},
...x
});
var prop = Object.getOwnPropertyDescriptor(y, 'a');
assertEquals(prop.value, 3);
assertFalse("get" in prop);
assertFalse("set" in prop);
assertTrue(prop.enumerable);
assertTrue(prop.configurable);
assertTrue(prop.writable);
var x = Object.seal({ a:4 });
assertEquals(x, y = { ...x });
var prop = Object.getOwnPropertyDescriptor(y, 'a');
assertEquals(prop.value, 4);
assertTrue(prop.enumerable);
assertTrue(prop.configurable);
assertTrue(prop.writable);
var x = Object.freeze({ a:5 });
assertEquals(x, y = { ...x });
var prop = Object.getOwnPropertyDescriptor(y, 'a');
assertEquals(prop.value, 5);
assertTrue(prop.enumerable);
assertTrue(prop.configurable);
assertTrue(prop.writable);

View File

@ -0,0 +1,26 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function testMegamorphicWithDontEnumTransition() {
function spread(o) { return { ...o }; }
// Set up transition tree
let obj = { ...{}, a: 0, b: 1, c: 2, };
Object.defineProperty(obj, "boom", { enumerable: false, configurable: true,
writable: true });
// make CloneObjectIC MEGAMORPHIC
spread(new Proxy({}, {}));
// Ensure we don't crash, and create the correct object
let result = spread({ a: 0, b: 1, c: 2, boom: 3 });
assertEquals({ a: 0, b: 1, c: 2, boom: 3 }, result);
assertEquals({
enumerable: true,
writable: true,
configurable: true,
value: 3,
}, Object.getOwnPropertyDescriptor(result, "boom"));
})();

View File

@ -0,0 +1,16 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function testMegamorphicWithNonSimpleTransitionHandler() {
function spread(o) { return { ...o }; }
// Set up transition tree
let obj = { ...{}, a: 0, b: 1, boom: 2};
// make CloneObjectIC MEGAMORPHIC
spread(new Proxy({}, {}));
// Ensure we don't crash, and create the correct object
assertEquals({ a: 0, b: 1, c: 2 }, spread({ a: 0, b: 1, c: 2 }));
})();

View File

@ -0,0 +1,176 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Test that cloning the empty object yields the same shape in monomorphic
// state.
(function() {
function clone(o) {
return {...o};
}
const o = {};
assertTrue(%HaveSameMap(o, clone(o)));
%PrepareFunctionForOptimization(clone);
assertTrue(%HaveSameMap(o, clone(o)));
assertTrue(%HaveSameMap(o, clone(o)));
%OptimizeFunctionOnNextCall(clone);
assertTrue(%HaveSameMap(o, clone(o)));
})();
// Test that cloning an object with a single data field yields the same shape
// in monomorphic state.
(function() {
function clone(o) {
return {...o};
}
const o = {a: "a"};
assertTrue(%HaveSameMap(o, clone(o)));
%PrepareFunctionForOptimization(clone);
assertTrue(%HaveSameMap(o, clone(o)));
assertTrue(%HaveSameMap(o, clone(o)));
%OptimizeFunctionOnNextCall(clone);
assertTrue(%HaveSameMap(o, clone(o)));
})();
// Test that cloning fast mode objects yields the same shape in polymorphic state.
(function() {
function clone(o) {
return {...o};
}
const o0 = {};
const o1 = {a: "a"};
const o2 = {a: "a", b: "b"};
assertTrue(%HaveSameMap(o0, clone(o0)));
assertTrue(%HaveSameMap(o1, clone(o1)));
assertTrue(%HaveSameMap(o2, clone(o2)));
%PrepareFunctionForOptimization(clone);
assertTrue(%HaveSameMap(o0, clone(o0)));
assertTrue(%HaveSameMap(o1, clone(o1)));
assertTrue(%HaveSameMap(o2, clone(o2)));
assertTrue(%HaveSameMap(o0, clone(o0)));
assertTrue(%HaveSameMap(o1, clone(o1)));
assertTrue(%HaveSameMap(o2, clone(o2)));
%OptimizeFunctionOnNextCall(clone);
assertTrue(%HaveSameMap(o0, clone(o0)));
assertTrue(%HaveSameMap(o1, clone(o1)));
assertTrue(%HaveSameMap(o2, clone(o2)));
})();
// Test that cloning the empty object with `null` prototype (in fast mode)
// yields the same shape in monomorphic state.
(function() {
function clone(o) {
return {...o, __proto__: null};
}
const o = {};
Object.setPrototypeOf(o, null);
assertTrue(%HasFastProperties(o));
assertNull(Object.getPrototypeOf(o));
assertTrue(%HaveSameMap(o, clone(o)));
%PrepareFunctionForOptimization(clone);
assertTrue(%HaveSameMap(o, clone(o)));
assertTrue(%HaveSameMap(o, clone(o)));
%OptimizeFunctionOnNextCall(clone);
assertTrue(%HaveSameMap(o, clone(o)));
})();
// Test that different CloneObjectICs produce the same shape for the same
// object literal inputs with non-default property attributes.
(function() {
function clone1(o) {
return {...o};
}
function clone2(o) {
return {...o};
}
const o1 = {x: "x", y: "y", z: "z"};
Object.defineProperty(o1, 'x', {configurable:false, writable:false});
Object.defineProperty(o1, 'y', {configurable:false});
Object.defineProperty(o1, 'z', {writable:false});
assertTrue(%HasFastProperties(o1));
const o2 = {a: 1, b: 2, c: 3, d: 4};
Object.defineProperty(o2, 'c', {writable:false});
Object.defineProperty(o2, 'd', {configurable:false});
assertTrue(%HasFastProperties(o2));
for (const o of [o1, o2]) {
for (const clone of [clone1, clone2]) {
const c = clone(o);
assertFalse(%HaveSameMap(o, c));
assertEquals(Object.keys(o), Object.keys(c));
for (const key of Object.keys(c)) {
const d = Object.getOwnPropertyDescriptor(c, key);
assertTrue(d.configurable);
assertTrue(d.enumerable);
assertTrue(d.writable);
assertEquals(d.value, o[key]);
}
}
}
assertTrue(%HaveSameMap(clone1(o1), {x: "x", y: "y", z: "z"}));
assertTrue(%HaveSameMap(clone2(o2), {a: 1, b: 2, c: 3, d: 4}));
%PrepareFunctionForOptimization(clone1);
%PrepareFunctionForOptimization(clone2);
assertTrue(%HaveSameMap(clone1(o1), clone2(o1)));
assertTrue(%HaveSameMap(clone1(o1), clone2(o1)));
assertTrue(%HaveSameMap(clone1(o2), clone2(o2)));
assertTrue(%HaveSameMap(clone1(o2), clone2(o2)));
assertTrue(%HaveSameMap(clone1(o1), {x: "x", y: "y", z: "z"}));
assertTrue(%HaveSameMap(clone2(o2), {a: 1, b: 2, c: 3, d: 4}));
%OptimizeFunctionOnNextCall(clone1);
%OptimizeFunctionOnNextCall(clone2);
assertTrue(%HaveSameMap(clone1(o1), clone2(o1)));
assertTrue(%HaveSameMap(clone1(o2), clone2(o2)));
assertTrue(%HaveSameMap(clone1(o1), {x: "x", y: "y", z: "z"}));
assertTrue(%HaveSameMap(clone2(o2), {a: 1, b: 2, c: 3, d: 4}));
})();
// Test that different CloneObjectICs produce the same shape for trivial
// constructor instances in monomorphic state.
(function() {
function clone1(o) {
return {...o};
}
function clone2(o) {
return {...o};
}
class A {
constructor() {
this.a = 1;
this.b = 2;
this.c = 3;
this.d = 4;
}
};
for (let i = 0; i < 10; ++i) new A(); // Finish slack tracking
assertTrue(%HaveSameMap(clone1(new A()), clone1(new A())));
assertTrue(%HaveSameMap(clone1(new A()), clone2(new A())));
assertTrue(%HaveSameMap(clone2(new A()), clone1(new A())));
assertTrue(%HaveSameMap(clone2(new A()), clone2(new A())));
%PrepareFunctionForOptimization(clone1);
%PrepareFunctionForOptimization(clone2);
assertTrue(%HaveSameMap(clone1(new A()), clone1(new A())));
assertTrue(%HaveSameMap(clone1(new A()), clone2(new A())));
assertTrue(%HaveSameMap(clone2(new A()), clone1(new A())));
assertTrue(%HaveSameMap(clone2(new A()), clone2(new A())));
assertTrue(%HaveSameMap(clone1(new A()), clone1(new A())));
assertTrue(%HaveSameMap(clone1(new A()), clone2(new A())));
assertTrue(%HaveSameMap(clone2(new A()), clone1(new A())));
assertTrue(%HaveSameMap(clone2(new A()), clone2(new A())));
%OptimizeFunctionOnNextCall(clone1);
%OptimizeFunctionOnNextCall(clone2);
assertTrue(%HaveSameMap(clone1(new A()), clone1(new A())));
assertTrue(%HaveSameMap(clone1(new A()), clone2(new A())));
assertTrue(%HaveSameMap(clone2(new A()), clone1(new A())));
assertTrue(%HaveSameMap(clone2(new A()), clone2(new A())));
})();

View File

@ -0,0 +1,123 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function testDoubleElements() {
function f(src) { return {...src}; }
var src = [1.5];
src[0] = 1;
// Uninitialized
assertEquals({ 0: 1 }, f(src));
src[0] = 1.3;
// Monomorphic
assertEquals({ 0: 1.3 }, f(src));
})();
(function testInObjectProperties() {
function f(src) { return {...src}; }
function C() { this.foo = "foo"; }
var src;
for (var i = 0; i < 10; ++i) {
src = new C();
}
// Uninitialized
assertEquals({ foo: "foo" }, f(src));
// Monomorphic
assertEquals({ foo: "foo" }, f(src));
})();
(function testInObjectProperties2() {
function f(src) { return {...src}; }
function C() {
this.foo = "foo";
this.p0 = "0";
this.p1 = "1";
this.p2 = "2";
this.p3 = "3";
}
var src;
for (var i = 0; i < 10; ++i) {
src = new C();
}
// Uninitialized
assertEquals({ foo: "foo", p0: "0", p1: "1", p2: "2", p3: "3" }, f(src));
// Monomorphic
assertEquals({ foo: "foo", p0: "0", p1: "1", p2: "2", p3: "3" }, f(src));
})();
(function testPolymorphicToMegamorphic() {
function f(src) { return {...src}; }
function C1() {
this.foo = "foo";
this.p0 = "0";
this.p1 = "1";
this.p2 = "2";
this.p3 = "3";
}
function C2() {
this.p0 = "0";
this.p1 = "1";
this[0] = 0;
}
function C3() {
this.x = 774;
this.y = 663;
this.rgb = 0xFF00FF;
}
function C4() {
this.qqq = {};
this.v_1 = [];
this.name = "C4";
this.constructor = C4;
}
// Uninitialized
assertEquals({ foo: "foo", p0: "0", p1: "1", p2: "2", p3: "3" }, f(new C1()));
// Monomorphic
assertEquals({ foo: "foo", p0: "0", p1: "1", p2: "2", p3: "3" }, f(new C1()));
// Polymorphic (2)
assertEquals({ 0: 0, p0: "0", p1: "1" }, f(new C2()));
assertEquals({ 0: 0, p0: "0", p1: "1" }, f(new C2()));
// Polymorphic (3)
assertEquals({ x: 774, y: 663, rgb: 0xFF00FF }, f(new C3()));
assertEquals({ x: 774, y: 663, rgb: 0xFF00FF }, f(new C3()));
// Polymorphic (4)
assertEquals({ qqq: {}, v_1: [], name: "C4", constructor: C4 }, f(new C4()));
assertEquals({ qqq: {}, v_1: [], name: "C4", constructor: C4 }, f(new C4()));
// Megamorphic
assertEquals({ boop: 1 }, f({ boop: 1 }));
})();
// There are 2 paths in CloneObjectIC's handler which need to handle double
// fields specially --- in object properties, and copying the property array.
function testMutableInlineProperties() {
function inobject() { "use strict"; this.x = 1.1; }
const src = new inobject();
const x0 = src.x;
const clone = { ...src, x: x0 + 1 };
assertEquals(x0, src.x);
assertEquals({ x: 2.1 }, clone);
}
testMutableInlineProperties()
function testMutableOutOfLineProperties() {
const src = { a: 1, b: 2, c: 3 };
src.x = 2.3;
const x0 = src.x;
const clone = { ...src, x: x0 + 1 };
assertEquals(x0, src.x);
assertEquals({ a: 1, b: 2, c: 3, x: 3.3 }, clone);
}
testMutableOutOfLineProperties();

View File

@ -0,0 +1,23 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Test that cloning the empty object into an object literal with
// `null` prototype works correctly.
(function() {
function clone(o) {
return {...o, __proto__: null};
}
assertNull(Object.getPrototypeOf(clone({})));
assertNull(Object.getPrototypeOf(clone({})));
assertNull(Object.getPrototypeOf(clone({})));
assertNull(Object.getPrototypeOf(clone({})));
%PrepareFunctionForOptimization(clone);
assertNull(Object.getPrototypeOf(clone({})));
assertNull(Object.getPrototypeOf(clone({})));
%OptimizeFunctionOnNextCall(clone);
assertNull(Object.getPrototypeOf(clone({})));
})();

View File

@ -0,0 +1,199 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function checkEquals(array, subject, regexp) {
// Do it once with the interpreter.
var result = subject.match(regexp);
assertEquals(array, result);
// Do it again with the machine code.
result = subject.match(regexp);
assertEquals(array, result);
}
function checkExec(array, regexp, subject) {
// Do it once with the interpreter.
var result = regexp.exec(subject);
assertEquals(array, result);
// Do it again with the machine code.
result = regexp.exec(subject);
assertEquals(array, result);
}
function checkNull(subject, regexp) {
// Do it once with the interpreter.
var result = subject.match(regexp);
assertNull(result);
// Do it again with the machine code.
result = subject.match(regexp);
assertNull(result);
}
// Simple fixed-length matches.
checkEquals(["a"], "a", /^.(?<=a)/);
checkNull("b", /^.(?<=a)/);
checkEquals(["foo"], "foo1", /^f..(?<=.oo)/);
checkEquals(["foo"], "foo2", /^f\w\w(?<=\woo)/);
checkNull("boo", /^f\w\w(?<=\woo)/);
checkNull("fao", /^f\w\w(?<=\woo)/);
checkNull("foa", /^f\w\w(?<=\woo)/);
checkEquals(["def"], "abcdef", /(?<=abc)\w\w\w/);
checkEquals(["def"], "abcdef", /(?<=a.c)\w\w\w/);
checkEquals(["def"], "abcdef", /(?<=a\wc)\w\w\w/);
checkEquals(["cde"], "abcdef", /(?<=a[a-z])\w\w\w/);
checkEquals(["def"], "abcdef", /(?<=a[a-z][a-z])\w\w\w/);
checkEquals(["def"], "abcdef", /(?<=a[a-z]{2})\w\w\w/);
checkEquals(["bcd"], "abcdef", /(?<=a{1})\w\w\w/);
checkEquals(["cde"], "abcdef", /(?<=a{1}b{1})\w\w\w/);
checkEquals(["def"], "abcdef", /(?<=a{1}[a-z]{2})\w\w\w/);
// Variable-length matches.
checkEquals(["def"], "abcdef", /(?<=[a|b|c]*)[^a|b|c]{3}/);
checkEquals(["def"], "abcdef", /(?<=\w*)[^a|b|c]{3}/);
// Start of line matches.
checkEquals(["def"], "abcdef", /(?<=^abc)def/);
checkEquals(["def"], "abcdef", /(?<=^[a-c]{3})def/);
checkEquals(["def"], "abcabcdef", /(?<=^[a-c]{6})def/);
checkEquals(["def"], "xyz\nabcdef", /(?<=^[a-c]{3})def/m);
checkEquals(["ab", "cd", "efg"], "ab\ncd\nefg", /(?<=^)\w+/gm);
checkEquals(["ab", "cd", "efg"], "ab\ncd\nefg", /\w+(?<=$)/gm);
checkEquals(["ab", "cd", "efg"], "ab\ncd\nefg", /(?<=^)\w+(?<=$)/gm);
checkNull("abcdef", /(?<=^[^a-c]{3})def/);
checkNull("foooo", /"^foooo(?<=^o+)$/);
checkNull("foooo", /"^foooo(?<=^o*)$/);
checkEquals(["foo"], "foo", /^foo(?<=^fo+)$/);
checkEquals(["foooo"], "foooo", /^foooo(?<=^fo*)/);
checkEquals(["foo", "f"], "foo", /^(f)oo(?<=^\1o+)$/);
checkEquals(["foo", "f"], "foo", /^(f)oo(?<=^\1o+)$/i);
checkEquals(["foo\u1234", "f"], "foo\u1234", /^(f)oo(?<=^\1o+).$/i);
checkEquals(["def"], "abcdefdef", /(?<=^\w+)def/);
checkEquals(["def", "def"], "abcdefdef", /(?<=^\w+)def/g);
// Word boundary matches.
checkEquals(["def"], "abc def", /(?<=\b)[d-f]{3}/);
checkEquals(["def"], "ab cdef", /(?<=\B)\w{3}/);
checkEquals(["def"], "ab cdef", /(?<=\B)(?<=c(?<=\w))\w{3}/);
checkNull("abcdef", /(?<=\b)[d-f]{3}/);
// Negative lookbehind.
checkEquals(["abc"], "abcdef", /(?<!abc)\w\w\w/);
checkEquals(["abc"], "abcdef", /(?<!a.c)\w\w\w/);
checkEquals(["abc"], "abcdef", /(?<!a\wc)\w\w\w/);
checkEquals(["abc"], "abcdef", /(?<!a[a-z])\w\w\w/);
checkEquals(["abc"], "abcdef", /(?<!a[a-z]{2})\w\w\w/);
checkNull("abcdef", /(?<!abc)def/);
checkNull("abcdef", /(?<!a.c)def/);
checkNull("abcdef", /(?<!a\wc)def/);
checkNull("abcdef", /(?<!a[a-z][a-z])def/);
checkNull("abcdef", /(?<!a[a-z]{2})def/);
checkNull("abcdef", /(?<!a{1}b{1})cde/);
checkNull("abcdef", /(?<!a{1}[a-z]{2})def/);
// Capturing matches.
checkEquals(["def", "c"], "abcdef", /(?<=(c))def/);
checkEquals(["def", "bc"], "abcdef", /(?<=(\w{2}))def/);
checkEquals(["def", "bc", "c"], "abcdef", /(?<=(\w(\w)))def/);
checkEquals(["def", "a"], "abcdef", /(?<=(\w){3})def/);
checkEquals(["d", "bc", undefined], "abcdef", /(?<=(bc)|(cd))./);
checkEquals(["c", "a", undefined],
"abcdef", /(?<=([ab]{1,2})\D|(abc))\w/);
checkEquals(["ab", "a", "b"], "abcdef", /\D(?<=([ab]+))(\w)/);
checkEquals(["c", "d"], "abcdef", /(?<=b|c)\w/g);
checkEquals(["cd", "ef"], "abcdef", /(?<=[b-e])\w{2}/g);
// Captures inside negative lookbehind. (They never capture.)
checkEquals(["de", undefined], "abcdef", /(?<!(^|[ab]))\w{2}/);
// Nested lookaround.
checkEquals(["ef"], "abcdef", /(?<=ab(?=c)\wd)\w\w/);
checkEquals(["ef", "bc"], "abcdef", /(?<=a(?=([^a]{2})d)\w{3})\w\w/);
checkEquals(["ef", "bc"],
"abcdef", /(?<=a(?=([bc]{2}(?<!a{2}))d)\w{3})\w\w/);
checkNull("abcdef", /(?<=a(?=([bc]{2}(?<!a*))d)\w{3})\w\w/);
checkEquals(["faaa"], "faaao", /^faaao?(?<=^f[oa]+(?=o))/);
// Back references.
checkEquals(["b", "b", "bb"], "abb", /(.)(?<=(\1\1))/);
checkEquals(["B", "B", "bB"], "abB", /(.)(?<=(\1\1))/i);
checkEquals(["aB", "aB", "a"], "aabAaBa", /((\w)\w)(?<=\1\2\1)/i);
checkEquals(["Ba", "Ba", "a"], "aabAaBa", /(\w(\w))(?<=\1\2\1)/i);
checkEquals(["b", "b", "B"], "abaBbAa", /(?=(\w))(?<=(\1))./i);
checkEquals(["foo", "'", "foo"], " 'foo' ", /(?<=(.))(\w+)(?=\1)/);
checkEquals(["foo", "\"", "foo"], " \"foo\" ", /(?<=(.))(\w+)(?=\1)/);
checkNull(" .foo\" ", /(?<=(.))(\w+)(?=\1)/);
checkNull("ab", /(.)(?<=\1\1\1)/);
checkNull("abb", /(.)(?<=\1\1\1)/);
checkEquals(["b", "b"], "abbb", /(.)(?<=\1\1\1)/);
checkNull("ab", /(..)(?<=\1\1\1)/);
checkNull("abb", /(..)(?<=\1\1\1)/);
checkNull("aabb", /(..)(?<=\1\1\1)/);
checkNull("abab", /(..)(?<=\1\1\1)/);
checkNull("fabxbab", /(..)(?<=\1\1\1)/);
checkNull("faxabab", /(..)(?<=\1\1\1)/);
checkEquals(["ab", "ab"], "fababab", /(..)(?<=\1\1\1)/);
// Back references to captures inside the lookbehind.
checkEquals(["d", "C"], "abcCd", /(?<=\1(\w))d/i);
checkEquals(["d", "x"], "abxxd", /(?<=\1([abx]))d/);
checkEquals(["c", "ab"], "ababc", /(?<=\1(\w+))c/);
checkEquals(["c", "b"], "ababbc", /(?<=\1(\w+))c/);
checkNull("ababdc", /(?<=\1(\w+))c/);
checkEquals(["c", "abab"], "ababc", /(?<=(\w+)\1)c/);
// Alternations are tried left to right,
// and we do not backtrack into a lookbehind.
checkEquals(["xabcd", "cd", ""], "xabcd", /.*(?<=(..|...|....))(.*)/);
checkEquals(["xabcd", "bcd", ""], "xabcd", /.*(?<=(xx|...|....))(.*)/);
checkEquals(["xxabcd", "bcd", ""], "xxabcd", /.*(?<=(xx|...))(.*)/);
checkEquals(["xxabcd", "xx", "abcd"], "xxabcd", /.*(?<=(xx|xxx))(.*)/);
// We do not backtrack into a lookbehind.
// The lookbehind captures "abc" so that \1 does not match. We do not backtrack
// to capture only "bc" in the lookbehind.
checkNull("abcdbc", /(?<=([abc]+)).\1/);
// Greedy loop.
checkEquals(["c", "bbbbbb"], "abbbbbbc", /(?<=(b+))c/);
checkEquals(["c", "b1234"], "ab1234c", /(?<=(b\d+))c/);
checkEquals(["c", "b12b23b34"], "ab12b23b34c", /(?<=((?:b\d{2})+))c/);
// Sticky
var re1 = /(?<=^(\w+))def/g;
assertEquals(["def", "abc"], re1.exec("abcdefdef"));
assertEquals(["def", "abcdef"], re1.exec("abcdefdef"));
var re2 = /\Bdef/g;
assertEquals(["def"], re2.exec("abcdefdef"));
assertEquals(["def"], re2.exec("abcdefdef"));
// Misc
checkNull("abcdef", /(?<=$abc)def/);
checkEquals(["foo"], "foo", /^foo(?<=foo)$/);
checkEquals(["foo"], "foo", /^f.o(?<=foo)$/);
checkNull("fno", /^f.o(?<=foo)$/);
checkNull("foo", /^foo(?<!foo)$/);
checkNull("foo", /^f.o(?<!foo)$/);
assertEquals(["fno"], "fno".match(/^f.o(?<!foo)$/));
assertEquals(["foooo"], "foooo".match(/^foooo(?<=fo+)$/));
assertEquals(["foooo"], "foooo".match(/^foooo(?<=fo*)$/));
checkExec(["abc", "abc"], /(abc\1)/, "abc");
checkExec(["abc", "abc"], /(abc\1)/, "abc\u1234");
checkExec(["abc", "abc"], /(abc\1)/i, "abc");
checkExec(["abc", "abc"], /(abc\1)/i, "abc\u1234");
var oob_subject = "abcdefghijklmnabcdefghijklmn".substr(14);
checkNull(oob_subject, /(?=(abcdefghijklmn))(?<=\1)a/i);
checkNull(oob_subject, /(?=(abcdefghijklmn))(?<=\1)a/);
checkNull("abcdefgabcdefg".substr(1), /(?=(abcdefg))(?<=\1)/);
// Mutual recursive capture/back references
checkExec(["cacb", "a", ""], /(?<=a(.\2)b(\1)).{4}/, "aabcacbc");
checkExec(["b", "ac", "ac"], /(?<=a(\2)b(..\1))b/, "aacbacb");
checkExec(["x", "aa"], /(?<=(?:\1b)(aa))./, "aabaax");
checkExec(["x", "aa"], /(?<=(?:\1|b)(aa))./, "aaaax");
// Restricted syntax in Annex B 1.4.
assertThrows("/(?<=.)*/u", SyntaxError);
assertThrows("/(?<=.){1,2}/u", SyntaxError);
assertThrows("/(?<=.)*/", SyntaxError);
assertThrows("/(?<=.)?/", SyntaxError);
assertThrows("/(?<=.)+/", SyntaxError);

View File

@ -0,0 +1,20 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var obj = { length: 1, 0: "spread" };
obj[Symbol.toStringTag] = "foo";
obj[Symbol.hasInstance] = function() { return true; }
obj[Symbol.isConcatSpreadable] = true;
var obj2 = { ...obj };
// Crash if fast result map bitfield is not set correctly, if verifying heap
%HeapObjectVerify(obj2);
// Ensure correct result for some well-known symbols
assertEquals("[object foo]", Object.prototype.toString.call(obj2));
assertTrue(Uint8Array instanceof obj2);
assertEquals(["spread"], [].concat(obj2));

View File

@ -0,0 +1,17 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Runtime_ObjectCloneIC_Slow() source argument must be a HeapObject handle,
// because undefined/null are allowed.
function spread(o) { return { ...o }; }
// Transition to MEGAMORPHIC
assertEquals({}, spread(new function C1() {}));
assertEquals({}, spread(new function C2() {}));
assertEquals({}, spread(new function C3() {}));
assertEquals({}, spread(new function C4() {}));
assertEquals({}, spread(new function C5() {}));
// Trigger Runtime_ObjectCloneIC_Slow() with a non-JSReceiver.
assertEquals({}, spread(undefined));

View File

@ -0,0 +1,18 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Check that we do appropriate used/unused field accounting
var p = Promise.resolve();
var then = p.then = () => {};
function spread() { return { ...p }; }
%PrepareFunctionForOptimization(spread);
assertEquals({ then }, spread());
assertEquals({ then }, spread());
assertEquals({ then }, spread());
%OptimizeFunctionOnNextCall(spread);
assertEquals({ then }, spread());

View File

@ -0,0 +1,20 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Check that IfException/IfSuccess rewiring works in JSInliner
function test() {
var spread = function(value) { return { ...value }; }
try {
assertEquals({}, spread());
} catch (e) {}
};
%PrepareFunctionForOptimization(test);
test();
test();
test();
%OptimizeFunctionOnNextCall(test);
test();

View File

@ -0,0 +1,11 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Check that property constness for out-of-object fields is valid
var o = {};
var toString = o.toString = function() {};
try {
assertEquals({ toString }, o = { ...o });
} catch (e) {}
o.toString = [];

View File

@ -0,0 +1,13 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Check that encountering deprecated Maps does not cause CloneObjectIC to
// crash.
var obj1 = { x: 1 };
var obj2 = { x: 2 }; // same map
obj2.x = null; // deprecate map
function f() { return { ...obj1 } };
assertEquals({ x: 1 }, f()); // missed, object migrated to cached new map
assertEquals({ x: 1 }, f()); // monomorphic cache-hit

View File

@ -0,0 +1,18 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-gc
function spread(o) { return { ...o }; }
(function setupPolymorphicFeedback() {
function C1() { this.p0 = 1; }
function C2() { this.p1 = 2; this.p2 = 3; }
assertEquals({ p0: 1 }, spread(new C1));
assertEquals({ p1: 2, p2: 3 }, spread(new C2));
})();
gc(); // Clobber cached map in feedback[0], and check that we don't crash
function C3() { this.p0 = 3; }
assertEquals({ p0: 3 }, spread(new C3));

View File

@ -0,0 +1,12 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Previously, spreading in-object properties would always treat double fields
// as tagged, potentially dereferencing a Float64.
function inobjectDouble() {
"use strict";
this.x = -3.9;
}
const instance = new inobjectDouble();
const clone = { ...instance, };

View File

@ -0,0 +1,15 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function clone(src) {
return { ...src };
}
function inobjectDoubles() {
"use strict";
this.p0 = -6400510997704731;
}
// Check that unboxed double is not treated as tagged
assertEquals({ p0: -6400510997704731 }, clone(new inobjectDoubles()));

View File

@ -0,0 +1,14 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Previously, spreading in-object properties would always treat double fields
// as tagged, potentially dereferencing a Float64.
// Ensure that we don't fail an assert from --verify-heap when cloning a
// HeapNumber in the CloneObjectIC handler case.
var src, clone;
for (var i = 0; i < 40000; i++) {
src = { ...i, x: -9007199254740991 };
clone = { ...src };
}

View File

@ -0,0 +1,870 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function check({cooked, raw, exprs}) {
return function(strs, ...args) {
assertArrayEquals(cooked, strs);
assertArrayEquals(raw, strs.raw);
assertArrayEquals(exprs, args);
};
}
// clang-format off
check({
'cooked': [
undefined
],
'raw': [
'\\01'
],
'exprs': []
})`\01`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\01',
'right'
],
'exprs': [
0
]
})`\01${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\01'
],
'exprs': [
0
]
})`left${0}\01`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\01',
'right'
],
'exprs': [
0,
1
]
})`left${0}\01${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\1'
],
'exprs': []
})`\1`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\1',
'right'
],
'exprs': [
0
]
})`\1${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\1'
],
'exprs': [
0
]
})`left${0}\1`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\1',
'right'
],
'exprs': [
0,
1
]
})`left${0}\1${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\xg'
],
'exprs': []
})`\xg`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\xg',
'right'
],
'exprs': [
0
]
})`\xg${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\xg'
],
'exprs': [
0
]
})`left${0}\xg`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\xg',
'right'
],
'exprs': [
0,
1
]
})`left${0}\xg${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\xAg'
],
'exprs': []
})`\xAg`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\xAg',
'right'
],
'exprs': [
0
]
})`\xAg${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\xAg'
],
'exprs': [
0
]
})`left${0}\xAg`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\xAg',
'right'
],
'exprs': [
0,
1
]
})`left${0}\xAg${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u0'
],
'exprs': []
})`\u0`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u0',
'right'
],
'exprs': [
0
]
})`\u0${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u0'
],
'exprs': [
0
]
})`left${0}\u0`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u0',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u0${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u0g'
],
'exprs': []
})`\u0g`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u0g',
'right'
],
'exprs': [
0
]
})`\u0g${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u0g'
],
'exprs': [
0
]
})`left${0}\u0g`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u0g',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u0g${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u00g'
],
'exprs': []
})`\u00g`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u00g',
'right'
],
'exprs': [
0
]
})`\u00g${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u00g'
],
'exprs': [
0
]
})`left${0}\u00g`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u00g',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u00g${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u000g'
],
'exprs': []
})`\u000g`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u000g',
'right'
],
'exprs': [
0
]
})`\u000g${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u000g'
],
'exprs': [
0
]
})`left${0}\u000g`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u000g',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u000g${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u{}'
],
'exprs': []
})`\u{}`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u{}',
'right'
],
'exprs': [
0
]
})`\u{}${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u{}'
],
'exprs': [
0
]
})`left${0}\u{}`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u{}',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u{}${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u{-0}'
],
'exprs': []
})`\u{-0}`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u{-0}',
'right'
],
'exprs': [
0
]
})`\u{-0}${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u{-0}'
],
'exprs': [
0
]
})`left${0}\u{-0}`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u{-0}',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u{-0}${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u{g}'
],
'exprs': []
})`\u{g}`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u{g}',
'right'
],
'exprs': [
0
]
})`\u{g}${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u{g}'
],
'exprs': [
0
]
})`left${0}\u{g}`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u{g}',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u{g}${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u{0'
],
'exprs': []
})`\u{0`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u{0',
'right'
],
'exprs': [
0
]
})`\u{0${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u{0'
],
'exprs': [
0
]
})`left${0}\u{0`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u{0',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u{0${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u{\\u{0}'
],
'exprs': []
})`\u{\u{0}`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u{\\u{0}',
'right'
],
'exprs': [
0
]
})`\u{\u{0}${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u{\\u{0}'
],
'exprs': [
0
]
})`left${0}\u{\u{0}`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u{\\u{0}',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u{\u{0}${1}right`;
check({
'cooked': [
undefined
],
'raw': [
'\\u{110000}'
],
'exprs': []
})`\u{110000}`;
check({
'cooked': [
undefined,
'right'
],
'raw': [
'\\u{110000}',
'right'
],
'exprs': [
0
]
})`\u{110000}${0}right`;
check({
'cooked': [
'left',
undefined
],
'raw': [
'left',
'\\u{110000}'
],
'exprs': [
0
]
})`left${0}\u{110000}`;
check({
'cooked': [
'left',
undefined,
'right'
],
'raw': [
'left',
'\\u{110000}',
'right'
],
'exprs': [
0,
1
]
})`left${0}\u{110000}${1}right`;
function checkMultiple(expectedArray) {
let results = [];
return function consume(strs, ...args) {
if (typeof strs === 'undefined') {
assertArrayEquals(expectedArray, results);
} else {
results.push({cooked: strs, raw: strs.raw, exprs: args});
return consume;
}
};
}
checkMultiple([{
'cooked': [
undefined
],
'raw': [
'\\u',
],
'exprs': []
}, {
'cooked': [
undefined
],
'raw': [
'\\u',
],
'exprs': []
}])`\u``\u`();
checkMultiple([{
'cooked': [
' '
],
'raw': [
' ',
],
'exprs': []
}, {
'cooked': [
undefined
],
'raw': [
'\\u',
],
'exprs': []
}])` ``\u`();
checkMultiple([{
'cooked': [
undefined
],
'raw': [
'\\u',
],
'exprs': []
}, {
'cooked': [
' '
],
'raw': [
' ',
],
'exprs': []
}])`\u`` `();
checkMultiple([{
'cooked': [
' '
],
'raw': [
' ',
],
'exprs': []
}, {
'cooked': [
' '
],
'raw': [
' ',
],
'exprs': []
}])` `` `();