fix(runtime): unwrap Proxy receivers and arguments before native dispatch - #485
Draft
edusperoni wants to merge 1 commit into
Draft
edusperoni wants to merge 1 commit into
edusperoni wants to merge 1 commit into
Conversation
…atch Native wrappers wrapped in a JS Proxy (e.g. by Vue's reactive()) expose no internal fields, so method calls were dispatched as class methods, property accessors returned undefined, toString returned an object, and passing a proxy as an argument aborted the process in GetCreationContext. - tns::UnwrapProxy walks Proxy::GetTarget chains; tns::GetValue resolves through it, so every wrapper lookup sees the target. - MethodCallback, property getter/setter and toString resolve a proxy receiver to its native target (or class constructor for methods) and throw a TypeError for revoked proxies or non-native targets. - WriteValue/WriteTypeValue/ToArray unwrap before marshalling and throw a TypeError for revoked proxies; ToObject and callback return values treat a revoked proxy as nil. - GetCreationContext call sites fall back to the current context instead of asserting when the object has none.
|
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
Native object wrappers wrapped in a JS
Proxy— which is what Vue 3'sreactive()does to anything stored in componentdata()— expose no internal fields, so the runtime could not find the native object behind them:proxy.someMethod()NSInvalidArgumentException: +[Klass someMethod]: unrecognized selector sent to classproxy.somePropertyundefinedString(proxy)/console.logTypeError: Cannot convert object to primitive valuensArray.addObject(proxy)tns::AssertinInterop::ToArray— a Proxy has no creation context)The same behavior exists on every previous release (the gates are identical in 8.9.2), so this is not a 9.1 regression; Vue 3 users have been working around it with
markRaw/toRaw.Changes
tns::UnwrapProxywalksProxy::GetTarget()chains (empty when revoked).tns::GetValueresolves through it, so every wrapper lookup sees the target.MethodCallback, property getter/setter andtoStringresolve a Proxy receiver to its native target (or class constructor, for methods) and dispatch exactly as on the target. A revoked Proxy, or one whose target is not a native object, throws a catchableTypeErrorinstead of a static call or an assert.WriteValue/WriteTypeValue/ToArrayunwrap arguments before marshalling, so proxied native objects, proxied JS arrays of native objects, proxied dictionaries and struct initializers all convert as their targets do. A revoked Proxy argument throws aTypeError.ToObjectand ffi-closure return values (where a C++ throw can't propagate) treat a revoked Proxy asnil.GetCreationContext()on a caller-supplied value falls back to the current context instead of asserting (incl.setTimeout/requestAnimationFramecallbacks that are callable Proxies).Proxy traps are consulted only for the JS-side lookup; the native call runs on the target (no reactivity tracking of native state — expected, same as Vue's own guidance for third-party class instances).
Related Pull Requests
Tests
TestRunner/app/tests/ProxyReceiverTests.js— 14 specs (instance/nested/class-constructor receivers, property get/set, string coercion, proxied object/array/dictionary/struct arguments, revoked-proxy receiver and argument, non-native target, traps-are-consulted). Full suite: 1748 specs, 0 failures.Shared-submodule versions of these specs can follow once both runtimes land.