Skip to content

Commit 7fe9b5b

Browse files
committed
BridgeJS: Basic properties setup
1 parent 8cad280 commit 7fe9b5b

27 files changed

+3429
-188
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 211 additions & 45 deletions
Large diffs are not rendered by default.

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 380 additions & 99 deletions
Large diffs are not rendered by default.

Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,15 @@ struct IntrinsicJSFragment: Sendable {
536536
printer.write("\(caseName): \(index),")
537537
}
538538
}
539-
printer.write("}")
539+
printer.write("},")
540+
541+
for function in enumDefinition.staticMethods {
542+
printer.write("\(function.name): null,")
543+
}
544+
545+
for property in enumDefinition.staticProperties {
546+
printer.write("\(property.name): null,")
547+
}
540548
}
541549
printer.write("};")
542550
printer.nextLine()
@@ -625,6 +633,14 @@ struct IntrinsicJSFragment: Sendable {
625633
let caseName = enumCase.name.capitalizedFirstLetter
626634
printer.write("\(caseName): \(index),")
627635
}
636+
637+
for function in enumDefinition.staticMethods {
638+
printer.write("\(function.name): null,")
639+
}
640+
641+
for property in enumDefinition.staticProperties {
642+
printer.write("\(property.name): null,")
643+
}
628644
}
629645
printer.write("};")
630646
printer.nextLine()
@@ -651,6 +667,14 @@ struct IntrinsicJSFragment: Sendable {
651667

652668
printer.write("\(caseName): \(formattedValue),")
653669
}
670+
671+
for function in enumDefinition.staticMethods {
672+
printer.write("\(function.name): null,")
673+
}
674+
675+
for property in enumDefinition.staticProperties {
676+
printer.write("\(property.name): null,")
677+
}
654678
}
655679
printer.write("};")
656680
printer.nextLine()

Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ public struct ExportedEnum: Codable, Equatable, Sendable {
136136
public let namespace: [String]?
137137
public let emitStyle: EnumEmitStyle
138138
public var staticMethods: [ExportedFunction]
139+
public var staticProperties: [ExportedProperty] = []
139140
public var enumType: EnumType {
140141
if cases.isEmpty {
141142
return .namespace
@@ -154,7 +155,8 @@ public struct ExportedEnum: Codable, Equatable, Sendable {
154155
rawType: String?,
155156
namespace: [String]?,
156157
emitStyle: EnumEmitStyle,
157-
staticMethods: [ExportedFunction] = []
158+
staticMethods: [ExportedFunction] = [],
159+
staticProperties: [ExportedProperty] = []
158160
) {
159161
self.name = name
160162
self.swiftCallName = swiftCallName
@@ -164,6 +166,7 @@ public struct ExportedEnum: Codable, Equatable, Sendable {
164166
self.namespace = namespace
165167
self.emitStyle = emitStyle
166168
self.staticMethods = staticMethods
169+
self.staticProperties = staticProperties
167170
}
168171
}
169172

@@ -246,23 +249,65 @@ public struct ExportedConstructor: Codable {
246249
}
247250
}
248251

249-
public struct ExportedProperty: Codable {
252+
public struct ExportedProperty: Codable, Equatable, Sendable {
250253
public var name: String
251254
public var type: BridgeType
252255
public var isReadonly: Bool
256+
public var isStatic: Bool = false
257+
public var staticContext: StaticContext?
253258

254-
public init(name: String, type: BridgeType, isReadonly: Bool = false) {
259+
public init(name: String, type: BridgeType, isReadonly: Bool = false, isStatic: Bool = false, staticContext: StaticContext? = nil) {
255260
self.name = name
256261
self.type = type
257262
self.isReadonly = isReadonly
263+
self.isStatic = isStatic
264+
self.staticContext = staticContext
258265
}
259266

260267
public func getterAbiName(className: String) -> String {
261-
return "bjs_\(className)_\(name)_get"
268+
if isStatic, let staticContext = staticContext {
269+
// Generate context-aware ABI names for static properties
270+
switch staticContext {
271+
case .className(let className):
272+
return "bjs_\(className)_static_\(name)_get"
273+
case .enumName(let enumName):
274+
return "bjs_\(enumName)_static_\(name)_get"
275+
case .namespaceEnum(let enumName):
276+
// Convert dots to underscores for namespace enums
277+
let abiEnumName = enumName.split(separator: ".").joined(separator: "_")
278+
return "bjs_\(abiEnumName)_static_\(name)_get"
279+
case .explicitNamespace(let namespace):
280+
let abiNamespace = namespace.joined(separator: "_")
281+
return "bjs_\(abiNamespace)_static_\(name)_get"
282+
}
283+
} else if isStatic {
284+
return "bjs_\(className)_static_\(name)_get"
285+
} else {
286+
return "bjs_\(className)_\(name)_get"
287+
}
262288
}
263289

264290
public func setterAbiName(className: String) -> String {
265-
return "bjs_\(className)_\(name)_set"
291+
if isStatic, let staticContext = staticContext {
292+
// Generate context-aware ABI names for static properties
293+
switch staticContext {
294+
case .className(let className):
295+
return "bjs_\(className)_static_\(name)_set"
296+
case .enumName(let enumName):
297+
return "bjs_\(enumName)_static_\(name)_set"
298+
case .namespaceEnum(let enumName):
299+
// Convert dots to underscores for namespace enums
300+
let abiEnumName = enumName.split(separator: ".").joined(separator: "_")
301+
return "bjs_\(abiEnumName)_static_\(name)_set"
302+
case .explicitNamespace(let namespace):
303+
let abiNamespace = namespace.joined(separator: "_")
304+
return "bjs_\(abiNamespace)_static_\(name)_set"
305+
}
306+
} else if isStatic {
307+
return "bjs_\(className)_static_\(name)_set"
308+
} else {
309+
return "bjs_\(className)_\(name)_set"
310+
}
266311
}
267312
}
268313

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
@JS class PropertyClass {
2+
@JS init() {}
3+
4+
@JS static let staticConstant: String = "constant"
5+
@JS static var staticVariable: Int = 42
6+
@JS static var jsObjectProperty: JSObject = JSObject()
7+
@JS class var classVariable: String = "overridable"
8+
9+
@JS static var computedProperty: String {
10+
get { return "\(staticVariable) computed" }
11+
set { staticVariable = newValue + 5 }
12+
}
13+
14+
@JS static var readOnlyComputed: Int {
15+
return 100
16+
}
17+
18+
@JS static var optionalProperty: String? = nil
19+
}
20+
21+
@JS enum PropertyEnum {
22+
case value1
23+
case value2
24+
25+
@JS static var enumProperty: String = "enum value"
26+
@JS static let enumConstant: Int = 42
27+
@JS static var computedEnum: String {
28+
get { return enumProperty + " computed" }
29+
set { enumProperty = newValue + " computed" }
30+
}
31+
}
32+
33+
@JS enum PropertyNamespace {
34+
@JS static var namespaceProperty: String = "namespace"
35+
@JS static let namespaceConstant: String = "constant"
36+
37+
@JS enum Nested {
38+
@JS nonisolated(unsafe) static var nestedProperty: Int = 999
39+
@JS static let nestedConstant: String = "nested"
40+
@JS nonisolated(unsafe) static var nestedDouble: Double = 1.414
41+
}
42+
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const APIResult = {
1212
Rate: 3,
1313
Precise: 4,
1414
Info: 5,
15-
}
15+
},
1616
};
1717

1818
const __bjs_createAPIResultHelpers = () => {
@@ -94,7 +94,7 @@ export const ComplexResult = {
9494
Coordinates: 3,
9595
Comprehensive: 4,
9696
Info: 5,
97-
}
97+
},
9898
};
9999

100100
const __bjs_createComplexResultHelpers = () => {
@@ -222,7 +222,7 @@ export const Result = {
222222
Success: 0,
223223
Failure: 1,
224224
Status: 2,
225-
}
225+
},
226226
};
227227

228228
const __bjs_createResultHelpers = () => {
@@ -293,7 +293,7 @@ export const NetworkingResult = {
293293
Tag: {
294294
Success: 0,
295295
Failure: 1,
296-
}
296+
},
297297
};
298298

299299
const __bjs_createNetworkingResultHelpers = () => {
@@ -347,7 +347,7 @@ export const APIOptionalResult = {
347347
Success: 0,
348348
Failure: 1,
349349
Status: 2,
350-
}
350+
},
351351
};
352352

