Skip to content

Commit 10bfff2

Browse files
Add doc comments for Runtime library interface
1 parent 2ba20d2 commit 10bfff2

File tree

2 files changed

+225
-61
lines changed

2 files changed

+225
-61
lines changed

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

+35
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,41 @@ public class JSClosure: JSFunction {
155155
}
156156
}
157157

158+
159+
// MARK: - `JSClosure` mechanism note
160+
//
161+
// 1. Create thunk function in JavaScript world, that has a reference
162+
// to Swift Closure.
163+
// ┌─────────────────────┬──────────────────────────┐
164+
// │ Swift side │ JavaScript side │
165+
// │ │ │
166+
// │ │ │
167+
// │ │ ┌──[Thunk function]──┐ │
168+
// │ ┌ ─ ─ ─ ─ ─│─ ─│─ ─ ─ ─ ─ ┐ │ │
169+
// │ ↓ │ │ │ │ │
170+
// │ [Swift Closure] │ │ Host Function ID │ │
171+
// │ │ │ │ │
172+
// │ │ └────────────────────┘ │
173+
// └─────────────────────┴──────────────────────────┘
174+
//
175+
// 2. When thunk function is invoked, it calls Swift Closure via
176+
// `_call_host_function` and callback the result through callback func
177+
// ┌─────────────────────┬──────────────────────────┐
178+
// │ Swift side │ JavaScript side │
179+
// │ │ │
180+
// │ │ │
181+
// │ Apply ┌──[Thunk function]──┐ │
182+
// │ ┌ ─ ─ ─ ─ ─│─ ─│─ ─ ─ ─ ─ ┐ │ │
183+
// │ ↓ │ │ │ │ │
184+
// │ [Swift Closure] │ │ Host Function ID │ │
185+
// │ │ │ │ │ │
186+
// │ │ │ └────────────────────┘ │
187+
// │ │ │ ↑ │
188+
// │ │ Apply │ │
189+
// │ └─[Result]─┼───>[Callback func]─┘ │
190+
// │ │ │
191+
// └─────────────────────┴──────────────────────────┘
192+
158193
@_cdecl("swjs_prepare_host_function_call")
159194
func _prepare_host_function_call(_ argc: Int32) -> UnsafeMutableRawPointer {
160195
let argumentSize = MemoryLayout<RawJSValue>.size * Int(argc)

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

+190-61
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
#include <stdlib.h>
55
#include <stdbool.h>
66

7+
/// `JavaScriptObjectRef` represents JavaScript object reference that is referenced by Swift side.
8+
/// This value is an address of `SwiftRuntimeHeap`.
79
typedef unsigned int JavaScriptObjectRef;
10+
/// `JavaScriptHostFuncRef` represents Swift closure that is referenced by JavaScript side.
11+
/// This value is produced by `JSClosure`.
812
typedef unsigned int JavaScriptHostFuncRef;
913

14+
/// `JavaScriptValueKind` represents the kind of JavaScript primitive value.
1015
typedef enum __attribute__((enum_extensibility(closed))) {
1116
JavaScriptValueKindInvalid = -1,
1217
JavaScriptValueKindBoolean = 0,
@@ -21,90 +26,214 @@ typedef enum __attribute__((enum_extensibility(closed))) {
2126
typedef unsigned JavaScriptPayload1;
2227
typedef double JavaScriptPayload2;
2328

29+
/// `RawJSValue` is abstract representaion of JavaScript primitive value.
30+
///
31+
/// For boolean value:
32+
/// payload1: 1 or 0
33+
/// payload2: 0
34+
///
35+
/// For string value:
36+
/// payload1: `JavaScriptObjectRef` of string
37+
/// payload2: 0
38+
///
39+
/// For number value:
40+
/// payload1: 0
41+
/// payload2: double number
42+
///
43+
/// For object value:
44+
/// payload1: `JavaScriptObjectRef`
45+
/// payload2: 0
46+
/// For null value:
47+
/// payload1: 0
48+
/// payload2: 0
49+
///
50+
/// For undefined value:
51+
/// payload1: 0
52+
/// payload2: 0
53+
///
54+
/// For function value:
55+
/// payload1: the target `JavaScriptHostFuncRef`
56+
/// payload2: 0
57+
///
2458
typedef struct {
2559
JavaScriptValueKind kind;
2660
JavaScriptPayload1 payload1;
2761
JavaScriptPayload2 payload2;
2862
} RawJSValue;
2963

3064
#if __wasm32__
31-
__attribute__((__import_module__("javascript_kit"),
32-
__import_name__("swjs_set_prop"))) extern void
33-
_set_prop(const JavaScriptObjectRef _this, const JavaScriptObjectRef prop,
34-
const JavaScriptValueKind kind, const JavaScriptPayload1 payload1,
35-
const JavaScriptPayload2 payload2);
3665

66+
/// `_set_prop` sets a value of `_this` JavaScript object.
67+
///
68+
/// @param _this The target JavaScript object to set the given value.
69+
/// @param prop A JavaScript string object to reference a member of `_this` object.
70+
/// @param kind A kind of JavaScript value to set the target object.
71+
/// @param payload1 The first payload of JavaScript value to set the target object.
72+
/// @param payload2 The second payload of JavaScript value to set the target object.
3773
__attribute__((__import_module__("javascript_kit"),
38-
__import_name__("swjs_get_prop"))) extern void
39-
_get_prop(const JavaScriptObjectRef _this, const JavaScriptObjectRef prop,
40-
JavaScriptValueKind *kind, JavaScriptPayload1 *payload1,
41-
JavaScriptPayload2 *payload2);
42-
74+
__import_name__("swjs_set_prop")))
75+
extern void _set_prop(const JavaScriptObjectRef _this,
76+
const JavaScriptObjectRef prop,
77+
const JavaScriptValueKind kind,
78+
const JavaScriptPayload1 payload1,
79+
const JavaScriptPayload2 payload2);
80+
81+
/// `_get_prop` gets a value of `_this` JavaScript object.
82+
///
83+
/// @param _this The target JavaScript object to get its member value.
84+
/// @param prop A JavaScript string object to reference a member of `_this` object.
85+
/// @param kind A result pointer of JavaScript value kind to get.
86+
/// @param payload1 A result pointer of first payload of JavaScript value to set the target object.
87+
/// @param payload2 A result pointer of second payload of JavaScript value to set the target object.
4388
__attribute__((__import_module__("javascript_kit"),
44-
__import_name__("swjs_set_subscript"))) extern void
45-
_set_subscript(const JavaScriptObjectRef _this, const int length,
46-
const JavaScriptValueKind kind,
47-
const JavaScriptPayload1 payload1,
48-
const JavaScriptPayload2 payload2);
49-
89+
__import_name__("swjs_get_prop")))
90+
extern void _get_prop(const JavaScriptObjectRef _this,
91+
const JavaScriptObjectRef prop,
92+
JavaScriptValueKind *kind,
93+
JavaScriptPayload1 *payload1,
94+
JavaScriptPayload2 *payload2);
95+
96+
/// `_set_subscript` sets a value of `_this` JavaScript object.
97+
///
98+
/// @param _this The target JavaScript object to set its member value.
99+
/// @param index A subscript index to set value.
100+
/// @param kind A kind of JavaScript value to set the target object.
101+
/// @param payload1 The first payload of JavaScript value to set the target object.
102+
/// @param payload2 The second payload of JavaScript value to set the target object.
50103
__attribute__((__import_module__("javascript_kit"),
51-
__import_name__("swjs_get_subscript"))) extern void
52-
_get_subscript(const JavaScriptObjectRef _this, const int length,
53-
JavaScriptValueKind *kind, JavaScriptPayload1 *payload1,
54-
JavaScriptPayload2 *payload2);
55-
104+
__import_name__("swjs_set_subscript")))
105+
extern void _set_subscript(const JavaScriptObjectRef _this,
106+
const int index,
107+
const JavaScriptValueKind kind,
108+
const JavaScriptPayload1 payload1,
109+
const JavaScriptPayload2 payload2);
110+
111+
/// `_get_subscript` gets a value of `_this` JavaScript object.
112+
///
113+
/// @param _this The target JavaScript object to get its member value.
114+
/// @param index A subscript index to get value.
115+
/// @param kind A result pointer of JavaScript value kind to get.
116+
/// @param payload1 A result pointer of first payload of JavaScript value to get the target object.
117+
/// @param payload2 A result pointer of second payload of JavaScript value to get the target object.
56118
__attribute__((__import_module__("javascript_kit"),
57-
__import_name__("swjs_encode_string"))) extern int
58-
_encode_string(const JavaScriptObjectRef str_obj, JavaScriptObjectRef *bytes_ptr_result);
59-
119+
__import_name__("swjs_get_subscript")))
120+
extern void _get_subscript(const JavaScriptObjectRef _this,
121+
const int index,
122+
JavaScriptValueKind *kind,
123+
JavaScriptPayload1 *payload1,
124+
JavaScriptPayload2 *payload2);
125+
126+
/// `_encode_string` encodes the `str_obj` to bytes sequence and returns the length of bytes.
127+
///
128+
/// @param str_obj A JavaScript string object ref to encode.
129+
/// @param bytes_result A result pointer of bytes sequence representation in JavaScript.
130+
/// This value will be used to load the actual bytes using `_load_string`.
131+
/// @result The length of bytes sequence. This value will be used to allocate Swift side string buffer to load the actual bytes.
60132
__attribute__((__import_module__("javascript_kit"),
61-
__import_name__("swjs_decode_string"))) extern JavaScriptObjectRef
62-
_decode_string(const unsigned char *bytes_ptr, const int length);
63-
133+
__import_name__("swjs_encode_string")))
134+
extern int _encode_string(const JavaScriptObjectRef str_obj, JavaScriptObjectRef *bytes_result);
135+
136+
/// `_decode_string` decodes the given bytes sequence into JavaScript string object.
137+
///
138+
/// @param bytes_ptr A `uint8_t` byte sequence to decode.
139+
/// @param length The length of `bytes_ptr`.
140+
/// @result The decoded JavaScript string object.
64141
__attribute__((__import_module__("javascript_kit"),
65-
__import_name__("swjs_load_string"))) extern void
66-
_load_string(const JavaScriptObjectRef ref, unsigned char *buffer);
142+
__import_name__("swjs_decode_string")))
143+
extern JavaScriptObjectRef _decode_string(const unsigned char *bytes_ptr, const int length);
67144

