diff --git a/static_core/plugins/ets/stdlib/std/core/Proxy.ets b/static_core/plugins/ets/stdlib/std/core/Proxy.ets index a1889bfcab52c2bf6bc4fd73c596292d2c6abb13..afa483ca29bdd2871d894030b3086194433dd6bc 100644 --- a/static_core/plugins/ets/stdlib/std/core/Proxy.ets +++ b/static_core/plugins/ets/stdlib/std/core/Proxy.ets @@ -239,11 +239,90 @@ export final class Proxy { const propertyName = getter.getName().substring(Proxy.GETTER_METHOD_PREFIX_LENGTH) const getterType = getter.getType() - + const resultType = getterType.getResultType() const getterCreator = new MethodCreator(getter.getName()) .addAccessModifier(getter.getAccessModifier()) - .addResult(getterType.getResultType()) - .addBody(new CallableBodyFunction((proxy: Object): NullishType => { + .addResult(resultType) + if (resultType.isPrimitive()) { + if (resultType instanceof IntType) { + getterCreator.addBody(new CallableBodyFunction((proxy: Object): Int => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + return (this.handlerGet(__narrowAny(target), __narrowAny>(handler), propertyName) as Numeric).toInt() + } + + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + })) + } else if (resultType instanceof DoubleType) { + getterCreator.addBody(new CallableBodyFunction((proxy: Object): Double => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + return (this.handlerGet(__narrowAny(target), __narrowAny>(handler), propertyName) as Numeric).toDouble() + } + + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + })) + } else if (resultType instanceof ShortType) { + getterCreator.addBody(new CallableBodyFunction((proxy: Object): Short => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + return (this.handlerGet(__narrowAny(target), __narrowAny>(handler), propertyName) as Numeric).toShort() + } + + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + })) + } else if (resultType instanceof FloatType) { + getterCreator.addBody(new CallableBodyFunction((proxy: Object): Float => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + return (this.handlerGet(__narrowAny(target), __narrowAny>(handler), propertyName) as Numeric).toFloat() + } + + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + })) + } else if (resultType instanceof ByteType) { + getterCreator.addBody(new CallableBodyFunction((proxy: Object): Byte => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + return (this.handlerGet(__narrowAny(target), __narrowAny>(handler), propertyName) as Numeric).toByte() + } + + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + })) + } else if (resultType instanceof CharType) { + getterCreator.addBody(new CallableBodyFunction((proxy: Object): Char => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + return this.handlerGet(__narrowAny(target), __narrowAny>(handler), propertyName) as Char + } + + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + })) + } else if (resultType instanceof LongType) { + getterCreator.addBody(new CallableBodyFunction((proxy: Object): Long => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + return (this.handlerGet(__narrowAny(target), __narrowAny>(handler), propertyName) as Numeric).toLong() + } + + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + })) + } else { + getterCreator.addBody(new CallableBodyFunction((proxy: Object): NullishType => { const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) if (handler instanceof ProxyHandler) { const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) @@ -253,7 +332,19 @@ export final class Proxy { throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) })) + } + } else { + getterCreator.addBody(new CallableBodyFunction((proxy: Object): NullishType => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + return this.handlerGet(__narrowAny(target), __narrowAny>(handler), propertyName) + } + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + })) + } proxyTypeCreator.addMethod(getterCreator) } @@ -272,7 +363,123 @@ export final class Proxy { .addAccessModifier(setter.getAccessModifier()) .addResult(setterType.getResultType()) .addParameter(new ParameterCreator(setterType.getParameter(0).getType())) - .addBody(new CallableBodyFunction((proxy: Object, value: NullishType): void => { + const setterParamType = setterType.getParameter(0).getType() + if (setterParamType.isPrimitive()) { + if (setterParamType instanceof IntType) { + setterCreator.addBody(new CallableBodyFunction((proxy: Object, value: Int): void => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + const success = this.handlerSet(__narrowAny(target), __narrowAny>(handler), propertyName, value as object) + if (!success) { + throw new TypeError(`proxy set handler returned false for propety '"${propertyName}"'`) + } + } else { + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + } + })) + } else if (setterParamType instanceof DoubleType) { + setterCreator.addBody(new CallableBodyFunction((proxy: Object, value: Double): void => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + const success = this.handlerSet(__narrowAny(target), __narrowAny>(handler), propertyName, value as object) + if (!success) { + throw new TypeError(`proxy set handler returned false for propety '"${propertyName}"'`) + } + } else { + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + } + })) + } else if (setterParamType instanceof ShortType) { + setterCreator.addBody(new CallableBodyFunction((proxy: Object, value: Short): void => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + const success = this.handlerSet(__narrowAny(target), __narrowAny>(handler), propertyName, value as object) + if (!success) { + throw new TypeError(`proxy set handler returned false for propety '"${propertyName}"'`) + } + } else { + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + } + })) + } else if (setterParamType instanceof FloatType) { + setterCreator.addBody(new CallableBodyFunction((proxy: Object, value: Float): void => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + const success = this.handlerSet(__narrowAny(target), __narrowAny>(handler), propertyName, value as object) + if (!success) { + throw new TypeError(`proxy set handler returned false for propety '"${propertyName}"'`) + } + } else { + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + } + })) + } else if (setterParamType instanceof ByteType) { + setterCreator.addBody(new CallableBodyFunction((proxy: Object, value: Byte): void => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + const success = this.handlerSet(__narrowAny(target), __narrowAny>(handler), propertyName, value as object) + if (!success) { + throw new TypeError(`proxy set handler returned false for propety '"${propertyName}"'`) + } + } else { + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + } + })) + } else if (setterParamType instanceof CharType) { + setterCreator.addBody(new CallableBodyFunction((proxy: Object, value: Char): void => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + const success = this.handlerSet(__narrowAny(target), __narrowAny>(handler), propertyName, value as object) + if (!success) { + throw new TypeError(`proxy set handler returned false for propety '"${propertyName}"'`) + } + } else { + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + } + })) + } else if (setterParamType instanceof LongType) { + setterCreator.addBody(new CallableBodyFunction((proxy: Object, value: Long): void => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + const success = this.handlerSet(__narrowAny(target), __narrowAny>(handler), propertyName, value as object) + if (!success) { + throw new TypeError(`proxy set handler returned false for propety '"${propertyName}"'`) + } + } else { + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + } + })) + } else { + setterCreator.addBody(new CallableBodyFunction((proxy: Object, value: NullishType): void => { + const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) + if (handler instanceof ProxyHandler) { + const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) + // using "wrapper" method to "capture" after smartcast + const success = this.handlerSet(__narrowAny(target), __narrowAny>(handler), propertyName, value as object) + if (!success) { + throw new TypeError(`proxy set handler returned false for propety '"${propertyName}"'`) + } + } else { + throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) + } + })) + } + } else { + setterCreator.addBody(new CallableBodyFunction((proxy: Object, value: NullishType): void => { const handler = Reflect.get(proxy, Proxy.PROXY_INSTANCE_HANDLER_FIELD) if (handler instanceof ProxyHandler) { const target = Reflect.get(proxy, Proxy.PROXY_INSTANCE_TARGET_FIELD) @@ -285,6 +492,7 @@ export final class Proxy { throw new TypeError("unexpected proxy handler type: " + Type.of(handler).getName()) } })) + } proxyTypeCreator.addMethod(setterCreator) } diff --git a/static_core/plugins/ets/stdlib/std/core/Type.ets b/static_core/plugins/ets/stdlib/std/core/Type.ets index cdeaa01d2162626750e9fafa3e453984ac442c3c..927b3a6c26a895ddfc8c1b2749933be97946d2b6 100644 --- a/static_core/plugins/ets/stdlib/std/core/Type.ets +++ b/static_core/plugins/ets/stdlib/std/core/Type.ets @@ -532,6 +532,9 @@ export abstract class Type extends Object { if (this instanceof BooleanType && other instanceof BooleanType) { return true } + if (this instanceof CharType && other instanceof CharType) { + return true + } return false } diff --git a/static_core/plugins/ets/tests/ets_func_tests/escompat/ProxyTest.ets b/static_core/plugins/ets/tests/ets_func_tests/escompat/ProxyTest.ets index 86b7cfbc72671ab21d681dd5716374932ee61405..e9462b4f557e415c51f9b27fde85a8a75eb24246 100644 --- a/static_core/plugins/ets/tests/ets_func_tests/escompat/ProxyTest.ets +++ b/static_core/plugins/ets/tests/ets_func_tests/escompat/ProxyTest.ets @@ -82,6 +82,37 @@ class ObjProxyHandler extends proxy.DefaultProxyHandler { } } +interface ProxyTest { + a1:number + a2:int + a3:short + a4:byte + a5:char + a6:double + a7:string + a8:float + a9:long +} + +class interfaceProxyHandler implements proxy.ProxyHandler{ + public get(target:T, name:string):NullishType { + const value = Reflect.get(target, name) as Any + return value + } + + public set(target:T, name:string, newValue:NullishType):boolean { + if (Reflect.get(target, name) !== newValue) { + const result = Reflect.set(target, name, newValue) + return result + } + return true + } + + public invoke(target:T, method:Method, args:FixedArray):NullishType { + return method.invoke(target, args) + } +} + function verifyObjectProxyOps(obj: ObjWithProps, objProxyHandler: ObjProxyHandler): void { arktest.assertFalse(objProxyHandler.getTrapped) arktest.assertFalse(objProxyHandler.setTrapped) @@ -125,11 +156,35 @@ function testStdLibClassesProxying(): void { arktest.assertTrue(map === mapProxy) } +function testInterfaceProxying(): void { + let testObj: ProxyTest = {a1: 100.2, a2: 100, a3: 2, a4: 3, a5: c'4', a6: 100.3, a7:"abc", a8: 100.23f, a9:99999999} + let proxyObj = proxy.Proxy.create(testObj, new interfaceProxyHandler()) + proxyObj.a1 = 200.2 + proxyObj.a2 = 200 + proxyObj.a3 = 3 + proxyObj.a4 = 4 + proxyObj.a5 = c'5' + proxyObj.a6 = 100.4 + proxyObj.a7 = "def" + proxyObj.a8 = 200.23f + proxyObj.a9 = 111111111 + arktest.assertTrue(proxyObj.a1 === 200.2) + arktest.assertTrue(proxyObj.a2 === 200) + arktest.assertTrue(proxyObj.a3 === 3) + arktest.assertTrue(proxyObj.a4 === 4) + arktest.assertTrue(proxyObj.a5 === c'5') + arktest.assertTrue(proxyObj.a6 === 100.4) + arktest.assertTrue(proxyObj.a7 === "def") + arktest.assertTrue(proxyObj.a8 === 200.23f) + arktest.assertTrue(proxyObj.a9 === 111111111) +} + function main(): int { const suite = new arktest.ArkTestsuite("Proxy API") suite.addTest("Object proxy operations", testObjectProxyOps) suite.addTest("StdLib classes proxying", testStdLibClassesProxying) + suite.addTest("interface primitive fields proxying", testInterfaceProxying) return suite.run() }