1

Is it possible to pass a Javascript ref type to assemblyScript solely for the purposes of being retrieved again later? To be clear, I do not want to access the JS object from the WASM side in any way. So no typing should be necessary, I literally want to ‘associate’ a WASM class instance with a corresponding JS instance, such that the JS side can set and retrieve its own ref in the WASM class;

AssemblyScript would look something like;

export function setRef(node: Node, jsRef: i32): void {
    node.jsRef = jsRef;
}

export function getRef(node: Node): i32 {
    return node.jsRef;
}

I cannot find any info that describes this or a similar scenario. Without this I am having to maintain a mapping on the JS side with all the huge performance implications that implies.

Using i32 my references get passed as zero and if I use externref instead the compiler crashes

spike
  • 11
  • 3
  • 1
    This functionality is actually supported if you import your AS module through `./build/release.js`. So if your JS file is `myProject/lib/entry.js` then inside `entry.js` import exported AS files like `import * as SomeNamespace from "../build/release.js";`. The class instances from AS side are passed to JS side as an opaque object (just a ref) and you can set any field of them through exported AS side functions like `setRef(opaque, 857)` or `getRef(opaque)` from the JS side. Explained [here](https://www.assemblyscript.org/compiler.html#host-bindings). – Redu Nov 25 '22 at 17:11
  • Doesn't work for reference types. Primitive types sure :) as in the 857 in your example. String types, also (a special case - they are in fact copied meaning the original ref is not preserved). But general object references get zeroed out. This is done on the AS side so there is no real scope for modifying the auto generated build/release.js file – spike Nov 26 '22 at 19:35
  • You can pass objects from AS side to JS side as opaque. Which means you can address and read/write their properties from the JS side through the exported functions. This mechanism also ensures that once the opaque object at the JS side get GCed it also gets GCed from the AS side as `release.js` keeps track of them and does `__unpin(pointer)`. You say you want to pass a JS object to AS side to "associate" it with an AS counterpart. Can you not wire up your logic the opposite way like passing the corresponding AS object from AS side to JS side to automate this job? – Redu Nov 26 '22 at 22:17
  • I think the opaque objects passed to JS side are just simple numeric reference objects based on instances of the `Internref` class which is a simple extension of `Number`. So they are Number objects eligible to GC collections and also registered in a [FinalizationRegistry](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry). Once your JS code do not reference them anymore they get GCed and the FR callback invokes `__unpin(pointer)` to get the AS side counterpart get cleaned up too. – Redu Nov 26 '22 at 22:31
  • Unfortunately I have a specific requirement that given an AS opaque ref I need to be able to derive the jsRef object. This is because a 'tree' of nodes is maintained on the AS side (for perf reasons) and so on only the AS side knows how to navigate the tree. When I call out to JS I need to look up the corresponding JS object. I posted on AssemblyScript discord and discovered that this 'could' be done with tables except that AS doesn't support them as yet – spike Nov 26 '22 at 22:57
  • Also there seems to be a related [issue](https://github.com/AssemblyScript/assemblyscript/issues/1620) you may also mention your requirement there. Besides if you plan to do this reference trafficing very often i suspect it's overhead might have a significant negative effect on the overall performance. – Redu Nov 26 '22 at 23:22
  • Exactly :) I'll link my requirement like u suggested. cheers – spike Nov 26 '22 at 23:29

0 Answers0