Skip to content

Commit 0d659a9

Browse files
committed
Embedded Swift support
1 parent ea06982 commit 0d659a9

36 files changed

+1351
-84
lines changed

Package.swift

+100-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,55 @@
1-
// swift-tools-version:5.7
1+
// swift-tools-version:5.10
22

33
import PackageDescription
44

5+
let embeddedSwiftSettings: [SwiftSetting] = [
6+
.enableExperimentalFeature("Embedded"),
7+
.interoperabilityMode(.Cxx),
8+
.unsafeFlags([
9+
"-wmo", "-disable-cmo",
10+
"-Xfrontend", "-gnone",
11+
"-Xfrontend", "-disable-stack-protector",
12+
"-Xfrontend", "-emit-empty-object-file"
13+
])
14+
]
15+
16+
let embeddedCSettings: [CSetting] = [
17+
.unsafeFlags(["-fdeclspec"])
18+
]
19+
20+
let linkerSettings: [LinkerSetting] = [
21+
.unsafeFlags([
22+
"-Xclang-linker", "-nostdlib",
23+
"-Xlinker", "--no-entry"
24+
])
25+
]
26+
27+
let libcSettings: [CSetting] = [
28+
.define("LACKS_TIME_H"),
29+
.define("LACKS_SYS_TYPES_H"),
30+
.define("LACKS_STDLIB_H"),
31+
.define("LACKS_STRING_H"),
32+
.define("LACKS_SYS_MMAN_H"),
33+
.define("LACKS_FCNTL_H"),
34+
.define("NO_MALLOC_STATS", to: "1"),
35+
.define("__wasilibc_unmodified_upstream"),
36+
]
37+
538
let package = Package(
639
name: "JavaScriptKit",
740
products: [
841
.library(name: "JavaScriptKit", targets: ["JavaScriptKit"]),
942
.library(name: "JavaScriptEventLoop", targets: ["JavaScriptEventLoop"]),
1043
.library(name: "JavaScriptBigIntSupport", targets: ["JavaScriptBigIntSupport"]),
1144
.library(name: "JavaScriptEventLoopTestSupport", targets: ["JavaScriptEventLoopTestSupport"]),
45+
// Embedded
46+
.library(name: "JavaScriptKitEmbedded", targets: ["JavaScriptKitEmbedded"]),
47+
.library(name: "JavaScriptEventLoopEmbedded", targets: ["JavaScriptEventLoopEmbedded"]),
48+
.library(name: "JavaScriptBigIntSupportEmbedded", targets: ["JavaScriptBigIntSupportEmbedded"]),
49+
.library(name: "JavaScriptEventLoopTestSupportEmbedded", targets: ["JavaScriptEventLoopTestSupportEmbedded"]),
50+
],
51+
dependencies: [
52+
.package(url: "https://github.com/swifweb/String16", branch: "0.1.0")
1253
],
1354
targets: [
1455
.target(
@@ -36,11 +77,64 @@ let package = Package(
3677
),
3778
.target(name: "_CJavaScriptEventLoopTestSupport"),
3879
.testTarget(
39-
name: "JavaScriptEventLoopTestSupportTests",
40-
dependencies: [
41-
"JavaScriptKit",
42-
"JavaScriptEventLoopTestSupport"
43-
]
80+
name: "JavaScriptEventLoopTestSupportTests",
81+
dependencies: [
82+
"JavaScriptKit",
83+
"JavaScriptEventLoopTestSupport"
84+
]
85+
),
86+
// Embedded
87+
.target(
88+
name: "JavaScriptKitEmbedded",
89+
dependencies: [
90+
"_CJavaScriptKitEmbedded",
91+
.product(name: "String16", package: "String16")
92+
],
93+
// resources: [.copy("Runtime")], // FIXME: doesn't work with embedded because trying to import Foundation
94+
cSettings: embeddedCSettings,
95+
swiftSettings: embeddedSwiftSettings,
96+
linkerSettings: linkerSettings
97+
),
98+
.target(
99+
name: "_CJavaScriptKitEmbedded",
100+
cSettings: libcSettings
101+
),
102+
.target(
103+
name: "JavaScriptBigIntSupportEmbedded",
104+
dependencies: ["_CJavaScriptBigIntSupportEmbedded", "JavaScriptKitEmbedded"],
105+
cSettings: embeddedCSettings,
106+
swiftSettings: embeddedSwiftSettings,
107+
linkerSettings: linkerSettings
108+
),
109+
.target(
110+
name: "_CJavaScriptBigIntSupportEmbedded",
111+
dependencies: ["_CJavaScriptKitEmbedded"],
112+
cSettings: libcSettings
113+
),
114+
.target(
115+
name: "JavaScriptEventLoopEmbedded",
116+
dependencies: ["JavaScriptKitEmbedded", "_CJavaScriptEventLoopEmbedded"],
117+
cSettings: embeddedCSettings,
118+
swiftSettings: embeddedSwiftSettings,
119+
linkerSettings: linkerSettings
120+
),
121+
.target(
122+
name: "_CJavaScriptEventLoopEmbedded",
123+
cSettings: libcSettings
124+
),
125+
.target(
126+
name: "JavaScriptEventLoopTestSupportEmbedded",
127+
dependencies: [
128+
"_CJavaScriptEventLoopTestSupportEmbedded",
129+
"JavaScriptEventLoopEmbedded",
130+
],
131+
cSettings: embeddedCSettings,
132+
swiftSettings: embeddedSwiftSettings,
133+
linkerSettings: linkerSettings
134+
),
135+
.target(
136+
name: "_CJavaScriptEventLoopTestSupportEmbedded",
137+
cSettings: libcSettings
44138
),
45139
]
46140
)

[email protected]

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// swift-tools-version:5.7
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "JavaScriptKit",
7+
products: [
8+
.library(name: "JavaScriptKit", targets: ["JavaScriptKit"]),
9+
.library(name: "JavaScriptEventLoop", targets: ["JavaScriptEventLoop"]),
10+
.library(name: "JavaScriptBigIntSupport", targets: ["JavaScriptBigIntSupport"]),
11+
.library(name: "JavaScriptEventLoopTestSupport", targets: ["JavaScriptEventLoopTestSupport"]),
12+
],
13+
targets: [
14+
.target(
15+
name: "JavaScriptKit",
16+
dependencies: ["_CJavaScriptKit"],
17+
resources: [.copy("Runtime")]
18+
),
19+
.target(name: "_CJavaScriptKit"),
20+
.target(
21+
name: "JavaScriptBigIntSupport",
22+
dependencies: ["_CJavaScriptBigIntSupport", "JavaScriptKit"]
23+
),
24+
.target(name: "_CJavaScriptBigIntSupport", dependencies: ["_CJavaScriptKit"]),
25+
.target(
26+
name: "JavaScriptEventLoop",
27+
dependencies: ["JavaScriptKit", "_CJavaScriptEventLoop"]
28+
),
29+
.target(name: "_CJavaScriptEventLoop"),
30+
.target(
31+
name: "JavaScriptEventLoopTestSupport",
32+
dependencies: [
33+
"_CJavaScriptEventLoopTestSupport",
34+
"JavaScriptEventLoop",
35+
]
36+
),
37+
.target(name: "_CJavaScriptEventLoopTestSupport"),
38+
.testTarget(
39+
name: "JavaScriptEventLoopTestSupportTests",
40+
dependencies: [
41+
"JavaScriptKit",
42+
"JavaScriptEventLoopTestSupport"
43+
]
44+
),
45+
]
46+
)

