Skip to content

Commit 408a99a

Browse files
Support new object construction
1 parent 7bdfe8c commit 408a99a

File tree

6 files changed

+77
-1
lines changed

6 files changed

+77
-1
lines changed

Diff for: src/swift/Sources/JavaScriptKit/JSFunction.swift

+15
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ public class JSFunctionRef: Equatable {
2828
return result.jsValue()
2929
}
3030

31+
public func new(_ arguments: [JSValue]) -> JSObjectRef {
32+
return arguments.withRawJSValues { rawValues in
33+
rawValues.withUnsafeBufferPointer { bufferPointer in
34+
let argv = bufferPointer.baseAddress
35+
let argc = bufferPointer.count
36+
var resultObj = JavaScriptPayload()
37+
_call_new(
38+
self.id, argv, Int32(argc),
39+
&resultObj
40+
)
41+
return JSObjectRef(id: resultObj)
42+
}
43+
}
44+
}
45+
3146
static var sharedFunctions: [([JSValue]) -> JSValue] = []
3247
public static func from(_ body: @escaping ([JSValue]) -> JSValue) -> JSFunctionRef {
3348
let id = JavaScriptHostFuncRef(sharedFunctions.count)

Diff for: src/swift/Sources/JavaScriptKit/XcodeSupport.swift

+7-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,11 @@ func _call_function(
3939
_ result_kind: UnsafeMutablePointer<JavaScriptValueKind>!,
4040
_ result_payload1: UnsafeMutablePointer<JavaScriptPayload>!,
4141
_ result_payload2: UnsafeMutablePointer<JavaScriptPayload>!) { fatalError() }
42-
func _create_function(_ host_func_id: JavaScriptHostFuncRef, _ func_ref_ptr: UnsafePointer<JavaScriptObjectRef>!) {}
42+
func _call_new(
43+
_ ref: JavaScriptObjectRef,
44+
_ argv: UnsafePointer<RawJSValue>!, _ argc: Int32,
45+
_ result_obj: UnsafeMutablePointer<JavaScriptPayload>!) { fatalError() }
46+
func _create_function(
47+
_ host_func_id: JavaScriptHostFuncRef,
48+
_ func_ref_ptr: UnsafePointer<JavaScriptObjectRef>!) { fatalError() }
4349
#endif

Diff for: src/swift/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h

+10
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ extern void _call_function(
9999
JavaScriptPayload *result_payload2
100100
);
101101

102+
__attribute__((
103+
__import_module__("javascript_kit"),
104+
__import_name__("swjs_call_new")
105+
))
106+
extern void _call_new(
107+
const JavaScriptObjectRef ref,
108+
const RawJSValue *argv, const int argc,
109+
JavaScriptPayload *result_obj
110+
);
111+
102112
__attribute__((
103113
__import_module__("javascript_kit"),
104114
__import_name__("swjs_create_function")

Diff for: src/web/src/index.ts

+10
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,16 @@ export class SwiftRuntime {
290290
})
291291
writeUint32(func_ref_ptr, func_ref)
292292
},
293+
swjs_call_new: (
294+
ref: ref, argv: pointer, argc: number,
295+
result_obj: pointer
296+
) => {
297+
const obj = this._heapValues[ref]
298+
const result = Reflect.construct(obj, decodeValues(argv, argc))
299+
if (typeof result != "object")
300+
throw Error(`Invalid result type of object constructor of "${obj}": "${result}"`)
301+
writeUint32(result_obj, allocValue(result));
302+
},
293303
}
294304
}
295305
}

Diff for: test/JavaScriptKitExec/Sources/JavaScriptKitExec/main.swift

+27
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ Object_Conversion: do {
6060
try expectEqual(actualElement, expectedElement)
6161
}
6262

63+
try expectEqual(getJSValue(this: globalObject1Ref, name: "undefined_prop"), .undefined)
64+
6365
} catch {
6466
print(error)
6567
}
@@ -155,3 +157,28 @@ Host_Function_Registration: do {
155157
} catch {
156158
print(error)
157159
}
160+
161+
New_Object_Construction: do {
162+
163+
// ```js
164+
// global.Animal = function(name, age, isCat) {
165+
// this.name = name
166+
// this.age = age
167+
// this.bark = () => {
168+
// return isCat ? "nyan" : "wan"
169+
// }
170+
// }
171+
// ```
172+
let objectConstructor = try expectFunction(getJSValue(this: .global(), name: "Animal"))
173+
let cat1 = objectConstructor.new([.string("Tama"), .number(3), .boolean(true)])
174+
try expectEqual(getJSValue(this: cat1, name: "name"), .string("Tama"))
175+
try expectEqual(getJSValue(this: cat1, name: "age"), .number(3))
176+
let cat1Bark = try expectFunction(getJSValue(this: cat1, name: "bark"))
177+
try expectEqual(cat1Bark(), .string("nyan"))
178+
179+
let dog1 = objectConstructor.new([.string("Pochi"), .number(3), .boolean(false)])
180+
let dog1Bark = try expectFunction(getJSValue(this: dog1, name: "bark"))
181+
try expectEqual(dog1Bark(), .string("wan"))
182+
} catch {
183+
print(error)
184+
}

Diff for: test/index.js

+8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ global.globalObject1 = {
4444
}
4545
}
4646

47+
global.Animal = function(name, age, isCat) {
48+
this.name = name
49+
this.age = age
50+
this.bark = () => {
51+
return isCat ? "nyan" : "wan"
52+
}
53+
}
54+
4755
const startWasiTask = async () => {
4856
// Fetch our Wasm File
4957
const wasmBinary = await readFile("./dist/JavaScriptKitExec.wasm");

0 commit comments

Comments
 (0)