-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdispatch.vsl
105 lines (84 loc) · 4.86 KB
/
dispatch.vsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// @mock(ui32)
// @dynamic(false)
// private class JSReference {
// deinit {
// freeReference(index: UInt32::self)
// }
// }
//
// private typealias WDSFrame = UInt32
// private const WDS_HEADER_SIZE: UInt64 = 4
// private const WDS_PARAM_TYPE_SIZE: UInt64 = 1
// private const WDS_PARAM_VALUE_SIZE: UInt64 = 4
//
// private const WDS_PARAM_TYPE_OBJREF = 0x01
// private const WDS_PARAM_TYPE_STRING = 0x00
private func metaGlobal() -> UInt32 external("meta.__objectheap_global");
private func metaUndefined() -> UInt32 external("meta.__objectheap_undefined");
private func metaNull() -> UInt32 external("meta.__objectheap_null");
// Constants
public const JS_GLOBAL: JSValue = JSValue::metaGlobal();
public const JS_UNDEFINED: JSValue = JSValue::metaUndefined();
public const JS_NULL: JSValue = JSValue::metaNull();
public lazy const JS_ARRAY: JSValue = JS_GLOBAL.dispatchAccess("Array");
public lazy const JS_STRING: JSValue = JS_GLOBAL.dispatchAccess("String");
// JS bridging class
typealias WASMDispatchStackFrame = Pointer<UInt8>
@mock(ui32)
@dynamic(false)
public class JSValue {
/// Creates a JSValue encapsulating a VSL string. These does not create any
/// reference, instead creates a copy in the JS context.
public static func from(string: String) -> JSValue external("meta.objectheap.fromString");
/// Creates a JSValue encapsulating a VSL number. These does not create any
/// reference, instead creates a copy in the JS context. Use of this is not
/// recommended, instead to directly pass the number to the JS interface.
public static func from(uint8: UInt8) -> JSValue external("meta.objectheap.fromNumber");
/// Creates a JSValue encapsulating a VSL number. These does not create any
/// reference, instead creates a copy in the JS context. Use of this is not
/// recommended, instead to directly pass the number to the JS interface.
public static func from(uint16: UInt16) -> JSValue external("meta.objectheap.fromNumber");
/// Creates a JSValue encapsulating a VSL number. These does not create any
/// reference, instead creates a copy in the JS context. Use of this is not
/// recommended, instead to directly pass the number to the JS interface.
public static func from(uint32: UInt32) -> JSValue external("meta.objectheap.fromNumber");
/// Creates a JSValue encapsulating a VSL number. These does not create any
/// reference, instead creates a copy in the JS context. Use of this is not
/// recommended, instead to directly pass the number to the JS interface.
public static func from(int8: Int8) -> JSValue external("meta.objectheap.fromNumber");
/// Creates a JSValue encapsulating a VSL number. These does not create any
/// reference, instead creates a copy in the JS context. Use of this is not
/// recommended, instead to directly pass the number to the JS interface.
public static func from(int16: Int16) -> JSValue external("meta.objectheap.fromNumber");
/// Creates a JSValue encapsulating a VSL number. These does not create any
/// reference, instead creates a copy in the JS context. Use of this is not
/// recommended, instead to directly pass the number to the JS interface.
public static func from(int32: Int32) -> JSValue external("meta.objectheap.fromNumber");
/// Creates a copy of the (assumed to be) JS string reference in the VSL
/// heap. Undefined behavior if the value is not actually a JS value. Use
/// the `checked: true` parameter for safe operations.
public func toString(free: Bool = false, checked: Bool = false) -> String {
if checked {
// Get the 'String' class from the global object and use that.
assert(self.dispatchInstanceOf(jsClass: JS_STRING), "invalid attempt to cast non-string to string")
}
let stringLength = UInt64::self.dispatchGetStringLength()
let ptr = Pointer<UInt8>.alloc(count: stringLength + 1)
// Set null byte at end
ptr.offset(by: Int64::stringLength).store(value: 0x00)
// Copy the string from JS -> VSL
self.dispatchCopyString(to: ptr)
if free {
self.dispatchFree()
}
return String(value: ptr, byteLength: UInt::stringLength)
}
private func dispatchGetStringLength() -> UInt32 external("dispatch.readStringLength");
private func dispatchCopyString(to pointer: Pointer<UInt8>) external("dispatch.copyString");
public func dispatchInstanceOf(jsClass: JSValue) -> Bool external("dispatch.instanceOf");
public func dispatchFree() external("dispatch.freeReference");
public func dispatchAccess(target: String) -> JSValue external("dispatch.access");
public func dispatchAnon(target: String) -> JSValue external("dispatch.anon");
public func dispatch(target: String, stackFrame: WASMDispatchStackFrame) -> JSValue external("dispatch.dispatch");
deinit { self.dispatchFree() }
}