Runtime/src/index.ts

+31-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ export class SwiftRuntime {
2121
private options: SwiftRuntimeOptions;
2222
private version: number = 708;
2323

24-
private textDecoder = new TextDecoder("utf-8");
24+
private textDecoderUTF8 = new TextDecoder("utf-8");
25+
private textDecoderUTF16 = new TextDecoder("utf-16");
2526
private textEncoder = new TextEncoder(); // Only support utf-8
2627

2728
constructor(options?: SwiftRuntimeOptions) {
@@ -210,6 +211,13 @@ export class SwiftRuntime {
210211
memory.writeUint32(bytes_ptr_result, bytes_ptr);
211212
return bytes.length;
212213
},
214+
swjs_encode_utf16_string: (ref: ref, bytes_ptr_result: pointer) => {
215+
const memory = this.memory;
216+
const bytes = memory.getObject(ref);
217+
const bytes_ptr = memory.retain(bytes);
218+
memory.writeUint32(bytes_ptr_result, bytes_ptr);
219+
return bytes.length;
220+
},
213221
swjs_decode_string: (
214222
// NOTE: TextDecoder can't decode typed arrays backed by SharedArrayBuffer
215223
this.options.sharedMemory == true
@@ -218,15 +226,35 @@ export class SwiftRuntime {
218226
const bytes = memory
219227
.bytes()
220228
.slice(bytes_ptr, bytes_ptr + length);
221-
const string = this.textDecoder.decode(bytes);
229+
const string = this.textDecoderUTF8.decode(bytes);
230+
return memory.retain(string);
231+
})
232+
: ((bytes_ptr: pointer, length: number) => {
233+
const memory = this.memory;
234+
const bytes = memory
235+
.bytes()
236+
.subarray(bytes_ptr, bytes_ptr + length);
237+
const string = this.textDecoderUTF8.decode(bytes);
238+
return memory.retain(string);
239+
})
240+
),
241+
swjs_decode_utf16_string: (
242+
// NOTE: TextDecoder can't decode typed arrays backed by SharedArrayBuffer
243+
this.options.sharedMemory == true
244+
? ((bytes_ptr: pointer, length: number) => {
245+
const memory = this.memory;
246+
const bytes = memory
247+
.bytes()
248+
.slice(bytes_ptr, bytes_ptr + length);
249+
const string = this.textDecoderUTF16.decode(bytes);
222250
return memory.retain(string);
223251
})
224252
: ((bytes_ptr: pointer, length: number) => {
225253
const memory = this.memory;
226254
const bytes = memory
227255
.bytes()
228256
.subarray(bytes_ptr, bytes_ptr + length);
229-
const string = this.textDecoder.decode(bytes);
257+
const string = this.textDecoderUTF16.decode(bytes);
230258
return memory.retain(string);
231259
})
232260
),

Runtime/src/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ export interface ImportedFunctions {
4949
payload2_ptr: pointer
5050
): JavaScriptValueKind;
5151
swjs_encode_string(ref: number, bytes_ptr_result: pointer): number;
52+
swjs_encode_utf16_string(ref: number, bytes_ptr_result: pointer): number;
5253
swjs_decode_string(bytes_ptr: pointer, length: number): number;
54+
swjs_decode_utf16_string(bytes_ptr: pointer, length: number): number;
5355
swjs_load_string(ref: number, buffer: pointer): void;
5456
swjs_call_function(
5557
ref: number,
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
JavaScriptBigIntSupport

Sources/JavaScriptEventLoopEmbedded

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
JavaScriptEventLoop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
JavaScriptEventLoopTestSupport

Sources/JavaScriptKit/BasicObjects/JSArray.swift

+17
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ public class JSArray: JSBridgedClass {
55
public static let constructor = JSObject.global.Array.function
66

77
static func isArray(_ object: JSObject) -> Bool {
8+
#if hasFeature(Embedded)
9+
constructor!.isArray!(object.jsValue).boolean!
10+
#else
811
constructor!.isArray!(object).boolean!
12+
#endif
913
}
1014

1115
public let jsObject: JSObject
@@ -51,9 +55,15 @@ extension JSArray: RandomAccessCollection {
5155
return nil
5256
}
5357
index += 1
58+
#if hasFeature(Embedded)
59+
guard jsObject.hasOwnProperty!(currentIndex.jsValue).boolean! else {
60+
return next()
61+
}
62+
#else
5463
guard jsObject.hasOwnProperty!(currentIndex).boolean! else {
5564
return next()
5665
}
66+
#endif
5767
let value = jsObject[currentIndex]
5868
return value
5969
}
@@ -91,11 +101,18 @@ extension JSArray: RandomAccessCollection {
91101
}
92102
}
93103

104+
#if hasFeature(Embedded)
105+
private func getObjectValuesLength(_ object: JSObject) -> Int {
106+
let values = object.filter!((JSClosure { _ in true.jsValue }).jsValue).object!
107+
return Int(values.length.number!)
108+
}
109+
#else
94110
private let alwaysTrue = JSClosure { _ in .boolean(true) }
95111
private func getObjectValuesLength(_ object: JSObject) -> Int {
96112
let values = object.filter!(alwaysTrue).object!
97113
return Int(values.length.number!)
98114
}
115+
#endif
99116

100117
public extension JSValue {
101118
var array: JSArray? {

0 commit comments

Comments
 (0)