Repository navigation
fix(ffi/objc): define only real C enum constant names as globals - #87
NathanWalker wants to merge 1 commit into
Conversation
With globals enabled, every key of every enum object became a global, including short member names such as Center, Fill and CloudKit's Zone. Libraries that feature-detect a global by name were misled: Angular's zoneless scheduler checks typeof Zone and crashed at bootstrap. The metadata only stored the shortened member names, so the bridge could not tell which alias was the real C constant. Metadata format v2 records, per enum, the prefix and suffix the generator stripped from its members, and flags members whose stored name is already the full C name. The reader rebuilds every member's exact C name from that; v1 metadata still loads but yields no C names. A shared alias builder (ffi/objc/shared/EnumMemberAliases.h) tags the C name among each member's aliases and is used by both the JSI bridge and the Node-API tree. The bridge exposes getEnumGlobalNames(enumName), and the shared global installer and installGlobals() in @nativescript/react-native define only those names. The Node-API tree defines only C names as globals. Short names and other conveniences stay on the enum object, which also gains the C name as a key, so constants like MKMapTypeStandard and CKErrorZoneBusy now resolve.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
|
@DjDeveloperr Can you take a look at this? I think this would break NativeScript core apps that simply using |
|
This shouldn't affect NativeScript core apps. Short member names were never globals in the NativeScript iOS runtime, and core doesn't use them as bare globals:
The only code that could break is code that relied on the short names this branch's bridges briefly put on |
|
LGTM as long as it aligns behavior with existing iOS runtime. New runtime is beta and we can make breaking changes like this (especially since it doesn't affect core apps). Good to remove any divergence. |
Replaces the enum part of #77 (item 6 of the "NativeScript bugs" list in ng-native/ng-native#931). This addresses the review point "Enum globals are chosen by a guess based on names … the decision should be made [in the bridge], in one place."
Summary
With
init("", { globals: true }), every key of every enum object became a global, including short member names likeCenter,Filland CloudKit'sZone. Angular's zoneless scheduler checkstypeof Zone, so it crashed at bootstrap.The bridge couldn't make that decision before: the generator strips enum members down to short names, so the full C names weren't in the metadata at all. Its rebuilt aliases matched the real C name for only about 47% of members in a sample of SDK headers.
MKMapTypeStandardandCKErrorZoneBusywere never produced, while invented names likeNSComparisonAscendingandkNSTextAlignmentCenterwere. So the metadata now records what was stripped:enum entry (metadata format v2) name + memberPrefix, memberSuffix // what transformEnumMemberNames stripped members[]: name | mdSectionOffsetEnumMemberCName flag, value // flag = stored name already is the C name C name = flagged ? name : memberPrefix + name + memberSuffix // exact; the generator fails the build otherwiseNSURLError-style unnamed enums were already stored as full-name constants and are unaffected.Evidence
Real-behaviour runtime tests in
platforms/apple/test/runtime/runner/app/tests/Marshalling/EnumTests.js:MKMapTypeStandard,CKErrorZoneBusy,CKRecordZoneCapabilityAtomicandCKRecordZoneEncryptionScopePerZone;Center,Zone,Ascending,Restricted,ZoneBusy,NSComparisonAscendingandkNSTextAlignmentCenterare not globals.node scripts/run-tests-ios.js)Center in globalThis: true)MACOS_TEST_FFI_BACKEND=napi node scripts/run-tests-macos.js)DBL_MAXdouble-marshalling specs.Not verified: the Hermes, JSC and QuickJS bridge builds, whose only change is one added
#include. TypeScript was not type-checked, and nothing was run on a physical device.Merge Danger
Door: one-way, for the metadata format.
The format version goes from 1 to 2. New runtimes read both versions. An older runtime reading v2 metadata exits with "Invalid metadata header version". Metadata is generated by the same package or runtime that reads it, so mixing only happens with a hand-copied
.nsmd.Blast Radius: enum globals on iOS/macOS
Center) breaks. It must useNSTextAlignment.CenterorNSTextAlignmentCenter.Enum[value]can now return the C name instead of the short name.