Skip to content

Commit 89deed0

Browse files
committed
refactor: Move identityMode to bridge-js.config.json following exposeToGlobal pattern
Add identityMode field to BridgeJSConfig, flow through SwiftToSkeleton and ExportedSkeleton to BridgeJSLink. Generated JS uses config value as default with runtime option as override via nullish coalescing. Create dedicated BridgeJSIdentityTests target with identityMode: pointer in its bridge-js.config.json. Remove IDENTITY_MODE env var, instantiateOptions spread from prelude.mjs, and unittest-pointer Makefile target. Identity tests now run as part of the normal test suite.
1 parent df960e6 commit 89deed0

62 files changed

Lines changed: 35259 additions & 917 deletions

Some content is hidden

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

Makefile

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,6 @@ unittest:
2121
--disable-sandbox \
2222
js test --prelude ./Tests/prelude.mjs -Xnode --expose-gc
2323

24-
.PHONY: unittest-pointer
25-
unittest-pointer:
26-
@echo Running unit tests with identityMode=pointer
27-
@test -n "$(SWIFT_SDK_ID)" || { \
28-
echo "SWIFT_SDK_ID is not set. Run 'swift sdk list' and pass a matching SDK, e.g. 'make unittest-pointer SWIFT_SDK_ID=<id>'."; \
29-
exit 2; \
30-
}
31-
IDENTITY_MODE=pointer swift package --swift-sdk "$(SWIFT_SDK_ID)" \
32-
$(TRACING_ARGS) \
33-
--disable-sandbox \
34-
js test --prelude ./Tests/prelude.mjs -Xnode --expose-gc
35-
3624
.PHONY: regenerate_swiftpm_resources
3725
regenerate_swiftpm_resources:
3826
npm run build

Package.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,5 +217,17 @@ let package = Package(
217217
],
218218
linkerSettings: testingLinkerFlags
219219
),
220+
.testTarget(
221+
name: "BridgeJSIdentityTests",
222+
dependencies: ["JavaScriptKit", "JavaScriptEventLoop"],
223+
exclude: [
224+
"bridge-js.config.json",
225+
"Generated/JavaScript",
226+
],
227+
swiftSettings: [
228+
.enableExperimentalFeature("Extern")
229+
],
230+
linkerSettings: testingLinkerFlags
231+
),
220232
]
221233
)

Package@swift-6.1.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,5 +206,17 @@ let package = Package(
206206
],
207207
linkerSettings: testingLinkerFlags
208208
),
209+
.testTarget(
210+
name: "BridgeJSIdentityTests",
211+
dependencies: ["JavaScriptKit", "JavaScriptEventLoop"],
212+
exclude: [
213+
"bridge-js.config.json",
214+
"Generated/JavaScript",
215+
],
216+
swiftSettings: [
217+
.enableExperimentalFeature("Extern")
218+
],
219+
linkerSettings: testingLinkerFlags
220+
),
209221
]
210222
)

