public void Constructor(RuntimeFunction ctor) { IsConstructorWLength(ctor, "Array", 1, Array.Prototype); That(Array.Construct(0)["length"], Is.EqualTo(0)); That(Array.Construct(1)["length"], Is.EqualTo(1)); That(Array.Construct(4294967295)["length"], Is.EqualTo(4294967295)); That(() => Array.Construct(-1), Throws.RangeError); That(() => Array.Construct(4294967296), Throws.RangeError); That(() => Array.Construct(4294967297), Throws.RangeError); That(() => Array.Construct(NaN), Throws.RangeError); That(() => Array.Construct(Infinity), Throws.RangeError); That(() => Array.Construct(-Infinity), Throws.RangeError); That(() => Array.Construct(1.5), Throws.RangeError); That(() => Array.Construct(Number["MAX_VALUE"]), Throws.RangeError); That(() => Array.Construct(Number["MIN_VALUE"]), Throws.RangeError); That(Array.Construct(Null), Is.EquivalentTo(new[] { Null })); That(Array.Construct(Undefined), Is.EquivalentTo(new[] { Undefined })); That(Array.Construct(true), Is.EquivalentTo(new[] { true })); That(Array.Construct("1"), Is.EquivalentTo(new[] { "1" })); EcmaValue falseObj = Boolean.Construct(false); That(Array.Construct(falseObj), Is.EquivalentTo(new[] { falseObj })); EcmaValue strObj = String.Construct("0"); That(Array.Construct(strObj), Is.EquivalentTo(new[] { strObj })); EcmaValue numObj = Number.Construct(0); That(Array.Construct(numObj), Is.EquivalentTo(new[] { numObj })); numObj = Number.Construct(4294967295); That(Array.Construct(numObj), Is.EquivalentTo(new[] { numObj })); numObj = Number.Construct(-1); That(Array.Construct(numObj), Is.EquivalentTo(new[] { numObj })); numObj = Number.Construct(4294967296); That(Array.Construct(numObj), Is.EquivalentTo(new[] { numObj })); numObj = Number.Construct(4294967297); That(Array.Construct(numObj), Is.EquivalentTo(new[] { numObj })); That(Array.Construct(), Is.EquivalentTo(EcmaValue.EmptyArray)); That(Array.Construct(0, 1, 0, 1), Is.EquivalentTo(new[] { 0, 1, 0, 1 })); That(Array.Construct(Undefined, Undefined), Is.EquivalentTo(new[] { Undefined, Undefined })); That(Array.Call().InstanceOf(Array)); That(Array.Call(), Is.EquivalentTo(EcmaValue.EmptyArray)); That(Array.Call(_, 0, 1, 0, 1), Is.EquivalentTo(new[] { 0, 1, 0, 1 })); That(Array.Call(_, Undefined, Undefined), Is.EquivalentTo(new[] { Undefined, Undefined })); }
public void ToString(RuntimeFunction toString) { IsUnconstructableFunctionWLength(toString, "toString", 0); It("should return \"true\" if this boolean value is true, \"false\" otherwise", () => { Case(Boolean.Construct(), "false"); Case(Boolean.Construct(false), "false"); Case(Boolean.Construct(true), "true"); Case(Boolean.Construct(1), "true"); Case(Boolean.Construct(0), "false"); Case(Boolean.Construct(Object.Construct()), "true"); Case((Boolean.Prototype, true), "false"); Case((Boolean.Construct(), true), "false"); Case((Boolean.Construct(false), true), "false"); Case((Boolean.Construct(true), false), "true"); Case((Boolean.Construct(1), false), "true"); Case((Boolean.Construct(0), true), "false"); Case((Boolean.Construct(Object.Construct()), false), "true"); });
public void Exec(RuntimeFunction exec) { IsUnconstructableFunctionWLength(exec, "exec", 1); IsAbruptedFromToPrimitive(exec.Bind(RegExp.Construct())); RequireThisRegExpObject(); It("should coerce its argument to string", () => { object undefined = Undefined; VerifyMatch(@"1|12", "123", new[] { "1" }, 0); VerifyMatch(@"1|12", 1.01, new[] { "1" }, 0); VerifyMatch(@"2|12", Number.Construct(1.012), new[] { "12" }, 3); VerifyMatch(@"\.14", CreateObject(toString: () => EcmaMath.PI), new[] { ".14" }, 1); VerifyMatch(@"t[a-b|q-s]", true, new[] { "tr" }, 0); VerifyMatch(@"AL|se", Boolean.Construct(), new[] { "se" }, 3); VerifyMatch(@"LS", "i", CreateObject(toString: () => false), new[] { "ls" }, 2); VerifyMatch(@"ll|l", Null, new[] { "ll" }, 2); VerifyMatch(@"nd|ne", Undefined, new[] { "nd" }, 1); VerifyMatch(@"((1)|(12))((3)|(23))", String.Construct("123"), new[] { "123", "1", "1", undefined, "23", undefined, "23" }, 0); VerifyMatch(@"a[a-z]{2,4}", Object.Construct("abcdefghi"), new[] { "abcde" }, 0); VerifyMatch(@"a[a-z]{2,4}?", CreateObject(toString: () => "abcdefghi"), new[] { "abc" }, 0); VerifyMatch(@"(aa|aabaac|ba|b|c)*", CreateObject(toString: () => new EcmaObject(), valueOf: () => "aabaac"), new[] { "aaba", "ba" }, 0); }); It("should read and reset lastIndex to 0 when global is set and the match fails", () => { EcmaValue re = RegExp.Construct("a", "g"); int lastIndexReads = 0; re["lastIndex"] = CreateObject(valueOf: () => { lastIndexReads++; return(42); }); Case((re, "abc"), Null); That(re["lastIndex"], Is.EqualTo(0)); That(lastIndexReads, Is.EqualTo(1)); lastIndexReads = 0; re["lastIndex"] = CreateObject(valueOf: () => { lastIndexReads++; return(-1); }); Case((re, "nbc"), Null); That(re["lastIndex"], Is.EqualTo(0)); That(lastIndexReads, Is.EqualTo(1)); });
public void SetLength() { EcmaArray arr = new EcmaArray(); Assume.That(arr.Length, Is.EqualTo(0)); arr.Length = 3; That(arr.ToValue(), Is.EquivalentTo(new[] { Undefined, Undefined, Undefined })); That(!arr.HasProperty(0)); That(!arr.HasProperty(1)); That(!arr.HasProperty(2)); // should delete properties whose name is an array index and is larger than new length arr = new EcmaArray(1, 2, 3); arr.Length = 2; That(arr.ToValue(), Is.EquivalentTo(new[] { 1, 2 })); That(!arr.HasProperty(2)); // should have changed if a property is added whose name is an array index arr = new EcmaArray(); Assume.That(arr.Length, Is.EqualTo(0)); arr[0] = 1; That(arr.ToValue(), Is.EquivalentTo(new[] { 1 })); arr[1] = 2; That(arr.ToValue(), Is.EquivalentTo(new[] { 1, 2 })); arr = new EcmaArray(); arr[-1] = 1; That(arr.Length, Is.EqualTo(0)); arr[true] = 1; That(arr.Length, Is.EqualTo(0)); arr[CreateObject(valueOf: () => 3)] = 1; That(arr.Length, Is.EqualTo(0)); arr["1"] = 1; That(arr.Length, Is.EqualTo(2)); arr[Number.Construct(2)] = 2; That(arr.Length, Is.EqualTo(3)); arr[String.Construct("3")] = 2; That(arr.Length, Is.EqualTo(4)); arr[4294967294] = 4294967294; That(arr.Length, Is.EqualTo(4294967295)); arr[4294967295] = 4294967295; That(arr.Length, Is.EqualTo(4294967295)); arr = new EcmaArray(); That(() => arr["length"] = -1, Throws.RangeError); That(() => arr["length"] = 4294967295, Throws.Nothing); That(() => arr["length"] = 4294967296, Throws.RangeError); That(() => arr["length"] = 4294967297, Throws.RangeError); That(() => arr["length"] = 1.5, Throws.RangeError); That(() => arr["length"] = NaN, Throws.RangeError); That(() => arr["length"] = Infinity, Throws.RangeError); That(() => arr["length"] = -Infinity, Throws.RangeError); That(() => arr["length"] = Undefined, Throws.RangeError); arr["length"] = true; That(arr.Length, Is.EqualTo(1)); arr["length"] = Null; That(arr.Length, Is.EqualTo(0)); arr["length"] = Boolean.Construct(false); That(arr.Length, Is.EqualTo(0)); arr["length"] = Number.Construct(1); That(arr.Length, Is.EqualTo(1)); arr["length"] = "1"; That(arr.Length, Is.EqualTo(1)); arr["length"] = String.Construct("1"); That(arr.Length, Is.EqualTo(1)); arr["length"] = CreateObject(valueOf: () => 2); That(arr.Length, Is.EqualTo(2)); arr["length"] = CreateObject(valueOf: () => 2, toString: () => 1); That(arr.Length, Is.EqualTo(2)); arr["length"] = CreateObject(valueOf: () => 2, toString: () => new EcmaObject()); That(arr.Length, Is.EqualTo(2)); arr["length"] = CreateObject(valueOf: () => 2, toString: ThrowTest262Exception); That(arr.Length, Is.EqualTo(2)); arr["length"] = CreateObject(toString: () => 1); That(arr.Length, Is.EqualTo(1)); arr["length"] = CreateObject(toString: () => 1, valueOf: () => new EcmaObject()); That(arr.Length, Is.EqualTo(1)); That(() => arr["length"] = CreateObject(valueOf: ThrowTest262Exception, toString: () => 1), Throws.Test262); That(() => arr["length"] = CreateObject(valueOf: () => new EcmaObject(), toString: () => new EcmaObject()), Throws.TypeError); }
public void StructuredSerialize() { RuntimeRealm other = new RuntimeRealm(); It("should clone object with own non-symbol properties", () => { EcmaValue obj = new EcmaObject(); obj["boolean"] = true; obj["number"] = 1; obj["string"] = ""; obj["circular"] = obj; obj["booleanObj"] = Boolean.Construct(false); obj["numberObj"] = Number.Construct(0); obj["stringObj"] = String.Construct(""); obj[new Symbol()] = "foo"; Object.Invoke("defineProperty", obj, "foo", CreateObject(new { enumerable = true, value = 1 })); Object.Invoke("defineProperty", obj, "bar", CreateObject(new { enumerable = true, get = FunctionLiteral(() => 0) })); Object.Invoke("defineProperty", obj, "baz", CreateObject(new { enumerable = false, value = 1 })); other.Execute(() => { EcmaValue clone = obj.ToObject().Clone(other); That(clone != obj); That(Object.Invoke("getPrototypeOf", clone), Is.EqualTo(Object.Prototype), "prototype is derived from target realm"); That(clone["boolean"], Is.EqualTo(true)); That(clone["number"], Is.EqualTo(1)); That(clone["string"], Is.EqualTo("")); That(clone["booleanObj"], Is.InstanceOf(Boolean), "Boolean object is copied"); That(clone["numberObj"], Is.InstanceOf(Number), "Number object is copied"); That(clone["stringObj"], Is.InstanceOf(String), "String object is copied"); That(clone["circular"], Is.EqualTo(clone), "circular reference is preserved"); That(clone, Has.OwnProperty("foo", 1, EcmaPropertyAttributes.DefaultDataProperty), "non-writable and non-configurable flag is not copied"); That(clone, Has.OwnProperty("bar", 0, EcmaPropertyAttributes.DefaultDataProperty), "accessor is copied as data"); That(Object.Invoke("getOwnPropertyDescriptor", clone, "baz"), Is.Undefined, "non-enumerable property is not copied"); That(Object.Invoke("getOwnPropertySymbols", clone)["length"], Is.Zero, "symbol property is not copied"); }); }); It("should not clone prototype chain", () => { EcmaValue obj = new EcmaObject(); EcmaValue customProto = Object.Invoke("create", obj); obj["foo"] = "bar"; Assume.That(Object.Invoke("getPrototypeOf", customProto), Is.EqualTo(obj)); Assume.That(customProto["foo"], Is.EqualTo("bar")); other.Execute(() => { EcmaValue clone = customProto.ToObject().Clone(other); That(clone != customProto); That(Object.Invoke("getPrototypeOf", clone), Is.EqualTo(Object.Prototype), "prototype chain is ignored"); That(Object.Invoke("getOwnPropertyNames", clone)["length"], Is.Zero, "inherited properties are not copied"); That(clone["foo"], Is.Undefined); }); }); It("should throw if property values are not cloneable", () => { EcmaValue poisoned = new EcmaObject(); poisoned["foo"] = new Symbol(); other.Execute(() => { That(() => poisoned.ToObject().Clone(other), Throws.Exception, "symbol value causes exception"); }); }); It("should shallow clone primitive objects", () => { EcmaValue boolObj = Boolean.Construct(false); EcmaValue numObj = Number.Construct(0); EcmaValue strObj = String.Construct(""); boolObj["foo"] = 1; numObj["foo"] = 1; strObj["foo"] = 1; Assume.That(Object.Invoke("getOwnPropertyNames", boolObj)["length"], Is.EqualTo(1)); Assume.That(Object.Invoke("getOwnPropertyNames", numObj)["length"], Is.EqualTo(1)); Assume.That(Object.Invoke("getOwnPropertyNames", strObj)["length"], Is.EqualTo(1)); other.Execute(() => { EcmaValue cboolObj = boolObj.ToObject().Clone(other); That(cboolObj, Is.TypeOf("object")); That(Object.Invoke("getOwnPropertyNames", cboolObj)["length"], Is.Zero); EcmaValue cnumObj = numObj.ToObject().Clone(other); That(cnumObj, Is.TypeOf("object")); That(Object.Invoke("getOwnPropertyNames", cnumObj)["length"], Is.Zero); EcmaValue cstrObj = strObj.ToObject().Clone(other); That(cstrObj, Is.TypeOf("object")); That(Object.Invoke("getOwnPropertyNames", cstrObj)["length"], Is.Zero); }); }); It("should shallow clone Date object", () => { EcmaValue date = Date.Construct(2020, 0, 1); EcmaValue ts = +date; date["foo"] = 1; other.Execute(() => { EcmaValue clone = date.ToObject().Clone(other); That(clone, Is.InstanceOf(Date)); That(+clone, Is.EqualTo(ts)); That(Object.Invoke("getOwnPropertyDescriptor", clone, "foo"), Is.Undefined); }); }); It("should deeply clone [[MapData]]", () => { EcmaValue map = Map.Construct(); map.Invoke("set", map, map); map.Invoke("set", "bar", "baz"); map["foo"] = 1; other.Execute(() => { EcmaValue clone = map.ToObject().Clone(other); That(clone, Is.InstanceOf(Map)); That(clone.Invoke("get", clone), Is.EqualTo(clone)); That(Object.Invoke("getOwnPropertyDescriptor", clone, "foo"), Is.Undefined, "own property is not copied"); clone.Invoke("set", map, 1); clone.Invoke("delete", "bar"); clone.Invoke("set", "baz", true); }); That(map.Invoke("get", map), Is.EqualTo(map), "original value is unchanged"); That(map.Invoke("get", "bar"), Is.EqualTo("baz"), "original entry is not deleted"); That(map.Invoke("has", "baz"), Is.False, "key added in clone is not added in original map"); }); It("should deeply clone [[SetData]]", () => { EcmaValue set = Set.Construct(); set.Invoke("add", set); set.Invoke("add", true); set["foo"] = 1; other.Execute(() => { EcmaValue clone = set.ToObject().Clone(other); That(clone, Is.InstanceOf(Set)); That(clone.Invoke("has", clone), Is.True); That(Object.Invoke("getOwnPropertyDescriptor", clone, "foo"), Is.Undefined, "own property is not copied"); clone.Invoke("delete", true); clone.Invoke("add", false); }); That(set.Invoke("has", true), Is.True); That(set.Invoke("has", false), Is.False); }); It("should clone [[ArrayBufferData]] with same byte contents", () => { EcmaValue buffer = Global.ArrayBuffer.Construct(4); EcmaValue view = Global.Uint8Array.Construct(buffer); view[1] = 1; view[2] = 2; view[3] = 3; buffer["foo"] = 1; other.Execute(() => { EcmaValue clone = buffer.ToObject().Clone(other); EcmaValue cloneView = Global.Uint8Array.Construct(clone); That(cloneView, Is.EquivalentTo(new[] { 0, 1, 2, 3 })); That(Object.Invoke("getOwnPropertyDescriptor", clone, "foo"), Is.Undefined, "own property is not copied"); cloneView[0] = 42; }); That(view, Is.EquivalentTo(new[] { 0, 1, 2, 3 })); }); It("should clone [[ArrayBufferData]] with same data block if it is shared", () => { EcmaValue buffer = Global.SharedArrayBuffer.Construct(4); EcmaValue view = Global.Uint8Array.Construct(buffer); view[1] = 1; view[2] = 2; view[3] = 3; buffer["foo"] = 1; other.Execute(() => { EcmaValue clone = buffer.ToObject().Clone(other); EcmaValue cloneView = Global.Uint8Array.Construct(clone); That(cloneView, Is.EquivalentTo(new[] { 0, 1, 2, 3 })); That(Object.Invoke("getOwnPropertyDescriptor", clone, "foo"), Is.Undefined, "own property is not copied"); cloneView[0] = 42; }); That(view, Is.EquivalentTo(new[] { 42, 1, 2, 3 })); }); It("should clone [[ViewedArrayBuffer]] with same byte contents", () => { EcmaValue buffer = Global.ArrayBuffer.Construct(4); EcmaValue view = Global.Uint8Array.Construct(buffer); view[1] = 1; view[2] = 2; view[3] = 3; view["foo"] = 1; other.Execute(() => { EcmaValue cloneView = view.ToObject().Clone(other); That(cloneView, Is.EquivalentTo(new[] { 0, 1, 2, 3 })); That(Object.Invoke("getOwnPropertyDescriptor", cloneView, "foo"), Is.Undefined, "own property is not copied"); cloneView[0] = 42; }); That(view, Is.EquivalentTo(new[] { 0, 1, 2, 3 })); }); It("should clone [[ViewedArrayBuffer]] with same data block if it is shared", () => { EcmaValue buffer = Global.SharedArrayBuffer.Construct(4); EcmaValue view = Global.Uint8Array.Construct(buffer); view[1] = 1; view[2] = 2; view[3] = 3; view["foo"] = 1; other.Execute(() => { EcmaValue cloneView = view.ToObject().Clone(other); That(cloneView, Is.EquivalentTo(new[] { 0, 1, 2, 3 })); That(Object.Invoke("getOwnPropertyDescriptor", cloneView, "foo"), Is.Undefined, "own property is not copied"); cloneView[0] = 42; }); That(view, Is.EquivalentTo(new[] { 42, 1, 2, 3 })); }); It("should throw if object is callable", () => { EcmaValue fn = FunctionLiteral(Noop); That(() => fn.ToObject().Clone(other), Throws.Exception); }); It("should throw if object has other internal slots", () => { EcmaValue symObj = Object.Construct(new Symbol()); That(() => symObj.ToObject().Clone(other), Throws.Exception); }); It("should detach array buffer if it is in the transfer list", () => { EcmaValue buffer = Global.ArrayBuffer.Construct(4); EcmaValue view = Global.Uint8Array.Construct(buffer); view[1] = 1; view[2] = 2; view[3] = 3; other.Execute(() => { EcmaValue clone = buffer.ToObject().Clone(other, buffer.ToObject()); EcmaValue cloneView = Global.Uint8Array.Construct(clone); That(cloneView, Is.EquivalentTo(new[] { 0, 1, 2, 3 })); }); That(() => view[1], Throws.TypeError); }); It("should throw if object in transfer list is not transferable", () => { EcmaValue buffer = Global.ArrayBuffer.Construct(4); That(() => buffer.ToObject().Clone(other, new EcmaObject()), Throws.Exception); }); It("should throw if array buffer in transfer list is detached", () => { EcmaValue buffer = Global.ArrayBuffer.Construct(4); EcmaValue detached = Global.ArrayBuffer.Construct(4); DetachBuffer(detached); That(() => buffer.ToObject().Clone(other, detached.ToObject()), Throws.Exception); }); }
public BooleanInstance CreateBoolean(bool value) { return((BooleanInstance)Boolean.Construct(value)); }
public void ToString(RuntimeFunction toString) { IsUnconstructableFunctionWLength(toString, "toString", 0); EcmaValue obj = new EcmaObject(); DefineProperty(obj, Symbol.ToStringTag, get: ThrowTest262Exception); Case(obj, Throws.Test262); EcmaValue args = default; FunctionLiteral(() => args = Arguments).Call(); Case(args, "[object Arguments]"); Case(new EcmaArray(), "[object Array]"); Case(true, "[object Boolean]"); Case(Boolean.Call(_, true), "[object Boolean]"); Case(Boolean.Construct(true), "[object Boolean]"); Case(Object.Call(_, true), "[object Boolean]"); Case(Object.Call(_, Boolean.Call(true)), "[object Boolean]"); Case(Object.Call(_, Boolean.Construct(true)), "[object Boolean]"); Case(new EcmaDate(), "[object Date]"); Case(Object.Call(_, new EcmaDate()), "[object Date]"); Case(FunctionLiteral(() => Undefined), "[object Function]"); Case(Null, "[object Null]"); Case(42, "[object Number]"); Case(Number.Call(_, 42), "[object Number]"); Case(Number.Construct(42), "[object Number]"); Case(Object.Call(_, 42), "[object Number]"); Case(Object.Call(_, Number.Call(42)), "[object Number]"); Case(Object.Call(_, Number.Construct(42)), "[object Number]"); Case(Object.Prototype, "[object Object]"); Case(new EcmaObject(), "[object Object]"); Case(RegExp.Construct("."), "[object RegExp]"); Case("", "[object String]"); Case(String.Call(_, ""), "[object String]"); Case(String.Construct(""), "[object String]"); Case(Object.Call(_, ""), "[object String]"); Case(Object.Call(_, String.Call("")), "[object String]"); Case(Object.Call(_, String.Construct("")), "[object String]"); Case(Undefined, "[object Undefined]"); Case(Proxy.Construct(Array.Construct(), Object.Construct()), "[object Array]"); // Non-string values of `@@toStringTag` property are ignored Case(CreateObject((Symbol.ToStringTag, Undefined)), "[object Object]"); Case(CreateObject((Symbol.ToStringTag, Null)), "[object Object]"); Case(CreateObject((Symbol.ToStringTag, Symbol.ToStringTag)), "[object Object]"); Case(CreateObject((Symbol.ToStringTag, 42)), "[object Object]"); Case(CreateObject((Symbol.ToStringTag, String.Construct(""))), "[object Object]"); Case(CreateObject((Symbol.ToStringTag, new EcmaObject())), "[object Object]"); Case(CreateObject((Symbol.ToStringTag, FunctionLiteral(() => ""))), "[object Object]"); }