145+
/// `_load_string` loads the actual bytes sequence of `bytes` into `buffer` which is a Swift side memory address.
146+
///
147+
/// @param bytes A bytes sequence representation in JavaScript to load. This value should be derived from `_encode_string`.
148+
/// @param buffer A Swift side string buffer to load the bytes.
68149
__attribute__((__import_module__("javascript_kit"),
69-
__import_name__("swjs_call_function"))) extern void
70-
_call_function(const JavaScriptObjectRef ref, const RawJSValue *argv,
71-
const int argc, JavaScriptValueKind *result_kind,
72-
JavaScriptPayload1 *result_payload1,
73-
JavaScriptPayload2 *result_payload2);
74-
150+
__import_name__("swjs_load_string")))
151+
extern void _load_string(const JavaScriptObjectRef bytes, unsigned char *buffer);
152+
153+
/// `_call_function` calls JavaScript function with given arguments list.
154+
///
155+
/// @param ref The target JavaScript function to call.
156+
/// @param argv A list of `RawJSValue` arguments to apply.
157+
/// @param argc The length of `argv``.
158+
/// @param result_kind A result pointer of JavaScript value kind to get.
159+
/// @param result_payload1 A result pointer of first payload of JavaScript value to set the target object.
160+
/// @param result_payload2 A result pointer of second payload of JavaScript value to set the target object.
75161
__attribute__((__import_module__("javascript_kit"),
76-
__import_name__("swjs_call_function_with_this"))) extern void
77-
_call_function_with_this(const JavaScriptObjectRef _this,
78-
const JavaScriptObjectRef func_ref,
79-
const RawJSValue *argv, const int argc,
80-
JavaScriptValueKind *result_kind,
81-
JavaScriptPayload1 *result_payload1,
82-
JavaScriptPayload2 *result_payload2);
83-
162+
__import_name__("swjs_call_function")))
163+
extern void _call_function(const JavaScriptObjectRef ref, const RawJSValue *argv,
164+
const int argc, JavaScriptValueKind *result_kind,
165+
JavaScriptPayload1 *result_payload1,
166+
JavaScriptPayload2 *result_payload2);
167+
168+
/// `_call_function_with_this` calls JavaScript function with given arguments list and given `_this`.
169+
///
170+
/// @param _this The value of `this` provided for the call to `func_ref`.
171+
/// @param func_ref The target JavaScript function to call.
172+
/// @param argv A list of `RawJSValue` arguments to apply.
173+
/// @param argc The length of `argv``.
174+
/// @param result_kind A result pointer of JavaScript value kind to get.
175+
/// @param result_payload1 A result pointer of first payload of JavaScript value to set the target object.
176+
/// @param result_payload2 A result pointer of second payload of JavaScript value to set the target object.
84177
__attribute__((__import_module__("javascript_kit"),
85-
__import_name__("swjs_call_new"))) extern void
86-
_call_new(const JavaScriptObjectRef ref, const RawJSValue *argv, const int argc,
87-
JavaScriptObjectRef *result_obj);
88-
178+
__import_name__("swjs_call_function_with_this")))
179+
extern void _call_function_with_this(const JavaScriptObjectRef _this,
180+
const JavaScriptObjectRef func_ref,
181+
const RawJSValue *argv, const int argc,
182+
JavaScriptValueKind *result_kind,
183+
JavaScriptPayload1 *result_payload1,
184+
JavaScriptPayload2 *result_payload2);
185+
186+
/// `_call_new` calls JavaScript object constructor with given arguments list.
187+
///
188+
/// @param ref The target JavaScript constructor to call.
189+
/// @param argv A list of `RawJSValue` arguments to apply.
190+
/// @param argc The length of `argv``.
191+
/// @param result_obj A result pointer of the constructed object.
89192
__attribute__((__import_module__("javascript_kit"),
90-
__import_name__("swjs_instanceof"))) extern bool
91-
_instanceof(const JavaScriptObjectRef obj,
92-
const JavaScriptObjectRef constructor);
93-
193+
__import_name__("swjs_call_new")))
194+
extern void _call_new(const JavaScriptObjectRef ref,
195+
const RawJSValue *argv, const int argc,
196+
JavaScriptObjectRef *result_obj);
197+
198+
/// `_instanceof` acts like JavaScript `instanceof` operator.
199+
///
200+
/// @param obj The target object to check its prototype chain.
201+
/// @param constructor The `constructor` object to check against.
202+
/// @result Return `true` if `constructor` appears anywhere in the prototype chain of `obj`. Return `false` if not.
94203
__attribute__((__import_module__("javascript_kit"),
95-
__import_name__("swjs_create_function"))) extern void
96-
_create_function(const JavaScriptHostFuncRef host_func_id,
97-
const JavaScriptObjectRef *func_ref_ptr);
98-
204+
__import_name__("swjs_instanceof")))
205+
extern bool _instanceof(const JavaScriptObjectRef obj,
206+
const JavaScriptObjectRef constructor);
207+
208+
/// `_create_function` creates a JavaScript thunk function that calls Swift side closure.
209+
/// See also comments on JSFunction.swift
210+
///
211+
/// @param host_func_id The target Swift side function called by the created thunk function.
212+
/// @param func_ref_ptr A result pointer of created thunk function.
99213
__attribute__((__import_module__("javascript_kit"),
100-
__import_name__("swjs_release"))) extern void
101-
_release(const JavaScriptObjectRef ref);
214+
__import_name__("swjs_create_function")))
215+
extern void _create_function(const JavaScriptHostFuncRef host_func_id,
216+
const JavaScriptObjectRef *func_ref_ptr);
102217

