@effindomv2/fui-as 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser/src/common-harness/managed-harness.ts +113 -0
- package/browser/src/host-events.ts +22 -1
- package/browser/src/host-services.ts +290 -10
- package/browser/src/worker-bootstrap.ts +27 -0
- package/package.json +1 -1
- package/scripts/build-demo-as.sh +36 -6
- package/scripts/build.sh +66 -6
- package/scripts/framework-host-services.ts +40 -0
- package/scripts/generate-host-events.ts +79 -6
- package/scripts/generate-host-services.ts +132 -15
- package/src/FuiPrimitives.ts +11 -1
- package/src/core/ffi.ts +8 -15
- package/src/core/generated/FrameworkHostServices.ts +36 -0
- package/src/host-services/runtime.ts +74 -1
|
@@ -21,6 +21,11 @@ function relativeImport(fromFile: string, targetFile: string): string {
|
|
|
21
21
|
return toPosix(relative);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
function sourcePathForHeader(sourceModulePath: string): string {
|
|
25
|
+
const relative = path.relative(process.cwd(), sourceModulePath);
|
|
26
|
+
return toPosix(relative.startsWith(".") ? relative : `./${relative}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
24
29
|
function asTypeName(type: HostServiceTypeName): string {
|
|
25
30
|
switch (type) {
|
|
26
31
|
case "string":
|
|
@@ -29,28 +34,71 @@ function asTypeName(type: HostServiceTypeName): string {
|
|
|
29
34
|
return "bool";
|
|
30
35
|
case "i32":
|
|
31
36
|
return "i32";
|
|
37
|
+
case "u32":
|
|
38
|
+
return "u32";
|
|
39
|
+
case "i64":
|
|
40
|
+
return "i64";
|
|
41
|
+
case "u64":
|
|
42
|
+
return "u64";
|
|
32
43
|
case "f64":
|
|
33
44
|
return "f64";
|
|
45
|
+
case "bytes":
|
|
46
|
+
return "Uint8Array";
|
|
47
|
+
case "i32_array":
|
|
48
|
+
return "Int32Array";
|
|
49
|
+
case "u32_array":
|
|
50
|
+
return "Uint32Array";
|
|
51
|
+
case "i64_array":
|
|
52
|
+
return "Int64Array";
|
|
53
|
+
case "u64_array":
|
|
54
|
+
return "Uint64Array";
|
|
55
|
+
case "f64_array":
|
|
56
|
+
return "Float64Array";
|
|
34
57
|
case "void":
|
|
35
58
|
return "void";
|
|
36
59
|
}
|
|
37
60
|
}
|
|
38
61
|
|
|
39
|
-
function
|
|
62
|
+
function isPointerLengthType(type: HostServiceTypeName): boolean {
|
|
63
|
+
return type === "string" ||
|
|
64
|
+
type === "bytes" ||
|
|
65
|
+
type === "i32_array" ||
|
|
66
|
+
type === "u32_array" ||
|
|
67
|
+
type === "i64_array" ||
|
|
68
|
+
type === "u64_array" ||
|
|
69
|
+
type === "f64_array";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function returnsBufferType(type: HostServiceTypeName): boolean {
|
|
73
|
+
return type === "string" ||
|
|
74
|
+
type === "bytes" ||
|
|
75
|
+
type === "i32_array" ||
|
|
76
|
+
type === "u32_array" ||
|
|
77
|
+
type === "i64_array" ||
|
|
78
|
+
type === "u64_array" ||
|
|
79
|
+
type === "f64_array";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function emitExternalSignature(
|
|
83
|
+
importName: string,
|
|
84
|
+
args: readonly HostServiceTypeName[],
|
|
85
|
+
returns: HostServiceTypeName,
|
|
86
|
+
moduleName: string,
|
|
87
|
+
): string {
|
|
40
88
|
const signatureParts: Array<string> = [];
|
|
41
89
|
args.forEach((type, index) => {
|
|
42
|
-
if (type
|
|
90
|
+
if (isPointerLengthType(type)) {
|
|
43
91
|
signatureParts.push(`arg${String(index)}Ptr: usize`, `arg${String(index)}Len: u32`);
|
|
44
92
|
return;
|
|
45
93
|
}
|
|
46
94
|
signatureParts.push(`arg${String(index)}: ${asTypeName(type)}`);
|
|
47
95
|
});
|
|
48
|
-
if (returns
|
|
96
|
+
if (returnsBufferType(returns)) {
|
|
49
97
|
signatureParts.push("resultPtr: usize", "resultCap: u32");
|
|
50
98
|
}
|
|
51
|
-
const returnType = returns
|
|
99
|
+
const returnType = returnsBufferType(returns) ? "u32" : asTypeName(returns);
|
|
52
100
|
return [
|
|
53
|
-
`@external("
|
|
101
|
+
`@external("${moduleName}", "${importName}")`,
|
|
54
102
|
`declare function __host_${importName}(${signatureParts.join(", ")}): ${returnType};`,
|
|
55
103
|
].join("\n");
|
|
56
104
|
}
|
|
@@ -61,6 +109,10 @@ function emitWrapper(importName: string, args: readonly HostServiceTypeName[], r
|
|
|
61
109
|
args.forEach((type, index) => {
|
|
62
110
|
if (type === "string") {
|
|
63
111
|
lines.push(` const arg${String(index)}Bytes = Uint8Array.wrap(String.UTF8.encode(arg${String(index)}, false));`);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (type === "bytes" || type === "i32_array" || type === "u32_array" || type === "i64_array" || type === "u64_array" || type === "f64_array") {
|
|
115
|
+
lines.push(` const arg${String(index)}Bytes = arg${String(index)};`);
|
|
64
116
|
}
|
|
65
117
|
});
|
|
66
118
|
const callArgs: Array<string> = [];
|
|
@@ -70,14 +122,38 @@ function emitWrapper(importName: string, args: readonly HostServiceTypeName[], r
|
|
|
70
122
|
callArgs.push(`<u32>arg${String(index)}Bytes.length`);
|
|
71
123
|
return;
|
|
72
124
|
}
|
|
125
|
+
if (type === "bytes") {
|
|
126
|
+
callArgs.push(`arg${String(index)}Bytes.length > 0 ? arg${String(index)}Bytes.dataStart : 0`);
|
|
127
|
+
callArgs.push(`<u32>arg${String(index)}Bytes.length`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (type === "i32_array" || type === "u32_array" || type === "i64_array" || type === "u64_array" || type === "f64_array") {
|
|
131
|
+
callArgs.push(`arg${String(index)}Bytes.length > 0 ? arg${String(index)}Bytes.dataStart : 0`);
|
|
132
|
+
callArgs.push(`<u32>arg${String(index)}Bytes.length`);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
73
135
|
callArgs.push(`arg${String(index)}`);
|
|
74
136
|
});
|
|
75
|
-
if (returns
|
|
137
|
+
if (returnsBufferType(returns)) {
|
|
76
138
|
lines.push(" const resultPtr = hostServiceResultBufferPtr();");
|
|
77
139
|
lines.push(" const resultCap = hostServiceResultBufferSize();");
|
|
78
140
|
callArgs.push("resultPtr", "resultCap");
|
|
79
141
|
lines.push(` const resultLen = __host_${importName}(${callArgs.join(", ")});`);
|
|
80
|
-
|
|
142
|
+
if (returns === "string") {
|
|
143
|
+
lines.push(` return decodeHostServiceStringResult(resultPtr, resultLen, "${importName}");`);
|
|
144
|
+
} else if (returns === "bytes") {
|
|
145
|
+
lines.push(` return decodeHostServiceBytesResult(resultPtr, resultLen, "${importName}");`);
|
|
146
|
+
} else if (returns === "i32_array") {
|
|
147
|
+
lines.push(` return decodeHostServiceI32ArrayResult(resultPtr, resultLen, "${importName}");`);
|
|
148
|
+
} else if (returns === "u32_array") {
|
|
149
|
+
lines.push(` return decodeHostServiceU32ArrayResult(resultPtr, resultLen, "${importName}");`);
|
|
150
|
+
} else if (returns === "i64_array") {
|
|
151
|
+
lines.push(` return decodeHostServiceI64ArrayResult(resultPtr, resultLen, "${importName}");`);
|
|
152
|
+
} else if (returns === "u64_array") {
|
|
153
|
+
lines.push(` return decodeHostServiceU64ArrayResult(resultPtr, resultLen, "${importName}");`);
|
|
154
|
+
} else {
|
|
155
|
+
lines.push(` return decodeHostServiceF64ArrayResult(resultPtr, resultLen, "${importName}");`);
|
|
156
|
+
}
|
|
81
157
|
} else if (returns === "void") {
|
|
82
158
|
lines.push(` __host_${importName}(${callArgs.join(", ")});`);
|
|
83
159
|
} else {
|
|
@@ -118,19 +194,51 @@ function emitBindingsFile(
|
|
|
118
194
|
exportName: string,
|
|
119
195
|
outputPath: string,
|
|
120
196
|
methods: ReturnType<typeof listHostServiceMethods>,
|
|
197
|
+
primitivesImportOverride: string | undefined,
|
|
198
|
+
moduleName: string,
|
|
121
199
|
): string {
|
|
122
|
-
const runtimeImport = relativeImport(outputPath, path.resolve(PACKAGE_DIR, "src/FuiPrimitives.ts"));
|
|
200
|
+
const runtimeImport = primitivesImportOverride ?? relativeImport(outputPath, path.resolve(PACKAGE_DIR, "src/FuiPrimitives.ts"));
|
|
123
201
|
const blocks: Array<string> = [
|
|
124
|
-
`// Generated by scripts/generate-host-services.ts from ${
|
|
202
|
+
`// Generated by scripts/generate-host-services.ts from ${sourcePathForHeader(sourceModulePath)}#${exportName}.`,
|
|
125
203
|
];
|
|
126
|
-
if (methods.some((method) => method.returns
|
|
127
|
-
|
|
204
|
+
if (methods.some((method) => returnsBufferType(method.returns))) {
|
|
205
|
+
const helpers = [
|
|
206
|
+
"hostServiceResultBufferPtr",
|
|
207
|
+
"hostServiceResultBufferSize",
|
|
208
|
+
...new Set(
|
|
209
|
+
methods
|
|
210
|
+
.map((method) => method.returns)
|
|
211
|
+
.filter((type) => returnsBufferType(type))
|
|
212
|
+
.map((type) => {
|
|
213
|
+
if (type === "string") {
|
|
214
|
+
return "decodeHostServiceStringResult";
|
|
215
|
+
}
|
|
216
|
+
if (type === "bytes") {
|
|
217
|
+
return "decodeHostServiceBytesResult";
|
|
218
|
+
}
|
|
219
|
+
if (type === "i32_array") {
|
|
220
|
+
return "decodeHostServiceI32ArrayResult";
|
|
221
|
+
}
|
|
222
|
+
if (type === "u32_array") {
|
|
223
|
+
return "decodeHostServiceU32ArrayResult";
|
|
224
|
+
}
|
|
225
|
+
if (type === "i64_array") {
|
|
226
|
+
return "decodeHostServiceI64ArrayResult";
|
|
227
|
+
}
|
|
228
|
+
if (type === "u64_array") {
|
|
229
|
+
return "decodeHostServiceU64ArrayResult";
|
|
230
|
+
}
|
|
231
|
+
return "decodeHostServiceF64ArrayResult";
|
|
232
|
+
}),
|
|
233
|
+
),
|
|
234
|
+
];
|
|
235
|
+
blocks.push(`import { ${helpers.join(", ")} } from "${runtimeImport}";`);
|
|
128
236
|
blocks.push("");
|
|
129
237
|
} else {
|
|
130
238
|
blocks.push("");
|
|
131
239
|
}
|
|
132
240
|
methods.forEach((method, index) => {
|
|
133
|
-
blocks.push(emitExternalSignature(method.importName, method.args, method.returns));
|
|
241
|
+
blocks.push(emitExternalSignature(method.importName, method.args, method.returns, moduleName));
|
|
134
242
|
blocks.push("");
|
|
135
243
|
blocks.push(emitWrapper(method.importName, method.args, method.returns));
|
|
136
244
|
if (index + 1 < methods.length) {
|
|
@@ -141,15 +249,24 @@ function emitBindingsFile(
|
|
|
141
249
|
}
|
|
142
250
|
|
|
143
251
|
async function main(): Promise<void> {
|
|
144
|
-
const [moduleArg, exportName, outputArg] = process.argv.slice(2);
|
|
252
|
+
const [moduleArg, exportName, outputArg, primitivesImportArg, hostModuleArg] = process.argv.slice(2);
|
|
145
253
|
if (moduleArg === undefined || exportName === undefined || outputArg === undefined) {
|
|
146
|
-
throw new Error(
|
|
254
|
+
throw new Error(
|
|
255
|
+
"Usage: generate-host-services <module-path> <export-name> <output-path> [primitives-import] [host-import-module]",
|
|
256
|
+
);
|
|
147
257
|
}
|
|
148
258
|
const modulePath = path.resolve(process.cwd(), moduleArg);
|
|
149
259
|
const outputPath = path.resolve(process.cwd(), outputArg);
|
|
150
260
|
const registry = await loadHostServices(modulePath, exportName);
|
|
151
261
|
const methods = listHostServiceMethods(registry as never);
|
|
152
|
-
const content = emitBindingsFile(
|
|
262
|
+
const content = emitBindingsFile(
|
|
263
|
+
modulePath,
|
|
264
|
+
exportName,
|
|
265
|
+
outputPath,
|
|
266
|
+
methods,
|
|
267
|
+
primitivesImportArg,
|
|
268
|
+
hostModuleArg ?? "fui_host_service",
|
|
269
|
+
);
|
|
153
270
|
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
154
271
|
await fs.writeFile(outputPath, content, "utf8");
|
|
155
272
|
}
|
package/src/FuiPrimitives.ts
CHANGED
|
@@ -12,4 +12,14 @@ export {
|
|
|
12
12
|
} from "./core/BoundCallback";
|
|
13
13
|
export { bind0, bind1, bind2, bindResult0, bindResult1 } from "./core/bind";
|
|
14
14
|
export { clearCurrentSelection, tryGetBounds } from "./bindings/ui";
|
|
15
|
-
export {
|
|
15
|
+
export {
|
|
16
|
+
decodeHostServiceBytesResult,
|
|
17
|
+
decodeHostServiceF64ArrayResult,
|
|
18
|
+
decodeHostServiceI64ArrayResult,
|
|
19
|
+
decodeHostServiceI32ArrayResult,
|
|
20
|
+
decodeHostServiceStringResult,
|
|
21
|
+
decodeHostServiceU64ArrayResult,
|
|
22
|
+
decodeHostServiceU32ArrayResult,
|
|
23
|
+
hostServiceResultBufferPtr,
|
|
24
|
+
hostServiceResultBufferSize,
|
|
25
|
+
} from "./host-services/runtime";
|
package/src/core/ffi.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export {
|
|
2
|
+
fui_get_accent_color,
|
|
3
|
+
fui_get_platform_family,
|
|
4
|
+
fui_is_coarse_pointer,
|
|
5
|
+
fui_is_dark_mode,
|
|
6
|
+
fui_now_ms,
|
|
7
|
+
} from "./generated/FrameworkHostServices";
|
|
8
|
+
|
|
1
9
|
export enum HandleValue {
|
|
2
10
|
Invalid = 0,
|
|
3
11
|
}
|
|
@@ -569,24 +577,9 @@ export declare function fui_start_timer(timerId: u32, delayMs: i32): void;
|
|
|
569
577
|
@external("fui_host", "fui_cancel_timer")
|
|
570
578
|
export declare function fui_cancel_timer(timerId: u32): void;
|
|
571
579
|
|
|
572
|
-
@external("fui_host", "fui_now_ms")
|
|
573
|
-
export declare function fui_now_ms(): f64;
|
|
574
|
-
|
|
575
580
|
@external("fui_host", "fui_set_cursor")
|
|
576
581
|
export declare function fui_set_cursor(style: u32): void;
|
|
577
582
|
|
|
578
|
-
@external("fui_host", "fui_is_dark_mode")
|
|
579
|
-
export declare function fui_is_dark_mode(): bool;
|
|
580
|
-
|
|
581
|
-
@external("fui_host", "fui_get_accent_color")
|
|
582
|
-
export declare function fui_get_accent_color(): u32;
|
|
583
|
-
|
|
584
|
-
@external("fui_host", "fui_get_platform_family")
|
|
585
|
-
export declare function fui_get_platform_family(): u32;
|
|
586
|
-
|
|
587
|
-
@external("fui_host", "fui_is_coarse_pointer")
|
|
588
|
-
export declare function fui_is_coarse_pointer(): bool;
|
|
589
|
-
|
|
590
583
|
@external("fui_host", "fui_show_url_preview")
|
|
591
584
|
export declare function fui_show_url_preview(ptr: usize, len: u32): void;
|
|
592
585
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Generated by scripts/generate-host-services.ts from ./scripts/framework-host-services.ts#frameworkHostServices.
|
|
2
|
+
|
|
3
|
+
@external("fui_host", "fui_get_accent_color")
|
|
4
|
+
declare function __host_fui_get_accent_color(): u32;
|
|
5
|
+
|
|
6
|
+
export function fui_get_accent_color(): u32 {
|
|
7
|
+
return __host_fui_get_accent_color();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@external("fui_host", "fui_get_platform_family")
|
|
11
|
+
declare function __host_fui_get_platform_family(): u32;
|
|
12
|
+
|
|
13
|
+
export function fui_get_platform_family(): u32 {
|
|
14
|
+
return __host_fui_get_platform_family();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@external("fui_host", "fui_is_coarse_pointer")
|
|
18
|
+
declare function __host_fui_is_coarse_pointer(): bool;
|
|
19
|
+
|
|
20
|
+
export function fui_is_coarse_pointer(): bool {
|
|
21
|
+
return __host_fui_is_coarse_pointer();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@external("fui_host", "fui_is_dark_mode")
|
|
25
|
+
declare function __host_fui_is_dark_mode(): bool;
|
|
26
|
+
|
|
27
|
+
export function fui_is_dark_mode(): bool {
|
|
28
|
+
return __host_fui_is_dark_mode();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@external("fui_host", "fui_now_ms")
|
|
32
|
+
declare function __host_fui_now_ms(): f64;
|
|
33
|
+
|
|
34
|
+
export function fui_now_ms(): f64 {
|
|
35
|
+
return __host_fui_now_ms();
|
|
36
|
+
}
|
|
@@ -8,7 +8,7 @@ export function hostServiceResultBufferSize(): u32 {
|
|
|
8
8
|
return __fui_text_buffer_size();
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
function assertResultByteLength(resultLen: u32, importName: string): void {
|
|
12
12
|
const capacity = __fui_text_buffer_size();
|
|
13
13
|
if (resultLen > capacity) {
|
|
14
14
|
throw new Error(
|
|
@@ -21,5 +21,78 @@ export function decodeHostServiceStringResult(resultPtr: usize, resultLen: u32,
|
|
|
21
21
|
".",
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function decodeHostServiceStringResult(resultPtr: usize, resultLen: u32, importName: string): string {
|
|
27
|
+
assertResultByteLength(resultLen, importName);
|
|
24
28
|
return resultLen == 0 ? "" : String.UTF8.decodeUnsafe(resultPtr, <usize>resultLen, false);
|
|
25
29
|
}
|
|
30
|
+
|
|
31
|
+
export function decodeHostServiceBytesResult(resultPtr: usize, resultLen: u32, importName: string): Uint8Array {
|
|
32
|
+
assertResultByteLength(resultLen, importName);
|
|
33
|
+
const bytes = new Uint8Array(<i32>resultLen);
|
|
34
|
+
if (resultLen > 0) {
|
|
35
|
+
memory.copy(bytes.dataStart, resultPtr, <usize>resultLen);
|
|
36
|
+
}
|
|
37
|
+
return bytes;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function decodeHostServiceI32ArrayResult(resultPtr: usize, resultLen: u32, importName: string): Int32Array {
|
|
41
|
+
assertResultByteLength(resultLen, importName);
|
|
42
|
+
if ((resultLen & 3) != 0) {
|
|
43
|
+
throw new Error("Host service " + importName + " returned misaligned Int32Array byte length.");
|
|
44
|
+
}
|
|
45
|
+
const values = new Int32Array(<i32>(resultLen >> 2));
|
|
46
|
+
if (resultLen > 0) {
|
|
47
|
+
memory.copy(values.dataStart, resultPtr, <usize>resultLen);
|
|
48
|
+
}
|
|
49
|
+
return values;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function decodeHostServiceU32ArrayResult(resultPtr: usize, resultLen: u32, importName: string): Uint32Array {
|
|
53
|
+
assertResultByteLength(resultLen, importName);
|
|
54
|
+
if ((resultLen & 3) != 0) {
|
|
55
|
+
throw new Error("Host service " + importName + " returned misaligned Uint32Array byte length.");
|
|
56
|
+
}
|
|
57
|
+
const values = new Uint32Array(<i32>(resultLen >> 2));
|
|
58
|
+
if (resultLen > 0) {
|
|
59
|
+
memory.copy(values.dataStart, resultPtr, <usize>resultLen);
|
|
60
|
+
}
|
|
61
|
+
return values;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function decodeHostServiceI64ArrayResult(resultPtr: usize, resultLen: u32, importName: string): Int64Array {
|
|
65
|
+
assertResultByteLength(resultLen, importName);
|
|
66
|
+
if ((resultLen & 7) != 0) {
|
|
67
|
+
throw new Error("Host service " + importName + " returned misaligned Int64Array byte length.");
|
|
68
|
+
}
|
|
69
|
+
const values = new Int64Array(<i32>(resultLen >> 3));
|
|
70
|
+
if (resultLen > 0) {
|
|
71
|
+
memory.copy(values.dataStart, resultPtr, <usize>resultLen);
|
|
72
|
+
}
|
|
73
|
+
return values;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function decodeHostServiceU64ArrayResult(resultPtr: usize, resultLen: u32, importName: string): Uint64Array {
|
|
77
|
+
assertResultByteLength(resultLen, importName);
|
|
78
|
+
if ((resultLen & 7) != 0) {
|
|
79
|
+
throw new Error("Host service " + importName + " returned misaligned Uint64Array byte length.");
|
|
80
|
+
}
|
|
81
|
+
const values = new Uint64Array(<i32>(resultLen >> 3));
|
|
82
|
+
if (resultLen > 0) {
|
|
83
|
+
memory.copy(values.dataStart, resultPtr, <usize>resultLen);
|
|
84
|
+
}
|
|
85
|
+
return values;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function decodeHostServiceF64ArrayResult(resultPtr: usize, resultLen: u32, importName: string): Float64Array {
|
|
89
|
+
assertResultByteLength(resultLen, importName);
|
|
90
|
+
if ((resultLen & 7) != 0) {
|
|
91
|
+
throw new Error("Host service " + importName + " returned misaligned Float64Array byte length.");
|
|
92
|
+
}
|
|
93
|
+
const values = new Float64Array(<i32>(resultLen >> 3));
|
|
94
|
+
if (resultLen > 0) {
|
|
95
|
+
memory.copy(values.dataStart, resultPtr, <usize>resultLen);
|
|
96
|
+
}
|
|
97
|
+
return values;
|
|
98
|
+
}
|