assemblyscript icon indicating copy to clipboard operation
assemblyscript copied to clipboard

[FR] Passing any JavaScript object/class to AssemblyScript

Open aminya opened this issue 4 years ago • 23 comments

It would be nice if AssemblyScript adds support for passing any JavaScript object/class to WASM using variants. This is similar to how node-addon-api supports passing any JavaScript object as Napi::Object. The calls to the methods and getter/setters will happen on the JS side.

The goal is to make it easier to pass random objects to AssemblyScript without the need for writing the types for it (the efficiency is not a priority).

The proposed syntax

function asFunc(obj: JS.Object) {

	// getting values
	const x = obj.get(1) as string
	
	// setting values
	obj.set(2, 1)
}

As a bonus, optional typing might be provided for a subset of the object that is needed:

// a subset of the object which is typed
interface MyObject {
	desiredMethod(a: i32): i32
}

function asFunc(obj: JS.Object) {
	const x = obj as MyObject
	x.desiredMethod()
}

This is different from the reference-type proposal, which is not supported in many environments, and waiting for it may take a long time. The same syntax might be used later with a more efficient backend implementation using reference types.

The possible implementation will look like this: https://github.com/nearprotocol/assemblyscript-json/blob/master/assembly/JSON.ts#L103 https://github.com/nearprotocol/assemblyscript-json/blob/master/assembly/JSON.ts#L202

P.S: I already discussed this with @MaxGraey in the discord chat.

aminya avatar Jan 11 '21 23:01 aminya

How would the object be referenced from within Wasm, if not with a reference type? And how would the compiler determine the intention of the programmer, to generate the necessary typed imports to interface with the object, if there are no types?

dcodeIO avatar Jan 11 '21 23:01 dcodeIO

Emscripten already does it: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#using-val-to-transliterate-javascript-to-c

aminya avatar Jan 12 '21 00:01 aminya

I already suggested this in Discord and duplicating here. With reference types it will be much more powerful and simpler. Something like:

@external("webapi", "DOMNode")
interface DOMNodeExternal {
  replaceChild(oldNode: DOMNodeExternal, newNode: DOMNodeExternal): DOMNodeExternal;
  ...
}

type DOMNode = Externref<DOMNodeExternal>

export function replaceChild(old: DOMNode, new_: DOMNode): DOMNode {
  return old.replaceChild(old, new_);
}

And you don't need expensive Variant accessor. But reftypes (externref) still very experimental and required more adoption from compiler for that. Externref<T> here is builtin proxy object which support and handled by compiler which automatically wrap every field with some Reflect's method.

MaxGraey avatar Jan 12 '21 00:01 MaxGraey

But reftypes (externref) still very experimental and required more adoption from compiler for that

Can we have something less efficient for now, so we can start thinking about using WASM? Without this, it is impossible for me to port some of my apps to WASM.

If we choose a good syntax, the same thing can be used for reference types which makes the later transition to actual reference types as easy as upgrading the AssemblyScript.

aminya avatar Jan 12 '21 05:01 aminya

Can we have something less efficient for now, so we can start thinking about using WASM?

Of course it's possible, but someone has to spend time on it. That's the main problem. But I agree, it would provide a way to start writing code now that would get a performance boost from reference types later, without existing user code changing much (if at all).

Can it be done as a library for AS (not in core)?

Whatever the solution will be, I hope we can keep it valid TypeScript syntax. In the previous example,

@external("webapi", "DOMNode")
interface DOMNodeExternal {
  replaceChild(oldNode: DOMNodeExternal, newNode: DOMNodeExternal): DOMNodeExternal;
  ...
}

decorators are not allowed there in TypeScript.

trusktr avatar Jan 13 '21 03:01 trusktr

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in one week if no further activity occurs. Thank you for your contributions!

github-actions[bot] avatar Jun 02 '21 00:06 github-actions[bot]

Unstale

aminya avatar Jun 07 '21 23:06 aminya

I have a related requirement; https://stackoverflow.com/questions/74554478/passing-javascript-references-to-assemblyscript

spikewoodman avatar Nov 26 '22 23:11 spikewoodman