Skip to content

Commit d13c994

Browse files
committed
BridgeJS: Register core generic type handles in JavaScriptKit
1 parent c58ffa4 commit d13c994

105 files changed

Lines changed: 201 additions & 558 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Benchmarks/Sources/Generated/BridgeJS.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2275,21 +2275,6 @@ fileprivate func _bjs_Benchmarks_register_type_handles_extern(_ base: UnsafePoin
22752275
@_expose(wasm, "bjs_Benchmarks_register_type_handles")
22762276
public func _bjs_Benchmarks_register_type_handles() {
22772277
let typeIds: [Int32] = [
2278-
Bool.bridgeJSTypeID,
2279-
Int.bridgeJSTypeID,
2280-
Int8.bridgeJSTypeID,
2281-
UInt8.bridgeJSTypeID,
2282-
Int16.bridgeJSTypeID,
2283-
UInt16.bridgeJSTypeID,
2284-
Int32.bridgeJSTypeID,
2285-
UInt32.bridgeJSTypeID,
2286-
UInt.bridgeJSTypeID,
2287-
Int64.bridgeJSTypeID,
2288-
UInt64.bridgeJSTypeID,
2289-
Float.bridgeJSTypeID,
2290-
Double.bridgeJSTypeID,
2291-
String.bridgeJSTypeID,
2292-
JSValue.bridgeJSTypeID,
22932278
SimpleStruct.bridgeJSTypeID,
22942279
Address.bridgeJSTypeID,
22952280
Person.bridgeJSTypeID,

Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -295,21 +295,6 @@ fileprivate func _bjs_PlayBridgeJS_register_type_handles_extern(_ base: UnsafePo
295295
@_expose(wasm, "bjs_PlayBridgeJS_register_type_handles")
296296
public func _bjs_PlayBridgeJS_register_type_handles() {
297297
let typeIds: [Int32] = [
298-
Bool.bridgeJSTypeID,
299-
Int.bridgeJSTypeID,
300-
Int8.bridgeJSTypeID,
301-
UInt8.bridgeJSTypeID,
302-
Int16.bridgeJSTypeID,
303-
UInt16.bridgeJSTypeID,
304-
Int32.bridgeJSTypeID,
305-
UInt32.bridgeJSTypeID,
306-
UInt.bridgeJSTypeID,
307-
Int64.bridgeJSTypeID,
308-
UInt64.bridgeJSTypeID,
309-
Float.bridgeJSTypeID,
310-
Double.bridgeJSTypeID,
311-
String.bridgeJSTypeID,
312-
JSValue.bridgeJSTypeID,
313298
PlayBridgeJSOutput.bridgeJSTypeID,
314299
PlayBridgeJSDiagnostic.bridgeJSTypeID,
315300
PlayBridgeJSResult.bridgeJSTypeID,

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,10 @@ struct GenericConformanceCodegen {
908908
/// registered type's `bridgeJSTypeID` into a buffer, in the canonical order of
909909
/// `BridgeJSSkeleton.typeRegistrationEntries`, and passes it to the JS import
910910
/// hook of the same name, which pairs the IDs with its codec array by index.
911+
///
912+
/// Only the module's own `@JS` types are listed; the core (primitive) handles are
913+
/// registered once by the JavaScriptKit library itself
914+
/// (`_bjs_core_register_type_handles`).
911915
public struct GenericTypeRegistrationCodegen {
912916
public init() {}
913917

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,11 @@ public struct BridgeJSLink {
348348
declarations.append(" return;")
349349
declarations.append(" }")
350350
declarations.append(" __bjs_typeHandlesRegistered = true;")
351+
// The core (primitive) handles live in the JavaScriptKit library, so
352+
// they are registered once here rather than by every module.
353+
declarations.append(
354+
" \(JSGlueVariableScope.reservedInstance).exports[\"\(ABINameGenerator.coreTypeRegistrationFunctionName)\"]();"
355+
)
351356
for skeleton in skeletons {
352357
guard skeleton.typeRegistrationEntries != nil else { continue }
353358
let name = ABINameGenerator.typeRegistrationFunctionName(moduleName: skeleton.moduleName)
@@ -426,46 +431,70 @@ public struct BridgeJSLink {
426431
)
427432
}
428433

434+
/// Pairs the type IDs Swift pushed with codecs in the matching skeleton order.
435+
private func writeTypeHandleRegistrationBody(into printer: CodeFragmentPrinter) {
436+
printer.write(
437+
"const typeIds = new Int32Array(\(JSGlueVariableScope.reservedMemory).buffer, base >>> 0, count >>> 0);"
438+
)
439+
printer.write("for (let i = 0; i < count; i++) {")
440+
printer.indent {
441+
printer.write("\(JSGlueVariableScope.reservedCodecByTypeId).set(typeIds[i], codecs[i]);")
442+
}
443+
printer.write("}")
444+
}
445+
446+
/// Installs the `bjs_core_register_type_handles` hook. The core handles are
447+
/// owned by the JavaScriptKit library rather than by generated code, so the
448+
/// wasm import exists in every binary that links JavaScriptKit and the hook
449+
/// is always installed; without generics anywhere in the build it is a no-op
450+
/// and the registration export is never called.
451+
private func generateCoreTypeRegistrationHook(into printer: CodeFragmentPrinter) throws {
452+
let hookName = ABINameGenerator.coreTypeRegistrationFunctionName
453+
guard hasGenerics else {
454+
printer.write("bjs[\"\(hookName)\"] = function() {};")
455+
return
456+
}
457+
try ContainerCodecJS.registerPrimitiveCodecs(context: makeCodecPrintContext(printer: printer))
458+
printer.write("bjs[\"\(hookName)\"] = function(base, count) {")
459+
printer.indent {
460+
// Same canonical order as `_bjs_core_register_type_handles` in the
461+
// JavaScriptKit library.
462+
printer.write("const codecs = [")
463+
printer.indent {
464+
for primitive in BridgeType.genericBridgeablePrimitives {
465+
printer.write("\(JSGlueVariableScope.reservedPrimitiveCodecs).\(primitive.token),")
466+
}
467+
}
468+
printer.write("];")
469+
writeTypeHandleRegistrationBody(into: printer)
470+
}
471+
printer.write("}")
472+
}
473+
429474
/// Installs the per-module `bjs_<Module>_register_type_handles` import
430475
/// hooks. A module with a registration function always carries the wasm
431476
/// import, so a hook is always installed; without generics anywhere in the
432477
/// build it is a no-op and the registration export is never called.
433478
private func generateTypeRegistrationHooks(into printer: CodeFragmentPrinter) throws {
479+
try generateCoreTypeRegistrationHook(into: printer)
434480
for skeleton in skeletons {
435-
guard skeleton.typeRegistrationEntries != nil else { continue }
481+
guard let moduleEntries = skeleton.typeRegistrationEntries else { continue }
436482
let hookName = ABINameGenerator.typeRegistrationFunctionName(moduleName: skeleton.moduleName)
437483
guard hasGenerics else {
438484
printer.write("bjs[\"\(hookName)\"] = function() {};")
439485
continue
440486
}
441-
// The hooks resolve type IDs against the shared primitive codec table.
442-
try ContainerCodecJS.registerPrimitiveCodecs(context: makeCodecPrintContext(printer: printer))
443-
let moduleEntries = skeleton.exported?.genericBridgeableTypeEntries ?? []
444487
printer.write("bjs[\"\(hookName)\"] = function(base, count) {")
445488
try printer.indent {
446-
// Same canonical order as the Swift registration function:
447-
// primitives first, then the module's own types.
489+
// Same order as the module's Swift registration function.
448490
printer.write("const codecs = [")
449-
printer.indent {
450-
for primitive in BridgeType.genericBridgeablePrimitives {
451-
printer.write("\(JSGlueVariableScope.reservedPrimitiveCodecs).\(primitive.token),")
452-
}
453-
}
454-
printer.write("].concat([")
455491
try printer.indent {
456492
for entry in moduleEntries {
457493
try appendGenericCodecLiteral(type: entry.bridgeType, into: printer)
458494
}
459495
}
460-
printer.write("]);")
461-
printer.write(
462-
"const typeIds = new Int32Array(\(JSGlueVariableScope.reservedMemory).buffer, base >>> 0, count >>> 0);"
463-
)
464-
printer.write("for (let i = 0; i < count; i++) {")
465-
printer.indent {
466-
printer.write("\(JSGlueVariableScope.reservedCodecByTypeId).set(typeIds[i], codecs[i]);")
467-
}
468-
printer.write("}")
496+
printer.write("];")
497+
writeTypeHandleRegistrationBody(into: printer)
469498
}
470499
printer.write("}")
471500
}

Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ public struct ABINameGenerator {
3232
"bjs_\(moduleName)_register_type_handles"
3333
}
3434

35+
/// Name of the core type-handle registration function. Unlike the per-module
36+
/// ones, this is defined once in the JavaScriptKit library (see
37+
/// `_bjs_core_register_type_handles` in `BridgeJSIntrinsics.swift`) so the
38+
/// primitive handles exist exactly once in the final binary and the JS glue
39+
/// registers their codecs once per linked bundle.
40+
public static let coreTypeRegistrationFunctionName = "bjs_core_register_type_handles"
41+
3542
/// Generates ABI name using standardized namespace + context pattern
3643
public static func generateABIName(
3744
baseName: String,
@@ -383,17 +390,17 @@ extension ExportedSkeleton {
383390

384391
extension BridgeJSSkeleton {
385392
/// The ordered list of types this module registers type handles for, or
386-
/// `nil` when it emits no registration function. Primitive handles are
387-
/// library singletons, so every module re-registering them writes the same
388-
/// ID-to-codec pair, and a pure-import build still gets a populated table.
393+
/// `nil` when it emits no registration function.
394+
///
395+
/// Only the module's own `@JS` types appear here: the core (primitive)
396+
/// handles are owned by the JavaScriptKit library, which registers them once
397+
/// for the whole binary via ``ABINameGenerator/coreTypeRegistrationFunctionName``.
398+
/// A module that only *uses* generics therefore needs no registration
399+
/// function of its own.
389400
public var typeRegistrationEntries: [GenericBridgeableTypeEntry]? {
390401
let exportedEntries = exported?.genericBridgeableTypeEntries ?? []
391-
let hasGenericImports = imported?.hasGenericDeclarations ?? false
392-
guard !exportedEntries.isEmpty || hasGenericImports else { return nil }
393-
let primitives = BridgeType.genericBridgeablePrimitives.map {
394-
GenericBridgeableTypeEntry(swiftName: $0.token, bridgeType: $0.type)
395-
}
396-
return primitives + exportedEntries
402+
guard !exportedEntries.isEmpty else { return nil }
403+
return exportedEntries
397404
}
398405
}
399406

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Alias.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -415,21 +415,6 @@ fileprivate func _bjs_TestModule_register_type_handles_extern(_ base: UnsafePoin
415415
@_expose(wasm, "bjs_TestModule_register_type_handles")
416416
public func _bjs_TestModule_register_type_handles() {
417417
let typeIds: [Int32] = [
418-
Bool.bridgeJSTypeID,
419-
Int.bridgeJSTypeID,
420-
Int8.bridgeJSTypeID,
421-
UInt8.bridgeJSTypeID,
422-
Int16.bridgeJSTypeID,
423-
UInt16.bridgeJSTypeID,
424-
Int32.bridgeJSTypeID,
425-
UInt32.bridgeJSTypeID,
426-
UInt.bridgeJSTypeID,
427-
Int64.bridgeJSTypeID,
428-
UInt64.bridgeJSTypeID,
429-
Float.bridgeJSTypeID,
430-
Double.bridgeJSTypeID,
431-
String.bridgeJSTypeID,
432-
JSValue.bridgeJSTypeID,
433418
PolygonReference.bridgeJSTypeID,
434419
TagReference.bridgeJSTypeID,
435420
InnerTag.bridgeJSTypeID,

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AliasInClosure.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -200,21 +200,6 @@ fileprivate func _bjs_TestModule_register_type_handles_extern(_ base: UnsafePoin
200200
@_expose(wasm, "bjs_TestModule_register_type_handles")
201201
public func _bjs_TestModule_register_type_handles() {
202202
let typeIds: [Int32] = [
203-
Bool.bridgeJSTypeID,
204-
Int.bridgeJSTypeID,
205-
Int8.bridgeJSTypeID,
206-
UInt8.bridgeJSTypeID,
207-
Int16.bridgeJSTypeID,
208-
UInt16.bridgeJSTypeID,
209-
Int32.bridgeJSTypeID,
210-
UInt32.bridgeJSTypeID,
211-
UInt.bridgeJSTypeID,
212-
Int64.bridgeJSTypeID,
213-
UInt64.bridgeJSTypeID,
214-
Float.bridgeJSTypeID,
215-
Double.bridgeJSTypeID,
216-
String.bridgeJSTypeID,
217-
JSValue.bridgeJSTypeID,
218203
PolygonReference.bridgeJSTypeID,
219204
]
220205
typeIds.withUnsafeBufferPointer { buffer in

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -664,21 +664,6 @@ fileprivate func _bjs_TestModule_register_type_handles_extern(_ base: UnsafePoin
664664
@_expose(wasm, "bjs_TestModule_register_type_handles")
665665
public func _bjs_TestModule_register_type_handles() {
666666
let typeIds: [Int32] = [
667-
Bool.bridgeJSTypeID,
668-
Int.bridgeJSTypeID,
669-
Int8.bridgeJSTypeID,
670-
UInt8.bridgeJSTypeID,
671-
Int16.bridgeJSTypeID,
672-
UInt16.bridgeJSTypeID,
673-
Int32.bridgeJSTypeID,
674-
UInt32.bridgeJSTypeID,
675-
UInt.bridgeJSTypeID,
676-
Int64.bridgeJSTypeID,
677-
UInt64.bridgeJSTypeID,
678-
Float.bridgeJSTypeID,
679-
Double.bridgeJSTypeID,
680-
String.bridgeJSTypeID,
681-
JSValue.bridgeJSTypeID,
682667
Point.bridgeJSTypeID,
683668
Direction.bridgeJSTypeID,
684669
Status.bridgeJSTypeID,

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -734,21 +734,6 @@ fileprivate func _bjs_TestModule_register_type_handles_extern(_ base: UnsafePoin
734734
@_expose(wasm, "bjs_TestModule_register_type_handles")
735735
public func _bjs_TestModule_register_type_handles() {
736736
let typeIds: [Int32] = [
737-
Bool.bridgeJSTypeID,
738-
Int.bridgeJSTypeID,
739-
Int8.bridgeJSTypeID,
740-
UInt8.bridgeJSTypeID,
741-
Int16.bridgeJSTypeID,
742-
UInt16.bridgeJSTypeID,
743-
Int32.bridgeJSTypeID,
744-
UInt32.bridgeJSTypeID,
745-
UInt.bridgeJSTypeID,
746-
Int64.bridgeJSTypeID,
747-
UInt64.bridgeJSTypeID,
748-
Float.bridgeJSTypeID,
749-
Double.bridgeJSTypeID,
750-
String.bridgeJSTypeID,
751-
JSValue.bridgeJSTypeID,
752737
AsyncPoint.bridgeJSTypeID,
753738
AsyncDirection.bridgeJSTypeID,
754739
AsyncTheme.bridgeJSTypeID,

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -126,21 +126,6 @@ fileprivate func _bjs_TestModule_register_type_handles_extern(_ base: UnsafePoin
126126
@_expose(wasm, "bjs_TestModule_register_type_handles")
127127
public func _bjs_TestModule_register_type_handles() {
128128
let typeIds: [Int32] = [
129-
Bool.bridgeJSTypeID,
130-
Int.bridgeJSTypeID,
131-
Int8.bridgeJSTypeID,
132-
UInt8.bridgeJSTypeID,
133-
Int16.bridgeJSTypeID,
134-
UInt16.bridgeJSTypeID,
135-
Int32.bridgeJSTypeID,
136-
UInt32.bridgeJSTypeID,
137-
UInt.bridgeJSTypeID,
138-
Int64.bridgeJSTypeID,
139-
UInt64.bridgeJSTypeID,
140-
Float.bridgeJSTypeID,
141-
Double.bridgeJSTypeID,
142-
String.bridgeJSTypeID,
143-
JSValue.bridgeJSTypeID,
144129
AsyncPayloadResult.bridgeJSTypeID,
145130
]
146131
typeIds.withUnsafeBufferPointer { buffer in

0 commit comments

Comments
 (0)