espruino / Espruino

The Espruino JavaScript interpreter - Official Repo
http://www.espruino.com/
Other
2.76k stars 743 forks source link

Feature request: Associate arbitrary, native-side app data with a JsVar #2414

Closed elima closed 1 year ago

elima commented 1 year ago

Checking JsVar API I couldn't find a way to associate some data to a variable that is not visible/accessible to the JS context, just to the native side.

Context: I own a BangleJs 2 and was experimenting with a new module where I need to expose a secret key object to JS, but not the key material, which would be associated with the JS object and retrievable only during native-side operations on that JS object.

I imagine there could be other use-cases where a native library would want to expose an object to the JS context, but not some of its internal data that would only be consumed/operated upon, in the native side.

Since I understand that growing JsVar struct with a void *user_data pointer is wasteful and would probably blow the stack, I wonder if there is other way to do that currently, or if others have had this use-case already and how was it solved.

gfwilliams commented 1 year ago

Normally what we do for that kind of thing is we just allocate a String/flat String containing the info and put it as a child of the variable - you can prefix the name with \xff to hide it from JS. For example this is what we do in Graphics to add a gfx variable with data in it:

>var b = Graphics.createArrayBuffer(8,8,1)
=Graphics: {
  buffer: new ArrayBuffer(8)
 }

so 'gfx' is not visible normally, but if you look inside with 'trace'...

>trace(b)
#10329[r1,l1] Object {
  #10281[r1,l2] Name String [2 blocks] "__proto__"    #19[r4,l0] Object {
      #20[r1,l2] Name String [2 blocks] "constructor"        #17[r3,l0] NativeFunction 0x5e451 (1) {
     .....
   }
  }
  #10332[r1,l2] Name String [2 blocks] "buffer"    #10262[r1,l0] ArrayBuffer (offs 0, len 8)      #10312[r1,l0] String [1 blocks] "\0\0\0\0\0\0\0\0"
  #10268[r1,l2] Name String [1 blocks] "\xFFgfx"    #9718[r1,l0] FlatString [4 blocks] "\0\0\0\b\0\b\0\1\1\0\0\0\0\0\0\0\1 \0\0\0\0\x0F\0\0\0\0\7\0\7\0\xFF\x7F\xFF\x7F\0\x80\0\x80"
}
=undefined
> 

Sure, you could access it from JS if you really tried, but since JS is able to use peek to access any area of memory, anything is ultimately accessible from JS if you try hard enough, so I feel like this is good enough

elima commented 1 year ago

Thanks for the quick response, @gfwilliams!

Ok, then as I understand it the whole system runs as a single trusted environment; apps can't really keep secrets from other apps.

In this context I agree that the method you describe is enough for hiding data that is not relevant to JS (apart from debugging, maybe). Sounds good.

Closing as feature already exists.