Skip to content

Commit c546244

Browse files
authored
fix: Support lifting/lowering of functions as internrefs (#2382)
1 parent c74ef5e commit c546244

File tree

14 files changed

+935
-693
lines changed

14 files changed

+935
-693
lines changed

src/bindings/js.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -799,11 +799,13 @@ export class JSBuilder extends ExportsWalker {
799799
}
800800
`);
801801
}
802+
if (this.needsLiftInternref || this.needsLowerInternref) {
803+
sb.push(" class Internref extends Number {}\n");
804+
}
802805
if (this.needsLiftInternref) {
803806
this.needsRetain = true;
804807
this.needsRelease = true;
805808
sb.push(` const registry = new FinalizationRegistry(__release);
806-
class Internref extends Number {}
807809
function __liftInternref(pointer) {
808810
if (!pointer) return null;
809811
const sentinel = new Internref(__retain(pointer));
@@ -1031,7 +1033,7 @@ export class JSBuilder extends ExportsWalker {
10311033
makeLowerToValue(name: string, type: Type, sb: string[] = this.sb): void {
10321034
if (type.isInternalReference) {
10331035
// Lower reference types
1034-
const clazz = assert(type.getClass());
1036+
const clazz = assert(type.getClassOrWrapper(this.program));
10351037
if (clazz.extends(this.program.arrayBufferInstance.prototype)) {
10361038
sb.push("__lowerBuffer(");
10371039
this.needsLowerBuffer = true;

tests/compiler/bindings/esm.debug.d.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,21 +124,32 @@ export declare function arrayFunction(a: Array<number>, b: Array<number>): Array
124124
* @param b `bindings/esm/PlainObject`
125125
* @returns `bindings/esm/PlainObject`
126126
*/
127-
export declare function objectFunction(a: __Record10<undefined>, b: __Record10<undefined>): __Record10<never>;
127+
export declare function objectFunction(a: __Record11<undefined>, b: __Record11<undefined>): __Record11<never>;
128128
/**
129129
* bindings/esm/newInternref
130130
* @returns `bindings/esm/NonPlainObject`
131131
*/
132-
export declare function newInternref(): __Internref13;
132+
export declare function newInternref(): __Internref14;
133133
/**
134134
* bindings/esm/internrefFunction
135135
* @param a `bindings/esm/NonPlainObject`
136136
* @param b `bindings/esm/NonPlainObject`
137137
* @returns `bindings/esm/NonPlainObject`
138138
*/
139-
export declare function internrefFunction(a: __Internref13, b: __Internref13): __Internref13;
139+
export declare function internrefFunction(a: __Internref14, b: __Internref14): __Internref14;
140+
/**
141+
* bindings/esm/functionFunction
142+
* @param fn `() => void`
143+
* @returns `() => void`
144+
*/
145+
export declare function functionFunction(fn: __Internref3): __Internref3;
146+
/** bindings/esm/fn */
147+
export declare const fn: {
148+
/** @type `() => void` */
149+
get value(): __Internref3
150+
};
140151
/** bindings/esm/PlainObject */
141-
declare interface __Record10<TOmittable> {
152+
declare interface __Record11<TOmittable> {
142153
/** @type `i8` */
143154
a: number | TOmittable;
144155
/** @type `i16` */
@@ -173,6 +184,10 @@ declare interface __Record10<TOmittable> {
173184
p: Array<string> | null | TOmittable;
174185
}
175186
/** bindings/esm/NonPlainObject */
176-
declare class __Internref13 extends Number {
177-
private __nominal13: symbol;
187+
declare class __Internref14 extends Number {
188+
private __nominal14: symbol;
189+
}
190+
/** ~lib/function/Function<%28%29=>void> */
191+
declare class __Internref3 extends Number {
192+
private __nominal3: symbol;
178193
}

tests/compiler/bindings/esm.debug.js

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ async function instantiate(module, imports = {}) {
127127
},
128128
typedarrayFunction(a, b) {
129129
// bindings/esm/typedarrayFunction(~lib/typedarray/Int16Array, ~lib/typedarray/Float32Array) => ~lib/typedarray/Uint64Array
130-
a = __retain(__lowerTypedArray(Int16Array, 3, 1, a) || __notnull());
131-
b = __lowerTypedArray(Float32Array, 4, 2, b) || __notnull();
130+
a = __retain(__lowerTypedArray(Int16Array, 4, 1, a) || __notnull());
131+
b = __lowerTypedArray(Float32Array, 5, 2, b) || __notnull();
132132
try {
133133
return __liftTypedArray(BigUint64Array, exports.typedarrayFunction(a, b) >>> 0);
134134
} finally {
@@ -137,8 +137,8 @@ async function instantiate(module, imports = {}) {
137137
},
138138
staticarrayFunction(a, b) {
139139
// bindings/esm/staticarrayFunction(~lib/staticarray/StaticArray<i32>, ~lib/staticarray/StaticArray<i32>) => ~lib/staticarray/StaticArray<i32>
140-
a = __retain(__lowerStaticArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 6, 2, a, Int32Array) || __notnull());
141-
b = __lowerStaticArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 6, 2, b, Int32Array) || __notnull();
140+
a = __retain(__lowerStaticArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 7, 2, a, Int32Array) || __notnull());
141+
b = __lowerStaticArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 7, 2, b, Int32Array) || __notnull();
142142
try {
143143
return __liftStaticArray(pointer => new Int32Array(memory.buffer)[pointer >>> 2], 2, exports.staticarrayFunction(a, b) >>> 0);
144144
} finally {
@@ -147,18 +147,18 @@ async function instantiate(module, imports = {}) {
147147
},
148148
staticarrayU16(a) {
149149
// bindings/esm/staticarrayU16(~lib/staticarray/StaticArray<u16>) => ~lib/staticarray/StaticArray<u16>
150-
a = __lowerStaticArray((pointer, value) => { new Uint16Array(memory.buffer)[pointer >>> 1] = value; }, 7, 1, a, Uint16Array) || __notnull();
150+
a = __lowerStaticArray((pointer, value) => { new Uint16Array(memory.buffer)[pointer >>> 1] = value; }, 8, 1, a, Uint16Array) || __notnull();
151151
return __liftStaticArray(pointer => new Uint16Array(memory.buffer)[pointer >>> 1], 1, exports.staticarrayU16(a) >>> 0);
152152
},
153153
staticarrayI64(a) {
154154
// bindings/esm/staticarrayI64(~lib/staticarray/StaticArray<i64>) => ~lib/staticarray/StaticArray<i64>
155-
a = __lowerStaticArray((pointer, value) => { new BigInt64Array(memory.buffer)[pointer >>> 3] = value || 0n; }, 8, 3, a, BigInt64Array) || __notnull();
155+
a = __lowerStaticArray((pointer, value) => { new BigInt64Array(memory.buffer)[pointer >>> 3] = value || 0n; }, 9, 3, a, BigInt64Array) || __notnull();
156156
return __liftStaticArray(pointer => new BigInt64Array(memory.buffer)[pointer >>> 3], 3, exports.staticarrayI64(a) >>> 0);
157157
},
158158
arrayFunction(a, b) {
159159
// bindings/esm/arrayFunction(~lib/array/Array<i32>, ~lib/array/Array<i32>) => ~lib/array/Array<i32>
160-
a = __retain(__lowerArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 9, 2, a) || __notnull());
161-
b = __lowerArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 9, 2, b) || __notnull();
160+
a = __retain(__lowerArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 10, 2, a) || __notnull());
161+
b = __lowerArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 10, 2, b) || __notnull();
162162
try {
163163
return __liftArray(pointer => new Int32Array(memory.buffer)[pointer >>> 2], 2, exports.arrayFunction(a, b) >>> 0);
164164
} finally {
@@ -167,10 +167,10 @@ async function instantiate(module, imports = {}) {
167167
},
168168
objectFunction(a, b) {
169169
// bindings/esm/objectFunction(bindings/esm/PlainObject, bindings/esm/PlainObject) => bindings/esm/PlainObject
170-
a = __retain(__lowerRecord10(a) || __notnull());
171-
b = __lowerRecord10(b) || __notnull();
170+
a = __retain(__lowerRecord11(a) || __notnull());
171+
b = __lowerRecord11(b) || __notnull();
172172
try {
173-
return __liftRecord10(exports.objectFunction(a, b) >>> 0);
173+
return __liftRecord11(exports.objectFunction(a, b) >>> 0);
174174
} finally {
175175
__release(a);
176176
}
@@ -189,12 +189,24 @@ async function instantiate(module, imports = {}) {
189189
__release(a);
190190
}
191191
},
192+
functionFunction(fn) {
193+
// bindings/esm/functionFunction(() => void) => () => void
194+
fn = __lowerInternref(fn) || __notnull();
195+
return __liftInternref(exports.functionFunction(fn) >>> 0);
196+
},
197+
fn: {
198+
// bindings/esm/fn: () => void
199+
valueOf() { return this.value; },
200+
get value() {
201+
return __liftInternref(exports.fn.value >>> 0);
202+
}
203+
},
192204
}, exports);
193-
function __lowerRecord10(value) {
205+
function __lowerRecord11(value) {
194206
// bindings/esm/PlainObject
195207
// Hint: Opt-out from lowering as a record by providing an empty constructor
196208
if (value == null) return 0;
197-
const pointer = exports.__pin(exports.__new(68, 10));
209+
const pointer = exports.__pin(exports.__new(68, 11));
198210
new Int8Array(memory.buffer)[pointer + 0 >>> 0] = value.a;
199211
new Int16Array(memory.buffer)[pointer + 2 >>> 1] = value.b;
200212
new Int32Array(memory.buffer)[pointer + 4 >>> 2] = value.c;
@@ -209,12 +221,12 @@ async function instantiate(module, imports = {}) {
209221
new Float32Array(memory.buffer)[pointer + 44 >>> 2] = value.l;
210222
new Float64Array(memory.buffer)[pointer + 48 >>> 3] = value.m;
211223
new Uint32Array(memory.buffer)[pointer + 56 >>> 2] = __lowerString(value.n);
212-
new Uint32Array(memory.buffer)[pointer + 60 >>> 2] = __lowerTypedArray(Uint8Array, 11, 0, value.o);
213-
new Uint32Array(memory.buffer)[pointer + 64 >>> 2] = __lowerArray((pointer, value) => { new Uint32Array(memory.buffer)[pointer >>> 2] = __lowerString(value) || __notnull(); }, 12, 2, value.p);
224+
new Uint32Array(memory.buffer)[pointer + 60 >>> 2] = __lowerTypedArray(Uint8Array, 12, 0, value.o);
225+
new Uint32Array(memory.buffer)[pointer + 64 >>> 2] = __lowerArray((pointer, value) => { new Uint32Array(memory.buffer)[pointer >>> 2] = __lowerString(value) || __notnull(); }, 13, 2, value.p);
214226
exports.__unpin(pointer);
215227
return pointer;
216228
}
217-
function __liftRecord10(pointer) {
229+
function __liftRecord11(pointer) {
218230
// bindings/esm/PlainObject
219231
// Hint: Opt-out from lifting as a record by providing an empty constructor
220232
if (!pointer) return null;
@@ -337,8 +349,8 @@ async function instantiate(module, imports = {}) {
337349
exports.__unpin(buffer);
338350
return buffer;
339351
}
340-
const registry = new FinalizationRegistry(__release);
341352
class Internref extends Number {}
353+
const registry = new FinalizationRegistry(__release);
342354
function __liftInternref(pointer) {
343355
if (!pointer) return null;
344356
const sentinel = new Internref(__retain(pointer));
@@ -395,7 +407,9 @@ export const {
395407
arrayFunction,
396408
objectFunction,
397409
newInternref,
398-
internrefFunction
410+
internrefFunction,
411+
functionFunction,
412+
fn
399413
} = await (async url => instantiate(
400414
await (async () => {
401415
try { return await globalThis.WebAssembly.compileStreaming(globalThis.fetch(url)); }

0 commit comments

Comments
 (0)