@@ -5,8 +5,14 @@ type NativeApiHost = {
55 classNames ?: ( ) => string [ ] ;
66 functionNames ?: ( ) => string [ ] ;
77 constantNames ?: ( ) => string [ ] ;
8+ protocolNames ?: ( ) => string [ ] ;
89 enumNames ?: ( ) => string [ ] ;
10+ structNames ?: ( ) => string [ ] ;
11+ unionNames ?: ( ) => string [ ] ;
912 } ;
13+ getProtocol ?: ( name : string ) => unknown ;
14+ getStruct ?: ( name : string ) => unknown ;
15+ getUnion ?: ( name : string ) => unknown ;
1016 runOnUI ?: ( callback ?: ( ) => void ) => Promise < void > ;
1117 [ name : string ] : unknown ;
1218} ;
@@ -34,24 +40,131 @@ function requireNativeApiHost(): NativeApiHost {
3440function defineLazyNativeGlobal (
3541 name : string ,
3642 resolve : ( name : string ) => unknown ,
43+ force = false ,
3744) {
38- if ( ! name || name in globalThis ) {
45+ if ( ! name || ( ! force && Object . prototype . hasOwnProperty . call ( globalThis , name ) ) ) {
3946 return ;
4047 }
4148
42- Object . defineProperty ( globalThis , name , {
43- configurable : true ,
44- enumerable : false ,
45- get ( ) {
46- const value = resolve ( name ) ;
49+ try {
50+ Object . defineProperty ( globalThis , name , {
51+ configurable : true ,
52+ enumerable : false ,
53+ get ( ) {
54+ const value = resolve ( name ) ;
55+ Object . defineProperty ( globalThis , name , {
56+ configurable : true ,
57+ enumerable : false ,
58+ writable : false ,
59+ value,
60+ } ) ;
61+ return value ;
62+ } ,
63+ } ) ;
64+ } catch {
65+ const value = resolve ( name ) ;
66+ if ( value !== undefined ) {
4767 Object . defineProperty ( globalThis , name , {
4868 configurable : true ,
4969 enumerable : false ,
5070 writable : false ,
5171 value,
5272 } ) ;
53- return value ;
54- } ,
73+ }
74+ }
75+ }
76+
77+ function wrapAggregateConstructor ( nativeConstructor : unknown ) : unknown {
78+ if ( typeof nativeConstructor !== 'function' ) {
79+ return nativeConstructor ;
80+ }
81+
82+ const aggregate = function NativeScriptAggregate ( initialValue ?: unknown ) {
83+ return nativeConstructor ( initialValue ) ;
84+ } ;
85+
86+ for ( const key of [ 'kind' , 'runtimeName' , 'metadataOffset' , 'sizeof' , 'fields' ] ) {
87+ try {
88+ Object . defineProperty ( aggregate , key , {
89+ configurable : true ,
90+ enumerable : false ,
91+ writable : false ,
92+ value : ( nativeConstructor as Record < string , unknown > ) [ key ] ,
93+ } ) ;
94+ } catch {
95+ // Best effort metadata copy for runtimes with stricter function objects.
96+ }
97+ }
98+
99+ return aggregate ;
100+ }
101+
102+ function wrapInteropFactory (
103+ nativeFactory : unknown ,
104+ properties : Record < string , unknown > ,
105+ ) : unknown {
106+ if ( typeof nativeFactory !== 'function' ) {
107+ return nativeFactory ;
108+ }
109+
110+ if ( ( nativeFactory as Record < string , unknown > ) . __nativeScriptConstructable ) {
111+ return nativeFactory ;
112+ }
113+
114+ const constructable = function NativeScriptInteropValue ( ...args : unknown [ ] ) {
115+ return ( nativeFactory as ( ...args : unknown [ ] ) => unknown ) ( ...args ) ;
116+ } ;
117+
118+ for ( const [ key , value ] of Object . entries ( properties ) ) {
119+ try {
120+ Object . defineProperty ( constructable , key , {
121+ configurable : true ,
122+ enumerable : false ,
123+ writable : false ,
124+ value,
125+ } ) ;
126+ } catch {
127+ // Best effort metadata copy for runtimes with stricter function objects.
128+ }
129+ }
130+
131+ Object . defineProperty ( constructable , '__nativeScriptConstructable' , {
132+ configurable : false ,
133+ enumerable : false ,
134+ writable : false ,
135+ value : true ,
136+ } ) ;
137+
138+ return constructable ;
139+ }
140+
141+ function installInteropConstructors ( ) : void {
142+ const interop = ( globalThis as Record < string , unknown > ) . interop as
143+ | Record < string , unknown >
144+ | undefined ;
145+ if ( ! interop || typeof interop !== 'object' ) {
146+ return ;
147+ }
148+
149+ const sizeof = interop . sizeof ;
150+ const pointerType = ( interop . types as Record < string , unknown > | undefined )
151+ ?. pointer ;
152+ let pointerSize : unknown = undefined ;
153+ if ( typeof sizeof === 'function' && pointerType !== undefined ) {
154+ try {
155+ pointerSize = sizeof ( pointerType ) ;
156+ } catch {
157+ pointerSize = undefined ;
158+ }
159+ }
160+
161+ interop . Pointer = wrapInteropFactory ( interop . Pointer , {
162+ kind : 'pointer' ,
163+ sizeof : pointerSize ,
164+ } ) ;
165+ interop . Reference = wrapInteropFactory ( interop . Reference , {
166+ kind : 'reference' ,
167+ sizeof : pointerSize ,
55168 } ) ;
56169}
57170
@@ -76,11 +189,39 @@ export function installGlobals(): boolean {
76189 defineLazyNativeGlobal ( name , ( constantName ) => api [ constantName ] ) ;
77190 }
78191
192+ const protocolNames = api . metadata ?. protocolNames ?.( ) ?? [ ] ;
193+ for ( const name of protocolNames ) {
194+ defineLazyNativeGlobal (
195+ name ,
196+ ( protocolName ) => api . getProtocol ?.( protocolName ) ?? api [ protocolName ] ,
197+ ) ;
198+ }
199+
79200 const enumNames = api . metadata ?. enumNames ?.( ) ?? [ ] ;
80201 for ( const name of enumNames ) {
81202 defineLazyNativeGlobal ( name , ( enumName ) => api [ enumName ] ) ;
82203 }
83204
205+ const structNames = api . metadata ?. structNames ?.( ) ?? [ ] ;
206+ for ( const name of structNames ) {
207+ defineLazyNativeGlobal (
208+ name ,
209+ ( structName ) =>
210+ wrapAggregateConstructor ( api . getStruct ?.( structName ) ?? api [ structName ] ) ,
211+ true ,
212+ ) ;
213+ }
214+
215+ const unionNames = api . metadata ?. unionNames ?.( ) ?? [ ] ;
216+ for ( const name of unionNames ) {
217+ defineLazyNativeGlobal (
218+ name ,
219+ ( unionName ) =>
220+ wrapAggregateConstructor ( api . getUnion ?.( unionName ) ?? api [ unionName ] ) ,
221+ true ,
222+ ) ;
223+ }
224+
84225 return true ;
85226}
86227
@@ -89,6 +230,9 @@ export function init(
89230 options : InstallOptions = { } ,
90231) : boolean {
91232 const installed = NativeScriptNativeApi . install ( metadataPath ) ;
233+ if ( installed ) {
234+ installInteropConstructors ( ) ;
235+ }
92236 if ( installed && options . globals !== false ) {
93237 installGlobals ( ) ;
94238 }
0 commit comments