218+
/// Decrements reference count of `ref` retained by `SwiftRuntimeHeap` in JavaScript side.
219+
///
220+
/// @param ref The target JavaScript object.
221+
__attribute__((__import_module__("javascript_kit"),
222+
__import_name__("swjs_release")))
223+
extern void _release(const JavaScriptObjectRef ref);
224+
225+
/// Instantiate a new `TypedArray` object with given elements
226+
/// This is used to provide an efficient way to create `TypedArray`.
227+
///
228+
/// @param constructor The `TypedArray` constructor.
229+
/// @param elements_ptr The elements pointer to initialize. They are assumed to be the same size of `constructor` elements size.
230+
/// @param length The length of `elements_ptr`
231+
/// @param result_obj A result pointer of the constructed object.
103232
__attribute__((__import_module__("javascript_kit"),
104-
__import_name__("swjs_create_typed_array"))) extern void
105-
_create_typed_array(const JavaScriptObjectRef constructor,
106-
const void *elementsPtr, const int length,
107-
JavaScriptObjectRef *result_obj);
233+
__import_name__("swjs_create_typed_array")))
234+
extern void _create_typed_array(const JavaScriptObjectRef constructor,
235+
const void *elements_ptr, const int length,
236+
JavaScriptObjectRef *result_obj);
108237

109238
#endif
110239

0 commit comments

Comments
 (0)