Skip to content

Data structure semantics #36

@ArcadeMode

Description

@ArcadeMode

Arrays exported to JS dont reflect changes in dotnet. This makes these types inconsistent with proxy objects as this effectively makes Arrays behave like structs upon crossing the interop boundary.

Strategies:

1. readonly reference types

By using ReadonlyArray it can be ensured that the original property cannot be manipulated without an explicit copy, from then on the user can adapt the array and potentially reassign it to a Property or pass it to an interop method.

Pros:

  • simple

Cons:

  • Requires Support JSObject #4 to work at all
  • performance for small changes is worse (i.e. arr[10] with 1 change sends 9 elements over interop for no reason)
  • limited extensibility
  • mixed state locality in proxies

2. interop for data types

Wrap common data structures in proxies to call interop for any operation.

Pros:

  • Proxy state locality remains in dotnet
  • Snapshots providing state locality to js makes more sense
  • Extensible to support other datastructures like Dictionary.
  • Performance for small changes is better

Cons:

  • More complex
  • Performance for reading is worse as changes in dotnet need to reflect in JS (cant keep a local [] copy on the JS side)
  • Less performant for large content changes
  • Every data structure proxy will also need inclusion in the Proxy snapshots #22 implementation.

This seems the preferable approach, especially looking forward at Dictionaries, Sets, Stacks etc. The semantics are better with the data structure behaving like a reference type. Lining this up with snapshots #22 would make for control of read/write performance depending on the users needs.

Design

Outlining different strategies.

Extra methods on properties ❌

User exports int[] from C#. The JSExport methods should implement methods for each property. (e.g. access index, set index value, get length). so besides get/set it'd be get/set/[], [i],.Length.

This does not fit for arrays returned from methods, as its impossible to write accessors reliably (does the method return the same instance like a property would/should?) It seems improbable that this would work well.

Generic array interop methods to invoke when dealing with arrays ❌

TypeShim can NOT define generic interop methods for array access as this would require passing a reference to the array, that would require marshalling the entire array back and forth, yielding crap performance.

Wrap the types ✅❓

The general strategy would be to wrap the user's type in a class, acquiring reference semantics with the existing implementation. Importantly this means TypeShim wouldnt use int[] on the interop method signature at all, avoiding the marshalling step.

A predefined ArrayShim<T> can be provided (or a template in the generator because generics are difficult to generate), this type is used by the generator in the JSExport method signatures. The current implementation already supports bringing the class to TypeScript. When snapshotted (#22) the user could retrieve their original [] in JS, untill then they have a reference to the exact array. The interop for ArrayShim<T> would need to have a method that returns the int[].

On the JS side it would be achievable to write shims to expose indexers.

On the JS side it would be necessary to be explicit about it not being a typical [], as its a proxy object it will require disposal when #20 comes around.

Semantical differences between .NET [] and JS []

  • JS [] is sparse and also an object (can set property on it)
  • JS does no bound checks (i.e. JS arr[999] == undefined, .net arr[999] throws index out of bounds).
  • C# arrays are covariant as classes are. so casting 'down' is possible. JS has no casting

Should TypeShim ask the user if they even want this or do it anyway? maybe later add a [AsJSArray] attribute? (snapshot would allow safety to some degree


Outline for implementations

Linear - Array, Stack, Queue

WIP

Hash - Set, Dictionary

TODO

Graphs

TODO

Trees

TODO

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions