Skip to content

Commit 5ca3335

Browse files
committed
BridgeJS: fix: don't allow for other than top-levels namespace macros
1 parent e91edce commit 5ca3335

File tree

7 files changed

+82
-72
lines changed

7 files changed

+82
-72
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,14 @@ class ExportSwift {
130130
let name = node.name.text
131131
let namespace = extractNamespace(from: jsAttribute)
132132

133+
if namespace != nil, case .classBody = state {
134+
diagnose(
135+
node: jsAttribute,
136+
message: "Namespace is only needed in top-level declaration",
137+
hint: "Remove the namespace from @JS attribute or move this function to top-level"
138+
)
139+
}
140+
133141
var parameters: [Parameter] = []
134142
for param in node.signature.parameterClause.parameters {
135143
guard let type = self.parent.lookupType(for: param.type) else {
@@ -214,6 +222,17 @@ class ExportSwift {
214222
diagnose(node: node, message: "@JS init must be inside a @JS class")
215223
return .skipChildren
216224
}
225+
226+
if let jsAttribute = node.attributes.firstJSAttribute,
227+
let namespace = extractNamespace(from: jsAttribute),
228+
namespace != nil {
229+
diagnose(
230+
node: jsAttribute,
231+
message: "Namespace is not supported for initializer declarations",
232+
hint: "Remove the namespace from @JS attribute"
233+
)
234+
}
235+
217236
var parameters: [Parameter] = []
218237
for param in node.signature.parameterClause.parameters {
219238
guard let type = self.parent.lookupType(for: param.type) else {

Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Namespaces.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
11
@JS func plainFunction() -> String { "plain" }
22

3+
@JS("MyModule.Utils") func namespacedFunction() -> String { "namespaced" }
4+
35
@JS("__Swift.Foundation") class Greeter {
46
var name: String
57

6-
@JS("__Swift.Foundation") init(name: String) {
8+
@JS init(name: String) {
79
self.name = name
810
}
911

10-
@JS("__Swift.Foundation") func greet() -> String {
12+
@JS func greet() -> String {
1113
return "Hello, " + self.name + "!"
1214
}
1315

14-
@JS("__Swift.Foundation") func changeName(name: String) {
16+
func changeName(name: String) {
1517
self.name = name
1618
}
1719
}
1820

1921
@JS("Utils.Converters") class Converter {
20-
@JS("Utils.Converters") init() {}
22+
@JS init() {}
2123

22-
@JS("Utils.Converters") func toString(value: Int) -> String {
24+
@JS func toString(value: Int) -> String {
2325
return String(value)
2426
}
2527
}
2628

2729
@JS("__Swift.Foundation")
2830
class UUID {
29-
@JS("__Swift.Foundation")
3031
@JS func uuidString() -> String {
3132
Foundation.UUID().uuidString
3233
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.d.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@ declare global {
2020
class Greeter {
2121
constructor(name: string);
2222
greet(): string;
23-
changeName(name: string): void;
2423
}
2524
class UUID {
2625
uuidString(): string;
2726
}
2827
}
2928
}
29+
namespace MyModule {
30+
namespace Utils {
31+
function namespacedFunction(): string;
32+
}
33+
}
3034
}
3135

3236
/// Represents a Swift heap object like a class instance or an actor instance.
@@ -38,7 +42,6 @@ export interface SwiftHeapObject {
3842
}
3943
export interface Greeter extends SwiftHeapObject {
4044
greet(): string;
41-
changeName(name: string): void;
4245
}
4346
export interface Converter extends SwiftHeapObject {
4447
toString(value: number): string;
@@ -56,6 +59,7 @@ export type Exports = {
5659
UUID: {
5760
}
5861
plainFunction(): string;
62+
namespacedFunction(): string;
5963
}
6064
export type Imports = {
6165
}

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,6 @@ export async function createInstantiator(options, swift) {
8989
tmpRetString = undefined;
9090
return ret;
9191
}
92-
changeName(name) {
93-
const nameBytes = textEncoder.encode(name);
94-
const nameId = swift.memory.retain(nameBytes);
95-
instance.exports.bjs_Greeter_changeName(this.pointer, nameId, nameBytes.length);
96-
swift.memory.release(nameId);
97-
}
9892
}
9993
class Converter extends SwiftHeapObject {
10094
constructor() {
@@ -126,8 +120,20 @@ export async function createInstantiator(options, swift) {
126120
tmpRetString = undefined;
127121
return ret;
128122
},
123+
namespacedFunction: function bjs_namespacedFunction() {
124+
instance.exports.bjs_namespacedFunction();
125+
const ret = tmpRetString;
126+
tmpRetString = undefined;
127+
return ret;
128+
},
129129
};
130130

131+
if (typeof globalThis.MyModule === 'undefined') {
132+
globalThis.MyModule = {};
133+
}
134+
if (typeof globalThis.MyModule.Utils === 'undefined') {
135+
globalThis.MyModule.Utils = {};
136+
}
131137
if (typeof globalThis.Utils === 'undefined') {
132138
globalThis.Utils = {};
133139
}
@@ -143,6 +149,7 @@ export async function createInstantiator(options, swift) {
143149
globalThis.__Swift.Foundation.Greeter = exports.Greeter;
144150
globalThis.Utils.Converters.Converter = exports.Converter;
145151
globalThis.__Swift.Foundation.UUID = exports.UUID;
152+
globalThis.MyModule.Utils.namespacedFunction = exports.namespacedFunction;
146153

147154
return exports;
148155
},

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.json

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,44 +27,12 @@
2727
"isThrows" : false
2828
},
2929
"name" : "greet",
30-
"namespace" : [
31-
"__Swift",
32-
"Foundation"
33-
],
3430
"parameters" : [
3531

3632
],
3733
"returnType" : {
3834
"string" : {
3935

40-
}
41-
}
42-
},
43-
{
44-
"abiName" : "bjs_Greeter_changeName",
45-
"effects" : {
46-
"isAsync" : false,
47-
"isThrows" : false
48-
},
49-
"name" : "changeName",
50-
"namespace" : [
51-
"__Swift",
52-
"Foundation"
53-
],
54-
"parameters" : [
55-
{
56-
"label" : "name",
57-
"name" : "name",
58-
"type" : {
59-
"string" : {
60-
61-
}
62-
}
63-
}
64-
],
65-
"returnType" : {
66-
"void" : {
67-
6836
}
6937
}
7038
}
@@ -94,10 +62,6 @@
9462
"isThrows" : false
9563
},
9664
"name" : "toString",
97-
"namespace" : [
98-
"Utils",
99-
"Converters"
100-
],
10165
"parameters" : [
10266
{
10367
"label" : "value",
@@ -131,10 +95,6 @@
13195
"isThrows" : false
13296
},
13397
"name" : "uuidString",
134-
"namespace" : [
135-
"__Swift",
136-
"Foundation"
137-
],
13898
"parameters" : [
13999

140100
],
@@ -162,6 +122,26 @@
162122
"name" : "plainFunction",
163123
"parameters" : [
164124

125+
],
126+
"returnType" : {
127+
"string" : {
128+
129+
}
130+
}
131+
},
132+
{
133+
"abiName" : "bjs_namespacedFunction",
134+
"effects" : {
135+
"isAsync" : false,
136+
"isThrows" : false
137+
},
138+
"name" : "namespacedFunction",
139+
"namespace" : [
140+
"MyModule",
141+
"Utils"
142+
],
143+
"parameters" : [
144+
165145
],
166146
"returnType" : {
167147
"string" : {

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ public func _bjs_plainFunction() -> Void {
1919
#endif
2020
}
2121

22+
@_expose(wasm, "bjs_namespacedFunction")
23+
@_cdecl("bjs_namespacedFunction")
24+
public func _bjs_namespacedFunction() -> Void {
25+
#if arch(wasm32)
26+
var ret = namespacedFunction()
27+
return ret.withUTF8 { ptr in
28+
_swift_js_return_string(ptr.baseAddress, Int32(ptr.count))
29+
}
30+
#else
31+
fatalError("Only available on WebAssembly")
32+
#endif
33+
}
34+
2235
@_expose(wasm, "bjs_Greeter_init")
2336
@_cdecl("bjs_Greeter_init")
2437
public func _bjs_Greeter_init(nameBytes: Int32, nameLen: Int32) -> UnsafeMutableRawPointer {
@@ -47,20 +60,6 @@ public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void {
4760
#endif
4861
}
4962

50-
@_expose(wasm, "bjs_Greeter_changeName")
51-
@_cdecl("bjs_Greeter_changeName")
52-
public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameBytes: Int32, nameLen: Int32) -> Void {
53-
#if arch(wasm32)
54-
let name = String(unsafeUninitializedCapacity: Int(nameLen)) { b in
55-
_swift_js_init_memory(nameBytes, b.baseAddress.unsafelyUnwrapped)
56-
return Int(nameLen)
57-
}
58-
Unmanaged<Greeter>.fromOpaque(_self).takeUnretainedValue().changeName(name: name)
59-
#else
60-
fatalError("Only available on WebAssembly")
61-
#endif
62-
}
63-
6463
@_expose(wasm, "bjs_Greeter_deinit")
6564
@_cdecl("bjs_Greeter_deinit")
6665
public func _bjs_Greeter_deinit(pointer: UnsafeMutableRawPointer) {

Sources/JavaScriptKit/Macros.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,19 @@
3434
/// UUID().uuidString
3535
/// }
3636
///
37-
/// // Export a class with a custom namespace (note that each method needs to specify the namespace)
37+
/// // Export a class with a custom namespace (note that only top level macro needs to specify the namespace)
3838
/// @JS("Utils.Greeters") class Greeter {
3939
/// var name: String
4040
///
41-
/// @JS("Utils.Greeters") init(name: String) {
41+
/// @JS init(name: String) {
4242
/// self.name = name
4343
/// }
4444
///
45-
/// @JS("Utils.Greeters") func greet() -> String {
45+
/// @JS func greet() -> String {
4646
/// return "Hello, " + self.name + "!"
4747
/// }
4848
///
49-
/// @JS("Utils.Greeters") func changeName(name: String) {
49+
/// @JS func changeName(name: String) {
5050
/// self.name = name
5151
/// }
5252
/// }

0 commit comments

Comments
 (0)