Unwrap Proxy receivers and arguments before Java dispatch - #2061
Draft
edusperoni wants to merge 1 commit into
Draft
edusperoni wants to merge 1 commit into
edusperoni wants to merge 1 commit into
Conversation
Reactive frameworks (Vue's reactive()) wrap Java object wrappers in a JS Proxy. A Proxy has no internal fields and no creation context, so the first Java method call on one aborted the process in GetInternalField, and any private-value lookup on one aborted in GetCreationContext. - ObjectManager::UnwrapProxy follows Proxy-of-Proxy chains to the target (null when revoked); GetJSInstanceInfo, and therefore every GetJavaObjectByJsObject caller, resolves through it. - Method, field, 'super', 'class' and 'null' accessors dispatch on the Proxy target. A revoked Proxy, or one whose target is not a Java object for an instance member, throws a TypeError. - JsArgConverter, JsArgToArrayConverter, JSToJavaConverter and MethodCache::GetType marshal the target of a Proxy argument, so proxied Java objects and proxied JS arrays convert as their targets do; a revoked Proxy argument is a conversion error. - Implementation objects passed to extend() or an interface constructor are unwrapped. - CallSuper is read only from objects that have the field, so a plain object as `this` throws instead of aborting. - Creation-context lookups fall back to the current context instead of aborting; Symbol.hasInstance catches native exceptions; URLImpl checks the field count before reading its pointer.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Java object wrappers wrapped in a JS
Proxy— which is what Vue 3'sreactive()does to anything stored in componentdata()— expose no internal fields and no creation context, so the runtime could not find the Java object behind them. Reproduced onmainwith a barenew Proxy(new java.lang.StringBuilder(), {}):proxy.append("x")# Fatal error in v8::Object::GetInternalField() / Internal field out of bounds(MetadataNode::MethodCallbackreadsCallSuperoffinfo.This())V8GetPrivateValue/V8SetPrivateValue)GetCreationContext().ToLocalChecked()— a Proxy never has a creation contextVue 3 users have been working around this with
markRaw/toRaw.Changes
ObjectManager::UnwrapProxyfollows Proxy-of-Proxy chains to the target (nullwhen revoked).GetJSInstanceInfo— and therefore everyGetJavaObjectByJsObjectcaller (arg converters,FieldAccessor,ArrayElementAccessor,instanceof,Interop,NativeScriptException,ArrayHelper) — resolves through it.super,classandnullaccessors dispatch on the Proxy target exactly as on a direct receiver. A revoked Proxy, or one whose target is not a Java object for an instance member, throws a catchableTypeError.CallSuperis read only from objects that actually carry the field, so a plain object asthisnow throws the existing "no Java counterpart" error instead of aborting.JsArgConverter,JsArgToArrayConverter,JSToJavaConverterandMethodCache::GetTypemarshal the target of a Proxy argument, so proxied Java objects and proxied JS arrays (and their elements) convert as their targets do; a revoked Proxy argument is a conversion error.extend()/ interface constructors are unwrapped.GetCreationContextOrCurrentreplaces everyGetCreationContext(...).ToLocalChecked();Symbol.hasInstancegets the standard try/catch →ReThrowToV8;URLImpl::GetPointerchecks the internal-field count first.Proxy traps are consulted only for the JS-side lookup; the Java call runs on the target.
Does your commit message include the wording below to reference a specific issue in this repo?
No linked issue (reported through nativescript-vue; root-caused in the runtime).
Related Pull Requests
Does your pull request have unit tests?
Yes —
test-app/app/src/main/assets/app/tests/testProxyReceivers.js, 16 specs (instance/trap/nested/static receivers, public field get/set, string coercion, proxied object/array/element arguments, array element assignment, revoked receiver and argument, non-Java target, plain-object receiver,instanceof, extended-class override +super). Full suite on the emulator: 1258 passed / 0 failed (main: 1242 / 0).Shared-submodule versions of these specs can follow once both runtimes land.