/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * @tc.name:builtinsreflect * @tc.desc:test builtins reflect * @tc.type: FUNC * @tc.require: issueI8SXHD */ print("builtins reflect start"); // test1 -- reflect set length var y = []; Object.defineProperty(y, 1, { value: 42, configurable: false }); var tag1 = Reflect.set(y, 'length', 0); var tag2 = Reflect.set(y, 'length', 5); print(tag1); print(tag2); const v0 = 102630708; let v55 = []; let v56 = Object.create(v55) Reflect.set(v56, "length", v0) Reflect.set(v55, "length", v0, v56) print("v56.length",v56.length) var global = this; var sym = Symbol("gaga"); var objects = [ {}, [], function() {}, function() { return arguments; }(), Object(1), Object(true), Object('bla'), new Date, new RegExp, new Set, new Map, new WeakMap, new WeakSet, new ArrayBuffer(10), new Int32Array(5), Object, Function, Date, RegExp, global ]; function prepare(target) { target["bla"] = true; target[4] = 42; target[sym] = "foo"; target["noconf"] = 43; Object.defineProperty(target, "noconf", { configurable: false }); Object.defineProperty(target, "nowrite", { writable: false, configurable: true, value: 44 }); Object.defineProperty(target, "getter", { get: function () {return this.bla}, configurable: true }); Object.defineProperty(target, "setter", { set: function (x) {this.gaga = x}, configurable: true }); Object.defineProperty(target, "setter2", { set: function (x) {}, configurable: true }); } (function testReflectGetOnObject() { let i = 0; for (let target of objects) { prepare(target); if (true == Reflect.get(target, "bla") && 42 == Reflect.get(target, 4) && 42 == Reflect.get(target, "4") && "foo" == Reflect.get(target, sym) && 43 == Reflect.get(target, "noconf") && true == Reflect.get(target, "getter") && undefined == Reflect.get(target, "setter") && undefined == Reflect.get(target, "foo") && undefined == Reflect.get(target, 333)) { print(i + "success_1"); } let proto = target.__proto__; target.__proto__ = { get foo() {return this.bla} }; if (true == Reflect.get(target, "foo")) { print(i + "success_2"); } target.__proto__ = proto; i++; } })(); let obj = {name:"tom"}; let pxobj = new Proxy(obj,{}); print(Reflect.get(pxobj,"name")) { try { let arr=[1,2,3,4]; arr.length=102600; Reflect.set(arr,"length","aaa",arr); } catch (error) { print(error.name) } try { let arr=[1,2,3,4]; arr.length=102600; Reflect.set(arr,"length","aaa"); } catch (error) { print(error.name) } } // reflect set ir print("Reflect.set Ir test") { // special test try { Reflect.set(undefined,"fail","fail") } catch (error) { print("Reflect.set undefined test pass") } try { Reflect.set(null,"fail","fail") } catch (error) { print("Reflect.set null test pass") } { let arrKey = [1,2,3] let testObj = {} Reflect.set(testObj,arrKey,"key is array") print(testObj[arrKey]) } { let bigThenMaxKey = 2147483645; let testObj = {} Reflect.set(testObj,bigThenMaxKey,"key is over int32 max") print(testObj[bigThenMaxKey]) } { let minusOne = -1; let testObj = {} Reflect.set(testObj,minusOne,"key is minusOne") print(testObj[minusOne]) } { let lessThanInt32Min = -2147483648 let testObj = {} Reflect.set(testObj,lessThanInt32Min,"key is lessThanInt32Min") print(testObj[lessThanInt32Min]) } { let strKeyNumber = "5" let testObj = {} Reflect.set(testObj,strKeyNumber,"key is strKeyNumber") print(testObj[strKeyNumber]) } { let strKeyNumberMinusOne = "-1" let testObj = {} Reflect.set(testObj,strKeyNumberMinusOne,"key is strKeyNumberMinusOne") print(testObj[strKeyNumberMinusOne]) } { let strKeyNumberOverInt32 = "2147483645" let testObj = {} Reflect.set(testObj,strKeyNumberOverInt32,"key is strKeyNumberOverInt32") print(testObj[strKeyNumberOverInt32]) } { let strKeyNumberLessInt32Min = "-2147483648" let testObj = {} Reflect.set(testObj,strKeyNumberLessInt32Min,"key is strKeyNumberLessInt32Min") print(testObj[strKeyNumberLessInt32Min]) } { try { let objToStringThrowError = { toString(){ throw new Error("toString error") } } let testObj = {} Reflect.set(testObj,objToStringThrowError,"fail!") } catch (error) { print(error.message) } } { const testObj = { t: "origin" } const proxy = new Proxy(testObj,{}) Reflect.set(proxy,"t","normal proxy") print(testObj["t"]) } { const testObj = { t: "origin" } const proxy = new Proxy(testObj,{ set(target,key,value){ if (value === "nothrow proxy") { target[key] = value return true } else if (value === "return false proxy") { target[key] = value return false } else if (value === "throw proxy") { target[key] = value throw new Error("throw error in proxy") } } }) Reflect.set(proxy,"t","return false proxy") print(testObj["t"]) Reflect.set(proxy,"t","nothrow proxy") print(testObj["t"]) try { Reflect.set(proxy,"t","throw proxy") } catch (error) { print(testObj["t"]) print(error.message) } } { const dynamicHandler = new Proxy({}, { get(target, prop) { if (prop === "set") { return null; } return Reflect.get(target, prop); } }); const target = {}; const proxy = new Proxy(target, dynamicHandler); Reflect.set(proxy, "a", 1); } // SetPropertyByIndex { let tArr = new Uint8Array(1) let sym = Symbol("error symbol") try { Reflect.set(tArr,"1",sym) } catch (error) { print("sym to number fail") } } { let arr = [] arr[1] = 1 Object.preventExtensions(arr) Reflect.set(arr,"2",2) print("shoud not throw arr not Extensions") } { let arr = [] arr[1] = 1 Object.defineProperty(arr,"length",{writable:false}) Reflect.set(arr,"5",2) print("don't throw error if length not writeable") } { let arr = [] arr[1] = 1 Object.defineProperty(arr,"2",{configurable:false}) Reflect.set(arr,"2",2) print("don't throw error if value not configurable") } { let arr = [] arr[0] = 5 arr[1025] = 1025 Object.defineProperty(arr,"length",{writable:false}) Reflect.set(arr,"1026",1026) print("no exception or dictionary arr") } const setterNothrow = { set x(v){ print("setterNothrow call setter") this.t = v } } const setterNothrowObj = Object.create(setterNothrow); Reflect.set(setterNothrowObj,"x","setterNothrow good") print(setterNothrowObj.t) const setterthrow = { set x(v){ print("setterthrow call setter") throw new Error("error in setter") } } const setterthrowObj = Object.create(setterthrow); try { Reflect.set(setterthrowObj,"x","setterThrow good") } catch (error) { print(error.message) } const setterReturnFalse = { set x(v){ print("setterReturnFalse call setter") return false } } const setterReturnFalseObj = Object.create(setterReturnFalse) Reflect.set(setterReturnFalseObj,"x","setterReturnFalse good"); // normal test (function testSetProperty() { const obj = { foo: 42 }; const result = Reflect.set(obj, "foo", 100); print("testSetProperty: ", obj.foo === 100 && result === true); })(); (function testSetNonExistentProperty() { const obj = { foo: 42 }; const result = Reflect.set(obj, "bar", 123); print("testSetNonExistentProperty: ", obj.bar === 123 && result === true); })(); (function testSetInProxy() { const obj = { foo: 42 }; const proxy = new Proxy(obj, { set(target, prop, value, receiver) { if (prop === "foo") { target[prop] = value + 1; // 在 Proxy 中对 foo 做一些修改 return true; } return Reflect.set(target, prop, value, receiver); } }); const result = Reflect.set(proxy, "foo", 100); print("testSetInProxy:", obj.foo === 101 && result === true); })(); (function testSetWithSymbol() { const sym = Symbol("bar"); const obj = {}; const result = Reflect.set(obj, sym, 200); print("testSetWithSymbol:", obj[sym] === 200 && result === true); })(); (function testSetReceiver() { const obj = { foo: 42 }; const receiver = { foo: 100 }; const result = Reflect.set(obj, "foo", 50, receiver); print("testSetReceiver:", obj.foo === 50 && receiver.foo === 100 && result === true); })(); (function testSetPropertyAndCheckExists() { const obj = {}; const result1 = Reflect.set(obj, "foo", 42); const result2 = Reflect.has(obj, "foo"); print("testSetPropertyAndCheckExists:", result1 === true && result2 === true); })(); (function testSetInProxyThrowsException() { const obj = { foo: 42 }; const proxy = new Proxy(obj, { set(target, prop, value, receiver) { if (prop === "foo") { throw new Error("Can't set foo!"); } return Reflect.set(target, prop, value, receiver); } }); try { Reflect.set(proxy, "foo", 100); } catch (e) { print("testSetInProxyThrowsException:", e.message === "Can't set foo!"); } })(); (function testSetThrowsError() { const obj = {}; try { Reflect.set(obj, "foo", undefined); print("testSetThrowsError: undefined assignment allowed"); } catch (e) { print("testSetThrowsError: Error while setting undefined"); } })(); (function testSetNestedObjectProperty() { const obj = { nested: { foo: 42 } }; const result = Reflect.set(obj.nested, "foo", 100); print("testSetNestedObjectProperty:", obj.nested.foo === 100 && result === true); })(); (function testSetNestedPropertyInProxy() { const obj = { nested: { foo: 42 } }; const proxy = new Proxy(obj, { set(target, prop, value, receiver) { if (prop === "nested") { target[prop].foo = value; return true; } return Reflect.set(target, prop, value, receiver); } }); const result = Reflect.set(proxy, "nested", { foo: 100 }); print("testSetNestedPropertyInProxy:", obj.nested.foo === 100 && result === true); })(); (function testSetNonConfigurableProperty() { const obj = {}; Object.defineProperty(obj, "foo", { value: 42, writable: true, configurable: false }); try { Reflect.set(obj, "foo", 100); print("testSetNonConfigurableProperty: No error for non-configurable"); } catch (e) { print("testSetNonConfigurableProperty: Error for non-configurable property"); } })(); (function testSetPrototypeProperty() { const proto = { foo: 42 }; const obj = Object.create(proto); const result = Reflect.set(obj, "foo", 100); print("testSetPrototypeProperty:", obj.foo === 100 && result === true); })(); (function testSetAccessorPropertyInProxy() { const obj = { get foo() { return 42; }, set foo(value) { this._foo = value; } }; const proxy = new Proxy(obj, { set(target, prop, value, receiver) { if (prop === "foo") { target[prop] = value + 1; return true; } return Reflect.set(target, prop, value, receiver); } }); const result = Reflect.set(proxy, "foo", 100); print("testSetAccessorPropertyInProxy:", obj._foo === 101 && result === true); })(); } // reflect get ir test print("Reflect.get Ir test") { (function testGetterUsesReceiverThis() { const obj = { get val() { return this.x + 1; } }; const receiver = { x: 10 }; const result = Reflect.get(obj, "val", receiver); print("testGetterUsesReceiverThis:", result === 11); })(); (function testReceiverIsNull() { const obj = { get val() { return this.x; } }; try { Reflect.get(obj, "val", null); } catch (e) { print("testReceiverIsNull:", e instanceof TypeError); } })(); (function testReceiverIsPrimitive() { const obj = { get val() { return this.length; } }; const result = Reflect.get(obj, "val", "hello"); print("testReceiverIsPrimitive:", result === 5); })(); (function testReceiverMissingFields() { const obj = { get val() { return this.foo + 1; } }; const receiver = {}; const result = Reflect.get(obj, "val", receiver); print("testReceiverMissingFields:", Number.isNaN(result)); })(); (function testReceiverWithOwnFields() { const obj = { get val() { return this.foo * 2; } }; const receiver = { foo: 21 }; const result = Reflect.get(obj, "val", receiver); print("testReceiverWithOwnFields:", result === 42); })(); (function testReceiverInheritance() { const base = { get foo() { return this.x; } }; const receiver = Object.create({ x: 123 }); const result = Reflect.get(base, "foo", receiver); print("testReceiverInheritance:", result === 123); })(); (function testReceiverIsSameAsTarget() { const obj = { get x() { return this === obj; } }; const result = Reflect.get(obj, "x", obj); print("testReceiverIsSameAsTarget:", result === true); })(); (function testReceiverArrayLength() { const obj = { get lastIndex() { return this.length - 1; } }; const result = Reflect.get(obj, "lastIndex", [1, 2, 3, 4]); print("testReceiverArrayLength:", result === 3); })(); (function testReceiverIsProxy() { const obj = { get val() { return this.x; } }; const proxy = new Proxy({ x: 42 }, { get(target, prop, receiver) { return Reflect.get(...arguments); } }); const result = Reflect.get(obj, "val", proxy); print("testReceiverIsProxy:", result === 42); })(); (function testReceiverIsClassInstance() { class MyClass { constructor(x) { this.x = x; } get val() { return this.x; } } const obj = new MyClass(100); const receiver = new MyClass(42); const result = Reflect.get(obj, "val", receiver); print("testReceiverIsClassInstance:", result === 42); // receiver 的 val 优先 })(); (function testReceiverIsInPrototypeChain() { const base = { get val() { return this.x; } }; const proto = { x: 100 }; const receiver = Object.create(proto); const result = Reflect.get(base, "val", receiver); print("testReceiverIsInPrototypeChain:", result === 100); })(); (function testReceiverIsNull() { const obj = { get val() { return this.x; } }; try { Reflect.get(obj, "val", null); } catch (e) { print("testReceiverIsNull:", e instanceof TypeError); } })(); (function testReceiverIsUndefined() { const obj = { get val() { return this.x; } }; try { Reflect.get(obj, "val", undefined); } catch (e) { print("testReceiverIsUndefined:", e instanceof TypeError); } })(); (function testReceiverModifiedBySet() { const obj = { get val() { return this.x; } }; const receiver = { x: 42 }; Reflect.set(receiver, "x", 100); const result = Reflect.get(obj, "val", receiver); print("testReceiverModifiedBySet:", result === 100); })(); } print("Reflect.has Ir test") { (function testHasPropertyExists() { const obj = { foo: 42 }; const result = Reflect.has(obj, "foo"); print("testHasPropertyExists:", result === true); })(); (function testHasPropertyDoesNotExist() { const obj = { foo: 42 }; const result = Reflect.has(obj, "bar"); print("testHasPropertyDoesNotExist:", result === false); })(); (function testHasPropertyInPrototypeChain() { const proto = { foo: 42 }; const obj = Object.create(proto); const result = Reflect.has(obj, "foo"); print("testHasPropertyInPrototypeChain:", result === true); })(); (function testHasWithNull() { try { Reflect.has(null, "foo"); } catch (e) { print("testHasWithNull:", e instanceof TypeError); } })(); (function testHasWithUndefined() { try { Reflect.has(undefined, "foo"); } catch (e) { print("testHasWithUndefined:", e instanceof TypeError); } })(); (function testHasInProxy() { const obj = { foo: 42 }; const proxy = new Proxy(obj, { has(target, prop) { return prop === "foo"; } }); const result1 = Reflect.has(proxy, "foo"); const result2 = Reflect.has(proxy, "bar"); print("testHasInProxy: foo exists:", result1 === true); print("testHasInProxy: bar exists:", result2 === false); })(); (function testHasAndGetCombination() { const obj = { foo: 42 }; const hasFoo = Reflect.has(obj, "foo"); const getFoo = hasFoo ? Reflect.get(obj, "foo") : undefined; print("testHasAndGetCombination:", getFoo === 42); })(); (function testHasInProxyWithNonExistentProperty() { const obj = {}; const proxy = new Proxy(obj, { has(target, prop) { return prop === "foo"; } }); const result = Reflect.has(proxy, "bar"); print("testHasInProxyWithNonExistentProperty:", result === false); })(); (function testHasVsInOperator() { const obj = { foo: 42 }; const resultReflect = Reflect.has(obj, "foo"); const resultIn = "foo" in obj; print("testHasVsInOperator:", resultReflect === resultIn); })(); (function testHasWithSymbol() { const sym = Symbol("bar"); const obj = { [sym]: 123 }; const result = Reflect.has(obj, sym); print("testHasWithSymbol:", result === true); })(); (function testHasWithNonExistentSymbol() { const sym = Symbol("bar"); const obj = { foo: 42 }; const result = Reflect.has(obj, sym); print("testHasWithNonExistentSymbol:", result === false); })(); } print("builtins reflect end");