{%- let interface_base_class = int.interface_base_class %} {% include "InterfaceBaseClass.sys.mjs" %} {{ int.js_docstring }} export class {{ int.js_class_name }} extends {{ int.interface_base_class.name }} { // Use `init` to instantiate this class. // DO NOT USE THIS CONSTRUCTOR DIRECTLY constructor(opts) { super(); if (!Object.prototype.hasOwnProperty.call(opts, constructUniffiObject)) { throw new UniFFIError("Attempting to construct an int using the JavaScript constructor directly" + "Please use a UDL defined constructor, or the init function for the primary constructor") } if (!(opts[constructUniffiObject] instanceof UniFFIPointer)) { throw new UniFFIError("Attempting to create a UniFFI object with a pointer that is not an instance of UniFFIPointer") } this[uniffiObjectPtr] = opts[constructUniffiObject]; } {%- for cons in int.constructors %} {%- let callable = cons.callable %} {{ cons.js_docstring|indent(4) }} static {% if cons.callable.is_js_async %}async {% endif %}{{ cons.name }}({% filter indent(8) %}{% include "js/CallableArgs.sys.mjs" %}{% endfilter %}) { {% filter indent(8) %}{% include "js/CallableBody.sys.mjs" %}{% endfilter %} } {%- endfor %} {%- for meth in int.methods %} {%- let callable = meth.callable %} {{ meth.js_docstring|indent(4) }} {% if meth.callable.is_js_async %}async {% endif %}{{ meth.name }}({% filter indent(8) %}{% include "js/CallableArgs.sys.mjs" %}{% endfilter %}) { {% filter indent(8) %}{% include "js/CallableBody.sys.mjs" %}{% endfilter %} } {%- endfor %} } {% match int.vtable -%} {% when None -%} // Export the FFIConverter object to make external types work. export class {{ int.self_type.ffi_converter }} extends FfiConverter { static lift(value) { const opts = {}; opts[constructUniffiObject] = value; return new {{ int.js_class_name }}(opts); } static lower(value) { const ptr = value[uniffiObjectPtr]; if (!(ptr instanceof UniFFIPointer)) { throw new UniFFITypeError("Object is not a '{{ int.js_class_name }}' instance"); } return ptr; } static lowerReceiver(value) { // This works exactly the same as lower for non-trait interfaces return this.lower(value); } static read(dataStream) { return this.lift(dataStream.readPointer({{ int.object_id }})); } static write(dataStream, value) { dataStream.writePointer({{ int.object_id }}, this.lower(value)); } static computeSize(value) { return 8; } } {% when Some(vtable) -%} // FfiConverter for a trait interface. This is a hybrid of the FFIConverter regular interfaces and // for callback interfaces. // // Export the FFIConverter object to make external types work. export class {{ int.self_type.ffi_converter }} extends FfiConverter { static lift(handle) { if (handle instanceof UniFFIPointer) { // Rust handle. Construct an object from it const opts = {}; opts[constructUniffiObject] = handle; return new {{ int.js_class_name }}(opts); } else { // JS handle. Get the JS object from the callback handler return {{ vtable.js_handler_var }}.takeCallbackObj(handle) } } static lower(value) { const ptr = value[uniffiObjectPtr]; if (ptr instanceof UniFFIPointer) { // Rust-implemented interface, return the ptr. The C++ code will clone it. return ptr; } else { // JS-implemented interface, store the object in the handle map and return the handle if (!(value instanceof {{ int.interface_base_class.name }})) { throw new UniFFITypeError("expected '{{ int.interface_base_class.name }}' subclass"); } return {{ vtable.js_handler_var }}.storeCallbackObj(value) } } // lowerReceiver is used when calling methods on an interface we got from Rust, // it treats value like a regular interface. static lowerReceiver(value) { const ptr = value[uniffiObjectPtr]; if (!(ptr instanceof UniFFIPointer)) { throw new UniFFITypeError("Object is not a '{{ int.js_class_name }}' instance"); } return ptr; } static read(dataStream) { return this.lift(dataStream.readHandleOrPointer({{ int.object_id }})) } static write(dataStream, value) { if (value[uniffiObjectPtr] instanceof UniFFIPointer) { // Rust-implemented interface, return the ptr. dataStream.writePointer({{ int.object_id }}, this.lower(value)); } else { dataStream.writeInt64(this.lower(value)) } } static computeSize(value) { return 8; } } {% include "CallbackInterfaceHandler.sys.mjs" -%} {% endmatch %}