Skip to content

Commit 70b015d

Browse files
committed
feat: namespace tests for functions, code cleanup
1 parent ea1a855 commit 70b015d

File tree

6 files changed

+244
-90
lines changed

6 files changed

+244
-90
lines changed

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 44 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,42 @@ struct BridgeJSLink {
203203
/** @param {WebAssembly.Instance} instance */
204204
createExports: (instance) => {
205205
const js = swift.memory.heap;
206-
\(exportsSection)
206+
\(exportsSection)
207207
}
208208
}
209209
"""
210+
211+
var dtsLines: [String] = []
212+
dtsLines.append(contentsOf: namespaceDeclarations())
213+
dtsLines.append(contentsOf: dtsClassLines)
214+
dtsLines.append("export type Exports = {")
215+
dtsLines.append(contentsOf: dtsExportLines.map { $0.indent(count: 4) })
216+
dtsLines.append("}")
217+
dtsLines.append("export type Imports = {")
218+
dtsLines.append(contentsOf: importObjectBuilders.flatMap { $0.dtsImportLines }.map { $0.indent(count: 4) })
219+
dtsLines.append("}")
220+
let outputDts = """
221+
// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
222+
// DO NOT EDIT.
223+
//
224+
// To update this file, just rebuild your project or run
225+
// `swift package bridge-js`.
226+
227+
\(dtsLines.joined(separator: "\n"))
228+
export function createInstantiator(options: {
229+
imports: Imports;
230+
}, swift: any): Promise<{
231+
addImports: (importObject: WebAssembly.Imports) => void;
232+
setInstance: (instance: WebAssembly.Instance) => void;
233+
createExports: (instance: WebAssembly.Instance) => Exports;
234+
}>;
235+
"""
236+
return (outputJs, outputDts)
237+
}
238+
239+
private func namespaceDeclarations() -> [String] {
240+
var dtsLines: [String] = []
210241

211-
// Collect namespace declarations for TypeScript
212242
var namespaceDeclarations: [String: [(name: String, parameters: [Parameter], returnType: BridgeType)]] = [:]
213243

214244
for skeleton in exportedSkeletons {
@@ -222,72 +252,35 @@ struct BridgeJSLink {
222252
}
223253
}
224254
}
255+
guard !namespaceDeclarations.isEmpty else { return dtsLines }
225256

226-
// Generate namespace declarations in TypeScript
227-
var dtsLines: [String] = []
228-
229-
// Only add export {} and declare global block if we have namespace declarations
230-
let hasNamespaceDeclarations = !namespaceDeclarations.isEmpty
257+
dtsLines.append("export {};")
258+
dtsLines.append("")
259+
dtsLines.append("declare global {")
231260

232-
if hasNamespaceDeclarations {
233-
dtsLines.append("export {};")
234-
dtsLines.append("")
235-
dtsLines.append("declare global {")
236-
}
237-
238-
// Generate namespace structure using nested declarations
239261
for (namespacePath, functions) in namespaceDeclarations.sorted(by: { $0.key < $1.key }) {
240262
let parts = namespacePath.split(separator: ".").map(String.init)
241263

242-
// Open namespaces with proper indentation
243264
for i in 0..<parts.count {
244-
dtsLines.append("namespace \(parts[i]) {".indent(count: 4*(hasNamespaceDeclarations ? i + 1: 1)) )
265+
dtsLines.append("namespace \(parts[i]) {".indent(count: 4*( i + 1)) )
245266
}
246267

247-
// Add function signatures with proper indentation
248-
let functionIndentationLevel = hasNamespaceDeclarations ? parts.count + 1 : parts.count
268+
let functionIndentationLevel = parts.count + 1
249269
for (name, parameters, returnType) in functions {
250270
let signature = "function \(name)\(renderTSSignature(parameters: parameters, returnType: returnType));"
251271
dtsLines.append("\(signature)".indent(count: 4*functionIndentationLevel))
252272
}
253273

254-
// Close namespaces with proper indentation (in reverse order)
255274
for i in (0..<parts.count).reversed() {
256-
let indentationLevel = hasNamespaceDeclarations ? i + 1 : i
275+
let indentationLevel = i + 1
257276
dtsLines.append("}".indent(count: 4*indentationLevel))
258277
}
259278
}
260279

261-
if hasNamespaceDeclarations {
262-
dtsLines.append("}")
263-
dtsLines.append("")
264-
}
265-
266-
// Add remaining class lines
267-
dtsLines.append(contentsOf: dtsClassLines)
268-
dtsLines.append("export type Exports = {")
269-
dtsLines.append(contentsOf: dtsExportLines.map { $0.indent(count: 4) })
270-
dtsLines.append("}")
271-
dtsLines.append("export type Imports = {")
272-
dtsLines.append(contentsOf: importObjectBuilders.flatMap { $0.dtsImportLines }.map { $0.indent(count: 4) })
273280
dtsLines.append("}")
274-
let outputDts = """
275-
// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
276-
// DO NOT EDIT.
277-
//
278-
// To update this file, just rebuild your project or run
279-
// `swift package bridge-js`.
280-
281-
\(dtsLines.joined(separator: "\n"))
282-
export function createInstantiator(options: {
283-
imports: Imports;
284-
}, swift: any): Promise<{
285-
addImports: (importObject: WebAssembly.Imports) => void;
286-
setInstance: (instance: WebAssembly.Instance) => void;
287-
createExports: (instance: WebAssembly.Instance) => Exports;
288-
}>;
289-
"""
290-
return (outputJs, outputDts)
281+
dtsLines.append("")
282+
283+
return dtsLines
291284
}
292285

293286
class ExportedThunkBuilder {
@@ -482,20 +475,11 @@ struct BridgeJSLink {
482475
return (jsLines, dtsTypeLines, dtsExportEntryLines)
483476
}
484477

485-
// __Swift.Foundation.UUID
486-
487-
// [__Swift, Foundation, UUID]
488-
// [[__Swift, Foundation, UUID], [__Swift, Foundation]]
489-
490-
// __Swift
491-
// __Swift.Foundation
492-
// __Swift.Foundation.UUID
493-
494478
func renderGlobalNamespace(namespacedFunctions: [ExportedFunction]) -> [String] {
495479
var lines: [String] = []
496480
var uniqueNamespaces: [String] = []
497481

498-
var namespacePaths: Set<[String]> = Set(namespacedFunctions
482+
let namespacePaths: Set<[String]> = Set(namespacedFunctions
499483
.compactMap { $0.namespace })
500484

501485
namespacePaths.forEach { namespacePath in
@@ -507,7 +491,7 @@ struct BridgeJSLink {
507491
}
508492
}
509493

510-
uniqueNamespaces.map { namespace in
494+
uniqueNamespaces.forEach { namespace in
511495
lines.append("if (typeof globalThis.\(namespace) === 'undefined') {")
512496
lines.append(" globalThis.\(namespace) = {};")
513497
lines.append("}")
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
@JS("__Swift.Foundation.UUID") func create() -> String {
2+
return UUID().uuidString
3+
}
4+
5+
@JS("__Swift.Foundation.UUID") func validate(uuid: String) -> Bool {
6+
return true
7+
}
8+
9+
@JS func plainFunction() -> String {
10+
return "plain"
11+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
2+
// DO NOT EDIT.
3+
//
4+
// To update this file, just rebuild your project or run
5+
// `swift package bridge-js`.
6+
7+
export {};
8+
9+
declare global {
10+
namespace __Swift {
11+
namespace Foundation {
12+
namespace UUID {
13+
function create(): string;
14+
function validate(uuid: string): boolean;
15+
}
16+
}
17+
}
18+
}
19+
20+
export type Exports = {
21+
create(): string;
22+
validate(uuid: string): boolean;
23+
plainFunction(): string;
24+
}
25+
export type Imports = {
26+
}
27+
export function createInstantiator(options: {
28+
imports: Imports;
29+
}, swift: any): Promise<{
30+
addImports: (importObject: WebAssembly.Imports) => void;
31+
setInstance: (instance: WebAssembly.Instance) => void;
32+
createExports: (instance: WebAssembly.Instance) => Exports;
33+
}>;
Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -46,34 +46,7 @@ export async function createInstantiator(options, swift) {
4646
bjs["swift_js_release"] = function(id) {
4747
swift.memory.release(id);
4848
}
49-
const TestModule = importObject["TestModule"] = {};
50-
TestModule["bjs_returnAnimatable"] = function bjs_returnAnimatable() {
51-
try {
52-
let ret = options.imports.returnAnimatable();
53-
return swift.memory.retain(ret);
54-
} catch (error) {
55-
setException(error);
56-
return 0
57-
}
58-
}
59-
TestModule["bjs_Animatable_animate"] = function bjs_Animatable_animate(self, keyframes, options) {
60-
try {
61-
let ret = swift.memory.getObject(self).animate(swift.memory.getObject(keyframes), swift.memory.getObject(options));
62-
return swift.memory.retain(ret);
63-
} catch (error) {
64-
setException(error);
65-
return 0
66-
}
67-
}
68-
TestModule["bjs_Animatable_getAnimations"] = function bjs_Animatable_getAnimations(self, options) {
69-
try {
70-
let ret = swift.memory.getObject(self).getAnimations(swift.memory.getObject(options));
71-
return swift.memory.retain(ret);
72-
} catch (error) {
73-
setException(error);
74-
return 0
75-
}
76-
}
49+
7750
},
7851
setInstance: (i) => {
7952
instance = i;
@@ -85,10 +58,42 @@ export async function createInstantiator(options, swift) {
8558
/** @param {WebAssembly.Instance} instance */
8659
createExports: (instance) => {
8760
const js = swift.memory.heap;
88-
89-
return {
9061

62+
const exports = {
63+
create: function bjs_create() {
64+
instance.exports.bjs_create();
65+
const ret = tmpRetString;
66+
tmpRetString = undefined;
67+
return ret;
68+
},
69+
validate: function bjs_validate(uuid) {
70+
const uuidBytes = textEncoder.encode(uuid);
71+
const uuidId = swift.memory.retain(uuidBytes);
72+
const ret = instance.exports.bjs_validate(uuidId, uuidBytes.length) !== 0;
73+
swift.memory.release(uuidId);
74+
return ret;
75+
},
76+
plainFunction: function bjs_plainFunction() {
77+
instance.exports.bjs_plainFunction();
78+
const ret = tmpRetString;
79+
tmpRetString = undefined;
80+
return ret;
81+
},
9182
};
83+
84+
if (typeof globalThis.__Swift === 'undefined') {
85+
globalThis.__Swift = {};
86+
}
87+
if (typeof globalThis.__Swift.Foundation === 'undefined') {
88+
globalThis.__Swift.Foundation = {};
89+
}
90+
if (typeof globalThis.__Swift.Foundation.UUID === 'undefined') {
91+
globalThis.__Swift.Foundation.UUID = {};
92+
}
93+
globalThis.__Swift.Foundation.UUID.create = exports.create;
94+
globalThis.__Swift.Foundation.UUID.validate = exports.validate;
95+
96+
return exports;
9297
},
9398
}
9499
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"classes" : [
3+
4+
],
5+
"functions" : [
6+
{
7+
"abiName" : "bjs_create",
8+
"effects" : {
9+
"isAsync" : false,
10+
"isThrows" : false
11+
},
12+
"name" : "create",
13+
"namespace" : [
14+
"__Swift",
15+
"Foundation",
16+
"UUID"
17+
],
18+
"parameters" : [
19+
20+
],
21+
"returnType" : {
22+
"string" : {
23+
24+
}
25+
}
26+
},
27+
{
28+
"abiName" : "bjs_validate",
29+
"effects" : {
30+
"isAsync" : false,
31+
"isThrows" : false
32+
},
33+
"name" : "validate",
34+
"namespace" : [
35+
"__Swift",
36+
"Foundation",
37+
"UUID"
38+
],
39+
"parameters" : [
40+
{
41+
"label" : "uuid",
42+
"name" : "uuid",
43+
"type" : {
44+
"string" : {
45+
46+
}
47+
}
48+
}
49+
],
50+
"returnType" : {
51+
"bool" : {
52+
53+
}
54+
}
55+
},
56+
{
57+
"abiName" : "bjs_plainFunction",
58+
"effects" : {
59+
"isAsync" : false,
60+
"isThrows" : false
61+
},
62+
"name" : "plainFunction",
63+
"parameters" : [
64+
65+
],
66+
"returnType" : {
67+
"string" : {
68+
69+
}
70+
}
71+
}
72+
]
73+
}

0 commit comments

Comments
 (0)