docs/api/transport.md
transportisTransportable(jsValue: any): booleanregister(transportableClass: new(...args: any[]) => any): voidmarshall(jsValue: any, context: TransportContext): stringunmarshall(json: string, context: TransporteContext): anyTransportContext
Transportable
TransportableObject
transportableObject.cid: stringtransportableObject.marshall(context: TransportContext): objecttransportableObject.unmarshall(payload: object, context: TransportContext): voidtransportableObject.save(payload: object, context: TransportContext): voidtransportableObject.load(payload: object, context: TransportContext): voidcidExisting JavaScript engines are not designed for running JavaScript across multiple VMs, which means every VM manages their own heap. Passing values from one VM to another has to be marshalled/unmarshalled. The size of payload and complexity of object will greatly impact communication efficiency. In Napa, we try to work out a design pattern for efficient object sharing, based on the fact that all JavaScript VMs (exposed as workers) reside in the same process, and native objects can be wrapped and exposed as JavaScripts objects.
Following concepts are introduced to implement this pattern:
Transportable types are JavaScript types that can be passed or shared transparently across Napa workers. They are used as value types for passing arguments in zone.broadcast / zone.execute, and sharing objects in key/value pairs via store.set / store.get.
Transportable types are:
Transportable interfaceFor user classes that implement the Transportable interface, Napa uses Constructor ID (cid) to lookup constructors for creating a right object from a string payload. cid is marshalled as a part of the payload. During unmarshalling, the transport layer will extract the cid, create an object instance using the constructor associated with it, and then call unmarshall on the object.
It's the class developer's responsibility to choose the right cid for your class. To avoid conflict, we suggest to use the combination of module.id and class name as cid. Developer can use class decorator cid to register a user Transportable class automatically, when using TypeScript with decorator feature enabled. Or call transport.register manually during module initialization.
There are states that cannot be saved or loaded in serialized form (like std::shared_ptr), or it's very inefficient to serialize (like JavaScript function). Transport context is introduced to help in these scenarios. TransportContext objects can be passed from one JavaScript VM to another, or stored in the native world, so lifecycle of shared native objects extended by using TransportContext. An example of the Transportable implementation using TransportContext is ShareableWrap.
JavaScript function is a special transportable type, through marshalling its definition into a store, and generate a new function from its definition on target thread.
Highlights on transporting functions are:
__dirname / __filename can be accessed in transported function, which is determined by origin property of the function. By default, origin property is set to the current working directory.JavaScript standard built-in objects in the whitelist can be transported among napa workers transparently. JavaScript Objects with properties in these types are also able to be transported. Please refer to unit tests for detail.
An example Parallel Quick Sort demonstrated transporting TypedArray (created from SharedArrayBuffer) among multiple Napa workers for efficient data sharing.
It tells whether a JavaScript value is transportable or not.
// JS primitives
assert(transport.isTransportable(undefined));
assert(transport.isTransportable(null));
assert(transport.isTransportable(1));
assert(transport.isTransportable('string'));
assert(transport.isTransportable(true));
// Transportable addon
assert(transport.isTransportable(napa.memory.crtAllocator));
// Composite of transportable types.
assert(transport.isTransportable([
1,
"string",
{ a: napa.memory.crtAllocator }
]));
class B {
field1: number;
field2: string;
}
// Not transportable JS class. (not registered with @cid).
assert(!transport.isTransportable(new B()));
Register a Transportable class before the transport layer can marshall/unmarshall its instances.
User can also use class decorator @cid for class registration.
Example:
class A extends transport.AutoTransportable {
field1: string,
method1(): string {
return this.field1;
}
}
// Explicitly register class A in transport.
transport.register(A);
Marshall a transportable JavaScript value into a JSON payload with a TransportContext.An Error will be thrown if the value is not transportable.
Example:
var context = transport.createTransportContext();
var jsonPayload = transport.marshall(
[1, 'string', napa.memory.crtAllocator],
context);
console.log(jsonPayload);
Unmarshall a transportable JavaScript value from a JSON payload with a TransportContext.An Error will be thrown if cid property is found and not registered with the transport layer.
Example:
var value = transport.unmarshall(jsonPayload, context);
TransportContextClass for Transport Context, that stores shared pointers and functions during marshall/unmarshall.
Save a shareable object in context.
Load a shareable object from handle.
Count of shareable objects saved in the current context.
TransportableInterface for the Transportable object.
Get accessor for Constructor ID. It is used to lookup constructor for the payload of the current class.
Marshall transforms this object into a plain JavaScript object with the help of TransportContext.
Unmarshall transforms marshalled payload into current object.
TransportableObjectTBD
cidTBD