Plugins/BridgeJS/Sources/BridgeJSCore/Misc.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,20 +342,32 @@ public struct BridgeJSConfig: Codable {
342342
/// Default: `false`
343343
public var exposeToGlobal: Bool
344344

345-
public init(tools: [String: String]? = nil, exposeToGlobal: Bool = false) {
345+
/// The identity mode to use for exported Swift heap objects.
346+
///
347+
/// When `"pointer"`, Swift heap objects are tracked by pointer identity,
348+
/// enabling identity-based caching. When `"none"` or `nil`, no identity
349+
/// tracking is performed.
350+
///
351+
/// Default: `nil` (treated as `"none"`)
352+
public var identityMode: String?
353+
354+
public init(tools: [String: String]? = nil, exposeToGlobal: Bool = false, identityMode: String? = nil) {
346355
self.tools = tools
347356
self.exposeToGlobal = exposeToGlobal
357+
self.identityMode = identityMode
348358
}
349359

350360
enum CodingKeys: String, CodingKey {
351361
case tools
352362
case exposeToGlobal
363+
case identityMode
353364
}
354365

355366
public init(from decoder: Decoder) throws {
356367
let container = try decoder.container(keyedBy: CodingKeys.self)
357368
tools = try container.decodeIfPresent([String: String].self, forKey: .tools)
358369
exposeToGlobal = try container.decodeIfPresent(Bool.self, forKey: .exposeToGlobal) ?? false
370+
identityMode = try container.decodeIfPresent(String.self, forKey: .identityMode)
359371
}
360372

361373
/// Load the configuration file from the SwiftPM package target directory.
@@ -398,7 +410,8 @@ public struct BridgeJSConfig: Codable {
398410
func merging(overrides: BridgeJSConfig) -> BridgeJSConfig {
399411
return BridgeJSConfig(
400412
tools: (tools ?? [:]).merging(overrides.tools ?? [:], uniquingKeysWith: { $1 }),
401-
exposeToGlobal: overrides.exposeToGlobal
413+
exposeToGlobal: overrides.exposeToGlobal,
414+
identityMode: overrides.identityMode ?? identityMode
402415
)
403416
}
404417
}

Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@ public final class SwiftToSkeleton {
1616
public let progress: ProgressReporting
1717
public let moduleName: String
1818
public let exposeToGlobal: Bool
19+
public let identityMode: String?
1920

2021
private var sourceFiles: [(sourceFile: SourceFileSyntax, inputFilePath: String)] = []
2122
let typeDeclResolver: TypeDeclResolver
2223

23-
public init(progress: ProgressReporting, moduleName: String, exposeToGlobal: Bool) {
24+
public init(progress: ProgressReporting, moduleName: String, exposeToGlobal: Bool, identityMode: String? = nil) {
2425
self.progress = progress
2526
self.moduleName = moduleName
2627
self.exposeToGlobal = exposeToGlobal
28+
self.identityMode = identityMode
2729
self.typeDeclResolver = TypeDeclResolver()
2830

2931
// Index known types provided by JavaScriptKit
@@ -42,7 +44,7 @@ public final class SwiftToSkeleton {
4244
public func finalize() throws -> BridgeJSSkeleton {
4345
var perSourceErrors: [(inputFilePath: String, errors: [DiagnosticError])] = []
4446
var importedFiles: [ImportedFileSkeleton] = []
45-
var exported = ExportedSkeleton(functions: [], classes: [], enums: [], exposeToGlobal: exposeToGlobal)
47+
var exported = ExportedSkeleton(functions: [], classes: [], enums: [], exposeToGlobal: exposeToGlobal, identityMode: identityMode)
4648
var exportCollectors: [ExportSwiftAPICollector] = []
4749

4850
for (sourceFile, inputFilePath) in sourceFiles {

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,8 @@ public struct BridgeJSLink {
983983

984984
try printer.indent {
985985
printer.write(lines: generateVariableDeclarations())
986-
printer.write("const identityMode = options.identityMode === \"pointer\" ? \"pointer\" : \"none\";")
986+
let configIdentityMode = skeletons.compactMap(\.exported).first?.identityMode ?? "none"
987+
printer.write("const identityMode = options.identityMode ?? \"\(configIdentityMode)\";")
987988
printer.write(
988989
"const shouldUseIdentityMap = identityMode === \"pointer\" && typeof WeakRef !== \"undefined\" && typeof FinalizationRegistry !== \"undefined\";"
989990
)

Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,20 +890,28 @@ public struct ExportedSkeleton: Codable {
890890
/// through the exports object.
891891
public var exposeToGlobal: Bool
892892

893+
/// The identity mode for exported Swift heap objects.
894+
///
895+
/// When `"pointer"`, Swift heap objects are tracked by pointer identity.
896+
/// When `"none"` or `nil`, no identity tracking is performed.
897+
public var identityMode: String?
898+
893899
public init(
894900
functions: [ExportedFunction],
895901
classes: [ExportedClass],
896902
enums: [ExportedEnum],
897903
structs: [ExportedStruct] = [],
898904
protocols: [ExportedProtocol] = [],
899-
exposeToGlobal: Bool
905+
exposeToGlobal: Bool,
906+
identityMode: String? = nil
900907
) {
901908
self.functions = functions
902909
self.classes = classes
903910
self.enums = enums
904911
self.structs = structs
905912
self.protocols = protocols
906913
self.exposeToGlobal = exposeToGlobal
914+
self.identityMode = identityMode
907915
}
908916

909917
public mutating func append(_ other: ExportedSkeleton) {
@@ -913,6 +921,7 @@ public struct ExportedSkeleton: Codable {
913921
self.structs.append(contentsOf: other.structs)
914922
self.protocols.append(contentsOf: other.protocols)
915923
assert(self.exposeToGlobal == other.exposeToGlobal)
924+
assert(self.identityMode == other.identityMode)
916925
}
917926

918927
public var isEmpty: Bool {

Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ import BridgeJSUtilities
165165
let swiftToSkeleton = SwiftToSkeleton(
166166
progress: progress,
167167
moduleName: moduleName,
168-
exposeToGlobal: config.exposeToGlobal
168+
exposeToGlobal: config.exposeToGlobal,
169+
identityMode: config.identityMode
169170
)
170171
for inputFile in inputFiles.sorted() {
171172
try withSpan("Parsing \(inputFile)") {

Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSLinkTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ import Testing
124124

125125
#expect(outputDts.contains("identityMode?: \"none\" | \"pointer\";"))
126126
#expect(
127-
outputJs.contains("const identityMode = options.identityMode === \"pointer\" ? \"pointer\" : \"none\";")
127+
outputJs.contains("const identityMode = options.identityMode ?? \"none\";")
128128
)
129129
#expect(
130130
outputJs.contains(

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export async function createInstantiator(options, swift) {
4343

4444
let _exports = null;
4545
let bjs = null;
46-
const identityMode = options.identityMode === "pointer" ? "pointer" : "none";
46+
const identityMode = options.identityMode ?? "none";
4747
const shouldUseIdentityMap = identityMode === "pointer" && typeof WeakRef !== "undefined" && typeof FinalizationRegistry !== "undefined";
4848
const __bjs_createPointHelpers = () => ({
4949
lower: (value) => {

0 commit comments

Comments
 (0)