webidl icon indicating copy to clipboard operation
webidl copied to clipboard

Help specifying WebAssembly.Function

Open Ms2ger opened this issue 5 years ago • 2 comments

There's a proposal to add WebAssembly.Function, which needs to kinda act like a function, but also has a static method (or an instance method) that returns the "type"; see https://github.com/WebAssembly/js-types/blob/cb08c70c3b62b5655e2b3b875ebfb3fa7fa46189/proposals/js-types/Overview.md#addition-of-webassemblyfunction. (There's an IDL snippet there, but it's meaningless given current IDL, afaict.)

How should I spec this? Is the proposed API even possible/desirable?

Ms2ger avatar Nov 12 '20 14:11 Ms2ger

For me, it's hard to understand what IDL would make sense here without first understanding the JS concepts it maps to. And I can't really get a sense of what that would be.

Could you help write some JS code that reifies WebAssembly.Function, and also shows how a wasmExport is connected to WebAssembly.Function?

domenic avatar Nov 12 '20 15:11 domenic

Could you help write some JS code that reifies WebAssembly.Function?

My understanding is that WebAssembly.Function instances are supposed to have a [[Call]] internal method (i.e.: their typeof is "function"), the following TypeScript‑like pseudocode demonstrates a way that could be accomplished:

/* Any copyright is dedicated to the Public Domain.
 * https://creativecommons.org/publicdomain/zero/1.0/ */

interface WebAssembly.Function {
	// Instances of `WasmFunction` are callable
	(...args: any): any;
}
class WebAssembly.Function extends globalThis.Function {
	/**
	 * The `[[FunctionAddress]]` internal slot.
	 *
	 * @see https://webassembly.github.io/spec/js-api/#exported-function-exotic-objects
	 */
	#FunctionAddress: number;

	constructor(type: FunctionType, func: globalThis.Function) {
		const parameters = Array.from(type.parameters, ToString);
		const results = Array.from(type.results, ToString);

		const F: WebAssembly.Function = Object.setPrototypeOf(
			/** @see https://webassembly.github.io/spec/js-api/#call-an-exported-function */
			(...args: unknown[]) => call_exported_function(F.#FunctionAddress, args),
			new.target.prototype,
		);

		/** @see https://github.com/littledan/proposal-new-initialize */
		new.initialize(F);

		/** @see https://webassembly.github.io/spec/js-api/#create-a-host-function */
		F.#FunctionAddress = create_host_function(func, {
			paramTypes: parameters,
			resultTypes: results,
		});

		return F;
	}

	type(): FunctionType {
		/** @see https://webassembly.github.io/spec/js-api/#associated-store */
		const store = surroundingAgent.wasmStore;

		/** @see https://webassembly.github.io/spec/core/appendix/embedding.html#embed-func-type */
		const functype = func_type(store, this.#FunctionAddress);

		return {
			parameters: Array.from(functype.paramTypes),
			results: Array.from(functype.resultTypes),
		};
	}
}

ExE-Boss avatar Aug 12 '21 14:08 ExE-Boss