353353
const __bjs_createAPIOptionalResultHelpers = () => {
@@ -651,7 +651,13 @@ export async function createInstantiator(options, swift) {
651651
/** @param {WebAssembly.Instance} instance */
652652
createExports: (instance) => {
653653
const js = swift.memory.heap;
654-
return {
654+
if (typeof globalThis.API === 'undefined') {
655+
globalThis.API = {};
656+
}
657+
if (typeof globalThis.Utilities === 'undefined') {
658+
globalThis.Utilities = {};
659+
}
660+
const exports = {
655661
handle: function bjs_handle(result) {
656662
const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.APIResult.lower(result);
657663
instance.exports.bjs_handle(resultCaseId);
@@ -782,6 +788,7 @@ export async function createInstantiator(options, swift) {
782788
return optResult;
783789
},
784790
};
791+
return exports;
785792
},
786793
}
787794
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,9 @@ export async function createInstantiator(options, swift) {
273273
instance.exports.bjs_TestServer_call(this.pointer, method);
274274
}
275275
}
276-
const exports = {
277-
Converter,
278-
HTTPServer,
279-
TestServer,
280-
};
276+
if (typeof globalThis.Configuration === 'undefined') {
277+
globalThis.Configuration = {};
278+
}
281279
if (typeof globalThis.Networking === 'undefined') {
282280
globalThis.Networking = {};
283281
}
@@ -293,6 +291,11 @@ export async function createInstantiator(options, swift) {
293291
if (typeof globalThis.Utils === 'undefined') {
294292
globalThis.Utils = {};
295293
}
294+
const exports = {
295+
Converter,
296+
HTTPServer,
297+
TestServer,
298+
};
296299
globalThis.Utils.Converter = exports.Converter;
297300
globalThis.Networking.API.HTTPServer = exports.HTTPServer;
298301
globalThis.Networking.APIV2.Internal.TestServer = exports.TestServer;

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -232,23 +232,6 @@ export async function createInstantiator(options, swift) {
232232
return ret;
233233
}
234234
}
235-
const exports = {
236-
Greeter,
237-
Converter,
238-
UUID,
239-
plainFunction: function bjs_plainFunction() {
240-
instance.exports.bjs_plainFunction();
241-
const ret = tmpRetString;
242-
tmpRetString = undefined;
243-
return ret;
244-
},
245-
namespacedFunction: function bjs_namespacedFunction() {
246-
instance.exports.bjs_namespacedFunction();
247-
const ret = tmpRetString;
248-
tmpRetString = undefined;
249-
return ret;
250-
},
251-
};
252235
if (typeof globalThis.MyModule === 'undefined') {
253236
globalThis.MyModule = {};
254237
}
@@ -267,6 +250,23 @@ export async function createInstantiator(options, swift) {
267250
if (typeof globalThis.__Swift.Foundation === 'undefined') {
268251
globalThis.__Swift.Foundation = {};
269252
}
253+
const exports = {
254+
Greeter,
255+
Converter,
256+
UUID,
257+
plainFunction: function bjs_plainFunction() {
258+
instance.exports.bjs_plainFunction();
259+
const ret = tmpRetString;
260+
tmpRetString = undefined;
261+
return ret;
262+
},
263+
namespacedFunction: function bjs_namespacedFunction() {
264+
instance.exports.bjs_namespacedFunction();
265+
const ret = tmpRetString;
266+
tmpRetString = undefined;
267+
return ret;
268+
},
269+
};
270270
globalThis.__Swift.Foundation.Greeter = exports.Greeter;
271271
globalThis.Utils.Converters.Converter = exports.Converter;
272272
globalThis.__Swift.Foundation.UUID = exports.UUID;

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const APIResult = {
1414
Tag: {
1515
Success: 0,
1616
Failure: 1,
17-
}
17+
},
1818
roundtrip: null,
1919
};
2020

@@ -256,17 +256,23 @@ export async function createInstantiator(options, swift) {
256256
return ret;
257257
}
258258
}
259+
if (typeof globalThis.Utils === 'undefined') {
260+
globalThis.Utils = {};
261+
}
262+
if (typeof globalThis.Utils.String === 'undefined') {
263+
globalThis.Utils.String = {};
264+
}
259265
Calculator.square = function(value) {
260266
const ret = instance.exports.bjs_Calculator_static_square(value);
261267
return ret;
262-
}
268+
};
263269
APIResult.roundtrip = function(value) {
264270
const { caseId: valueCaseId, cleanup: valueCleanup } = enumHelpers.APIResult.lower(value);
265271
instance.exports.bjs_APIResult_static_roundtrip(valueCaseId);
266272
const ret = enumHelpers.APIResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s);
267273
if (valueCleanup) { valueCleanup(); }
268274
return ret;
269-
}
275+
};
270276
const exports = {
271277
MathUtils,
272278
uppercase: function bjs_Utils_String_uppercase(text) {
@@ -279,12 +285,6 @@ export async function createInstantiator(options, swift) {
279285
return ret;
280286
},
281287
};
282-
if (typeof globalThis.Utils === 'undefined') {
283-
globalThis.Utils = {};
284-
}
285-
if (typeof globalThis.Utils.String === 'undefined') {
286-
globalThis.Utils.String = {};
287-
}
288288
globalThis.Utils.String.uppercase = exports.uppercase;
289289
return exports;
290290
},

0 commit comments

Comments
 (0)