| // Generated by src/wasm/idl/generate.py from bindings.py. Do not edit. | |
| // | |
| // rive_module_imports.mjs, the lane modules, rive_parallel.mjs and | |
| // rive_script_runner.mjs as one script. | |
| // Link it into an emscripten build of librive with --pre-js and the | |
| // script runner installs itself as Module.riveScripting. | |
| (function () { | |
| // Generated by src/wasm/idl/generate.py from bindings.py. Do not edit. | |
| // The runtime import object for script modules executing on the | |
| // browser engine. Scalars forward straight into the host call | |
| // table; str/buf/pod params stage through the host heap because | |
| // the host cannot dereference module memory. `addr` params pass | |
| // through as module addresses, which the host reads through its | |
| // own memory seam. | |
| // | |
| // host contract: | |
| // calls per-op host entry points (native-pointer convention) | |
| // heapU8() Uint8Array over the host heap (refresh per call) | |
| // stackSave() -> mark | |
| // stackAlloc(size) -> host heap ptr valid until its mark is restored | |
| // stackRestore(mark) | |
| // malloc(size) -> host heap ptr, free(ptr) | |
| // counters optional bridge tallies, counted while counters.on | |
| // Staging nests: a host op may call back into the module, whose | |
| // imports stage again above the outer call. Buffers too big for the | |
| // host stack stage on its heap instead. | |
| // moduleMemory: late-bound accessor for the script module memory, | |
| // set after instantiation. | |
| // only: the one namespace to build, as a lane needs, or null for all. | |
| // | |
| // Names that cross to wasm are quoted so a closure compiled host | |
| // cannot rename them. | |
| function createRiveModuleImports(host, moduleMemory, only = null) { | |
| const want = (module) => only === null || only === module; | |
| const calls = host.calls; | |
| const stackSave = host.stackSave; | |
| const stackRestore = host.stackRestore; | |
| const kStackStageLimit = 4096; | |
| const counters = host.counters ?? { on: false }; | |
| // Rebuilt only when the module memory grows. | |
| let moduleBytes = null; | |
| const moduleU8 = () => { | |
| const buffer = moduleMemory().buffer; | |
| if (moduleBytes === null || moduleBytes.buffer !== buffer) { | |
| moduleBytes = new Uint8Array(buffer); | |
| } | |
| return moduleBytes; | |
| }; | |
| // Checked first: a range the module lacks throws before the alloc. | |
| // Module addresses and lengths arrive as signed i32s. | |
| const stageOut = (ptr, len) => { | |
| if (len < 0 || (ptr >>> 0) + len > moduleU8().length) { | |
| throw new RangeError('module range out of bounds'); | |
| } | |
| const dst = | |
| len > kStackStageLimit ? host.malloc(len) : host.stackAlloc(len); | |
| if (dst === 0) { | |
| throw new Error(`could not stage ${len} bytes for the host`); | |
| } | |
| return dst; | |
| }; | |
| const stageIn = (ptr, len) => { | |
| const dst = stageOut(ptr, len); | |
| ptr >>>= 0; | |
| host.heapU8().set(moduleBytes.subarray(ptr, ptr + len), dst); | |
| if (counters.on) counters.bytesStaged += len; | |
| return dst; | |
| }; | |
| const unstage = (dst, len) => { | |
| if (dst !== 0 && len > kStackStageLimit) { | |
| host.free(dst); | |
| } | |
| }; | |
| const copyOut = (src, ptr, len) => { | |
| if (len === 0) { | |
| return; | |
| } | |
| moduleU8().set(host.heapU8().subarray(src, src + len), ptr >>> 0); | |
| if (counters.on) counters.bytesCopiedOut += len; | |
| }; | |
| // The elements a size answer wrote: all of them when they fit. | |
| const fitted = (size, capacity) => | |
| size >>> 0 <= capacity ? size >>> 0 : 0; | |
| // Stages the managed string at text for fn(staged, byteLength). Null | |
| // reads as empty and the rest outside module memory traps, as on WAMR. | |
| const stageManaged = (text, fn) => { | |
| const length = managedLength(moduleMemory().buffer, text); | |
| const mark = stackSave(); | |
| let text_p = 0; | |
| try { | |
| text_p = stageIn(text, length); | |
| fn(text_p, length); | |
| } finally { | |
| unstage(text_p, length); | |
| stackRestore(mark); | |
| } | |
| }; | |
| // The std console, under the method codes rive_web_console takes. | |
| const consoleCall = (method) => (text) => | |
| stageManaged(text, (text_p, length) => | |
| calls.rive_console(method, text_p, length) | |
| ); | |
| return { | |
| // Imported only by scripts that call Math.random, trace or console. | |
| 'env': { | |
| 'seed': () => Date.now() * Math.random(), | |
| // Where modules baked before rive_rt_v1.now read the clocks. | |
| 'emscripten_get_now': () => performance.now(), | |
| 'emscripten_date_now': () => Date.now(), | |
| 'trace': (message, n, a0, a1, a2, a3, a4) => | |
| stageManaged(message, (text_p, length) => | |
| calls.rive_trace(text_p, length, n, a0, a1, a2, a3, a4) | |
| ), | |
| 'console.log': consoleCall(0), | |
| 'console.debug': consoleCall(0), | |
| 'console.info': consoleCall(0), | |
| 'console.warn': consoleCall(0), | |
| 'console.error': consoleCall(0), | |
| 'console.time': consoleCall(1), | |
| 'console.timeLog': consoleCall(2), | |
| 'console.timeEnd': consoleCall(3), | |
| }, | |
| 'rive_rt_v1': want('rive_rt_v1') && { | |
| 'log': (level, message, length) => { | |
| const mark = stackSave(); | |
| let message_p = 0; | |
| try { | |
| message_p = stageIn(message, length); | |
| calls.rive_rt_log(level, message_p, length); | |
| } finally { | |
| unstage(message_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'mark_needs_update': calls.rive_rt_mark_needs_update, | |
| 'budget_exceeded': calls.rive_rt_budget_exceeded, | |
| 'error': (message, length) => { | |
| const mark = stackSave(); | |
| let message_p = 0; | |
| try { | |
| message_p = stageIn(message, length); | |
| calls.rive_rt_error(message_p, length); | |
| } finally { | |
| unstage(message_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'now': () => performance.now(), | |
| 'date_now': () => Date.now(), | |
| 'debug_enter': calls.rive_rt_debug_enter, | |
| 'debug_line': calls.rive_rt_debug_line, | |
| 'debug_leave': calls.rive_rt_debug_leave, | |
| 'utc_offset': calls.rive_rt_utc_offset, | |
| 'is_dst': calls.rive_rt_is_dst, | |
| 'zone_name': (epochSeconds, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageIn(buffer, capacity); | |
| const ret = calls.rive_rt_zone_name(epochSeconds, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, capacity); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_data_v1': want('rive_data_v1') && { | |
| 'view_model': calls.rive_data_view_model, | |
| 'root_view_model': calls.rive_data_root_view_model, | |
| 'global_view_model': (object, name, nameLength) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| return calls.rive_data_global_view_model(object, name_p, nameLength); | |
| } finally { | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'global_view_model_names': (object, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageIn(buffer, capacity); | |
| const ret = calls.rive_data_global_view_model_names(object, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, capacity); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'context': calls.rive_data_context, | |
| 'context_parent': calls.rive_data_context_parent, | |
| 'context_view_model': calls.rive_data_context_view_model, | |
| 'context_release': calls.rive_data_context_release, | |
| 'has_view_model': (name, nameLength) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| return calls.rive_data_has_view_model(name_p, nameLength); | |
| } finally { | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'new_view_model': (name, nameLength, templateName, templateLength) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| let templateName_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| templateName_p = stageIn(templateName, templateLength); | |
| return calls.rive_data_new_view_model(name_p, nameLength, templateName_p, templateLength); | |
| } finally { | |
| unstage(templateName_p, templateLength); | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_release': calls.rive_data_vmi_release, | |
| 'vmi_number': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_number(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_boolean': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_boolean(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_string': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_string(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_trigger': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_trigger(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_color': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_color(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_view_model': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_view_model(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_property': (vmi, name, length, kindOut, kindCount) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| let kindOut_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| kindOut_p = stageIn(kindOut, kindCount * 4); | |
| const ret = calls.rive_data_vmi_property(vmi, name_p, length, kindOut_p, kindCount); | |
| copyOut(kindOut_p, kindOut, kindCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(kindOut_p, kindCount * 4); | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_instance': (vmi, name, nameLength) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| return calls.rive_data_vmi_instance(vmi, name_p, nameLength); | |
| } finally { | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_symbol_index': calls.rive_data_vmi_symbol_index, | |
| 'vmi_equal': calls.rive_data_vmi_equal, | |
| 'view_model_get': calls.rive_data_view_model_get, | |
| 'vmi_list': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_list(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_enum': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_enum(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_image': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_image(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_font': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_font(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_blob': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_blob(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'vmi_artboard': (vmi, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_data_vmi_artboard(vmi, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'image_get': calls.rive_data_image_get, | |
| 'image_set': calls.rive_data_image_set, | |
| 'font_get': calls.rive_data_font_get, | |
| 'font_set': calls.rive_data_font_set, | |
| 'font_release': calls.rive_data_font_release, | |
| 'blob_present': calls.rive_data_blob_present, | |
| 'blob_get': (property, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageIn(buffer, capacity); | |
| const ret = calls.rive_data_blob_get(property, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, capacity); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'blob_name': (property, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageIn(buffer, capacity); | |
| const ret = calls.rive_data_blob_name(property, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, capacity); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'blob_set': (property, bytes, byteCount) => { | |
| const mark = stackSave(); | |
| let bytes_p = 0; | |
| try { | |
| bytes_p = stageIn(bytes, byteCount); | |
| calls.rive_data_blob_set(property, bytes_p, byteCount); | |
| } finally { | |
| unstage(bytes_p, byteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'blob_clear': calls.rive_data_blob_clear, | |
| 'artboard_get': calls.rive_data_artboard_get, | |
| 'artboard_set': calls.rive_data_artboard_set, | |
| 'enum_get': (property, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageIn(buffer, capacity); | |
| const ret = calls.rive_data_enum_get(property, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, capacity); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'enum_set': (property, value, length) => { | |
| const mark = stackSave(); | |
| let value_p = 0; | |
| try { | |
| value_p = stageIn(value, length); | |
| calls.rive_data_enum_set(property, value_p, length); | |
| } finally { | |
| unstage(value_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'enum_values': (property, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageIn(buffer, capacity); | |
| const ret = calls.rive_data_enum_values(property, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, capacity); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'prop_release': calls.rive_data_prop_release, | |
| 'trigger_fire': calls.rive_data_trigger_fire, | |
| 'list_length': calls.rive_data_list_length, | |
| 'list_push': calls.rive_data_list_push, | |
| 'list_pop': calls.rive_data_list_pop, | |
| 'list_shift': calls.rive_data_list_shift, | |
| 'list_clear': calls.rive_data_list_clear, | |
| 'list_swap': calls.rive_data_list_swap, | |
| 'list_insert': calls.rive_data_list_insert, | |
| 'list_remove': calls.rive_data_list_remove, | |
| 'list_remove_at': calls.rive_data_list_remove_at, | |
| 'list_remove_all_of': calls.rive_data_list_remove_all_of, | |
| 'list_get': calls.rive_data_list_get, | |
| 'view_model_set': calls.rive_data_view_model_set, | |
| 'color_get': calls.rive_data_color_get, | |
| 'color_set': calls.rive_data_color_set, | |
| 'number_get': calls.rive_data_number_get, | |
| 'number_set': calls.rive_data_number_set, | |
| 'boolean_get': calls.rive_data_boolean_get, | |
| 'boolean_set': calls.rive_data_boolean_set, | |
| 'string_get': (property, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageIn(buffer, capacity); | |
| const ret = calls.rive_data_string_get(property, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, capacity); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'string_changed': calls.rive_data_string_changed, | |
| 'string_set': (property, value, length) => { | |
| const mark = stackSave(); | |
| let value_p = 0; | |
| try { | |
| value_p = stageIn(value, length); | |
| calls.rive_data_string_set(property, value_p, length); | |
| } finally { | |
| unstage(value_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'watch': calls.rive_data_watch, | |
| 'unwatch': calls.rive_data_unwatch, | |
| 'convert_result': (kind, number, booleanValue, color, value, length) => { | |
| const mark = stackSave(); | |
| let value_p = 0; | |
| try { | |
| value_p = stageIn(value, length); | |
| calls.rive_data_convert_result(kind, number, booleanValue, color, value_p, length); | |
| } finally { | |
| unstage(value_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_artboard_v1': want('rive_artboard_v1') && { | |
| 'release': calls.rive_artboard_release, | |
| 'advance': calls.rive_artboard_advance, | |
| 'draw': calls.rive_artboard_draw, | |
| 'instance': calls.rive_artboard_instance, | |
| 'data': calls.rive_artboard_data, | |
| 'width': calls.rive_artboard_width, | |
| 'height': calls.rive_artboard_height, | |
| 'set_width': calls.rive_artboard_set_width, | |
| 'set_height': calls.rive_artboard_set_height, | |
| 'frame_origin': calls.rive_artboard_frame_origin, | |
| 'set_frame_origin': calls.rive_artboard_set_frame_origin, | |
| 'bounds': (artboard, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| calls.rive_artboard_bounds(artboard, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'pointer_event': calls.rive_artboard_pointer_event, | |
| 'scroll_event': calls.rive_artboard_scroll_event, | |
| 'gamepad_event': (artboard, payload, byteCount) => { | |
| const mark = stackSave(); | |
| let payload_p = 0; | |
| try { | |
| payload_p = stageIn(payload, byteCount); | |
| return calls.rive_artboard_gamepad_event(artboard, payload_p, byteCount); | |
| } finally { | |
| unstage(payload_p, byteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'animation': (artboard, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_artboard_animation(artboard, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'animation_release': calls.rive_artboard_animation_release, | |
| 'animation_duration': calls.rive_artboard_animation_duration, | |
| 'animation_advance': calls.rive_artboard_animation_advance, | |
| 'animation_set_time': calls.rive_artboard_animation_set_time, | |
| 'add_to_path': calls.rive_artboard_add_to_path, | |
| 'node': (artboard, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_artboard_node(artboard, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'node_release': calls.rive_artboard_node_release, | |
| 'node_transform': (node, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| calls.rive_artboard_node_transform(node, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'node_set': calls.rive_artboard_node_set, | |
| 'node_world_transform': (node, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| calls.rive_artboard_node_world_transform(node, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'node_set_world_transform': (node, values, floatCount) => { | |
| const mark = stackSave(); | |
| let values_p = 0; | |
| try { | |
| values_p = stageIn(values, floatCount * 4); | |
| calls.rive_artboard_node_set_world_transform(node, values_p, floatCount); | |
| } finally { | |
| unstage(values_p, floatCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'node_decompose': (node, values, floatCount) => { | |
| const mark = stackSave(); | |
| let values_p = 0; | |
| try { | |
| values_p = stageIn(values, floatCount * 4); | |
| calls.rive_artboard_node_decompose(node, values_p, floatCount); | |
| } finally { | |
| unstage(values_p, floatCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'node_path_verbs': (node, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount); | |
| const ret = calls.rive_artboard_node_path_verbs(node, out_p, outCount); | |
| copyOut(out_p, out, outCount); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'node_path_points': (node, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_artboard_node_path_points(node, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'node_paint': (node, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_artboard_node_paint(node, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'node_children': (node, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_artboard_node_children(node, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'node_parent': calls.rive_artboard_node_parent, | |
| 'property_key': (artboard, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_artboard_property_key(artboard, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'draw_visit': calls.rive_artboard_draw_visit, | |
| 'draw_modulated': calls.rive_artboard_draw_modulated, | |
| 'drawable_draw': calls.rive_artboard_drawable_draw, | |
| 'drawable_value': (drawable, key, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_artboard_drawable_value(drawable, key, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'drawable_string': (drawable, key, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount); | |
| const ret = calls.rive_artboard_drawable_string(drawable, key, out_p, outCount); | |
| copyOut(out_p, out, outCount); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'drawable_properties': (drawable, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount); | |
| const ret = calls.rive_artboard_drawable_properties(drawable, out_p, outCount); | |
| copyOut(out_p, out, outCount); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_audio_v1': want('rive_audio_v1') && { | |
| 'source': (object, name, nameLength) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| return calls.rive_audio_source(object, name_p, nameLength); | |
| } finally { | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'source_release': calls.rive_audio_source_release, | |
| 'source_duration': calls.rive_audio_source_duration, | |
| 'source_sample_rate': calls.rive_audio_source_sample_rate, | |
| 'source_channels': calls.rive_audio_source_channels, | |
| 'source_to_blob': calls.rive_audio_source_to_blob, | |
| 'stream': calls.rive_audio_stream, | |
| 'stream_ring': calls.rive_audio_stream_ring, | |
| 'stream_seeks': calls.rive_audio_stream_seeks, | |
| 'stream_channels': calls.rive_audio_stream_channels, | |
| 'stream_sample_rate': calls.rive_audio_stream_sample_rate, | |
| 'stream_seek_frame': calls.rive_audio_stream_seek_frame, | |
| 'stream_set_loop': calls.rive_audio_stream_set_loop, | |
| 'stream_ended': calls.rive_audio_stream_ended, | |
| 'stream_release': calls.rive_audio_stream_release, | |
| 'play': calls.rive_audio_play, | |
| 'play_at_time': calls.rive_audio_play_at_time, | |
| 'play_in_time': calls.rive_audio_play_in_time, | |
| 'play_at_frame': calls.rive_audio_play_at_frame, | |
| 'play_in_frame': calls.rive_audio_play_in_frame, | |
| 'time': calls.rive_audio_time, | |
| 'time_frame': calls.rive_audio_time_frame, | |
| 'sample_rate': calls.rive_audio_sample_rate, | |
| 'processor_sample_rate': calls.rive_audio_processor_sample_rate, | |
| 'processor_channels': calls.rive_audio_processor_channels, | |
| 'sound_release': calls.rive_audio_sound_release, | |
| 'sound_play': calls.rive_audio_sound_play, | |
| 'sound_pause': calls.rive_audio_sound_pause, | |
| 'sound_resume': calls.rive_audio_sound_resume, | |
| 'sound_stop': calls.rive_audio_sound_stop, | |
| 'sound_seek': calls.rive_audio_sound_seek, | |
| 'sound_seek_frame': calls.rive_audio_sound_seek_frame, | |
| 'sound_completed': calls.rive_audio_sound_completed, | |
| 'sound_time': calls.rive_audio_sound_time, | |
| 'sound_time_frame': calls.rive_audio_sound_time_frame, | |
| 'sound_volume': calls.rive_audio_sound_volume, | |
| 'sound_set_volume': calls.rive_audio_sound_set_volume, | |
| }, | |
| 'rive_path_v1': want('rive_path_v1') && { | |
| 'new': calls.rive_path_new, | |
| 'update': (path, verbs, verbCount, points, floatCount, fillRule) => { | |
| const mark = stackSave(); | |
| let verbs_p = 0; | |
| let points_p = 0; | |
| try { | |
| verbs_p = stageIn(verbs, verbCount); | |
| points_p = stageIn(points, floatCount * 4); | |
| calls.rive_path_update(path, verbs_p, verbCount, points_p, floatCount, fillRule); | |
| } finally { | |
| unstage(points_p, floatCount * 4); | |
| unstage(verbs_p, verbCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'release': calls.rive_path_release, | |
| 'add': calls.rive_path_add, | |
| 'verbs': (path, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount); | |
| const ret = calls.rive_path_verbs(path, out_p, outCount); | |
| copyOut(out_p, out, outCount); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'points': (path, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_path_points(path, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'effect_result': (verbs, verbCount, points, floatCount) => { | |
| const mark = stackSave(); | |
| let verbs_p = 0; | |
| let points_p = 0; | |
| try { | |
| verbs_p = stageIn(verbs, verbCount); | |
| points_p = stageIn(points, floatCount * 4); | |
| calls.rive_path_effect_result(verbs_p, verbCount, points_p, floatCount); | |
| } finally { | |
| unstage(points_p, floatCount * 4); | |
| unstage(verbs_p, verbCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_measure_v1': want('rive_measure_v1') && { | |
| 'path_new': (verbs, verbCount, points, floatCount) => { | |
| const mark = stackSave(); | |
| let verbs_p = 0; | |
| let points_p = 0; | |
| try { | |
| verbs_p = stageIn(verbs, verbCount); | |
| points_p = stageIn(points, floatCount * 4); | |
| return calls.rive_measure_path_new(verbs_p, verbCount, points_p, floatCount); | |
| } finally { | |
| unstage(points_p, floatCount * 4); | |
| unstage(verbs_p, verbCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'contours_new': (verbs, verbCount, points, floatCount) => { | |
| const mark = stackSave(); | |
| let verbs_p = 0; | |
| let points_p = 0; | |
| try { | |
| verbs_p = stageIn(verbs, verbCount); | |
| points_p = stageIn(points, floatCount * 4); | |
| return calls.rive_measure_contours_new(verbs_p, verbCount, points_p, floatCount); | |
| } finally { | |
| unstage(points_p, floatCount * 4); | |
| unstage(verbs_p, verbCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'contour_next': calls.rive_measure_contour_next, | |
| 'length': calls.rive_measure_length, | |
| 'is_closed': calls.rive_measure_is_closed, | |
| 'pos_tan': (measure, distance, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| calls.rive_measure_pos_tan(measure, distance, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'warp': (measure, x, y, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| calls.rive_measure_warp(measure, x, y, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'extract': calls.rive_measure_extract, | |
| 'extract_read': (measure, verbs, verbCount, points, floatCount) => { | |
| const mark = stackSave(); | |
| let verbs_p = 0; | |
| let points_p = 0; | |
| try { | |
| verbs_p = stageIn(verbs, verbCount); | |
| points_p = stageIn(points, floatCount * 4); | |
| const ret = calls.rive_measure_extract_read(measure, verbs_p, verbCount, points_p, floatCount); | |
| copyOut(verbs_p, verbs, verbCount); | |
| copyOut(points_p, points, floatCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(points_p, floatCount * 4); | |
| unstage(verbs_p, verbCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'release': calls.rive_measure_release, | |
| }, | |
| 'rive_paint_v1': want('rive_paint_v1') && { | |
| 'new': calls.rive_paint_new, | |
| 'release': calls.rive_paint_release, | |
| 'style': calls.rive_paint_style, | |
| 'color': calls.rive_paint_color, | |
| 'thickness': calls.rive_paint_thickness, | |
| 'join': calls.rive_paint_join, | |
| 'cap': calls.rive_paint_cap, | |
| 'blend_mode': calls.rive_paint_blend_mode, | |
| 'feather': calls.rive_paint_feather, | |
| 'shader': calls.rive_paint_shader, | |
| 'shader_transform': (paint, values, floatCount) => { | |
| const mark = stackSave(); | |
| let values_p = 0; | |
| try { | |
| values_p = stageIn(values, floatCount * 4); | |
| calls.rive_paint_shader_transform(paint, values_p, floatCount); | |
| } finally { | |
| unstage(values_p, floatCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_canvas_v1': want('rive_canvas_v1') && { | |
| 'new': calls.rive_canvas_new, | |
| 'release': calls.rive_canvas_release, | |
| 'width': calls.rive_canvas_width, | |
| 'height': calls.rive_canvas_height, | |
| 'resize': calls.rive_canvas_resize, | |
| 'image': calls.rive_canvas_image, | |
| 'begin_frame': calls.rive_canvas_begin_frame, | |
| 'end_frame': calls.rive_canvas_end_frame, | |
| }, | |
| 'rive_gpu_v1': want('rive_gpu_v1') && { | |
| 'features': (out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_gpu_features(out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'canvas_new': calls.rive_gpu_canvas_new, | |
| 'canvas_release': calls.rive_gpu_canvas_release, | |
| 'canvas_color_view': (canvas, props, propCount) => { | |
| const mark = stackSave(); | |
| let props_p = 0; | |
| try { | |
| props_p = stageIn(props, propCount * 4); | |
| const ret = calls.rive_gpu_canvas_color_view(canvas, props_p, propCount); | |
| copyOut(props_p, props, propCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(props_p, propCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'canvas_image': calls.rive_gpu_canvas_image, | |
| 'canvas_resize': (canvas, width, height, props, propCount) => { | |
| const mark = stackSave(); | |
| let props_p = 0; | |
| try { | |
| props_p = stageIn(props, propCount * 4); | |
| const ret = calls.rive_gpu_canvas_resize(canvas, width, height, props_p, propCount); | |
| copyOut(props_p, props, propCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(props_p, propCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'target_view': (current, props, propCount) => { | |
| const mark = stackSave(); | |
| let props_p = 0; | |
| try { | |
| props_p = stageIn(props, propCount * 4); | |
| const ret = calls.rive_gpu_target_view(current, props_p, propCount); | |
| copyOut(props_p, props, propCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(props_p, propCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'pass_begin': (desc, descByteCount, blob, blobCount) => { | |
| const mark = stackSave(); | |
| let desc_p = 0; | |
| let blob_p = 0; | |
| try { | |
| desc_p = stageIn(desc, descByteCount); | |
| blob_p = stageIn(blob, blobCount); | |
| return calls.rive_gpu_pass_begin(desc_p, descByteCount, blob_p, blobCount); | |
| } finally { | |
| unstage(blob_p, blobCount); | |
| unstage(desc_p, descByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'pass_set_pipeline': calls.rive_gpu_pass_set_pipeline, | |
| 'pass_set_vertex_buffer': calls.rive_gpu_pass_set_vertex_buffer, | |
| 'pass_set_index_buffer': calls.rive_gpu_pass_set_index_buffer, | |
| 'pass_set_bind_group': (pass, groupIndex, bindGroup, dynamicOffsets, dynamicOffsetByteCount) => { | |
| const mark = stackSave(); | |
| let dynamicOffsets_p = 0; | |
| try { | |
| dynamicOffsets_p = stageIn(dynamicOffsets, dynamicOffsetByteCount); | |
| calls.rive_gpu_pass_set_bind_group(pass, groupIndex, bindGroup, dynamicOffsets_p, dynamicOffsetByteCount); | |
| } finally { | |
| unstage(dynamicOffsets_p, dynamicOffsetByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'pass_set_viewport': calls.rive_gpu_pass_set_viewport, | |
| 'pass_set_scissor': calls.rive_gpu_pass_set_scissor, | |
| 'pass_set_stencil_reference': calls.rive_gpu_pass_set_stencil_reference, | |
| 'pass_set_blend_color': calls.rive_gpu_pass_set_blend_color, | |
| 'pass_draw': calls.rive_gpu_pass_draw, | |
| 'pass_draw_indexed': calls.rive_gpu_pass_draw_indexed, | |
| 'pass_finish': calls.rive_gpu_pass_finish, | |
| 'pass_release': calls.rive_gpu_pass_release, | |
| 'image_view': calls.rive_gpu_image_view, | |
| 'buffer_new': (usage, sizeInBytes, immutable, data, dataCount) => { | |
| const mark = stackSave(); | |
| let data_p = 0; | |
| try { | |
| data_p = stageIn(data, dataCount); | |
| return calls.rive_gpu_buffer_new(usage, sizeInBytes, immutable, data_p, dataCount); | |
| } finally { | |
| unstage(data_p, dataCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'buffer_update': (buffer, dstOffset, data, dataCount) => { | |
| const mark = stackSave(); | |
| let data_p = 0; | |
| try { | |
| data_p = stageIn(data, dataCount); | |
| calls.rive_gpu_buffer_update(buffer, dstOffset, data_p, dataCount); | |
| } finally { | |
| unstage(data_p, dataCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'buffer_update_blob': calls.rive_gpu_buffer_update_blob, | |
| 'buffer_new_blob': calls.rive_gpu_buffer_new_blob, | |
| 'buffer_release': calls.rive_gpu_buffer_release, | |
| 'texture_new': (desc, descByteCount) => { | |
| const mark = stackSave(); | |
| let desc_p = 0; | |
| try { | |
| desc_p = stageIn(desc, descByteCount); | |
| return calls.rive_gpu_texture_new(desc_p, descByteCount); | |
| } finally { | |
| unstage(desc_p, descByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'texture_upload': (texture, region, regionByteCount, data, dataCount) => { | |
| const mark = stackSave(); | |
| let region_p = 0; | |
| let data_p = 0; | |
| try { | |
| region_p = stageIn(region, regionByteCount); | |
| data_p = stageIn(data, dataCount); | |
| calls.rive_gpu_texture_upload(texture, region_p, regionByteCount, data_p, dataCount); | |
| } finally { | |
| unstage(data_p, dataCount); | |
| unstage(region_p, regionByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'texture_release': calls.rive_gpu_texture_release, | |
| 'sampler_new': (desc, descByteCount) => { | |
| const mark = stackSave(); | |
| let desc_p = 0; | |
| try { | |
| desc_p = stageIn(desc, descByteCount); | |
| return calls.rive_gpu_sampler_new(desc_p, descByteCount); | |
| } finally { | |
| unstage(desc_p, descByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'sampler_release': calls.rive_gpu_sampler_release, | |
| 'texture_view_new': (texture, desc, descByteCount) => { | |
| const mark = stackSave(); | |
| let desc_p = 0; | |
| try { | |
| desc_p = stageIn(desc, descByteCount); | |
| return calls.rive_gpu_texture_view_new(texture, desc_p, descByteCount); | |
| } finally { | |
| unstage(desc_p, descByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'texture_view_release': calls.rive_gpu_texture_view_release, | |
| 'shader_target': calls.rive_gpu_shader_target, | |
| 'shader_asset_bytes': (object, name, nameLength, out, outCount) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| let out_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| out_p = stageIn(out, outCount); | |
| const ret = calls.rive_gpu_shader_asset_bytes(object, name_p, nameLength, out_p, outCount); | |
| copyOut(out_p, out, outCount); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount); | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'shader_asset_id': (object, name, nameLength) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| return calls.rive_gpu_shader_asset_id(object, name_p, nameLength); | |
| } finally { | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'shader_module_from_asset': (object, name, nameLength, entry) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| return calls.rive_gpu_shader_module_from_asset(object, name_p, nameLength, entry); | |
| } finally { | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'shader_module_from_rstb': (rstb, rstbCount, assetId, entry) => { | |
| const mark = stackSave(); | |
| let rstb_p = 0; | |
| try { | |
| rstb_p = stageIn(rstb, rstbCount); | |
| return calls.rive_gpu_shader_module_from_rstb(rstb_p, rstbCount, assetId, entry); | |
| } finally { | |
| unstage(rstb_p, rstbCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'shader_module_release': calls.rive_gpu_shader_module_release, | |
| 'bind_group_layout_new': (groupIndex, entries, entryByteCount) => { | |
| const mark = stackSave(); | |
| let entries_p = 0; | |
| try { | |
| entries_p = stageIn(entries, entryByteCount); | |
| return calls.rive_gpu_bind_group_layout_new(groupIndex, entries_p, entryByteCount); | |
| } finally { | |
| unstage(entries_p, entryByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'bind_group_layout_release': calls.rive_gpu_bind_group_layout_release, | |
| 'bind_group_layout_from_shader': (shaderModule, groupIndex, dynamicUBOs, dynamicUBOCount) => { | |
| const mark = stackSave(); | |
| let dynamicUBOs_p = 0; | |
| try { | |
| dynamicUBOs_p = stageIn(dynamicUBOs, dynamicUBOCount * 4); | |
| return calls.rive_gpu_bind_group_layout_from_shader(shaderModule, groupIndex, dynamicUBOs_p, dynamicUBOCount); | |
| } finally { | |
| unstage(dynamicUBOs_p, dynamicUBOCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'bind_group_layout_from_shaders': (vertexModule, fragmentModule, groupIndex, dynamicUBOs, dynamicUBOCount) => { | |
| const mark = stackSave(); | |
| let dynamicUBOs_p = 0; | |
| try { | |
| dynamicUBOs_p = stageIn(dynamicUBOs, dynamicUBOCount * 4); | |
| return calls.rive_gpu_bind_group_layout_from_shaders(vertexModule, fragmentModule, groupIndex, dynamicUBOs_p, dynamicUBOCount); | |
| } finally { | |
| unstage(dynamicUBOs_p, dynamicUBOCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'bind_group_layout_from_entries': (vertexModule, vertexEntry, vertexEntryLength, fragmentModule, fragmentEntry, fragmentEntryLength, groupIndex) => { | |
| const mark = stackSave(); | |
| let vertexEntry_p = 0; | |
| let fragmentEntry_p = 0; | |
| try { | |
| vertexEntry_p = stageIn(vertexEntry, vertexEntryLength); | |
| fragmentEntry_p = stageIn(fragmentEntry, fragmentEntryLength); | |
| return calls.rive_gpu_bind_group_layout_from_entries(vertexModule, vertexEntry_p, vertexEntryLength, fragmentModule, fragmentEntry_p, fragmentEntryLength, groupIndex); | |
| } finally { | |
| unstage(fragmentEntry_p, fragmentEntryLength); | |
| unstage(vertexEntry_p, vertexEntryLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'bind_group_new': (layout, ubos, uboByteCount, textures, textureByteCount, samplers, samplerByteCount) => { | |
| const mark = stackSave(); | |
| let ubos_p = 0; | |
| let textures_p = 0; | |
| let samplers_p = 0; | |
| try { | |
| ubos_p = stageIn(ubos, uboByteCount); | |
| textures_p = stageIn(textures, textureByteCount); | |
| samplers_p = stageIn(samplers, samplerByteCount); | |
| return calls.rive_gpu_bind_group_new(layout, ubos_p, uboByteCount, textures_p, textureByteCount, samplers_p, samplerByteCount); | |
| } finally { | |
| unstage(samplers_p, samplerByteCount); | |
| unstage(textures_p, textureByteCount); | |
| unstage(ubos_p, uboByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'bind_group_release': calls.rive_gpu_bind_group_release, | |
| 'pipeline_new': (desc, descByteCount, blob, blobCount) => { | |
| const mark = stackSave(); | |
| let desc_p = 0; | |
| let blob_p = 0; | |
| try { | |
| desc_p = stageIn(desc, descByteCount); | |
| blob_p = stageIn(blob, blobCount); | |
| return calls.rive_gpu_pipeline_new(desc_p, descByteCount, blob_p, blobCount); | |
| } finally { | |
| unstage(blob_p, blobCount); | |
| unstage(desc_p, descByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'pipeline_release': calls.rive_gpu_pipeline_release, | |
| }, | |
| 'rive_mat4_v1': want('rive_mat4_v1') && { | |
| 'multiply': (out, outBytes, a, aBytes, b, bBytes) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| let a_p = 0; | |
| let b_p = 0; | |
| try { | |
| out_p = stageIn(out, outBytes); | |
| a_p = stageIn(a, aBytes); | |
| b_p = stageIn(b, bBytes); | |
| calls.rive_mat4_multiply(out_p, outBytes, a_p, aBytes, b_p, bBytes); | |
| copyOut(out_p, out, outBytes); | |
| } finally { | |
| unstage(b_p, bBytes); | |
| unstage(a_p, aBytes); | |
| unstage(out_p, outBytes); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'invert': (out, outBytes, src, srcBytes) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| let src_p = 0; | |
| try { | |
| out_p = stageIn(out, outBytes); | |
| src_p = stageIn(src, srcBytes); | |
| const ret = calls.rive_mat4_invert(out_p, outBytes, src_p, srcBytes); | |
| copyOut(out_p, out, outBytes); | |
| return ret; | |
| } finally { | |
| unstage(src_p, srcBytes); | |
| unstage(out_p, outBytes); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_buffer_v1': want('rive_buffer_v1') && { | |
| 'new': calls.rive_buffer_new, | |
| 'update': (buffer, bytes, byteCount) => { | |
| const mark = stackSave(); | |
| let bytes_p = 0; | |
| try { | |
| bytes_p = stageIn(bytes, byteCount); | |
| calls.rive_buffer_update(buffer, bytes_p, byteCount); | |
| } finally { | |
| unstage(bytes_p, byteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'release': calls.rive_buffer_release, | |
| }, | |
| 'rive_mesh_instances_v1': want('rive_mesh_instances_v1') && { | |
| 'new': calls.rive_mesh_instances_new, | |
| 'resize': calls.rive_mesh_instances_resize, | |
| 'update': (instances, first, bytes, byteCount) => { | |
| const mark = stackSave(); | |
| let bytes_p = 0; | |
| try { | |
| bytes_p = stageIn(bytes, byteCount); | |
| calls.rive_mesh_instances_update(instances, first, bytes_p, byteCount); | |
| } finally { | |
| unstage(bytes_p, byteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'release': calls.rive_mesh_instances_release, | |
| }, | |
| 'rive_blob_v1': want('rive_blob_v1') && { | |
| 'asset_bytes': (object, name, nameLength, out, outCount) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| let out_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| out_p = stageIn(out, outCount); | |
| const ret = calls.rive_blob_asset_bytes(object, name_p, nameLength, out_p, outCount); | |
| copyOut(out_p, out, outCount); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount); | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_image_v1': want('rive_image_v1') && { | |
| 'from_asset': (object, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_image_from_asset(object, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'width': calls.rive_image_width, | |
| 'height': calls.rive_image_height, | |
| 'release': calls.rive_image_release, | |
| 'decode': (bytes, byteCount, token) => { | |
| const mark = stackSave(); | |
| let bytes_p = 0; | |
| try { | |
| bytes_p = stageIn(bytes, byteCount); | |
| return calls.rive_image_decode(bytes_p, byteCount, token); | |
| } finally { | |
| unstage(bytes_p, byteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'decode_cancel': calls.rive_image_decode_cancel, | |
| }, | |
| 'rive_font_v1': want('rive_font_v1') && { | |
| 'from_asset': (object, name, length) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, length); | |
| return calls.rive_font_from_asset(object, name_p, length); | |
| } finally { | |
| unstage(name_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'decode': (bytes, byteCount) => { | |
| const mark = stackSave(); | |
| let bytes_p = 0; | |
| try { | |
| bytes_p = stageIn(bytes, byteCount); | |
| return calls.rive_font_decode(bytes_p, byteCount); | |
| } finally { | |
| unstage(bytes_p, byteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'release': calls.rive_font_release, | |
| 'metrics': (font, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| calls.rive_font_metrics(font, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'weight': calls.rive_font_weight, | |
| 'is_italic': calls.rive_font_is_italic, | |
| 'axis_count': calls.rive_font_axis_count, | |
| 'axis': (font, index, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| calls.rive_font_axis(font, index, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'axis_value': calls.rive_font_axis_value, | |
| 'features': (font, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_font_features(font, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'has_glyph': calls.rive_font_has_glyph, | |
| 'with_options': (font, coords, coordCount, features, featureCount) => { | |
| const mark = stackSave(); | |
| let coords_p = 0; | |
| let features_p = 0; | |
| try { | |
| coords_p = stageIn(coords, coordCount * 4); | |
| features_p = stageIn(features, featureCount * 4); | |
| return calls.rive_font_with_options(font, coords_p, coordCount, features_p, featureCount); | |
| } finally { | |
| unstage(features_p, featureCount * 4); | |
| unstage(coords_p, coordCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'glyph_verbs': (font, glyph, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount); | |
| const ret = calls.rive_font_glyph_verbs(font, glyph, out_p, outCount); | |
| copyOut(out_p, out, outCount); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'glyph_points': (font, glyph, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_font_glyph_points(font, glyph, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_text_v1': want('rive_text_v1') && { | |
| 'new': calls.rive_text_new, | |
| 'release': calls.rive_text_release, | |
| 'append': (text, chars, length, font, paint, size, lineHeight, letterSpacing, foreground) => { | |
| const mark = stackSave(); | |
| let chars_p = 0; | |
| try { | |
| chars_p = stageIn(chars, length); | |
| calls.rive_text_append(text, chars_p, length, font, paint, size, lineHeight, letterSpacing, foreground); | |
| } finally { | |
| unstage(chars_p, length); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'clear': calls.rive_text_clear, | |
| 'layout': (text, desc, descByteCount) => { | |
| const mark = stackSave(); | |
| let desc_p = 0; | |
| try { | |
| desc_p = stageIn(desc, descByteCount); | |
| calls.rive_text_layout(text, desc_p, descByteCount); | |
| } finally { | |
| unstage(desc_p, descByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'draw': calls.rive_text_draw, | |
| 'bounds': (text, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| calls.rive_text_bounds(text, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'length': calls.rive_text_length, | |
| 'lines': (text, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_text_lines(text, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'runs': (text, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_text_runs(text, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'glyphs': (text, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_text_glyphs(text, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'hit_test': calls.rive_text_hit_test, | |
| 'caret': (text, index, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_text_caret(text, index, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'selection_rects': (text, from, to, out, outCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageIn(out, outCount * 4); | |
| const ret = calls.rive_text_selection_rects(text, from, to, out_p, outCount); | |
| copyOut(out_p, out, outCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_shader_v1': want('rive_shader_v1') && { | |
| 'linear': calls.rive_shader_linear, | |
| 'radial': calls.rive_shader_radial, | |
| 'release': calls.rive_shader_release, | |
| }, | |
| 'rive_test_v1': want('rive_test_v1') && { | |
| 'blob': (name, nameLength, out, outCount) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| let out_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| out_p = stageIn(out, outCount); | |
| const ret = calls.rive_test_blob(name_p, nameLength, out_p, outCount); | |
| copyOut(out_p, out, outCount); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outCount); | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_transition_v1': want('rive_transition_v1') && { | |
| 'child_draw': calls.rive_transition_child_draw, | |
| 'child_width': calls.rive_transition_child_width, | |
| 'child_height': calls.rive_transition_child_height, | |
| }, | |
| 'rive_renderer_v1': want('rive_renderer_v1') && { | |
| 'save': calls.rive_renderer_save, | |
| 'restore': calls.rive_renderer_restore, | |
| 'transform': calls.rive_renderer_transform, | |
| 'draw_path': calls.rive_renderer_draw_path, | |
| 'clip_path': calls.rive_renderer_clip_path, | |
| 'modulate_opacity': calls.rive_renderer_modulate_opacity, | |
| 'modulate_color': calls.rive_renderer_modulate_color, | |
| 'draw_image': calls.rive_renderer_draw_image, | |
| 'draw_image_mesh': calls.rive_renderer_draw_image_mesh, | |
| 'draw_image_mesh_instanced': calls.rive_renderer_draw_image_mesh_instanced, | |
| }, | |
| 'rive_net_v1': want('rive_net_v1') && { | |
| 'fetch': (request, requestCount, token) => { | |
| const mark = stackSave(); | |
| let request_p = 0; | |
| try { | |
| request_p = stageIn(request, requestCount); | |
| return calls.rive_net_fetch(request_p, requestCount, token); | |
| } finally { | |
| unstage(request_p, requestCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'fetch_cancel': calls.rive_net_fetch_cancel, | |
| }, | |
| 'rive_file_v1': want('rive_file_v1') && { | |
| 'decode': (bytes, byteCount, statusOut, statusCount) => { | |
| const mark = stackSave(); | |
| let bytes_p = 0; | |
| let statusOut_p = 0; | |
| try { | |
| bytes_p = stageIn(bytes, byteCount); | |
| statusOut_p = stageIn(statusOut, statusCount * 4); | |
| const ret = calls.rive_file_decode(bytes_p, byteCount, statusOut_p, statusCount); | |
| copyOut(statusOut_p, statusOut, statusCount * 4); | |
| return ret; | |
| } finally { | |
| unstage(statusOut_p, statusCount * 4); | |
| unstage(bytes_p, byteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'release': calls.rive_file_release, | |
| 'artboard_count': calls.rive_file_artboard_count, | |
| 'artboard_name': (file, index, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageIn(buffer, capacity); | |
| const ret = calls.rive_file_artboard_name(file, index, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, capacity); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'bindable': (file, name, nameLength, useDefault) => { | |
| const mark = stackSave(); | |
| let name_p = 0; | |
| try { | |
| name_p = stageIn(name, nameLength); | |
| return calls.rive_file_bindable(file, name_p, nameLength, useDefault); | |
| } finally { | |
| unstage(name_p, nameLength); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'bindable_release': calls.rive_file_bindable_release, | |
| 'bindable_name': (bindable, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageIn(buffer, capacity); | |
| const ret = calls.rive_file_bindable_name(bindable, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, capacity); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'bindable_data': calls.rive_file_bindable_data, | |
| 'bindable_equal': calls.rive_file_bindable_equal, | |
| }, | |
| 'rive_lanes_v1': want('rive_lanes_v1') && { | |
| 'start': (kind, entry, input, inputByteCount, holds, holdCount) => { | |
| const mark = stackSave(); | |
| let input_p = 0; | |
| let holds_p = 0; | |
| try { | |
| input_p = stageIn(input, inputByteCount); | |
| holds_p = stageIn(holds, holdCount * 4); | |
| return calls.rive_lanes_start(kind, entry, input_p, inputByteCount, holds_p, holdCount); | |
| } finally { | |
| unstage(holds_p, holdCount * 4); | |
| unstage(input_p, inputByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'state': calls.rive_lanes_state, | |
| 'failed': (lane, buffer, capacity) => { | |
| const mark = stackSave(); | |
| let buffer_p = 0; | |
| try { | |
| buffer_p = stageOut(buffer, capacity); | |
| const ret = calls.rive_lanes_failed(lane, buffer_p, capacity); | |
| copyOut(buffer_p, buffer, fitted(ret, capacity)); | |
| return ret; | |
| } finally { | |
| unstage(buffer_p, capacity); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'stop': calls.rive_lanes_stop, | |
| 'release': calls.rive_lanes_release, | |
| 'result': calls.rive_lanes_result, | |
| 'watch': calls.rive_lanes_watch, | |
| 'wait': calls.rive_lanes_wait, | |
| 'cancel_wait': calls.rive_lanes_cancel_wait, | |
| 'wait_within': calls.rive_lanes_wait_within, | |
| }, | |
| 'rive_jobs_v1': want('rive_jobs_v1') && { | |
| 'threads': calls.rive_jobs_threads, | |
| 'join': calls.rive_jobs_join, | |
| 'join_any': (jobs, count, timeoutSeconds) => { | |
| const mark = stackSave(); | |
| let jobs_p = 0; | |
| try { | |
| jobs_p = stageIn(jobs, count * 4); | |
| return calls.rive_jobs_join_any(jobs_p, count, timeoutSeconds); | |
| } finally { | |
| unstage(jobs_p, count * 4); | |
| stackRestore(mark); | |
| } | |
| }, | |
| }, | |
| 'rive_parallel_v1': want('rive_parallel_v1') && { | |
| 'size': calls.rive_parallel_size, | |
| 'run': calls.rive_parallel_run, | |
| 'waiting': () => undefined, | |
| }, | |
| 'rive_shared_v1': want('rive_shared_v1') && { | |
| 'region_create': calls.rive_shared_region_create, | |
| 'region_size': calls.rive_shared_region_size, | |
| 'region_lock': calls.rive_shared_region_lock, | |
| 'region_unlock': calls.rive_shared_region_unlock, | |
| 'region_read': (region, offset, out, outByteCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageOut(out, outByteCount); | |
| const ret = calls.rive_shared_region_read(region, offset, out_p, outByteCount); | |
| copyOut(out_p, out, ret !== 0 ? outByteCount : 0); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'region_write': (region, offset, data, dataByteCount) => { | |
| const mark = stackSave(); | |
| let data_p = 0; | |
| try { | |
| data_p = stageIn(data, dataByteCount); | |
| return calls.rive_shared_region_write(region, offset, data_p, dataByteCount); | |
| } finally { | |
| unstage(data_p, dataByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'region_poisoned': calls.rive_shared_region_poisoned, | |
| 'atomic_load': calls.rive_shared_atomic_load, | |
| 'atomic_store': calls.rive_shared_atomic_store, | |
| 'atomic_add': calls.rive_shared_atomic_add, | |
| 'atomic_cas': calls.rive_shared_atomic_cas, | |
| 'ring_create': calls.rive_shared_ring_create, | |
| 'ring_write': (ring, data, dataByteCount, holds, holdCount) => { | |
| const mark = stackSave(); | |
| let data_p = 0; | |
| let holds_p = 0; | |
| try { | |
| data_p = stageIn(data, dataByteCount); | |
| holds_p = stageIn(holds, holdCount * 4); | |
| return calls.rive_shared_ring_write(ring, data_p, dataByteCount, holds_p, holdCount); | |
| } finally { | |
| unstage(holds_p, holdCount * 4); | |
| unstage(data_p, dataByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'ring_read': (ring, out, outByteCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageOut(out, outByteCount); | |
| const ret = calls.rive_shared_ring_read(ring, out_p, outByteCount); | |
| copyOut(out_p, out, fitted(ret - 1, outByteCount)); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'ring_drop': calls.rive_shared_ring_drop, | |
| 'ring_used': calls.rive_shared_ring_used, | |
| 'ring_signal': calls.rive_shared_ring_signal, | |
| 'snapshot_create': calls.rive_shared_snapshot_create, | |
| 'snapshot_publish': (snapshot, data, dataByteCount, holds, holdCount) => { | |
| const mark = stackSave(); | |
| let data_p = 0; | |
| let holds_p = 0; | |
| try { | |
| data_p = stageIn(data, dataByteCount); | |
| holds_p = stageIn(holds, holdCount * 4); | |
| return calls.rive_shared_snapshot_publish(snapshot, data_p, dataByteCount, holds_p, holdCount); | |
| } finally { | |
| unstage(holds_p, holdCount * 4); | |
| unstage(data_p, dataByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'snapshot_read': (snapshot, out, outByteCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageOut(out, outByteCount); | |
| const ret = calls.rive_shared_snapshot_read(snapshot, out_p, outByteCount); | |
| copyOut(out_p, out, fitted(ret - 1, outByteCount)); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'snapshot_seq': calls.rive_shared_snapshot_seq, | |
| 'read_done': calls.rive_shared_read_done, | |
| 'signal_create': calls.rive_shared_signal_create, | |
| 'signal_notify': calls.rive_shared_signal_notify, | |
| 'signal_seq': calls.rive_shared_signal_seq, | |
| 'blob_create': (data, dataByteCount) => { | |
| const mark = stackSave(); | |
| let data_p = 0; | |
| try { | |
| data_p = stageIn(data, dataByteCount); | |
| return calls.rive_shared_blob_create(data_p, dataByteCount); | |
| } finally { | |
| unstage(data_p, dataByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'blob_size': calls.rive_shared_blob_size, | |
| 'blob_read': (blob, offset, out, outByteCount) => { | |
| const mark = stackSave(); | |
| let out_p = 0; | |
| try { | |
| out_p = stageOut(out, outByteCount); | |
| const ret = calls.rive_shared_blob_read(blob, offset, out_p, outByteCount); | |
| copyOut(out_p, out, fitted(ret, outByteCount)); | |
| return ret; | |
| } finally { | |
| unstage(out_p, outByteCount); | |
| stackRestore(mark); | |
| } | |
| }, | |
| 'retain': calls.rive_shared_retain, | |
| 'release': calls.rive_shared_release, | |
| }, | |
| }; | |
| } | |
| // host.calls for one VM. hostCall(index) is the librive function at | |
| // that index of its kRiveWebCalls table, undefined for a missing op. | |
| // ctx.vm is the VM | |
| // handle, zeroed when the VM goes away while its module is still | |
| // instantiating. ctx.raised holds a raiseModuleError message: it is | |
| // thrown once the host call has returned, so only module frames | |
| // unwind. Anything thrown from inside librive unwound its frames | |
| // without their destructors, so ctx.hostFault marks the VM done for. | |
| // ctx.counters, when given, tallies the calls into librive. | |
| // A fault in a nested script call unwinds the outer module frames too. | |
| // only binds just that namespace's calls, as in createRiveModuleImports. | |
| function bindRiveHostCalls(hostCall, ctx, only = null) { | |
| const want = (module) => only === null || only === module; | |
| const counters = ctx.counters ?? { on: false }; | |
| const raise = () => { | |
| const error = new Error(ctx.raised); | |
| ctx.raised = null; | |
| throw error; | |
| }; | |
| const fault = (error) => { | |
| ctx.hostFault = true; | |
| throw error; | |
| }; | |
| const nestedFault = () => { | |
| throw new Error('librive faulted in a nested script call'); | |
| }; | |
| const released = () => { | |
| throw new Error('script VM was released'); | |
| }; | |
| return { | |
| rive_rt_log: want('rive_rt_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(0)), | |
| rive_rt_mark_needs_update: want('rive_rt_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(1)), | |
| rive_rt_budget_exceeded: want('rive_rt_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(2)), | |
| rive_rt_error: want('rive_rt_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(3)), | |
| rive_rt_debug_enter: want('rive_rt_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(4)), | |
| rive_rt_debug_line: want('rive_rt_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(5)), | |
| rive_rt_debug_leave: want('rive_rt_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(6)), | |
| rive_rt_utc_offset: want('rive_rt_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(7)), | |
| rive_rt_is_dst: want('rive_rt_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(8)), | |
| rive_rt_zone_name: want('rive_rt_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(9)), | |
| rive_data_view_model: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(10)), | |
| rive_data_root_view_model: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(11)), | |
| rive_data_global_view_model: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(12)), | |
| rive_data_global_view_model_names: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(13)), | |
| rive_data_context: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(14)), | |
| rive_data_context_parent: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(15)), | |
| rive_data_context_view_model: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(16)), | |
| rive_data_context_release: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(17)), | |
| rive_data_has_view_model: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(18)), | |
| rive_data_new_view_model: want('rive_data_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(19)), | |
| rive_data_vmi_release: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(20)), | |
| rive_data_vmi_number: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(21)), | |
| rive_data_vmi_boolean: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(22)), | |
| rive_data_vmi_string: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(23)), | |
| rive_data_vmi_trigger: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(24)), | |
| rive_data_vmi_color: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(25)), | |
| rive_data_vmi_view_model: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(26)), | |
| rive_data_vmi_property: want('rive_data_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(27)), | |
| rive_data_vmi_instance: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(28)), | |
| rive_data_vmi_symbol_index: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(29)), | |
| rive_data_vmi_equal: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(30)), | |
| rive_data_view_model_get: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(31)), | |
| rive_data_vmi_list: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(32)), | |
| rive_data_vmi_enum: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(33)), | |
| rive_data_vmi_image: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(34)), | |
| rive_data_vmi_font: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(35)), | |
| rive_data_vmi_blob: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(36)), | |
| rive_data_vmi_artboard: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(37)), | |
| rive_data_image_get: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(38)), | |
| rive_data_image_set: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(39)), | |
| rive_data_font_get: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(40)), | |
| rive_data_font_set: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(41)), | |
| rive_data_font_release: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(42)), | |
| rive_data_blob_present: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(43)), | |
| rive_data_blob_get: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(44)), | |
| rive_data_blob_name: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(45)), | |
| rive_data_blob_set: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(46)), | |
| rive_data_blob_clear: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(47)), | |
| rive_data_artboard_get: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(48)), | |
| rive_data_artboard_set: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(49)), | |
| rive_data_enum_get: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(50)), | |
| rive_data_enum_set: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(51)), | |
| rive_data_enum_values: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(52)), | |
| rive_data_prop_release: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(53)), | |
| rive_data_trigger_fire: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(54)), | |
| rive_data_list_length: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(55)), | |
| rive_data_list_push: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(56)), | |
| rive_data_list_pop: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(57)), | |
| rive_data_list_shift: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(58)), | |
| rive_data_list_clear: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(59)), | |
| rive_data_list_swap: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(60)), | |
| rive_data_list_insert: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(61)), | |
| rive_data_list_remove: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(62)), | |
| rive_data_list_remove_at: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(63)), | |
| rive_data_list_remove_all_of: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(64)), | |
| rive_data_list_get: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(65)), | |
| rive_data_view_model_set: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(66)), | |
| rive_data_color_get: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(67)), | |
| rive_data_color_set: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(68)), | |
| rive_data_number_get: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(69)), | |
| rive_data_number_set: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(70)), | |
| rive_data_boolean_get: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(71)), | |
| rive_data_boolean_set: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(72)), | |
| rive_data_string_get: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(73)), | |
| rive_data_string_changed: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(74)), | |
| rive_data_string_set: want('rive_data_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(75)), | |
| rive_data_watch: want('rive_data_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(76)), | |
| rive_data_unwatch: want('rive_data_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(77)), | |
| rive_data_convert_result: want('rive_data_v1') && ((fn) => (a0, a1, a2, a3, a4, a5) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(78)), | |
| rive_artboard_release: want('rive_artboard_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(79)), | |
| rive_artboard_advance: want('rive_artboard_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(80)), | |
| rive_artboard_draw: want('rive_artboard_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(81)), | |
| rive_artboard_instance: want('rive_artboard_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(82)), | |
| rive_artboard_data: want('rive_artboard_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(83)), | |
| rive_artboard_width: want('rive_artboard_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(84)), | |
| rive_artboard_height: want('rive_artboard_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(85)), | |
| rive_artboard_set_width: want('rive_artboard_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(86)), | |
| rive_artboard_set_height: want('rive_artboard_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(87)), | |
| rive_artboard_frame_origin: want('rive_artboard_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(88)), | |
| rive_artboard_set_frame_origin: want('rive_artboard_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(89)), | |
| rive_artboard_bounds: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(90)), | |
| rive_artboard_pointer_event: want('rive_artboard_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(91)), | |
| rive_artboard_scroll_event: want('rive_artboard_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6, a7, a8) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6, a7, a8); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(92)), | |
| rive_artboard_gamepad_event: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(93)), | |
| rive_artboard_animation: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(94)), | |
| rive_artboard_animation_release: want('rive_artboard_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(95)), | |
| rive_artboard_animation_duration: want('rive_artboard_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(96)), | |
| rive_artboard_animation_advance: want('rive_artboard_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(97)), | |
| rive_artboard_animation_set_time: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(98)), | |
| rive_artboard_add_to_path: want('rive_artboard_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6, a7) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6, a7); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(99)), | |
| rive_artboard_node: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(100)), | |
| rive_artboard_node_release: want('rive_artboard_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(101)), | |
| rive_artboard_node_transform: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(102)), | |
| rive_artboard_node_set: want('rive_artboard_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(103)), | |
| rive_artboard_node_world_transform: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(104)), | |
| rive_artboard_node_set_world_transform: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(105)), | |
| rive_artboard_node_decompose: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(106)), | |
| rive_artboard_node_path_verbs: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(107)), | |
| rive_artboard_node_path_points: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(108)), | |
| rive_artboard_node_paint: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(109)), | |
| rive_artboard_node_children: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(110)), | |
| rive_artboard_node_parent: want('rive_artboard_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(111)), | |
| rive_artboard_property_key: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(112)), | |
| rive_artboard_draw_visit: want('rive_artboard_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(113)), | |
| rive_artboard_draw_modulated: want('rive_artboard_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(114)), | |
| rive_artboard_drawable_draw: want('rive_artboard_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(115)), | |
| rive_artboard_drawable_value: want('rive_artboard_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(116)), | |
| rive_artboard_drawable_string: want('rive_artboard_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(117)), | |
| rive_artboard_drawable_properties: want('rive_artboard_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_artboard_v1', 'drawable_properties') : (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(118)), | |
| rive_audio_source: want('rive_audio_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(119)), | |
| rive_audio_source_release: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(120)), | |
| rive_audio_source_duration: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(121)), | |
| rive_audio_source_sample_rate: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(122)), | |
| rive_audio_source_channels: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(123)), | |
| rive_audio_source_to_blob: want('rive_audio_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(124)), | |
| rive_audio_stream: want('rive_audio_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(125)), | |
| rive_audio_stream_ring: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(126)), | |
| rive_audio_stream_seeks: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(127)), | |
| rive_audio_stream_channels: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(128)), | |
| rive_audio_stream_sample_rate: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(129)), | |
| rive_audio_stream_seek_frame: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(130)), | |
| rive_audio_stream_set_loop: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(131)), | |
| rive_audio_stream_ended: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(132)), | |
| rive_audio_stream_release: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(133)), | |
| rive_audio_play: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(134)), | |
| rive_audio_play_at_time: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(135)), | |
| rive_audio_play_in_time: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(136)), | |
| rive_audio_play_at_frame: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(137)), | |
| rive_audio_play_in_frame: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(138)), | |
| rive_audio_time: want('rive_audio_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(139)), | |
| rive_audio_time_frame: want('rive_audio_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(140)), | |
| rive_audio_sample_rate: want('rive_audio_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(141)), | |
| rive_audio_processor_sample_rate: want('rive_audio_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(142)), | |
| rive_audio_processor_channels: want('rive_audio_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(143)), | |
| rive_audio_sound_release: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(144)), | |
| rive_audio_sound_play: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(145)), | |
| rive_audio_sound_pause: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(146)), | |
| rive_audio_sound_resume: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(147)), | |
| rive_audio_sound_stop: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(148)), | |
| rive_audio_sound_seek: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(149)), | |
| rive_audio_sound_seek_frame: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(150)), | |
| rive_audio_sound_completed: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(151)), | |
| rive_audio_sound_time: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(152)), | |
| rive_audio_sound_time_frame: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(153)), | |
| rive_audio_sound_volume: want('rive_audio_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(154)), | |
| rive_audio_sound_set_volume: want('rive_audio_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(155)), | |
| rive_path_new: want('rive_path_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(156)), | |
| rive_path_update: want('rive_path_v1') && ((fn) => (a0, a1, a2, a3, a4, a5) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(157)), | |
| rive_path_release: want('rive_path_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(158)), | |
| rive_path_add: want('rive_path_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6, a7) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6, a7); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(159)), | |
| rive_path_verbs: want('rive_path_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(160)), | |
| rive_path_points: want('rive_path_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(161)), | |
| rive_path_effect_result: want('rive_path_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(162)), | |
| rive_measure_path_new: want('rive_measure_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(163)), | |
| rive_measure_contours_new: want('rive_measure_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(164)), | |
| rive_measure_contour_next: want('rive_measure_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(165)), | |
| rive_measure_length: want('rive_measure_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(166)), | |
| rive_measure_is_closed: want('rive_measure_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(167)), | |
| rive_measure_pos_tan: want('rive_measure_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(168)), | |
| rive_measure_warp: want('rive_measure_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(169)), | |
| rive_measure_extract: want('rive_measure_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(170)), | |
| rive_measure_extract_read: want('rive_measure_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(171)), | |
| rive_measure_release: want('rive_measure_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(172)), | |
| rive_paint_new: want('rive_paint_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(173)), | |
| rive_paint_release: want('rive_paint_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(174)), | |
| rive_paint_style: want('rive_paint_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(175)), | |
| rive_paint_color: want('rive_paint_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(176)), | |
| rive_paint_thickness: want('rive_paint_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(177)), | |
| rive_paint_join: want('rive_paint_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(178)), | |
| rive_paint_cap: want('rive_paint_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(179)), | |
| rive_paint_blend_mode: want('rive_paint_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(180)), | |
| rive_paint_feather: want('rive_paint_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(181)), | |
| rive_paint_shader: want('rive_paint_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(182)), | |
| rive_paint_shader_transform: want('rive_paint_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(183)), | |
| rive_canvas_new: want('rive_canvas_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(184)), | |
| rive_canvas_release: want('rive_canvas_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(185)), | |
| rive_canvas_width: want('rive_canvas_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(186)), | |
| rive_canvas_height: want('rive_canvas_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(187)), | |
| rive_canvas_resize: want('rive_canvas_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(188)), | |
| rive_canvas_image: want('rive_canvas_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(189)), | |
| rive_canvas_begin_frame: want('rive_canvas_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(190)), | |
| rive_canvas_end_frame: want('rive_canvas_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(191)), | |
| rive_gpu_features: want('rive_gpu_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(192)), | |
| rive_gpu_canvas_new: want('rive_gpu_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(193)), | |
| rive_gpu_canvas_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(194)), | |
| rive_gpu_canvas_color_view: want('rive_gpu_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(195)), | |
| rive_gpu_canvas_image: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(196)), | |
| rive_gpu_canvas_resize: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(197)), | |
| rive_gpu_target_view: want('rive_gpu_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(198)), | |
| rive_gpu_pass_begin: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(199)), | |
| rive_gpu_pass_set_pipeline: want('rive_gpu_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(200)), | |
| rive_gpu_pass_set_vertex_buffer: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(201)), | |
| rive_gpu_pass_set_index_buffer: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(202)), | |
| rive_gpu_pass_set_bind_group: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(203)), | |
| rive_gpu_pass_set_viewport: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(204)), | |
| rive_gpu_pass_set_scissor: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(205)), | |
| rive_gpu_pass_set_stencil_reference: want('rive_gpu_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(206)), | |
| rive_gpu_pass_set_blend_color: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(207)), | |
| rive_gpu_pass_draw: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(208)), | |
| rive_gpu_pass_draw_indexed: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4, a5) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(209)), | |
| rive_gpu_pass_finish: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(210)), | |
| rive_gpu_pass_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(211)), | |
| rive_gpu_image_view: want('rive_gpu_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(212)), | |
| rive_gpu_buffer_new: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(213)), | |
| rive_gpu_buffer_update: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(214)), | |
| rive_gpu_buffer_update_blob: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(215)), | |
| rive_gpu_buffer_new_blob: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(216)), | |
| rive_gpu_buffer_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(217)), | |
| rive_gpu_texture_new: want('rive_gpu_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(218)), | |
| rive_gpu_texture_upload: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(219)), | |
| rive_gpu_texture_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(220)), | |
| rive_gpu_sampler_new: want('rive_gpu_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(221)), | |
| rive_gpu_sampler_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(222)), | |
| rive_gpu_texture_view_new: want('rive_gpu_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(223)), | |
| rive_gpu_texture_view_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(224)), | |
| rive_gpu_shader_target: want('rive_gpu_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(225)), | |
| rive_gpu_shader_asset_bytes: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(226)), | |
| rive_gpu_shader_asset_id: want('rive_gpu_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(227)), | |
| rive_gpu_shader_module_from_asset: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(228)), | |
| rive_gpu_shader_module_from_rstb: want('rive_gpu_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_gpu_v1', 'shader_module_from_rstb') : (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(229)), | |
| rive_gpu_shader_module_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(230)), | |
| rive_gpu_bind_group_layout_new: want('rive_gpu_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(231)), | |
| rive_gpu_bind_group_layout_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(232)), | |
| rive_gpu_bind_group_layout_from_shader: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(233)), | |
| rive_gpu_bind_group_layout_from_shaders: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(234)), | |
| rive_gpu_bind_group_layout_from_entries: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(235)), | |
| rive_gpu_bind_group_new: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(236)), | |
| rive_gpu_bind_group_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(237)), | |
| rive_gpu_pipeline_new: want('rive_gpu_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(238)), | |
| rive_gpu_pipeline_release: want('rive_gpu_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(239)), | |
| rive_mat4_multiply: want('rive_mat4_v1') && ((fn) => (a0, a1, a2, a3, a4, a5) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(240)), | |
| rive_mat4_invert: want('rive_mat4_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(241)), | |
| rive_buffer_new: want('rive_buffer_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(242)), | |
| rive_buffer_update: want('rive_buffer_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(243)), | |
| rive_buffer_release: want('rive_buffer_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(244)), | |
| rive_mesh_instances_new: want('rive_mesh_instances_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(245)), | |
| rive_mesh_instances_resize: want('rive_mesh_instances_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(246)), | |
| rive_mesh_instances_update: want('rive_mesh_instances_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(247)), | |
| rive_mesh_instances_release: want('rive_mesh_instances_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(248)), | |
| rive_blob_asset_bytes: want('rive_blob_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(249)), | |
| rive_image_from_asset: want('rive_image_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(250)), | |
| rive_image_width: want('rive_image_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(251)), | |
| rive_image_height: want('rive_image_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(252)), | |
| rive_image_release: want('rive_image_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(253)), | |
| rive_image_decode: want('rive_image_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(254)), | |
| rive_image_decode_cancel: want('rive_image_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(255)), | |
| rive_font_from_asset: want('rive_font_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(256)), | |
| rive_font_decode: want('rive_font_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_font_v1', 'decode') : (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(257)), | |
| rive_font_release: want('rive_font_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(258)), | |
| rive_font_metrics: want('rive_font_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(259)), | |
| rive_font_weight: want('rive_font_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(260)), | |
| rive_font_is_italic: want('rive_font_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(261)), | |
| rive_font_axis_count: want('rive_font_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(262)), | |
| rive_font_axis: want('rive_font_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(263)), | |
| rive_font_axis_value: want('rive_font_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(264)), | |
| rive_font_features: want('rive_font_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(265)), | |
| rive_font_has_glyph: want('rive_font_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(266)), | |
| rive_font_with_options: want('rive_font_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(267)), | |
| rive_font_glyph_verbs: want('rive_font_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_font_v1', 'glyph_verbs') : (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(268)), | |
| rive_font_glyph_points: want('rive_font_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_font_v1', 'glyph_points') : (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(269)), | |
| rive_text_new: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'new') : () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(270)), | |
| rive_text_release: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'release') : (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(271)), | |
| rive_text_append: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'append') : (a0, a1, a2, a3, a4, a5, a6, a7, a8) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6, a7, a8); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(272)), | |
| rive_text_clear: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'clear') : (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(273)), | |
| rive_text_layout: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'layout') : (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(274)), | |
| rive_text_draw: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'draw') : (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(275)), | |
| rive_text_bounds: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'bounds') : (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(276)), | |
| rive_text_length: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'length') : (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(277)), | |
| rive_text_lines: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'lines') : (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(278)), | |
| rive_text_runs: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'runs') : (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(279)), | |
| rive_text_glyphs: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'glyphs') : (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(280)), | |
| rive_text_hit_test: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'hit_test') : (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(281)), | |
| rive_text_caret: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'caret') : (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(282)), | |
| rive_text_selection_rects: want('rive_text_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_text_v1', 'selection_rects') : (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(283)), | |
| rive_shader_linear: want('rive_shader_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(284)), | |
| rive_shader_radial: want('rive_shader_v1') && ((fn) => (a0, a1, a2, a3, a4, a5) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4, a5); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(285)), | |
| rive_shader_release: want('rive_shader_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(286)), | |
| rive_test_blob: want('rive_test_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(287)), | |
| rive_transition_child_draw: want('rive_transition_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(288)), | |
| rive_transition_child_width: want('rive_transition_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(289)), | |
| rive_transition_child_height: want('rive_transition_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(290)), | |
| rive_renderer_save: want('rive_renderer_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(291)), | |
| rive_renderer_restore: want('rive_renderer_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(292)), | |
| rive_renderer_transform: want('rive_renderer_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(293)), | |
| rive_renderer_draw_path: want('rive_renderer_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(294)), | |
| rive_renderer_clip_path: want('rive_renderer_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(295)), | |
| rive_renderer_modulate_opacity: want('rive_renderer_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(296)), | |
| rive_renderer_modulate_color: want('rive_renderer_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(297)), | |
| rive_renderer_draw_image: want('rive_renderer_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(298)), | |
| rive_renderer_draw_image_mesh: want('rive_renderer_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6, a7) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6, a7); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(299)), | |
| rive_renderer_draw_image_mesh_instanced: want('rive_renderer_v1') && ((fn) => (a0, a1, a2, a3, a4, a5, a6) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(300)), | |
| rive_net_fetch: want('rive_net_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(301)), | |
| rive_net_fetch_cancel: want('rive_net_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(302)), | |
| rive_file_decode: want('rive_file_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(303)), | |
| rive_file_release: want('rive_file_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(304)), | |
| rive_file_artboard_count: want('rive_file_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(305)), | |
| rive_file_artboard_name: want('rive_file_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(306)), | |
| rive_file_bindable: want('rive_file_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(307)), | |
| rive_file_bindable_release: want('rive_file_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(308)), | |
| rive_file_bindable_name: want('rive_file_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(309)), | |
| rive_file_bindable_data: want('rive_file_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(310)), | |
| rive_file_bindable_equal: want('rive_file_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(311)), | |
| rive_lanes_start: want('rive_lanes_v1') && ((fn) => (a0, a1, a2, a3, a4, a5) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4, a5); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(312)), | |
| rive_lanes_state: want('rive_lanes_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(313)), | |
| rive_lanes_failed: want('rive_lanes_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(314)), | |
| rive_lanes_stop: want('rive_lanes_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(315)), | |
| rive_lanes_release: want('rive_lanes_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(316)), | |
| rive_lanes_result: want('rive_lanes_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(317)), | |
| rive_lanes_watch: want('rive_lanes_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(318)), | |
| rive_lanes_wait: want('rive_lanes_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(319)), | |
| rive_lanes_cancel_wait: want('rive_lanes_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(320)), | |
| rive_lanes_wait_within: want('rive_lanes_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(321)), | |
| rive_jobs_threads: want('rive_jobs_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(322)), | |
| rive_jobs_join: want('rive_jobs_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(323)), | |
| rive_jobs_join_any: want('rive_jobs_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(324)), | |
| rive_parallel_size: want('rive_parallel_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(325)), | |
| rive_parallel_run: want('rive_parallel_v1') && ((fn) => fn === undefined ? unlinkedImport('rive_parallel_v1', 'run') : (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(326)), | |
| rive_shared_region_create: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(327)), | |
| rive_shared_region_size: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(328)), | |
| rive_shared_region_lock: want('rive_shared_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(329)), | |
| rive_shared_region_unlock: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(330)), | |
| rive_shared_region_read: want('rive_shared_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(331)), | |
| rive_shared_region_write: want('rive_shared_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(332)), | |
| rive_shared_region_poisoned: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(333)), | |
| rive_shared_atomic_load: want('rive_shared_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(334)), | |
| rive_shared_atomic_store: want('rive_shared_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(335)), | |
| rive_shared_atomic_add: want('rive_shared_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(336)), | |
| rive_shared_atomic_cas: want('rive_shared_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(337)), | |
| rive_shared_ring_create: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(338)), | |
| rive_shared_ring_write: want('rive_shared_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(339)), | |
| rive_shared_ring_read: want('rive_shared_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(340)), | |
| rive_shared_ring_drop: want('rive_shared_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(341)), | |
| rive_shared_ring_used: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(342)), | |
| rive_shared_ring_signal: want('rive_shared_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(343)), | |
| rive_shared_snapshot_create: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(344)), | |
| rive_shared_snapshot_publish: want('rive_shared_v1') && ((fn) => (a0, a1, a2, a3, a4) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3, a4); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(345)), | |
| rive_shared_snapshot_read: want('rive_shared_v1') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(346)), | |
| rive_shared_snapshot_seq: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(347)), | |
| rive_shared_read_done: want('rive_shared_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(348)), | |
| rive_shared_signal_create: want('rive_shared_v1') && ((fn) => () => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(349)), | |
| rive_shared_signal_notify: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(350)), | |
| rive_shared_signal_seq: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(351)), | |
| rive_shared_blob_create: want('rive_shared_v1') && ((fn) => (a0, a1) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(352)), | |
| rive_shared_blob_size: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(353)), | |
| rive_shared_blob_read: want('rive_shared_v1') && ((fn) => (a0, a1, a2, a3) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0, a1, a2, a3); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(354)), | |
| rive_shared_retain: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| let ret; | |
| try { ret = fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| return ret; | |
| })(hostCall(355)), | |
| rive_shared_release: want('rive_shared_v1') && ((fn) => (a0) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(356)), | |
| rive_console: want('env') && ((fn) => (a0, a1, a2) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(357)), | |
| rive_trace: want('env') && ((fn) => (a0, a1, a2, a3, a4, a5, a6, a7) => { | |
| if (ctx.vm === 0) released(); | |
| if (counters.on) counters.hostCalls++; | |
| try { fn(ctx.vm, a0, a1, a2, a3, a4, a5, a6, a7); } catch (error) { fault(error); } | |
| if (ctx.hostFault) nestedFault(); | |
| if (ctx.raised !== null) raise(); | |
| })(hostCall(358)), | |
| }; | |
| } | |
| // Stands in for an import the host lacks, so the module still links | |
| // and only a call to it traps, as on WAMR. | |
| function unlinkedImport(module, name) { | |
| return () => { | |
| throw new Error( | |
| 'failed to call unlinked import function ' + module + '.' + name | |
| ); | |
| }; | |
| } | |
| // Generated by src/wasm/idl/generate.py from bindings.py and | |
| // lane_layout.py. Do not edit. | |
| // | |
| // What each kind of lane module may import, which the page runner | |
| // checks it against, and the numbers lanes and the page agree on. | |
| // The console imports every lane gets. | |
| const kLaneConsole = [ | |
| 'console.log', | |
| 'console.debug', | |
| 'console.info', | |
| 'console.warn', | |
| 'console.error', | |
| ]; | |
| // [module, name or null for all of it, kinds, refusal or null], the | |
| // first match deciding. | |
| const kLaneImportRules = [ | |
| ['rive_rt_v1', 'now', ['job', 'worker'], null], | |
| ['rive_lanes_v1', 'wait_within', [], 'blocks on a signal, which only the main lane may; a worker awaits Signal.next or Port.receive instead'], | |
| ['rive_shared_v1', 'region_lock', ['job', 'worker'], 'locks a shared region, which the audio thread may not wait on; share through atomics, rings and snapshots instead'], | |
| ['rive_shared_v1', 'read_done', [], null], | |
| ['rive_shared_v1', null, ['job', 'worker', 'processor'], null], | |
| ['rive_lane_v1', null, ['job', 'worker', 'processor'], null], | |
| ['rive_job_v1', null, ['job'], null], | |
| ['rive_worker_v1', null, ['worker'], null], | |
| ['env', 'console.log', ['job', 'worker', 'processor'], null], | |
| ['env', 'console.debug', ['job', 'worker', 'processor'], null], | |
| ['env', 'console.info', ['job', 'worker', 'processor'], null], | |
| ['env', 'console.warn', ['job', 'worker', 'processor'], null], | |
| ['env', 'console.error', ['job', 'worker', 'processor'], null], | |
| ['env', 'console.time', ['job', 'worker'], null], | |
| ['env', 'console.timeLog', ['job', 'worker'], null], | |
| ['env', 'console.timeEnd', ['job', 'worker'], null], | |
| ]; | |
| // Why a lane module of kind ('job', 'worker' or 'processor') may not | |
| // import module.name: null when it may, else the end of "<kind> code ...", | |
| // empty when no rule says why. | |
| function laneImportRefusal(kind, module, name) { | |
| for (const [ruleModule, ruleName, kinds, refusal] of kLaneImportRules) { | |
| if (module === ruleModule && (ruleName === null || name === ruleName)) { | |
| return kinds.includes(kind) ? null : refusal ?? ''; | |
| } | |
| } | |
| return ''; | |
| } | |
| // [section, kind] for each lane kind, in rive_lanes_v1's order. | |
| const kLaneSections = [ | |
| ['rive.jobs', 'job'], | |
| ['rive.workers', 'worker'], | |
| ['rive.audio', 'processor'], | |
| ]; | |
| // The prefix each kind's entries export under, before their number. | |
| const kLaneEntryPrefixes = { | |
| 'job': '__rive_job_', | |
| 'worker': '__rive_worker_', | |
| 'processor': '__rive_processor_', | |
| }; | |
| // The rive_lanes_v1 states every lane moves through. | |
| const kLaneStates = { | |
| 'starting': 0, | |
| 'running': 1, | |
| 'done': 2, | |
| 'failed': 3, | |
| 'stopped': 4, | |
| }; | |
| // What a processor event carries for a console line, in place of a state. | |
| const kProcessorEventLog = 0xffffffff; | |
| // The most 64 KiB pages a job instance's memory may have grown to for another | |
| // job to reuse it, as memory never shrinks. | |
| const kReuseMaxPages = 256; | |
| // How long a processor's init may run in milliseconds, natively per step and in | |
| // a worklet as a whole, far longer than a block as it may build tables. | |
| const kProcessorInitMs = 1000; | |
| // Where a parallel call's control block keeps each word, in bytes from its | |
| // start. The words its parts race on sit 128 bytes apart, each alone on a cache | |
| // line, Apple's included. The claim takes 8 bytes, so no grain can wrap it. | |
| const kParallelThunk = 0; | |
| const kParallelArgs = 4; | |
| const kParallelParts = 8; | |
| const kParallelCount = 12; | |
| const kParallelAtOnce = 16; | |
| const kParallelCallerParks = 20; | |
| const kParallelGeneration = 128; | |
| const kParallelArrived = 256; | |
| const kParallelSleepers = 384; | |
| const kParallelClaim = 512; | |
| const kParallelStop = 640; | |
| // The exports a lane module may carry besides its entries. | |
| const kLaneAllocExport = '__rive_lane_alloc'; | |
| const kLaneFreeExport = '__rive_lane_free'; | |
| const kWorkerWakeExport = '__rive_worker_wake'; | |
| const kProcessorProcessExport = '__rive_processor_process'; | |
| const kFrameMinorExport = '__riveFrameMinor'; | |
| const kLiftedStartExport = '__riveLiftedStart'; | |
| const kLaneResetExport = '__riveLaneReset'; | |
| // What lanes report the same way on every host. | |
| const kProcessorHolds = | |
| 'a processor cannot pass shared objects through rings or snapshots, as the audio thread may ' + | |
| 'not hold or give them back; pass them in Audio.start\'s argument'; | |
| const kProcessorOverran = 'processor overran its block budget'; | |
| const kProcessorInitOverran = 'processor init overran its budget'; | |
| const kProcessorNode = 'rive-processors'; | |
| // A processor block's budget in milliseconds, first for its first block; 0 for none. | |
| function processorBlockBudgetMs(hardBlocks, frames, sampleRate, first) { | |
| return hardBlocks === 0 ? 0.0 : Math.max(first ? 100.0 : 1.0, Math.ceil(hardBlocks * 1000.0 * frames / sampleRate)); | |
| } | |
| // Why a lane module that imports module.name cannot load. | |
| function laneImportError(module, name) { | |
| return 'lane module imports ' + module + '.' + name + ', which it cannot reach'; | |
| } | |
| // Generated by src/wasm/idl/generate.py from shared_layout.py. Do not edit. | |
| // | |
| // The shared memory words librive and rive_shared_lane.mjs both read, | |
| // as byte offsets into librive's heap. | |
| // What a block holds, its first word. | |
| const kKindRegion = 0; | |
| const kKindRing = 1; | |
| const kKindSnapshot = 2; | |
| const kKindSignal = 3; | |
| const kKindBlob = 4; | |
| // Every block starts with these words. | |
| const kHeaderKind = 0; | |
| const kHeaderLock = 4; | |
| const kHeaderCapacity = 8; | |
| // A region after its header. | |
| const kRegionPoisoned = 16; | |
| const kRegionData = 32; | |
| // A ring after its header; signals are registry ids. | |
| const kRingHead = 16; | |
| const kRingUsed = 20; | |
| const kRingDataSignal = 24; | |
| const kRingSpaceSignal = 28; | |
| const kRingData = 32; | |
| // A snapshot after its header: copies of capacity bytes each, a version per | |
| // copy that is odd while a publish writes it. | |
| const kSnapshotLatest = 16; | |
| const kSnapshotSeq = 24; | |
| const kSnapshotSeqHigh = 28; | |
| const kSnapshotVersions = 32; | |
| const kSnapshotSizes = 40; | |
| const kSnapshotData = 48; | |
| const kSnapshotCopies = 2; | |
| // A ring record's length word or a snapshot copy's size. With the holds bit | |
| // set, the bytes end in the shared ids the value holds and then their count. | |
| const kRecordHolds = 0x80000000; | |
| // A signal after its header; watchers point at wake words. | |
| const kSignalWatcherCount = 16; | |
| const kSignalSeq = 24; | |
| const kSignalSeqHigh = 28; | |
| const kSignalWatchers = 32; | |
| // A blob after its header: bytes fixed once made. | |
| const kBlobData = 16; | |
| // The futex word a watcher parks on. | |
| const kWakeWordWord = 0; | |
| // The registry, at SharedRegistry::table(). | |
| const kTableLanes = 16; | |
| const kTableTokens = 144; | |
| const kTableChunks = 148; | |
| // A registry slot. Its state packs the generation in the low bits, a live bit, | |
| // then the pins librive holds. | |
| const kSlotState = 0; | |
| const kSlotBlock = 4; | |
| const kSlotOwner = 16; | |
| const kSlotOwnerHigh = 20; | |
| const kSlotSize = 24; | |
| const kSlotLive = 4096; | |
| const kSlotPin = 8192; | |
| // Slots come in chunks that never move once made. | |
| const kChunkShift = 10; | |
| const kChunkSlots = 1024; | |
| // An id: the top bit, its slot, the generation's low bits. | |
| const kIdBit = 0x80000000; | |
| const kIdSlotShift = 12; | |
| const kIdGenerationMask = 4095; | |
| // Lanes without librive. | |
| const kLaneCount = 32; | |
| const kLaneIdle = 1; | |
| const kLaneFirstToken = 2; | |
| // What ring_write answers. | |
| const kRingWriteFull = 0; | |
| const kRingWriteWritten = 1; | |
| const kRingWriteNeverFits = 2; | |
| // What region_lock answers. | |
| const kRegionLockGone = 0; | |
| // Words of the counter an NRDP page shares with its worklet thread, so it can | |
| // free what the thread held when it ends it. | |
| const kHoldBlocks = 0; | |
| const kHoldStarting = 1; | |
| const kHoldToken = 2; | |
| const kHoldLock = 3; | |
| const kHoldWords = 4; | |
| // The rive_shared_v1 natives for a lane without librive, such as an audio | |
| // worklet, through Atomics on librive's heap; like librive's, none ever waits. | |
| // Traps as WAMR does when byteLength bytes at ptr leave a module's memory. | |
| function checkBounds(buffer, ptr, byteLength) { | |
| if (ptr + byteLength > buffer.byteLength) { | |
| throw new Error('out of bounds memory access'); | |
| } | |
| } | |
| // The byte length of the std string at ptr, which the word before it holds. | |
| // Null reads as empty. Addresses and lengths arrive from wasm as signed i32s. | |
| function managedLength(buffer, ptr) { | |
| ptr >>>= 0; | |
| if (ptr < 4) { | |
| return 0; | |
| } | |
| checkBounds(buffer, ptr, 0); | |
| const length = new DataView(buffer).getUint32(ptr - 4, true); | |
| checkBounds(buffer, ptr, length); | |
| return length; | |
| } | |
| // UTF-16 text in a module's memory. Audio worklet scopes may have no | |
| // TextDecoder. | |
| function utf16Text(buffer, ptr, byteLength) { | |
| ptr >>>= 0; | |
| byteLength >>>= 0; | |
| checkBounds(buffer, ptr, byteLength); | |
| if (typeof TextDecoder !== 'undefined') { | |
| return new TextDecoder('utf-16le', { ignoreBOM: true }).decode( | |
| new Uint8Array(buffer, ptr, byteLength) | |
| ); | |
| } | |
| // A Uint16Array cannot start at an odd address, so text there is copied. | |
| const units = | |
| ptr % 2 === 0 | |
| ? new Uint16Array(buffer, ptr, byteLength >> 1) | |
| : new Uint16Array(buffer.slice(ptr, ptr + byteLength - (byteLength % 2))); | |
| let text = ''; | |
| for (let i = 0; i < units.length; i += 4096) { | |
| text += String.fromCharCode.apply(null, units.subarray(i, i + 4096)); | |
| } | |
| return text; | |
| } | |
| // Each thread's lane word and lock token, per table. Past the table's lane | |
| // words a lane pins through the slot's count, which no page can free. | |
| const laneClaims = new Map(); | |
| const kOverflowToken = kLaneFirstToken + kLaneCount; | |
| function claimLane(i32, table) { | |
| let claim = laneClaims.get(table); | |
| if (claim === undefined) { | |
| for (let i = 0; i < kLaneCount && claim === undefined; i++) { | |
| const word = (table + kTableLanes + i * 4) >>> 2; | |
| if (Atomics.compareExchange(i32, word, 0, kLaneIdle) === 0) { | |
| claim = { word, token: kLaneFirstToken + i }; | |
| } | |
| } | |
| // Still a token of its own, so its locks tell from librive's and | |
| // other lanes'. | |
| claim ??= { | |
| word: -1, | |
| token: kOverflowToken + Atomics.add(i32, (table + kTableTokens) >>> 2, 1), | |
| }; | |
| laneClaims.set(table, claim); | |
| } | |
| return claim; | |
| } | |
| // The id names the slot's live object. | |
| const slotNames = (state, id) => | |
| (state & kSlotLive) !== 0 && ((state ^ id) & kIdGenerationMask) === 0; | |
| // heap() answers librive's heap buffer, table is SharedRegistry::table() and | |
| // owner the VM whose objects the lane reaches; the lane records its token and | |
| // lock in holds, for a page to free them. | |
| function createSharedLaneImports(heap, table, owner, moduleMemory, holds = null, fail = () => {}) { | |
| table >>>= 0; | |
| const ownerLow = owner % 0x100000000; | |
| const ownerHigh = Math.floor(owner / 0x100000000); | |
| // Views over the heap and the lane's memory, rebuilt only when growth | |
| // replaces a buffer, so no call allocates on the audio thread. | |
| let buffer = null; | |
| let u8 = null; | |
| let i32 = null; | |
| let u32 = null; | |
| let moduleBuffer = null; | |
| let moduleU8 = null; | |
| const views = () => { | |
| const current = heap(); | |
| if (current !== buffer) { | |
| buffer = current; | |
| u8 = new Uint8Array(buffer); | |
| i32 = new Int32Array(buffer); | |
| u32 = new Uint32Array(buffer); | |
| } | |
| }; | |
| views(); | |
| const claim = claimLane(i32, table); | |
| if (holds !== null) { | |
| Atomics.store(holds, kHoldToken, claim.token); | |
| } | |
| // The lane's bytes when [ptr, ptr + length) lies in its memory, checked | |
| // before any lock is taken; null otherwise, as WAMR would trap. | |
| const moduleRange = (ptr, length) => { | |
| const current = moduleMemory().buffer; | |
| if (current !== moduleBuffer) { | |
| moduleBuffer = current; | |
| moduleU8 = new Uint8Array(current); | |
| } | |
| return ptr + length <= moduleU8.length ? moduleU8 : null; | |
| }; | |
| const copy = (to, toAt, from, fromAt, size) => { | |
| for (let i = 0; i < size; i++) { | |
| to[toAt + i] = from[fromAt + i]; | |
| } | |
| }; | |
| // Recorded before the swap, so whichever way an ended thread stopped, | |
| // the word holds this token only if the lane took it. | |
| const lock = (address) => { | |
| if (holds !== null) { | |
| Atomics.store(holds, kHoldLock, address); | |
| } | |
| while (Atomics.compareExchange(i32, address >>> 2, 0, claim.token) !== 0) {} | |
| }; | |
| const unlock = (address) => { | |
| Atomics.store(i32, address >>> 2, 0); | |
| if (holds !== null) { | |
| Atomics.store(holds, kHoldLock, 0); | |
| } | |
| }; | |
| // The block an id names, pinned so librive cannot free it until unpin; | |
| // 0 when the id is stale, another VM's or of another kind. A lane pins | |
| // one at a time. | |
| let pinned = 0; | |
| const pin = (id, kind) => { | |
| views(); | |
| id >>>= 0; | |
| if ((id & kIdBit) === 0) { | |
| return 0; | |
| } | |
| const index = (id & ~kIdBit) >>> kIdSlotShift; | |
| const chunk = Atomics.load(u32, (table + kTableChunks + (index >>> kChunkShift) * 4) >>> 2); | |
| if (chunk === 0) { | |
| return 0; | |
| } | |
| const slot = chunk + (index & (kChunkSlots - 1)) * kSlotSize; | |
| const stateAt = (slot + kSlotState) >>> 2; | |
| if (claim.word >= 0) { | |
| // Stored before the state is checked, as librive retires a slot | |
| // before scanning the lane words: one of the two sees the other. | |
| Atomics.store(u32, claim.word, slot); | |
| if (!slotNames(Atomics.load(u32, stateAt), id)) { | |
| Atomics.store(u32, claim.word, kLaneIdle); | |
| return 0; | |
| } | |
| } else { | |
| for (;;) { | |
| const state = Atomics.load(u32, stateAt); | |
| if (!slotNames(state, id)) { | |
| return 0; | |
| } | |
| if (Atomics.compareExchange(u32, stateAt, state, state + kSlotPin) === state) { | |
| break; | |
| } | |
| } | |
| } | |
| pinned = slot; | |
| const block = Atomics.load(u32, (slot + kSlotBlock) >>> 2); | |
| if ( | |
| u32[(block + kHeaderKind) >>> 2] !== kind || | |
| u32[(slot + kSlotOwner) >>> 2] !== ownerLow || | |
| u32[(slot + kSlotOwnerHigh) >>> 2] !== ownerHigh | |
| ) { | |
| unpin(); | |
| return 0; | |
| } | |
| return block; | |
| }; | |
| const unpin = () => { | |
| if (claim.word >= 0) { | |
| Atomics.store(u32, claim.word, kLaneIdle); | |
| } else { | |
| Atomics.sub(u32, (pinned + kSlotState) >>> 2, kSlotPin); | |
| } | |
| }; | |
| const capacityOf = (block) => u32[(block + kHeaderCapacity) >>> 2]; | |
| // A sequence is a low and a high word, as a 64 bit atomic allocates here. | |
| const bumpSeq = (low, high) => { | |
| if (Atomics.add(u32, low >>> 2, 1) === 0xffffffff) { | |
| Atomics.add(u32, high >>> 2, 1); | |
| } | |
| }; | |
| // High first, so a read during a carry answers less, never more. | |
| const readSeq = (low, high) => { | |
| const top = Atomics.load(u32, high >>> 2); | |
| return top * 0x100000000 + Atomics.load(u32, low >>> 2); | |
| }; | |
| const notify = (signal) => { | |
| const block = pin(signal, kKindSignal); | |
| if (block === 0) { | |
| return; | |
| } | |
| bumpSeq(block + kSignalSeq, block + kSignalSeqHigh); | |
| lock(block + kHeaderLock); | |
| try { | |
| const count = u32[(block + kSignalWatcherCount) >>> 2]; | |
| const watchers = u32[(block + kSignalWatchers) >>> 2] >>> 2; | |
| for (let i = 0; i < count; i++) { | |
| // A watcher's wake word: a futex word librive's threads wait on. | |
| const word = (u32[watchers + i] + kWakeWordWord) >>> 2; | |
| Atomics.add(i32, word, 1); | |
| Atomics.notify(i32, word); | |
| } | |
| } finally { | |
| unlock(block + kHeaderLock); | |
| unpin(); | |
| } | |
| }; | |
| // Ring bytes wrap around the block's data. | |
| const ringCopyIn = (block, at, from, fromAt, size) => { | |
| const capacity = capacityOf(block); | |
| const first = Math.min(size, capacity - at); | |
| copy(u8, block + kRingData + at, from, fromAt, first); | |
| copy(u8, block + kRingData, from, fromAt + first, size - first); | |
| }; | |
| const ringCopyOut = (block, at, to, toAt, size) => { | |
| const capacity = capacityOf(block); | |
| at %= capacity; | |
| const first = Math.min(size, capacity - at); | |
| copy(to, toAt, u8, block + kRingData + at, first); | |
| copy(to, toAt + first, u8, block + kRingData, size - first); | |
| }; | |
| // A record's length, four bytes little endian. | |
| const sizeBytes = new Uint8Array(4); | |
| const sizeWord = new Uint32Array(sizeBytes.buffer); | |
| const refuseHolds = () => { | |
| fail(kProcessorHolds); | |
| return 0; | |
| }; | |
| // Pops the head record into to at out if it fits capacity, or with to null drops it if it | |
| // does not, and notifies space. Answers its size plus one, 0 when empty or a drop keeps it. | |
| const pop = (ring, to, out, capacity) => { | |
| const block = pin(ring, kKindRing); | |
| if (block === 0) { | |
| return 0; | |
| } | |
| let signal = 0; | |
| let size = 0; | |
| lock(block + kHeaderLock); | |
| try { | |
| const used = u32[(block + kRingUsed) >>> 2]; | |
| if (used === 0) { | |
| return 0; | |
| } | |
| const head = u32[(block + kRingHead) >>> 2]; | |
| ringCopyOut(block, head, sizeBytes, 0, 4); | |
| size = sizeWord[0]; | |
| if ((size & kRecordHolds) !== 0) { | |
| return refuseHolds(); | |
| } | |
| if (to === null) { | |
| if (size <= capacity) { | |
| return 0; | |
| } | |
| } else if (out === 0 || size > capacity) { | |
| return size + 1; | |
| } else { | |
| ringCopyOut(block, head + 4, to, out, size); | |
| } | |
| u32[(block + kRingHead) >>> 2] = (head + 4 + size) % capacityOf(block); | |
| u32[(block + kRingUsed) >>> 2] = used - 4 - size; | |
| signal = u32[(block + kRingSpaceSignal) >>> 2]; | |
| } finally { | |
| unlock(block + kHeaderLock); | |
| unpin(); | |
| } | |
| notify(signal); | |
| return size + 1; | |
| }; | |
| // A region word's index, or -1 outside the region. | |
| const word = (block, offset) => { | |
| offset >>>= 0; | |
| if ((offset & 3) !== 0 || offset + 4 > capacityOf(block)) { | |
| return -1; | |
| } | |
| return (block + kRegionData + offset) >>> 2; | |
| }; | |
| // -1 outside the region or once it is gone, which the std throws for. | |
| const atomic = (region, offset, use) => { | |
| const block = pin(region, kKindRegion); | |
| if (block === 0) { | |
| return -1; | |
| } | |
| try { | |
| const at = word(block, offset); | |
| return at < 0 ? -1 : use(at) >>> 0; | |
| } finally { | |
| unpin(); | |
| } | |
| }; | |
| return { | |
| 'region_create': () => 0, | |
| 'region_size': (region) => { | |
| const block = pin(region, kKindRegion); | |
| if (block === 0) { | |
| return 0; | |
| } | |
| const size = capacityOf(block); | |
| unpin(); | |
| return size; | |
| }, | |
| 'region_lock': () => kRegionLockGone, | |
| 'region_unlock': () => {}, | |
| 'region_read': () => 0, | |
| 'region_write': () => 0, | |
| 'region_poisoned': (region) => { | |
| const block = pin(region, kKindRegion); | |
| if (block === 0) { | |
| return 0; | |
| } | |
| const poisoned = u32[(block + kRegionPoisoned) >>> 2] !== 0 ? 1 : 0; | |
| unpin(); | |
| return poisoned; | |
| }, | |
| 'atomic_load': (region, offset) => atomic(region, offset, (at) => Atomics.load(i32, at)), | |
| 'atomic_store': (region, offset, value) => | |
| atomic(region, offset, (at) => { | |
| Atomics.store(i32, at, value | 0); | |
| return 0; | |
| }), | |
| 'atomic_add': (region, offset, value) => | |
| atomic(region, offset, (at) => Atomics.add(i32, at, value | 0)), | |
| 'atomic_cas': (region, offset, expected, desired) => | |
| atomic(region, offset, (at) => | |
| Atomics.compareExchange(i32, at, expected | 0, desired | 0) | |
| ), | |
| 'ring_create': () => 0, | |
| 'ring_write': (ring, data, dataByteCount, holds, holdCount) => { | |
| data >>>= 0; | |
| dataByteCount >>>= 0; | |
| const from = moduleRange(data, dataByteCount); | |
| const block = from !== null ? pin(ring, kKindRing) : 0; | |
| if (block === 0) { | |
| return kRingWriteFull; | |
| } | |
| if (holdCount !== 0) { | |
| unpin(); | |
| return refuseHolds(); | |
| } | |
| let signal = 0; | |
| lock(block + kHeaderLock); | |
| try { | |
| const capacity = capacityOf(block); | |
| if (4 + dataByteCount > capacity) { | |
| return kRingWriteNeverFits; | |
| } | |
| const used = u32[(block + kRingUsed) >>> 2]; | |
| if (used + 4 + dataByteCount > capacity) { | |
| return kRingWriteFull; | |
| } | |
| const head = u32[(block + kRingHead) >>> 2]; | |
| sizeWord[0] = dataByteCount; | |
| ringCopyIn(block, (head + used) % capacity, sizeBytes, 0, 4); | |
| ringCopyIn(block, (head + used + 4) % capacity, from, data, dataByteCount); | |
| u32[(block + kRingUsed) >>> 2] = used + 4 + dataByteCount; | |
| signal = u32[(block + kRingDataSignal) >>> 2]; | |
| } finally { | |
| unlock(block + kHeaderLock); | |
| unpin(); | |
| } | |
| notify(signal); | |
| return kRingWriteWritten; | |
| }, | |
| 'ring_read': (ring, out, outByteCount) => { | |
| out >>>= 0; | |
| outByteCount >>>= 0; | |
| const to = moduleRange(out, outByteCount); | |
| return to !== null ? pop(ring, to, out, outByteCount) : 0; | |
| }, | |
| 'ring_drop': (ring, capacity) => pop(ring, null, 0, capacity >>> 0), | |
| 'ring_used': (ring) => { | |
| const block = pin(ring, kKindRing); | |
| if (block === 0) { | |
| return 0; | |
| } | |
| lock(block + kHeaderLock); | |
| const used = u32[(block + kRingUsed) >>> 2]; | |
| unlock(block + kHeaderLock); | |
| unpin(); | |
| return used; | |
| }, | |
| 'ring_signal': (ring, space) => { | |
| const block = pin(ring, kKindRing); | |
| if (block === 0) { | |
| return 0; | |
| } | |
| const signal = u32[(block + (space !== 0 ? kRingSpaceSignal : kRingDataSignal)) >>> 2]; | |
| unpin(); | |
| return signal; | |
| }, | |
| 'snapshot_create': () => 0, | |
| // As SharedSnapshot::publish: publishers take turns writing the copy | |
| // readers are not on. | |
| 'snapshot_publish': (snapshot, data, dataByteCount, holds, holdCount) => { | |
| data >>>= 0; | |
| dataByteCount >>>= 0; | |
| const from = moduleRange(data, dataByteCount); | |
| const block = from !== null ? pin(snapshot, kKindSnapshot) : 0; | |
| if (block === 0) { | |
| return 0; | |
| } | |
| try { | |
| const capacity = capacityOf(block); | |
| if (holdCount !== 0) { | |
| return refuseHolds(); | |
| } | |
| if (dataByteCount > capacity) { | |
| return 0; | |
| } | |
| lock(block + kHeaderLock); | |
| try { | |
| const latestAt = (block + kSnapshotLatest) >>> 2; | |
| const latest = Atomics.load(u32, latestAt); | |
| const sizesAt = (block + kSnapshotSizes) >>> 2; | |
| const replaced = latest !== 0 ? Atomics.load(u32, sizesAt + latest - 1) : 0; | |
| // Nothing here could give back the replaced value's holds. | |
| if ((replaced & kRecordHolds) !== 0) { | |
| return refuseHolds(); | |
| } | |
| const index = latest % kSnapshotCopies; | |
| const versionAt = ((block + kSnapshotVersions) >>> 2) + index; | |
| const version = Atomics.load(u32, versionAt) | 1; | |
| Atomics.store(u32, versionAt, version); | |
| // A load after the store keeps the bytes from landing | |
| // before the odd version, as JS has no fence. | |
| Atomics.load(u32, versionAt); | |
| copy(u8, block + kSnapshotData + index * capacity, from, data, dataByteCount); | |
| Atomics.store(u32, sizesAt + index, dataByteCount); | |
| Atomics.store(u32, versionAt, version + 1); | |
| Atomics.store(u32, latestAt, index + 1); | |
| bumpSeq(block + kSnapshotSeq, block + kSnapshotSeqHigh); | |
| } finally { | |
| unlock(block + kHeaderLock); | |
| } | |
| return 1; | |
| } finally { | |
| unpin(); | |
| } | |
| }, | |
| // As SharedSnapshot::read, without the lock. | |
| 'snapshot_read': (snapshot, out, outByteCount) => { | |
| out >>>= 0; | |
| outByteCount >>>= 0; | |
| const to = moduleRange(out, outByteCount); | |
| const block = to !== null ? pin(snapshot, kKindSnapshot) : 0; | |
| if (block === 0) { | |
| return 0; | |
| } | |
| try { | |
| for (;;) { | |
| const latest = Atomics.load(u32, (block + kSnapshotLatest) >>> 2); | |
| if (latest === 0) { | |
| return 0; | |
| } | |
| const index = latest - 1; | |
| const versionAt = ((block + kSnapshotVersions) >>> 2) + index; | |
| const version = Atomics.load(u32, versionAt); | |
| if ((version & 1) !== 0) { | |
| continue; | |
| } | |
| const word = Atomics.load(u32, ((block + kSnapshotSizes) >>> 2) + index); | |
| const capacity = capacityOf(block); | |
| const at = block + kSnapshotData + index * capacity; | |
| const refused = (word & kRecordHolds) !== 0; | |
| // A torn read answers what the version check discards. | |
| const size = Math.min(word, capacity); | |
| if (!refused && out !== 0 && size <= outByteCount) { | |
| copy(to, out, u8, at, size); | |
| } | |
| // An exchange rather than a load keeps the copy from | |
| // reading past the check. | |
| if (Atomics.compareExchange(u32, versionAt, version, version) === version) { | |
| return refused ? refuseHolds() : size + 1; | |
| } | |
| } | |
| } finally { | |
| unpin(); | |
| } | |
| }, | |
| 'snapshot_seq': (snapshot) => { | |
| const block = pin(snapshot, kKindSnapshot); | |
| if (block === 0) { | |
| return 0; | |
| } | |
| const seq = readSeq(block + kSnapshotSeq, block + kSnapshotSeqHigh); | |
| unpin(); | |
| return seq; | |
| }, | |
| 'signal_create': () => 0, | |
| 'signal_notify': (signal) => notify(signal), | |
| 'signal_seq': (signal) => { | |
| const block = pin(signal, kKindSignal); | |
| if (block === 0) { | |
| return 0; | |
| } | |
| const seq = readSeq(block + kSignalSeq, block + kSignalSeqHigh); | |
| unpin(); | |
| return seq; | |
| }, | |
| 'blob_create': () => 0, | |
| 'blob_size': (blob) => { | |
| const block = pin(blob, kKindBlob); | |
| if (block === 0) { | |
| return 0; | |
| } | |
| const size = capacityOf(block); | |
| unpin(); | |
| return size; | |
| }, | |
| // A blob never changes, so the copy takes no lock. | |
| 'blob_read': (blob, offset, out, outByteCount) => { | |
| offset >>>= 0; | |
| out >>>= 0; | |
| outByteCount >>>= 0; | |
| const to = moduleRange(out, outByteCount); | |
| const block = to !== null ? pin(blob, kKindBlob) : 0; | |
| if (block === 0) { | |
| return 0; | |
| } | |
| const size = capacityOf(block); | |
| const count = offset < size ? Math.min(outByteCount, size - offset) : 0; | |
| copy(to, out, u8, block + kBlobData + offset, count); | |
| unpin(); | |
| return count; | |
| }, | |
| 'retain': () => 0, | |
| 'release': () => {}, | |
| }; | |
| } | |
| // Frees the lock word and lane word a lane left held, for a page that ended | |
| // its thread, once that thread is surely gone. | |
| function releaseSharedLane(heap, table, holds) { | |
| const token = Atomics.load(holds, kHoldToken); | |
| if (token < kLaneFirstToken) { | |
| return; | |
| } | |
| const i32 = new Int32Array(heap()); | |
| const lockAt = Atomics.load(holds, kHoldLock); | |
| if (lockAt !== 0) { | |
| Atomics.compareExchange(i32, lockAt >>> 2, token, 0); | |
| } | |
| // Last: the slot it pinned keeps the locked block alive until here. | |
| if (token < kOverflowToken) { | |
| Atomics.store(i32, (((table >>> 0) + kTableLanes) >>> 2) + token - kLaneFirstToken, 0); | |
| } | |
| } | |
| // Instances of the lane modules a script module carries, started the same way | |
| // by the page runner and, through createProcessorMixer, by the audio worklets. | |
| function errorText(error) { | |
| return String(error?.message ?? error); | |
| } | |
| // Chrome's worklet scope has no performance; Date's milliseconds still catch a | |
| // block of several. | |
| const monotonicNow = | |
| globalThis.performance !== undefined ? () => globalThis.performance.now() : Date.now; | |
| // The console imports: each line is a std string, its byte length before it. | |
| // Only jobs and workers import the timers. | |
| function laneConsole(memory, log, timers = new Map()) { | |
| const text = (ptr) => { | |
| const buffer = memory().buffer; | |
| return utf16Text(buffer, ptr, managedLength(buffer, ptr)); | |
| }; | |
| const env = {}; | |
| for (const name of kLaneConsole) { | |
| env[name] = (ptr) => log(text(ptr)); | |
| } | |
| const report = (end) => (ptr) => { | |
| const label = text(ptr); | |
| const started = timers.get(label); | |
| if (started === undefined) { | |
| log(`Timer '${label}' does not exist`); | |
| return; | |
| } | |
| if (end) { | |
| timers.delete(label); | |
| } | |
| log(`${label}: ${(monotonicNow() - started).toFixed(3)}ms`); | |
| }; | |
| env['console.time'] = (ptr) => timers.set(text(ptr), monotonicNow()); | |
| env['console.timeLog'] = report(false); | |
| env['console.timeEnd'] = report(true); | |
| return env; | |
| } | |
| const noFuelCheck = () => {}; | |
| // An instance of lane.module whose imports reach the lane's own natives, log, | |
| // timers, clock and fuel check. Returns { exports, memory, failure } or | |
| // { error }. | |
| function instantiateLane(lane) { | |
| let memory = null; | |
| let thrown = null; | |
| const failure = (error) => thrown ?? errorText(error); | |
| const imports = { | |
| 'env': laneConsole(() => memory, lane.log, lane.timers), | |
| 'rive_shared_v1': lane.shared(() => memory), | |
| 'rive_rt_v1': { 'now': lane.now ?? monotonicNow }, | |
| 'rive_lane_v1': { | |
| 'error': (ptr, byteLength) => { | |
| thrown = utf16Text(memory.buffer, ptr, byteLength); | |
| lane.onThrow?.(thrown); | |
| }, | |
| 'fuel_check': lane.fuel ?? noFuelCheck, | |
| }, | |
| }; | |
| if (lane.natives !== undefined) { | |
| imports[lane.natives] = lane.own(() => memory); | |
| } | |
| try { | |
| const exports = new WebAssembly.Instance(lane.module, imports).exports; | |
| memory = exports['memory']; | |
| return { exports, memory, failure }; | |
| } catch (error) { | |
| return { error: failure(error) }; | |
| } | |
| } | |
| // Runs the instance's start, or its reset when a job ran in it before, then | |
| // prefix + entry with a copy of input and args, freeing the copy after when | |
| // lane.free. Returns { result } or { error }. | |
| function enterLane(instance, lane, reset = false) { | |
| try { | |
| const exports = instance.exports; | |
| exports[reset ? kLaneResetExport : kLiftedStartExport]?.(); | |
| const input = lane.input; | |
| const at = exports[kLaneAllocExport](input.length) >>> 0; | |
| new Uint8Array(instance.memory.buffer, at, input.length).set(input); | |
| const result = exports[lane.prefix + lane.entry]( | |
| at, | |
| input.length, | |
| ...(lane.args ?? []) | |
| ); | |
| if (lane.free) { | |
| exports[kLaneFreeExport](at); | |
| } | |
| return { result }; | |
| } catch (error) { | |
| return { error: instance.failure(error) }; | |
| } | |
| } | |
| // A new instance, entered. Returns { exports, memory, result, failure } or | |
| // { error }. | |
| function startLane(lane) { | |
| const instance = instantiateLane(lane); | |
| const entered = instance.error === undefined ? enterLane(instance, lane) : instance; | |
| return entered.error === undefined ? { ...instance, result: entered.result } : entered; | |
| } | |
| // One script audio processor, whose init may take kProcessorInitMs. Returns | |
| // { lane } or { error }; shared(memory, fail) answers its shared imports. | |
| function startProcessorLane(module, entry, input, format, shared, log) { | |
| // As natively, a native that fails the processor lets the block finish. | |
| let failed = null; | |
| const fail = (text) => { | |
| failed ??= text; | |
| }; | |
| // When its fuel checks end it and why, made once so a block allocates | |
| // nothing on the audio thread. | |
| const bounds = { until: monotonicNow() + kProcessorInitMs, reason: kProcessorInitOverran }; | |
| const started = startLane({ | |
| module, | |
| shared: (memory) => shared(memory, fail), | |
| log, | |
| fuel: () => { | |
| if (monotonicNow() > bounds.until) { | |
| throw bounds.reason; | |
| } | |
| }, | |
| prefix: kLaneEntryPrefixes['processor'], | |
| entry, | |
| input, | |
| args: [format.sampleRate, format.maxFrames, format.channels], | |
| free: true, | |
| }); | |
| if (started.error !== undefined || failed !== null) { | |
| return { error: started.error ?? failed }; | |
| } | |
| bounds.until = Infinity; | |
| bounds.reason = kProcessorOverran; | |
| const exports = started.exports; | |
| const memory = started.memory; | |
| // Rebuilt only when the block moves or memory grows, so a block | |
| // allocates nothing on the audio thread. | |
| let view = null; | |
| return { | |
| lane: { | |
| // Ends the block past budget ms, if any; sink gets its samples | |
| // before a collection can move them. Null, or why it failed. | |
| render(frames, startFrame, sink, budget = 0) { | |
| if (budget > 0) { | |
| bounds.until = monotonicNow() + budget; | |
| } | |
| try { | |
| const at = exports[kProcessorProcessExport](frames, startFrame) >>> 0; | |
| if (failed !== null) { | |
| return failed; | |
| } | |
| const length = frames * format.channels; | |
| if ( | |
| view === null || | |
| view.buffer !== memory.buffer || | |
| view.byteOffset !== at || | |
| view.length !== length | |
| ) { | |
| view = new Float32Array(memory.buffer, at, length); | |
| } | |
| sink(view); | |
| exports[kFrameMinorExport]?.(); | |
| return null; | |
| } catch (error) { | |
| return started.failure(error); | |
| } finally { | |
| bounds.until = Infinity; | |
| } | |
| }, | |
| }, | |
| }; | |
| } | |
| // Every processor a real time output runs, as the page's messages say, with | |
| // answers through post. It counts blocks and starts in holds, the Hold words. | |
| function createProcessorMixer(heap, table, post, holds) { | |
| const lanes = new Map(); | |
| // What render walks, rebuilt only when lanes change, so a block does not | |
| // allocate an iterator. | |
| let order = []; | |
| const relist = () => { | |
| order = [...lanes.entries()]; | |
| }; | |
| // Null while compiling, then the module or the compile's error text, | |
| // until the page forgets it. | |
| const modules = new Map(); | |
| // Starts not yet run, behind one whose module still compiles. | |
| const waiting = []; | |
| // The output's add and where in its block a chunk goes, set as render | |
| // walks, so sinks allocate nothing. | |
| let add = null; | |
| let offset = 0; | |
| let frame = -1; | |
| const fail = (id, text) => { | |
| lanes.delete(id); | |
| relist(); | |
| post({ id, kind: 'failed', text }); | |
| }; | |
| const start = (message) => { | |
| const id = message.id; | |
| const module = modules.get(message.moduleId); | |
| if (typeof module === 'string') { | |
| post({ id, kind: 'failed', text: module }); | |
| return; | |
| } | |
| const format = message.format; | |
| const started = startProcessorLane( | |
| module, | |
| message.entry, | |
| message.input, | |
| format, | |
| (moduleMemory, fail) => | |
| createSharedLaneImports(heap, table, message.sharedOwner, moduleMemory, holds, fail), | |
| (text) => post({ id, kind: 'log', text }) | |
| ); | |
| if (started.error !== undefined) { | |
| post({ id, kind: 'failed', text: started.error }); | |
| return; | |
| } | |
| const channels = format.channels; | |
| lanes.set(id, { | |
| lane: started.lane, | |
| maxFrames: format.maxFrames, | |
| // A block past its hard limit, where there is one, ends at its | |
| // next fuel check, or without fuel once it returns. | |
| hardBlocks: message.hardBlocks, | |
| sampleRate: format.sampleRate, | |
| warm: false, | |
| sink: (block) => add(block, channels, offset), | |
| }); | |
| relist(); | |
| post({ id, kind: 'running' }); | |
| }; | |
| // Starts in arrival order, up to the first whose module still compiles. | |
| const drain = () => { | |
| while (waiting.length > 0 && modules.get(waiting[0].moduleId) !== null) { | |
| start(waiting.shift()); | |
| // Each start gets the page's whole start limit, and the checks it | |
| // took must not count under the shorter limit after it. | |
| Atomics.add(holds, kHoldBlocks, 1); | |
| } | |
| if (waiting.length === 0) { | |
| Atomics.store(holds, kHoldStarting, 0); | |
| } | |
| }; | |
| return { | |
| receive(message) { | |
| if (message.kind === 'forget') { | |
| modules.delete(message.moduleId); | |
| return; | |
| } | |
| if (message.kind === 'stop') { | |
| // A stop beats the start it follows when that still waits. | |
| const at = waiting.findIndex((queued) => queued.id === message.id); | |
| if (at >= 0) { | |
| waiting.splice(at, 1); | |
| drain(); | |
| } else { | |
| lanes.delete(message.id); | |
| relist(); | |
| } | |
| return; | |
| } | |
| if (message.kind === 'end') { | |
| // The page gave up on this output and failed what it ran. | |
| lanes.clear(); | |
| relist(); | |
| waiting.length = 0; | |
| return; | |
| } | |
| const moduleId = message.moduleId; | |
| if (!modules.has(moduleId) && message.bytes === null) { | |
| // A fresh worklet lacks modules the page sent the one before. | |
| post({ id: message.id, kind: 'resend' }); | |
| return; | |
| } | |
| if (!modules.has(moduleId)) { | |
| // Compiling on the audio thread would stall every processor. | |
| modules.set(moduleId, null); | |
| const settle = (value) => { | |
| if (modules.has(moduleId)) { | |
| modules.set(moduleId, value); | |
| } | |
| }; | |
| WebAssembly.compile(message.bytes) | |
| .then(settle, (error) => settle(errorText(error))) | |
| .then(drain); | |
| } | |
| Atomics.store(holds, kHoldStarting, 1); | |
| waiting.push(message); | |
| drain(); | |
| }, | |
| // Hands into(block, channels, offset) each processor's interleaved | |
| // samples, in chunks of at most its block, offset frames in. | |
| render(frames, firstFrame, into) { | |
| if (frame < 0) { | |
| frame = firstFrame; | |
| } | |
| add = into; | |
| // A failure relists, which must not shift the rest of this pass. | |
| const list = order; | |
| for (let i = 0; i < list.length; i++) { | |
| const [id, entry] = list[i]; | |
| for (offset = 0; offset < frames; offset += entry.maxFrames) { | |
| const chunk = Math.min(entry.maxFrames, frames - offset); | |
| const budget = processorBlockBudgetMs( | |
| entry.hardBlocks, | |
| chunk, | |
| entry.sampleRate, | |
| !entry.warm | |
| ); | |
| const began = monotonicNow(); | |
| let error = entry.lane.render(chunk, frame + offset, entry.sink, budget); | |
| if (error === null && budget > 0 && monotonicNow() - began > budget) { | |
| error = kProcessorOverran; | |
| } | |
| entry.warm = true; | |
| if (error !== null) { | |
| fail(id, error); | |
| break; | |
| } | |
| } | |
| } | |
| frame += frames; | |
| Atomics.add(holds, kHoldBlocks, 1); | |
| }, | |
| // The output went away: every processor it ran ends with text. | |
| failAll(text) { | |
| for (const id of [...lanes.keys()]) { | |
| fail(id, text); | |
| } | |
| for (const message of waiting.splice(0)) { | |
| post({ id: message.id, kind: 'failed', text }); | |
| } | |
| }, | |
| }; | |
| } | |
| // Parallel calls on a page with threads. A team of pool threads runs a | |
| // module's parts on members: instances of the module that share its memory, | |
| // made without its start or its data, which would undo what the page's own | |
| // instance already did to that memory. A call hands its parts to the team | |
| // through words in shared memory, and the page's thread runs its own part | |
| // while the members run theirs. The page's thread cannot wait, so it spins. | |
| // Team threads spin a while after each call, then park in a way that still | |
| // lets them take the memory of a module loaded later. | |
| // The team's words, by Int32 index. Words that threads race on sit on cache | |
| // lines of their own. | |
| const kTeamCall = 0; | |
| const kTeamParked = 16; | |
| const kTeamThreads = 32; | |
| const kTeamVm = 33; | |
| const kTeamControl = 34; | |
| const kTeamGlobals = 35; | |
| const kTeamFailed = 48; | |
| const kTeamFailKind = 49; | |
| const kTeamFailAt = 50; | |
| const kTeamFailLength = 51; | |
| const kTeamFailMs = 52; | |
| const kTeamFailBytes = 53; | |
| const kTeamWaits = 54; | |
| // Each thread's line: the call it last finished, the call the page assigned | |
| // it until the thread takes its part, its part in that call, and the last | |
| // call it saw. The page writes an assignment before the call starts, so a | |
| // thread that wakes late never takes a later call's part as its own, and | |
| // clears one the thread never took, so it never runs it after the call ends. | |
| const kTeamDone = 128; | |
| const kTeamAssigned = 1; | |
| const kTeamPart = 2; | |
| const kTeamSeen = 3; | |
| // As many as a native call's team. | |
| const kTeamMax = 63; | |
| // The most parts a call gets by default, one per core up to this. | |
| const kDefaultParts = 8; | |
| const kTeamTextAt = (kTeamDone + 16 * kTeamMax) * 4; | |
| const kTeamTextBytes = 512; | |
| const kFailTrap = 1; | |
| const kFailThrow = 2; | |
| const kFailBudget = 3; | |
| const kWaitAsync = 1; | |
| const kWaitTimed = 2; | |
| // How long a team thread polls for the next call before it parks, as the | |
| // native team does, so a frame's next stage starts without a wake. | |
| const kSpinMs = 0.05; | |
| // A parked thread without Atomics.waitAsync looks for messages this often. | |
| const kTimedWaitMs = 2; | |
| // How long a call waits for a thread to take its part before it wakes the | |
| // team again, and before it gives up on the thread. | |
| const kRewakeMs = 1; | |
| const kTakeMs = 1000; | |
| // How long preparing a module waits for its members. | |
| const kReadyMs = 10000; | |
| // As each native member's spill zone, which fills the frame collector's | |
| // 64 KiB raw block after its header. | |
| const kSpillBytes = 65536 - 16; | |
| const textOf = (error) => String(error?.message ?? error); | |
| // Polls done until it holds or about ms pass, reading the clock only now and | |
| // then since a read costs more than a poll. | |
| function spinFor(done, ms) { | |
| const until = performance.now() + ms; | |
| for (let polls = 1; ; polls++) { | |
| if (done()) { | |
| return true; | |
| } | |
| if ((polls & 63) === 0 && performance.now() >= until) { | |
| return false; | |
| } | |
| } | |
| } | |
| // One event loop turn, so a parked thread takes its messages. | |
| function nextTurn() { | |
| const channel = new MessageChannel(); | |
| return new Promise((resolve) => { | |
| channel.port1.onmessage = () => { | |
| channel.port1.close(); | |
| resolve(); | |
| }; | |
| channel.port2.postMessage(0); | |
| }); | |
| } | |
| // What a member may import: the clock, aligned to the page's so a deadline | |
| // the page set means the same here, the throw and budget reports a part's | |
| // failure carries, debug probes, which only matter where a debugger runs | |
| // everything on the page's thread, and the check in only part 0 makes. | |
| // Anything else the build refused. | |
| function memberImports(module, memory, state, offset) { | |
| const imports = {}; | |
| const stopped = () => state.view !== null && Atomics.load(state.view, state.stop) !== 0; | |
| const known = { | |
| 'rive_rt_v1': { | |
| 'now': () => { | |
| // A fuel check reads the clock, so a stopped call ends there. | |
| if (stopped()) { | |
| throw new Error('stopped by another part'); | |
| } | |
| return performance.now() + offset; | |
| }, | |
| 'budget_exceeded': (ms) => { | |
| state.budgetMs = ms; | |
| throw new Error('execution exceeded timeout'); | |
| }, | |
| 'error': (at, length) => { | |
| state.thrown = [at, length]; | |
| }, | |
| 'debug_enter': () => {}, | |
| 'debug_line': () => 0, | |
| 'debug_leave': () => {}, | |
| }, | |
| 'rive_parallel_v1': { | |
| 'waiting': () => {}, | |
| }, | |
| }; | |
| for (const wanted of WebAssembly.Module.imports(module)) { | |
| const space = (imports[wanted['module']] ??= {}); | |
| if (wanted['kind'] === 'memory') { | |
| space[wanted['name']] = memory; | |
| } else if (wanted['kind'] === 'function') { | |
| space[wanted['name']] = | |
| known[wanted['module']]?.[wanted['name']] ?? | |
| (() => { | |
| throw new Error( | |
| `parallel code called the host through ${wanted['module']}.${wanted['name']}` | |
| ); | |
| }); | |
| } | |
| } | |
| return imports; | |
| } | |
| // The team thread's side: its members, by module, and its loop. | |
| function teamThread() { | |
| const members = new Map(); | |
| let words = null; | |
| let index = -1; | |
| function addMember(data) { | |
| const ready = new Int32Array(data['ready']); | |
| const state = { thrown: null, budgetMs: -1, view: null, stop: 0 }; | |
| try { | |
| // Each thread compiles its own, as threads that lazily compile | |
| // one shared module at once have crashed the engine. | |
| const module = new WebAssembly.Module(data['bytes']); | |
| const memory = data['memory']; | |
| const offset = performance.timeOrigin - data['origin']; | |
| const instance = new WebAssembly.Instance( | |
| module, | |
| memberImports(module, memory, state, offset) | |
| ); | |
| const exports = instance.exports; | |
| // A module whose code never spills exports no spill floor. | |
| const spill = exports['__riveSpillFloor'] === undefined ? 0 : data['spill']; | |
| if (spill !== 0) { | |
| exports['__riveSpillFloor'].value = spill; | |
| } | |
| members.set(data['key'], { exports, memory, state, spill, buffer: null, view: null }); | |
| Atomics.store(ready, index, 1); | |
| } catch (error) { | |
| Atomics.store(ready, index, 2); | |
| } | |
| Atomics.notify(ready, index); | |
| } | |
| // The first failure of the call wins; it stops the other parts at their | |
| // next check or sync. | |
| function fail(participant, member, error) { | |
| if (Atomics.compareExchange(words, kTeamFailed, -1, participant) !== -1) { | |
| return; | |
| } | |
| const state = member.state; | |
| if (state.thrown !== null) { | |
| words[kTeamFailKind] = kFailThrow; | |
| words[kTeamFailAt] = state.thrown[0]; | |
| words[kTeamFailLength] = state.thrown[1]; | |
| } else if (state.budgetMs >= 0) { | |
| words[kTeamFailKind] = kFailBudget; | |
| words[kTeamFailMs] = state.budgetMs; | |
| } else { | |
| words[kTeamFailKind] = kFailTrap; | |
| const text = new TextEncoder().encode(textOf(error)).subarray(0, kTeamTextBytes); | |
| new Uint8Array(words.buffer, kTeamTextAt, text.length).set(text); | |
| words[kTeamFailBytes] = text.length; | |
| } | |
| Atomics.store(member.view, member.state.stop, 1); | |
| } | |
| function runShare(generation) { | |
| const line = kTeamDone + 16 * index; | |
| if (Atomics.compareExchange(words, line + kTeamAssigned, generation, 0) !== generation) { | |
| return false; | |
| } | |
| const participant = words[line + kTeamPart]; | |
| const threads = words[kTeamThreads]; | |
| const member = members.get(words[kTeamVm]); | |
| if (member === undefined) { | |
| return true; | |
| } | |
| // The page grows the memory only between calls. | |
| const buffer = member.memory.buffer; | |
| if (member.buffer !== buffer) { | |
| member.buffer = buffer; | |
| member.view = new Int32Array(buffer); | |
| } | |
| const view = member.view; | |
| const control = words[kTeamControl] >>> 0; | |
| const state = member.state; | |
| state.thrown = null; | |
| state.budgetMs = -1; | |
| state.view = view; | |
| state.stop = (control + kParallelStop) >>> 2; | |
| const exports = member.exports; | |
| // A trap skips the epilogues that give back spill space. | |
| if (member.spill !== 0) { | |
| exports['__riveCallSpill'].value = member.spill + kSpillBytes; | |
| } | |
| try { | |
| exports['__riveLoadGlobals'](words[kTeamGlobals]); | |
| } catch (error) { | |
| fail(participant, member, error); | |
| return true; | |
| } | |
| const count = view[(control + kParallelCount) >>> 2]; | |
| const thunk = view[(control + kParallelThunk) >>> 2]; | |
| const args = view[(control + kParallelArgs) >>> 2]; | |
| const parts = view[(control + kParallelParts) >>> 2] >>> 2; | |
| const call = exports['__riveParallelCall']; | |
| for (let part = participant; part < count; part += threads) { | |
| if (Atomics.load(view, state.stop) !== 0) { | |
| break; | |
| } | |
| try { | |
| call(thunk, view[parts + part], args); | |
| } catch (error) { | |
| fail(participant, member, error); | |
| break; | |
| } | |
| } | |
| return true; | |
| } | |
| async function loop() { | |
| // Tests under node keep a thread from taking parts with | |
| // RIVE_PARALLEL_DEAF_THREAD, as one whose wake was lost would. | |
| if (String(index) === globalThis.process?.['env']?.['RIVE_PARALLEL_DEAF_THREAD']) { | |
| return; | |
| } | |
| let seen = Atomics.load(words, kTeamCall); | |
| const moved = () => Atomics.load(words, kTeamCall) !== seen; | |
| // WebKit can lose the wake of an async wait, which stalls a call | |
| // until it gives up on the thread. Tests under node take the timed | |
| // path with RIVE_PARALLEL_TIMED_WAITS. | |
| const userAgent = globalThis.navigator?.userAgent ?? ''; | |
| const waitAsync = | |
| typeof Atomics.waitAsync === 'function' && | |
| !(userAgent.includes('AppleWebKit/') && !userAgent.includes('Chrome/')) && | |
| globalThis.process?.['env']?.['RIVE_PARALLEL_TIMED_WAITS'] === undefined; | |
| Atomics.store(words, kTeamWaits, waitAsync ? kWaitAsync : kWaitTimed); | |
| let turned = performance.now(); | |
| for (;;) { | |
| if (!spinFor(moved, kSpinMs)) { | |
| Atomics.add(words, kTeamParked, 1); | |
| if (waitAsync) { | |
| const waited = Atomics.waitAsync(words, kTeamCall, seen); | |
| if (waited.async) { | |
| await waited.value; | |
| } | |
| } else if (performance.now() - turned >= kTimedWaitMs) { | |
| // Messages get a turn in place of a sleep, so a woken | |
| // call never waits on one. | |
| await nextTurn(); | |
| turned = performance.now(); | |
| } else { | |
| Atomics.wait(words, kTeamCall, seen, kTimedWaitMs); | |
| } | |
| Atomics.sub(words, kTeamParked, 1); | |
| continue; | |
| } | |
| seen = Atomics.load(words, kTeamCall); | |
| Atomics.store(words, kTeamDone + 16 * index + kTeamSeen, seen); | |
| if (runShare(seen)) { | |
| Atomics.store(words, kTeamDone + 16 * index, seen); | |
| } | |
| } | |
| } | |
| return { | |
| // The page's messages to this thread; false for any other. | |
| message(data) { | |
| const team = data?.['riveParallelTeam']; | |
| if (team !== undefined) { | |
| words = new Int32Array(team['words']); | |
| index = team['index']; | |
| loop(); | |
| return true; | |
| } | |
| const vm = data?.['riveParallelVm']; | |
| if (vm !== undefined) { | |
| addMember(vm); | |
| return true; | |
| } | |
| const drop = data?.['riveParallelDrop']; | |
| if (drop !== undefined) { | |
| members.delete(drop); | |
| return true; | |
| } | |
| return false; | |
| }, | |
| }; | |
| } | |
| // The page's side: the team, which every module on the page shares, one call | |
| // at a time, and each module's members on it. threads.start() starts a team | |
| // thread and answers its worker, or null where there are no threads. | |
| function createParallel(threads) { | |
| let team = null; | |
| let nextKey = 1; | |
| const thread = teamThread(); | |
| // The call the page's thread is in. | |
| let current = null; | |
| // Team threads to size - 1, started once and kept. | |
| function teamOf(size) { | |
| team ??= { | |
| words: new Int32Array( | |
| new SharedArrayBuffer(kTeamTextAt + kTeamTextBytes) | |
| ), | |
| workers: [], | |
| // By thread, the last call it saw when a call gave up on it, or | |
| // undefined; it sits out calls until it sees another. | |
| lost: [], | |
| }; | |
| while (team.workers.length + 1 < Math.min(size, kTeamMax + 1)) { | |
| const index = team.workers.length; | |
| const worker = threads.start(); | |
| if (worker === null) { | |
| break; | |
| } | |
| worker.postMessage({ 'riveParallelTeam': { 'words': team.words.buffer, 'index': index } }); | |
| team.workers.push(worker); | |
| } | |
| return team; | |
| } | |
| // Members on the team for a module whose memory is shared, once its own | |
| // instance has started, from the bytes each member compiles. Null when | |
| // there is no team to run them. | |
| function setUp(entry, bytes, size) { | |
| const exports = entry.instance.exports; | |
| if ( | |
| size <= 1 || | |
| !threads.can() || | |
| exports['__riveParallelCall'] === undefined || | |
| exports['__riveSaveGlobals'] === undefined || | |
| exports['__riveRawAlloc'] === undefined | |
| ) { | |
| return null; | |
| } | |
| const { workers } = teamOf(size); | |
| if (workers.length === 0) { | |
| return null; | |
| } | |
| // The allocator traps once the memory cannot grow. As natively, the | |
| // members made before then stay, and without any a call runs alone. | |
| const alloc = (bytes) => { | |
| try { | |
| return exports['__riveRawAlloc'](bytes) >>> 0; | |
| } catch { | |
| return 0; | |
| } | |
| }; | |
| const globals = alloc(Math.max(exports['__riveGlobalBytes'].value, 4)); | |
| if (globals === 0) { | |
| return null; | |
| } | |
| const parallel = { | |
| key: nextKey++, | |
| globals, | |
| ready: new Int32Array(new SharedArrayBuffer(4 * workers.length)), | |
| running: false, | |
| }; | |
| workers.forEach((worker, index) => { | |
| const spill = alloc(kSpillBytes); | |
| if (spill === 0) { | |
| Atomics.store(parallel.ready, index, 2); | |
| return; | |
| } | |
| worker.postMessage({ | |
| 'riveParallelVm': { | |
| 'key': parallel.key, | |
| 'bytes': bytes, | |
| 'memory': entry.memory, | |
| 'spill': spill, | |
| 'ready': parallel.ready.buffer, | |
| 'origin': performance.timeOrigin, | |
| }, | |
| }); | |
| }); | |
| return parallel; | |
| } | |
| // Settles once every member of the module started or failed to, or a | |
| // team thread that never answers is left out. It polls on timers, as a | |
| // pending waitAsync would not keep node running. | |
| async function ready(parallel) { | |
| const until = performance.now() + kReadyMs; | |
| while (parallel.ready.some((state) => state === 0) && performance.now() < until) { | |
| await new Promise((done) => setTimeout(done, 1)); | |
| } | |
| } | |
| function release(parallel) { | |
| for (const worker of team?.workers ?? []) { | |
| worker.postMessage({ 'riveParallelDrop': parallel.key }); | |
| } | |
| } | |
| // Whether a thread a call gave up on has since seen another call, as one | |
| // that only woke late has. | |
| function present(index) { | |
| const lost = team.lost[index]; | |
| if (lost === undefined) { | |
| return true; | |
| } | |
| if (Atomics.load(team.words, kTeamDone + 16 * index + kTeamSeen) === lost) { | |
| return false; | |
| } | |
| team.lost[index] = undefined; | |
| return true; | |
| } | |
| // For a member that has not taken its part: once the call fails, the | |
| // page takes the part back. Until then the page wakes the team again, | |
| // since the member may have missed its wake, and fails the call once the | |
| // member is too late. | |
| function nudge(call, index, now) { | |
| const words = team.words; | |
| const line = kTeamDone + 16 * index; | |
| if (Atomics.load(words, line + kTeamAssigned) !== call.generation) { | |
| return; | |
| } | |
| if (Atomics.load(call.view, call.stop) === 0 && now - call.began >= kTakeMs) { | |
| call.fail(new Error( | |
| `a thread of the page's team did not start its part of a parallel call within ${kTakeMs} ms` | |
| )); | |
| } | |
| if (Atomics.load(call.view, call.stop) !== 0) { | |
| if (Atomics.compareExchange(words, line + kTeamAssigned, call.generation, 0) === call.generation) { | |
| team.lost[index] = Atomics.load(words, line + kTeamSeen); | |
| call.taken.add(index); | |
| } | |
| } else if (now - call.woke >= kRewakeMs) { | |
| call.woke = now; | |
| Atomics.notify(words, kTeamCall); | |
| } | |
| } | |
| // Waits for each member to finish its part, or for the page to take it | |
| // back. A call past its budget fails here too. | |
| function join(call, fuelCheck) { | |
| const words = team.words; | |
| for (const index of call.members) { | |
| const line = kTeamDone + 16 * index; | |
| for (let polls = 1; Atomics.load(words, line) !== call.generation; polls++) { | |
| if ((polls & 1023) !== 0) { | |
| continue; | |
| } | |
| if (call.taken.has(index)) { | |
| break; | |
| } | |
| if (Atomics.load(call.view, call.stop) === 0 && fuelCheck !== undefined) { | |
| try { | |
| fuelCheck(); | |
| } catch (error) { | |
| call.fail(error); | |
| } | |
| } | |
| nudge(call, index, performance.now()); | |
| } | |
| } | |
| } | |
| // Part 0 checking in from a sync, where the page's thread waits inside | |
| // the module and the join cannot run. | |
| function waiting() { | |
| const call = current; | |
| if (call === null) { | |
| return; | |
| } | |
| const now = performance.now(); | |
| for (const index of call.members) { | |
| nudge(call, index, now); | |
| } | |
| } | |
| // Runs the call whose control block is at control, one part per thread | |
| // it gets when the call asks for every part at once, and answers the | |
| // threads that ran parts. report raises a member's throw or budget | |
| // failure as the page's own instance would. | |
| function run(entry, parallel, control, report) { | |
| if (parallel?.running) { | |
| throw new Error('parallel calls cannot nest'); | |
| } | |
| // A word an atomic reads must be aligned. | |
| if ((control & 3) !== 0) { | |
| throw new Error('parallel call control block is not aligned'); | |
| } | |
| // The page grows the memory only between calls. | |
| const buffer = entry.memory.buffer; | |
| if (entry.view32?.buffer !== buffer) { | |
| entry.view32 = new Int32Array(buffer); | |
| } | |
| const view = entry.view32; | |
| const word = (offset) => (control + offset) >>> 2; | |
| let count = view[word(kParallelCount)]; | |
| const members = []; | |
| for (let index = 0; index < (parallel?.ready.length ?? 0) && members.length + 1 < count; index++) { | |
| if (Atomics.load(parallel.ready, index) === 1 && present(index)) { | |
| members.push(index); | |
| } | |
| } | |
| const threads = members.length + 1; | |
| if (view[word(kParallelAtOnce)] !== 0) { | |
| count = threads; | |
| view[word(kParallelCount)] = count; | |
| } | |
| view[word(kParallelAtOnce)] = threads >= count ? 1 : 0; | |
| // The claim takes two words, and the page's thread may not park. | |
| for (const offset of [ | |
| kParallelGeneration, | |
| kParallelArrived, | |
| kParallelSleepers, | |
| kParallelClaim, | |
| kParallelClaim + 4, | |
| kParallelStop, | |
| kParallelCallerParks, | |
| ]) { | |
| Atomics.store(view, word(offset), 0); | |
| } | |
| const exports = entry.instance.exports; | |
| const call = exports['__riveParallelCall']; | |
| const thunk = view[word(kParallelThunk)]; | |
| const args = view[word(kParallelArgs)]; | |
| const parts = view[word(kParallelParts)] >>> 2; | |
| if (threads === 1) { | |
| for (let part = 0; part < count; part++) { | |
| call(thunk, view[parts + part], args); | |
| } | |
| return 1; | |
| } | |
| const words = team.words; | |
| parallel.running = true; | |
| try { | |
| exports['__riveSaveGlobals'](parallel.globals); | |
| words[kTeamThreads] = threads; | |
| words[kTeamVm] = parallel.key; | |
| words[kTeamControl] = control; | |
| words[kTeamGlobals] = parallel.globals; | |
| Atomics.store(words, kTeamFailed, -1); | |
| // An assignment of 0 is none. | |
| const generation = ((Atomics.load(words, kTeamCall) + 1) | 0) || 1; | |
| members.forEach((index, j) => { | |
| const line = kTeamDone + 16 * index; | |
| words[line + kTeamPart] = j + 1; | |
| Atomics.store(words, line + kTeamAssigned, generation); | |
| }); | |
| Atomics.store(words, kTeamCall, generation); | |
| if (Atomics.load(words, kTeamParked) !== 0) { | |
| Atomics.notify(words, kTeamCall); | |
| } | |
| let thrown = null; | |
| const began = performance.now(); | |
| current = { | |
| members, | |
| generation, | |
| view, | |
| stop: word(kParallelStop), | |
| began, | |
| woke: began, | |
| // Members whose parts the page took back. | |
| taken: new Set(), | |
| // The page's own failure, which stops the other parts unless | |
| // a member failed first. | |
| fail(error) { | |
| thrown ??= error; | |
| if (Atomics.compareExchange(words, kTeamFailed, -1, 0) === -1) { | |
| Atomics.store(view, word(kParallelStop), 1); | |
| } | |
| }, | |
| }; | |
| for (let part = 0; part < count; part += threads) { | |
| if (Atomics.load(view, word(kParallelStop)) !== 0) { | |
| break; | |
| } | |
| try { | |
| call(thunk, view[parts + part], args); | |
| } catch (error) { | |
| current.fail(error); | |
| break; | |
| } | |
| } | |
| join(current, exports['__riveFuelCheck']); | |
| const failed = Atomics.load(words, kTeamFailed); | |
| if (failed > 0) { | |
| const kind = words[kTeamFailKind]; | |
| if (kind === kFailThrow) { | |
| report.thrown(words[kTeamFailAt], words[kTeamFailLength]); | |
| } else if (kind === kFailBudget) { | |
| report.budget(words[kTeamFailMs]); | |
| if (thrown !== null) { | |
| throw thrown; | |
| } | |
| } | |
| const text = new Uint8Array(words[kTeamFailBytes]); | |
| text.set(new Uint8Array(words.buffer, kTeamTextAt, text.length)); | |
| throw new Error( | |
| kind === kFailTrap ? new TextDecoder().decode(text) : 'parallel part trapped' | |
| ); | |
| } | |
| if (thrown !== null) { | |
| throw thrown; | |
| } | |
| return threads; | |
| } finally { | |
| parallel.running = false; | |
| current = null; | |
| } | |
| } | |
| return { | |
| setUp, | |
| ready, | |
| release, | |
| run, | |
| waiting, | |
| message: thread.message, | |
| // The parts a call gets: chosen, where the host chose a number, else | |
| // the page's default. | |
| parts(chosen) { | |
| const parts = Math.trunc(chosen ?? NaN); | |
| return Number.isFinite(parts) | |
| ? Math.min(Math.max(parts, 1), kTeamMax + 1) | |
| : Math.min(globalThis.navigator?.hardwareConcurrency ?? 1, kDefaultParts); | |
| }, | |
| // How the team waits when parked, for tests to report. | |
| state() { | |
| const waits = team === null ? 0 : Atomics.load(team.words, kTeamWaits); | |
| return { | |
| 'team': team?.workers.length ?? 0, | |
| 'waits': waits === kWaitAsync ? 'async' : waits === kWaitTimed ? 'timed' : 'none', | |
| }; | |
| }, | |
| }; | |
| } | |
| // The JS half of the browser scripting lane. Script modules run on the | |
| // browser's own wasm engine; librive reaches them through the EM_JS calls in | |
| // browser_scripting_vm.cpp, which forward to the runner installed here. | |
| // | |
| // Loading a file is two steps. File::import makes each script VM and | |
| // registers its module bytes here, without instantiating. The host then | |
| // awaits prepare(), which compiles and instantiates every registered module | |
| // asynchronously, and only then asks librive to start the file's scripts. | |
| // A host that skips prepare() still works where the browser allows | |
| // synchronous compilation on the calling thread: start() instantiates inline. | |
| // | |
| // Hosts link rive_scripting_pre.js, generated from this file, into their | |
| // emscripten build with --pre-js. It installs the runner by itself, so a | |
| // host only does: | |
| // ... import a file ... | |
| // await Module.riveScripting.prepare(); | |
| // ... start the file's scripts ... | |
| // WasmScriptingVM::CallOutcome, then the browser's own host fault. | |
| const kOk = 0; | |
| const kMissing = 1; | |
| const kTrapped = 2; | |
| const kHostFault = 3; | |
| // One function returning v128.const zero, then one returning the relaxed | |
| // swizzle of two: the smallest modules each SIMD flavor needs. | |
| const kV128Zero = [0xfd, 0x0c, ...new Array(16).fill(0)]; | |
| const kSimdProbe = probeModule([...kV128Zero]); | |
| const kRelaxedSimdProbe = probeModule([ | |
| ...kV128Zero, | |
| ...kV128Zero, | |
| 0xfd, | |
| 0x80, | |
| 0x02, | |
| ]); | |
| function probeModule(body) { | |
| const code = [0, ...body, 0x0b]; | |
| return new Uint8Array([ | |
| 0x00, 0x61, 0x73, 0x6d, 1, 0, 0, 0, | |
| // One type, () -> v128, and one function of it. | |
| 1, 5, 1, 0x60, 0, 1, 0x7b, | |
| 3, 2, 1, 0, | |
| 10, code.length + 2, 1, code.length, ...code, | |
| ]); | |
| } | |
| // Index immediates of the 0xfc ops by sub-opcode: none for the saturating | |
| // truncations, then memory.init through table.fill. | |
| const kBulkIndices = [0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1]; | |
| // The ops past the variable accesses that take one LEB. | |
| const kOneLebOps = [0x0c, 0x0d, 0x10, 0x12, 0x3f, 0x40, 0x41, 0x42, 0xd0, 0xd2]; | |
| // The SIMD a module's types and code need: 2 for relaxed, 1 for plain, 0 for | |
| // none, or -1 when they hold what this walk does not read. | |
| function simdNeeded(bytes) { | |
| let needed = 0; | |
| let at = 8; | |
| const need = (flavor) => { | |
| needed = Math.max(needed, flavor); | |
| }; | |
| const next = () => { | |
| const [value, end] = readLeb(bytes, at); | |
| at = end; | |
| return value; | |
| }; | |
| const memarg = () => { | |
| if (next() & 0x40) { | |
| next(); | |
| } | |
| next(); | |
| }; | |
| // False for a reference type with a heap type, which takes more bytes. | |
| const valueType = () => { | |
| const type = bytes[at++]; | |
| if (type === 0x7b) { | |
| need(1); | |
| } | |
| return type !== 0x63 && type !== 0x64; | |
| }; | |
| const instruction = () => { | |
| const op = bytes[at++]; | |
| if (op === 0xfd) { | |
| const sub = next(); | |
| need(sub >= 0x100 && sub <= 0x113 ? 2 : 1); | |
| if (sub <= 0x0b || sub === 0x5c || sub === 0x5d) { | |
| memarg(); | |
| } else if (sub === 0x0c || sub === 0x0d) { | |
| at += 16; | |
| } else if (sub >= 0x15 && sub <= 0x22) { | |
| at += 1; | |
| } else if (sub >= 0x54 && sub <= 0x5b) { | |
| memarg(); | |
| at += 1; | |
| } | |
| } else if (op === 0xfc) { | |
| const sub = next(); | |
| if (sub >= kBulkIndices.length) { | |
| return false; | |
| } | |
| for (let i = 0; i < kBulkIndices[sub]; i++) { | |
| next(); | |
| } | |
| } else if (op === 0xfe) { | |
| // atomic.fence takes a byte, the other atomics a memarg. | |
| if (next() === 3) { | |
| at += 1; | |
| } else { | |
| memarg(); | |
| } | |
| } else if (op >= 0x28 && op <= 0x3e) { | |
| memarg(); | |
| } else if (op >= 0x02 && op <= 0x04) { | |
| // A block type: one byte, or a type index. | |
| if (bytes[at] === 0x7b) { | |
| need(1); | |
| } | |
| next(); | |
| } else if (op === 0x0e) { | |
| for (let labels = next(); labels >= 0 && at < bytes.length; labels--) { | |
| next(); | |
| } | |
| } else if (op === 0x1c) { | |
| for (let types = next(); types > 0 && at < bytes.length; types--) { | |
| if (!valueType()) { | |
| return false; | |
| } | |
| } | |
| } else if (op === 0x11 || op === 0x13) { | |
| next(); | |
| next(); | |
| } else if (op === 0x43 || op === 0x44) { | |
| at += op === 0x43 ? 4 : 8; | |
| } else if ((op >= 0x20 && op <= 0x26) || kOneLebOps.includes(op)) { | |
| next(); | |
| } else if (!(op <= 0x01 || op === 0x05 || op === 0x0b || op === 0x0f || | |
| op === 0x1a || op === 0x1b || op === 0xd1 || | |
| (op >= 0x45 && op <= 0xc4))) { | |
| return false; | |
| } | |
| return true; | |
| }; | |
| while (at < bytes.length) { | |
| const id = bytes[at]; | |
| const [size, body] = readLeb(bytes, at + 1); | |
| at = body; | |
| if (id === 1) { | |
| for (let types = next(); types > 0 && at < bytes.length; types--) { | |
| // Function types only: params, then results. | |
| if (bytes[at++] !== 0x60) { | |
| return -1; | |
| } | |
| for (let list = 0; list < 2; list++) { | |
| for (let n = next(); n > 0 && at < bytes.length; n--) { | |
| if (!valueType()) { | |
| return -1; | |
| } | |
| } | |
| } | |
| } | |
| } else if (id === 10) { | |
| for (let bodies = next(); bodies > 0 && at < bytes.length; bodies--) { | |
| const end = Math.min(next() + at, bytes.length); | |
| for (let locals = next(); locals > 0 && at < end; locals--) { | |
| next(); | |
| if (!valueType()) { | |
| return -1; | |
| } | |
| } | |
| while (at < end) { | |
| if (!instruction()) { | |
| return -1; | |
| } | |
| } | |
| } | |
| } | |
| at = body + size; | |
| } | |
| return needed; | |
| } | |
| function readLeb(bytes, at) { | |
| let value = 0; | |
| let shift = 0; | |
| let byte; | |
| do { | |
| byte = bytes[at++]; | |
| value |= (byte & 0x7f) << shift; | |
| shift += 7; | |
| } while (byte & 0x80); | |
| return [value >>> 0, at]; | |
| } | |
| function leb(value) { | |
| const out = []; | |
| do { | |
| const byte = value & 0x7f; | |
| value >>>= 7; | |
| out.push(value ? byte | 0x80 : byte); | |
| } while (value); | |
| return out; | |
| } | |
| // Each section of a module: its id, where it starts, its body and its end. | |
| function sectionsOf(bytes) { | |
| const sections = []; | |
| for (let at = 8; at < bytes.length; ) { | |
| const [size, body] = readLeb(bytes, at + 1); | |
| sections.push({ id: bytes[at], at, body, end: body + size }); | |
| at = body + size; | |
| } | |
| return sections; | |
| } | |
| const kLaneSectionNames = kLaneSections.map(([name]) => | |
| Array.from(name, (c) => c.charCodeAt(0)) | |
| ); | |
| // The lane modules a script module carries in its custom sections. | |
| function laneModulesOf(bytes) { | |
| const lanes = []; | |
| for (const section of sectionsOf(bytes)) { | |
| if (section.id !== 0) { | |
| continue; | |
| } | |
| const [length, name] = readLeb(bytes, section.body); | |
| const named = (wanted) => | |
| wanted.length === length && wanted.every((c, i) => bytes[name + i] === c); | |
| if (kLaneSectionNames.some(named)) { | |
| lanes.push(bytes.subarray(name + length, section.end)); | |
| } | |
| } | |
| return lanes; | |
| } | |
| // rasc runs every script's top level in the module's start function, and a | |
| // top level can pass memory to the host. The module's memory is an export, | |
| // which the page cannot reach until start has returned. So the start section | |
| // is dropped and its function exported, for the runner to call once the | |
| // instance and its memory exist. Modules without one come back untouched. | |
| // Lane modules are cached by these bytes, so they must match wasm_lane.cpp's. | |
| function liftStart(bytes) { | |
| const all = sectionsOf(bytes); | |
| const start = all.find((section) => section.id === 8); | |
| const sections = all.filter((section) => section !== start); | |
| if (start === undefined || !sections.some((section) => section.id === 7)) { | |
| return bytes; | |
| } | |
| const startFunction = readLeb(bytes, start.body)[0]; | |
| const parts = [bytes.subarray(0, 8)]; | |
| for (const section of sections) { | |
| let body = bytes.subarray(section.body, section.end); | |
| if (section.id === 7) { | |
| const [count, first] = readLeb(bytes, section.body); | |
| const name = Array.from(kLiftedStartExport, (c) => c.charCodeAt(0)); | |
| body = Uint8Array.from([ | |
| ...leb(count + 1), | |
| ...bytes.subarray(first, section.end), | |
| ...leb(name.length), | |
| ...name, | |
| 0, | |
| ...leb(startFunction), | |
| ]); | |
| } | |
| parts.push(Uint8Array.from([section.id, ...leb(body.length)]), body); | |
| } | |
| const out = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0)); | |
| let at = 0; | |
| for (const part of parts) { | |
| out.set(part, at); | |
| at += part.length; | |
| } | |
| return out; | |
| } | |
| // A parallel module declares a shared memory up to wasm32's limit, which a | |
| // browser would set aside whole and which needs cross origin isolation. Its | |
| // memory moves to an import instead, so the runner picks the memory to give | |
| // it: shared up to what the device can set aside, else unshared, where its | |
| // parts run one at a time. Every other module comes back untouched. | |
| const kMemoryImport = ['rive_parallel_v1', 'memory']; | |
| const kSharedTryPages = 32768; | |
| function importMemory(bytes) { | |
| const all = sectionsOf(bytes); | |
| const memory = all.find((section) => section.id === 5); | |
| const imports = all.find((section) => section.id === 2); | |
| if (memory === undefined || imports === undefined) { | |
| return { bytes, memory: null }; | |
| } | |
| let [count, at] = readLeb(bytes, memory.body); | |
| const flags = bytes[at++]; | |
| if (count !== 1 || (flags & 2) === 0) { | |
| return { bytes, memory: null }; | |
| } | |
| const [initial, afterInitial] = readLeb(bytes, at); | |
| const declared = flags & 1 ? readLeb(bytes, afterInitial)[0] : 65536; | |
| const shared = | |
| typeof SharedArrayBuffer === 'function' && | |
| globalThis.crossOriginIsolated !== false; | |
| let maximum = declared; | |
| let created = null; | |
| if (shared) { | |
| // Halving down to what the module needs, as a 32-bit browser or one | |
| // short of address space refuses a large reservation. | |
| maximum = Math.min(declared, kSharedTryPages); | |
| for (;;) { | |
| try { | |
| // Quoted, as closure renames a key its externs lack. | |
| created = new WebAssembly.Memory({ | |
| 'initial': initial, | |
| 'maximum': maximum, | |
| 'shared': shared, | |
| }); | |
| break; | |
| } catch (error) { | |
| if (!(error instanceof RangeError) || maximum <= initial) { | |
| throw error; | |
| } | |
| maximum = Math.max(initial, maximum >>> 1); | |
| } | |
| } | |
| } else { | |
| created = new WebAssembly.Memory({ initial, maximum }); | |
| } | |
| const name = (text) => [...leb(text.length), ...Array.from(text, (c) => c.charCodeAt(0))]; | |
| const entry = [ | |
| ...name(kMemoryImport[0]), | |
| ...name(kMemoryImport[1]), | |
| 2, | |
| shared ? 3 : 1, | |
| ...leb(initial), | |
| ...leb(maximum), | |
| ]; | |
| const [importCount, first] = readLeb(bytes, imports.body); | |
| const parts = [bytes.subarray(0, 8)]; | |
| for (const section of all) { | |
| if (section === memory) { | |
| continue; | |
| } | |
| let body = bytes.subarray(section.body, section.end); | |
| if (section === imports) { | |
| body = Uint8Array.from([ | |
| ...leb(importCount + 1), | |
| ...bytes.subarray(first, section.end), | |
| ...entry, | |
| ]); | |
| } | |
| parts.push(Uint8Array.from([section.id, ...leb(body.length)]), body); | |
| } | |
| const out = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0)); | |
| let offset = 0; | |
| for (const part of parts) { | |
| out.set(part, offset); | |
| offset += part.length; | |
| } | |
| return { bytes: out, memory: created }; | |
| } | |
| // A member of a parallel module shares the memory the page's instance already | |
| // filled, so its data segments are made passive, which instantiating leaves | |
| // alone. Its start is already lifted out. | |
| function passiveData(bytes) { | |
| const all = sectionsOf(bytes); | |
| const data = all.find((section) => section.id === 11); | |
| if (data === undefined) { | |
| return bytes; | |
| } | |
| let [count, at] = readLeb(bytes, data.body); | |
| const body = [Uint8Array.from(leb(count))]; | |
| for (let i = 0; i < count; i++) { | |
| let flags; | |
| [flags, at] = readLeb(bytes, at); | |
| if (flags === 2) { | |
| at = readLeb(bytes, at)[1]; | |
| } | |
| // The offset is one constant instruction and end. | |
| if (flags !== 1) { | |
| for (let op = bytes[at++]; op !== 0x0b; op = bytes[at++]) { | |
| at = readLeb(bytes, at)[1]; | |
| } | |
| } | |
| const [length, first] = readLeb(bytes, at); | |
| body.push(Uint8Array.from([1, ...leb(length)]), bytes.subarray(first, first + length)); | |
| at = first + length; | |
| } | |
| const parts = [bytes.subarray(0, 8)]; | |
| for (const section of all) { | |
| const sectionBody = | |
| section === data ? concatBytes(body) : bytes.subarray(section.body, section.end); | |
| parts.push(Uint8Array.from([section.id, ...leb(sectionBody.length)]), sectionBody); | |
| } | |
| return concatBytes(parts); | |
| } | |
| function concatBytes(parts) { | |
| const out = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0)); | |
| let at = 0; | |
| for (const part of parts) { | |
| out.set(part, at); | |
| at += part.length; | |
| } | |
| return out; | |
| } | |
| // Args by index: spreading a subarray of the heap cost more than the call. | |
| function callExport(fn, args, at, argc) { | |
| switch (argc) { | |
| case 0: | |
| return fn(); | |
| case 1: | |
| return fn(args[at]); | |
| case 2: | |
| return fn(args[at], args[at + 1]); | |
| case 3: | |
| return fn(args[at], args[at + 1], args[at + 2]); | |
| case 4: | |
| return fn(args[at], args[at + 1], args[at + 2], args[at + 3]); | |
| case 5: | |
| return fn(args[at], args[at + 1], args[at + 2], args[at + 3], | |
| args[at + 4]); | |
| case 6: | |
| return fn(args[at], args[at + 1], args[at + 2], args[at + 3], | |
| args[at + 4], args[at + 5]); | |
| case 7: | |
| return fn(args[at], args[at + 1], args[at + 2], args[at + 3], | |
| args[at + 4], args[at + 5], args[at + 6]); | |
| case 8: | |
| return fn(args[at], args[at + 1], args[at + 2], args[at + 3], | |
| args[at + 4], args[at + 5], args[at + 6], args[at + 7]); | |
| default: | |
| return fn(...args.subarray(at, at + argc)); | |
| } | |
| } | |
| function installRiveScripting(Module) { | |
| // Primitives over the librive heap and exports, handed over by librive | |
| // itself on first use because only code inside it can see them. | |
| let host = null; | |
| // A pool thread's own clock starts late, so lanes read the page's, as | |
| // native lanes share one steady clock. | |
| let laneNow = monotonicNow; | |
| const vms = new Map(); | |
| // Bridge traffic, tallied only while a page measures it. | |
| const counters = { | |
| on: false, | |
| hostCalls: 0, | |
| bytesStaged: 0, | |
| bytesCopiedOut: 0, | |
| bytesRead: 0, | |
| bytesWritten: 0, | |
| }; | |
| // What the generated imports need from librive, for calls under ctx, | |
| // binding only that namespace when only names one. | |
| function librive(ctx, only = null) { | |
| return { | |
| calls: bindRiveHostCalls(host.hostCall, ctx, only), | |
| heapU8: host.heapU8, | |
| stackSave: host.stackSave, | |
| stackAlloc: host.stackAlloc, | |
| stackRestore: host.stackRestore, | |
| malloc: host.malloc, | |
| free: host.free, | |
| counters, | |
| }; | |
| } | |
| // Tests stand in for an engine without SIMD with their own validator, | |
| // and run offline processors on the natives a worklet uses. | |
| const validate = | |
| Module['riveScriptingValidate'] ?? | |
| ((bytes) => WebAssembly.validate(bytes)); | |
| const laneTwin = Module['riveScriptingLaneTwin'] === true; | |
| let features = null; | |
| // Why this engine refuses a module or a lane module it carries, when a | |
| // SIMD flavor it lacks is the reason; null otherwise. | |
| function missingSimd(bytes) { | |
| features ??= { | |
| simd: validate(kSimdProbe), | |
| relaxed: validate(kRelaxedSimdProbe), | |
| }; | |
| const modules = [bytes, ...laneModulesOf(bytes)]; | |
| if ( | |
| (features.simd && features.relaxed) || | |
| modules.every((module) => validate(module)) | |
| ) { | |
| return null; | |
| } | |
| const needed = Math.max(...modules.map(simdNeeded)); | |
| if (!features.simd && needed > 0) { | |
| return "this browser lacks WebAssembly SIMD, so this file's scripts " + | |
| 'are off; bake with wasmSimd: off to support it'; | |
| } | |
| if (!features.relaxed && needed === 2) { | |
| return "this browser lacks WebAssembly relaxed SIMD, so this file's " + | |
| 'scripts are off; bake with wasmSimd: on to support it'; | |
| } | |
| return null; | |
| } | |
| // The module's bytes once its memory is the runner's to give. | |
| function withMemory(entry) { | |
| const { bytes, memory } = importMemory(entry.bytes); | |
| entry.parallelMemory = memory; | |
| return bytes; | |
| } | |
| const sharedMemory = (entry) => | |
| typeof SharedArrayBuffer === 'function' && | |
| entry.parallelMemory?.buffer instanceof SharedArrayBuffer; | |
| // The bytes a team thread instantiates a member from, or null where a | |
| // call never gets more than one part. | |
| function memberBytes(entry, lifted) { | |
| return sharedMemory(entry) && teamWorkerOf !== null ? passiveData(lifted) : null; | |
| } | |
| // Members on the team once the page's own instance has started. | |
| function adoptMembers(entry, bytes) { | |
| if (bytes !== null && entry.instance !== null) { | |
| entry.parallel = parallel.setUp(entry, bytes, entry.parallelSize()); | |
| } | |
| } | |
| function importsFor(entry, module) { | |
| const imports = createRiveModuleImports( | |
| librive(entry.ctx), | |
| () => { | |
| if (entry.memory === null) { | |
| // Only a start function liftStart could not move. | |
| throw new Error( | |
| 'script passed memory to the host while its module ' + | |
| 'was still starting' | |
| ); | |
| } | |
| return entry.memory; | |
| } | |
| ); | |
| if (entry.parallelMemory !== null) { | |
| const space = (imports[kMemoryImport[0]] ??= {}); | |
| space[kMemoryImport[1]] = entry.parallelMemory; | |
| // Calls share the memory with a team of threads only where it is | |
| // shared; elsewhere a call gets one part. Where librive allows | |
| // more, the page picks how many. | |
| const size = space['size']; | |
| const shared = sharedMemory(entry); | |
| space['size'] = () => | |
| shared && size() > 1 ? parallel.parts(runner['parallelParts']) : 1; | |
| const rt = imports['rive_rt_v1']; | |
| const budget = rt['budget_exceeded']; | |
| // A budget the page's own part already reported is not reported | |
| // again for a member that ran out at the same time. | |
| rt['budget_exceeded'] = (ms) => { | |
| entry.budgeted = true; | |
| return budget(ms); | |
| }; | |
| const report = { | |
| thrown: (at, length) => rt['error'](at, length), | |
| budget: (ms) => (entry.budgeted ? undefined : budget(ms)), | |
| }; | |
| space['run'] = (control) => { | |
| entry.budgeted = false; | |
| return parallel.run(entry, entry.parallel, control >>> 0, report); | |
| }; | |
| space['waiting'] = parallel.waiting; | |
| entry.parallelSize = space['size']; | |
| } | |
| // The browser refuses a module with an import nothing provides. | |
| for (const wanted of WebAssembly.Module.imports(module)) { | |
| if (wanted['kind'] === 'function') { | |
| const space = (imports[wanted['module']] ??= {}); | |
| space[wanted['name']] ??= unlinkedImport( | |
| wanted['module'], | |
| wanted['name'] | |
| ); | |
| } | |
| } | |
| return imports; | |
| } | |
| // Before its lanes compile and a start liftStart left in place runs, as | |
| // top levels already pass strings and a refused module must do neither. | |
| function announceExports(entry, module) { | |
| const mark = host.stackSave(); | |
| for (const { name } of WebAssembly.Module.exports(module)) { | |
| if (!name.startsWith('__rive')) { | |
| continue; | |
| } | |
| const capacity = name.length * 3 + 1; | |
| const ptr = host.stackAlloc(capacity); | |
| host.writeUtf8(name, ptr, capacity); | |
| host.exports['_rive_web_vm_module_export'](entry.ctx.vm, ptr); | |
| } | |
| host.stackRestore(mark); | |
| const refusal = | |
| host.exports['_rive_web_vm_start_refusal'](entry.ctx.vm); | |
| if (refusal !== 0) { | |
| throw new Error(host.utf8(refusal)); | |
| } | |
| } | |
| function adopt(entry, instance) { | |
| entry.memory = instance.exports['memory']; | |
| entry.bytes = null; | |
| // State of the call in progress, which a trap unwinds without | |
| // restoring; a global the module cannot write is not state. | |
| entry.callState = Object.keys(instance.exports) | |
| .filter((name) => name.startsWith('__riveCall')) | |
| .map((name) => instance.exports[name]) | |
| .filter((global) => { | |
| if (!(global instanceof WebAssembly.Global)) { | |
| return false; | |
| } | |
| try { | |
| global.value = global.value; | |
| return true; | |
| } catch { | |
| return false; | |
| } | |
| }); | |
| // One stack for nested calls, so hot paths allocate nothing. | |
| entry.callSaved = []; | |
| // A metered module's own fuel bounds its top level, as it does its | |
| // calls. | |
| const fuelMs = host.exports['_rive_web_vm_start_fuel'](entry.ctx.vm); | |
| const arm = instance.exports['__riveFuelArm']; | |
| const end = instance.exports['__riveFuelEnd']; | |
| const fueled = fuelMs > 0 && arm !== undefined && end !== undefined; | |
| const booting = host.exports['_rive_web_vm_booting']; | |
| booting(entry.ctx.vm); | |
| const mark = host.stackSave(); | |
| // A wait in the top level moves a metered module's fuel on with a call. | |
| entry.instance = instance; | |
| try { | |
| if (fueled) arm(fuelMs); | |
| instance.exports[kLiftedStartExport]?.(); | |
| if (fueled) end(); | |
| } catch (error) { | |
| entry.instance = null; | |
| // A host fault skips the epilogues of the librive frames it unwinds. | |
| host.stackRestore(mark); | |
| entry.ctx.raised = null; | |
| throw error; | |
| } finally { | |
| booting(0); | |
| } | |
| } | |
| async function prepareEntry(entry) { | |
| try { | |
| const lifted = liftStart(withMemory(entry)); | |
| const module = await WebAssembly.compile(lifted); | |
| const members = memberBytes(entry, lifted); | |
| if (entry.ctx.vm === 0) { | |
| return; | |
| } | |
| announceExports(entry, module); | |
| const lanes = prepareLanes(module); | |
| const instance = await WebAssembly.instantiate( | |
| module, | |
| importsFor(entry, module) | |
| ); | |
| await lanes; | |
| // Released while instantiating. | |
| if (entry.ctx.vm === 0) { | |
| return; | |
| } | |
| adopt(entry, instance); | |
| adoptMembers(entry, members); | |
| if (entry.parallel !== null) { | |
| await parallel.ready(entry.parallel); | |
| } | |
| } catch (error) { | |
| entry.error = errorText(error); | |
| } | |
| } | |
| // Lanes run the lane modules a script module carries, on whichever thread | |
| // runs them, reaching only their own natives, shared memory and the console. | |
| // Compiled lane modules, oldest first, matched by id or by their lifted | |
| // bytes, which librive hands over; a dropped one only costs a recompile. | |
| const laneModules = []; | |
| const kLaneModuleCache = 8; | |
| // The page's idle pthread workers, on a pthread build. | |
| let threads = () => []; | |
| // A team thread's worker by thread, on a pthread build. | |
| let teamWorkerOf = null; | |
| const parallel = createParallel({ | |
| can: () => teamWorkerOf !== null, | |
| start() { | |
| const thread = host.exports['_rive_web_parallel_team_thread'](); | |
| return thread === 0 ? null : (teamWorkerOf(thread) ?? null); | |
| }, | |
| }); | |
| function sameBytes(a, b) { | |
| if (a.length !== b.length) { | |
| return false; | |
| } | |
| for (let i = 0; i < a.length; i++) { | |
| if (a[i] !== b[i]) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| function cacheLane(bytes, module, error) { | |
| // job is the instance a finished job left on this thread for the next. | |
| const compiled = { bytes, module, error, ids: new Set(), job: null }; | |
| laneModules.push(compiled); | |
| if (laneModules.length > kLaneModuleCache) { | |
| laneModules.shift(); | |
| } | |
| return compiled; | |
| } | |
| const laneCached = (bytes) => laneModules.some((lane) => sameBytes(lane.bytes, bytes)); | |
| // A thread that missed the page's compile compiles its own. | |
| function shareLane(bytes, module) { | |
| if (laneCached(bytes)) { | |
| return; | |
| } | |
| cacheLane(bytes, module, null); | |
| for (const worker of threads()) { | |
| worker.postMessage({ 'riveLane': { 'bytes': bytes, 'module': module } }); | |
| } | |
| } | |
| const takeLane = (data) => { | |
| if (parallel.message(data)) { | |
| return; | |
| } | |
| const lane = data?.['riveLane']; | |
| if (lane !== undefined) { | |
| shareLane(lane['bytes'], lane['module']); | |
| } | |
| }; | |
| const nodeThreads = globalThis.process?.getBuiltinModule?.('worker_threads'); | |
| if (nodeThreads?.isMainThread === false) { | |
| nodeThreads.parentPort.on('message', takeLane); | |
| } else if (globalThis.WorkerGlobalScope !== undefined) { | |
| globalThis.addEventListener('message', (event) => takeLane(event.data)); | |
| } | |
| function checkLaneImports(module, kind) { | |
| for (const wanted of WebAssembly.Module.imports(module)) { | |
| if (laneImportRefusal(kind, wanted['module'], wanted['name']) !== null) { | |
| throw new Error(laneImportError(wanted['module'], wanted['name'])); | |
| } | |
| } | |
| } | |
| // Compiles a main module's lane sections for every thread, off the page's | |
| // thread unless now. One that fails is left to fail where it first runs. | |
| function prepareLanes(main, now = false) { | |
| const compiles = []; | |
| for (const [name, kind] of kLaneSections) { | |
| for (const section of WebAssembly.Module.customSections(main, name)) { | |
| const bytes = liftStart(new Uint8Array(section)); | |
| if (laneCached(bytes)) { | |
| continue; | |
| } | |
| const share = (module) => { | |
| checkLaneImports(module, kind); | |
| shareLane(bytes, module); | |
| }; | |
| if (now) { | |
| try { | |
| share(new WebAssembly.Module(bytes)); | |
| } catch (error) {} | |
| } else { | |
| compiles.push(WebAssembly.compile(bytes).then(share).catch(() => {})); | |
| } | |
| } | |
| } | |
| return Promise.all(compiles); | |
| } | |
| function laneModule(id, bytes, kind) { | |
| let compiled = laneModules.find((lane) => lane.ids.has(id)); | |
| if (compiled === undefined) { | |
| const lifted = bytes(); | |
| compiled = laneModules.find((lane) => sameBytes(lane.bytes, lifted)); | |
| if (compiled === undefined) { | |
| compiled = cacheLane(lifted, null, null); | |
| try { | |
| const module = new WebAssembly.Module(lifted); | |
| checkLaneImports(module, kind); | |
| compiled.module = module; | |
| } catch (error) { | |
| compiled.error = errorText(error); | |
| } | |
| } | |
| compiled.ids.add(id); | |
| if (compiled.ids.size > kLaneModuleCache) { | |
| compiled.ids.delete(compiled.ids.values().next().value); | |
| } | |
| } | |
| return compiled; | |
| } | |
| // A lane's shared imports: librive's natives, or with twin Atomics on | |
| // librive's heap reaching owner's objects, as an audio worklet does. | |
| function sharedImports(twin = false, owner = 0) { | |
| return (memory, fail) => | |
| twin | |
| ? createSharedLaneImports( | |
| () => host.heapU8().buffer, | |
| host.exports['_rive_shared_table'](), | |
| owner, | |
| memory, | |
| null, | |
| fail | |
| ) | |
| : createRiveModuleImports( | |
| librive( | |
| { vm: 1, raised: null, hostFault: false, counters }, | |
| 'rive_shared_v1' | |
| ), | |
| memory, | |
| 'rive_shared_v1' | |
| )['rive_shared_v1']; | |
| } | |
| // A browser cannot interrupt a lane, so a metered one's fuel checks throw | |
| // why librive would. | |
| function laneFuel(lane) { | |
| const stop = host.laneStop(lane); | |
| if (stop !== null) { | |
| throw stop; | |
| } | |
| } | |
| // The instance a job left idle on this thread, or a new one, whose imports | |
| // reach whichever job it runs. | |
| function jobInstance(compiled) { | |
| const idle = compiled.job; | |
| compiled.job = null; | |
| if (idle !== null) { | |
| idle.timers.clear(); | |
| return idle; | |
| } | |
| const job = { lane: 0, cancelled: null, timers: new Map(), reset: false }; | |
| return Object.assign( | |
| job, | |
| instantiateLane({ | |
| module: compiled.module, | |
| natives: 'rive_job_v1', | |
| own: () => ({ 'cancelled': () => job.cancelled() }), | |
| shared: sharedImports(), | |
| log: (line) => host.laneLog(job.lane, line), | |
| timers: job.timers, | |
| now: laneNow, | |
| fuel: () => laneFuel(job.lane), | |
| }) | |
| ); | |
| } | |
| // A stop reaches a running job through its cancelled() and its fuel | |
| // checks. The output views the job's memory. | |
| function runJob(lane, id, bytes, entry, input, cancelled) { | |
| const compiled = laneModule(id, bytes, 'job'); | |
| if (compiled.error !== null) { | |
| return { ok: false, error: compiled.error }; | |
| } | |
| const job = jobInstance(compiled); | |
| if (job.error !== undefined) { | |
| return { ok: false, error: job.error }; | |
| } | |
| job.lane = lane; | |
| job.cancelled = cancelled; | |
| const entered = enterLane( | |
| job, | |
| { prefix: kLaneEntryPrefixes['job'], entry, input }, | |
| job.reset | |
| ); | |
| if (entered.error !== undefined) { | |
| return { ok: false, error: entered.error }; | |
| } | |
| try { | |
| const buffer = job.memory.buffer; | |
| const words = new Uint32Array(buffer, entered.result >>> 0, 2); | |
| const output = | |
| words[1] === 0 ? new Uint8Array(0) : new Uint8Array(buffer, words[0], words[1]); | |
| // Only a job that returned, unstopped, with small memory leaves its | |
| // instance; the next resets it once this output is copied out. | |
| if ( | |
| job.exports[kLaneResetExport] !== undefined && | |
| buffer.byteLength <= kReuseMaxPages * 65536 && | |
| !cancelled() | |
| ) { | |
| job.reset = true; | |
| compiled.job = job; | |
| } | |
| return { ok: true, output }; | |
| } catch (error) { | |
| return { ok: false, error: job.failure(error) }; | |
| } | |
| } | |
| // Workers keep their instance between wakes, on the thread that started | |
| // them; librive steps each one and owns its waits. | |
| const workers = new Map(); | |
| let nextWorker = 1; | |
| // A worker's natives call back into librive through natives. | |
| function workerStart(lane, id, bytes, entry, input, natives) { | |
| const compiled = laneModule(id, bytes, 'worker'); | |
| if (compiled.error !== null) { | |
| return { ok: false, error: compiled.error }; | |
| } | |
| const started = startLane({ | |
| module: compiled.module, | |
| natives: 'rive_worker_v1', | |
| // A view of the worker's memory, which librive copies once. | |
| own: (memory) => ({ | |
| 'finished': (ok, at, length) => | |
| natives.finished( | |
| ok, | |
| new Uint8Array(memory().buffer, at >>> 0, length >>> 0) | |
| ), | |
| 'wait': natives.wait, | |
| 'stopping': natives.stopping, | |
| }), | |
| onThrow: (text) => host.laneFail(lane, text), | |
| shared: sharedImports(), | |
| log: (line) => host.laneLog(lane, line), | |
| now: laneNow, | |
| fuel: () => laneFuel(lane), | |
| prefix: kLaneEntryPrefixes['worker'], | |
| entry, | |
| input, | |
| free: true, | |
| }); | |
| if (started.error !== undefined) { | |
| return { ok: false, error: started.error }; | |
| } | |
| const worker = nextWorker++; | |
| workers.set(worker, { | |
| wake: started.exports[kWorkerWakeExport], | |
| collect: started.exports[kFrameMinorExport], | |
| }); | |
| return { ok: true, id: worker }; | |
| } | |
| // Returns null once the worker took the wake, else the error. | |
| function workerWake(worker, wait, value) { | |
| try { | |
| workers.get(worker).wake(wait, value); | |
| return null; | |
| } catch (error) { | |
| return errorText(error); | |
| } | |
| } | |
| // Back at the host no frame is live, so the frame collector may run. | |
| // Returns null, or the error that ended the worker. | |
| function workerCollect(worker) { | |
| try { | |
| workers.get(worker)?.collect?.(); | |
| return null; | |
| } catch (error) { | |
| return errorText(error); | |
| } | |
| } | |
| function workerEnd(worker) { | |
| workers.delete(worker); | |
| } | |
| // A processor rendered offline: librive pulls each block. | |
| const processors = new Map(); | |
| let nextProcessor = 1; | |
| function processorStart(lane, id, bytes, entry, input, format, sharedOwner) { | |
| const compiled = laneModule(id, bytes, 'processor'); | |
| if (compiled.error !== null) { | |
| return { ok: false, error: compiled.error }; | |
| } | |
| const started = startProcessorLane( | |
| compiled.module, | |
| entry, | |
| input, | |
| format, | |
| sharedImports(laneTwin, sharedOwner), | |
| (line) => host.laneLog(lane, line) | |
| ); | |
| if (started.error !== undefined) { | |
| return { ok: false, error: started.error }; | |
| } | |
| const processor = nextProcessor++; | |
| processors.set(processor, started.lane); | |
| return { ok: true, id: processor }; | |
| } | |
| function processorRender(processor, frames, startFrame, sink) { | |
| return processors.get(processor).render(frames, startFrame, sink); | |
| } | |
| // Processors in real time run on an audio worklet that reaches librive's | |
| // heap through Atomics; README.md says what the host provides for it. | |
| // owners: the librive processor and module behind each worklet id. | |
| const audio = { output: null, owners: new Map(), next: 1 }; | |
| // Checks of the worklet's block counter that may see no block before the | |
| // output ends. A start outlasts init's budget, which ends a metered one. | |
| const kStallCheckMs = 50; | |
| const kStallChecks = 2; | |
| const kStartStallChecks = kProcessorInitMs / kStallCheckMs + 10; | |
| const kReadyChecks = 40; | |
| // A stuck browser worklet holds up only its own context, and a slow block | |
| // that returns fails on its budget, so a stall there must last longer. | |
| const kBrowserStallChecks = 20; | |
| // An ended NRDP thread ran on for up to 39 ms on the devices we measured. | |
| const kEndedThreadMs = 200; | |
| const kContextClosed = 'script audio context closed'; | |
| // A context the browser lets start does so well within this. | |
| const kGestureWaitMs = 1000; | |
| // NRDP's names are quoted so a closure compiled host keeps them. | |
| const nrdp = () => globalThis['nrdp']; | |
| const onNrdp = () => nrdp()?.['audio']?.['output'] !== undefined; | |
| // The worklet a host serves, else the one a threaded build carries, which | |
| // needs nothing served beside the runtime. NRDP only runs its own bundle. | |
| let carriedWorklet = null; | |
| function workletUrl() { | |
| const given = runner['audioWorkletUrl']; | |
| if (typeof given === 'string') { | |
| return given; | |
| } | |
| const source = Module['riveAudioWorkletSource']; | |
| if (onNrdp() || typeof source !== 'string') { | |
| return null; | |
| } | |
| carriedWorklet ??= URL.createObjectURL( | |
| new Blob([source], { type: 'text/javascript' }) | |
| ); | |
| return carriedWorklet; | |
| } | |
| // Null when processors can run in real time, else why not. | |
| function audioRefusal() { | |
| if (!onNrdp() && globalThis.crossOriginIsolated !== true) { | |
| return 'real time audio needs cross origin isolation'; | |
| } | |
| // The worklet reaches librive's heap through Atomics. | |
| if ( | |
| typeof SharedArrayBuffer === 'undefined' || | |
| !(host.memory().buffer instanceof SharedArrayBuffer) | |
| ) { | |
| return 'real time audio needs librive built with threads'; | |
| } | |
| if (workletUrl() === null) { | |
| return 'real time audio needs riveScripting.audioWorkletUrl'; | |
| } | |
| if (typeof AudioContext === 'undefined') { | |
| return 'real time audio needs Web Audio'; | |
| } | |
| const given = runner['audioContext']; | |
| if (given?.state === 'closed') { | |
| return 'real time audio cannot start on a closed AudioContext'; | |
| } | |
| // A stuck worklet holds every later addModule on its context. | |
| if (contextHolds.get(given)?.stalled) { | |
| return "real time audio stalled the host's AudioContext; hand riveScripting a new one"; | |
| } | |
| return null; | |
| } | |
| // What both outputs share: messages queue until the worklet can take | |
| // them, and those that never reach it fail their processors. | |
| function audioQueue() { | |
| let queue = []; | |
| let send = null; | |
| return { | |
| post(message) { | |
| if (send !== null) { | |
| send(message); | |
| } else { | |
| queue.push(message); | |
| } | |
| }, | |
| open(sender) { | |
| send = sender; | |
| for (const message of queue) { | |
| send(message); | |
| } | |
| queue = []; | |
| }, | |
| fail(text) { | |
| for (const message of queue) { | |
| audioEvent({ 'id': message['id'], 'kind': 'failed', 'text': text }); | |
| } | |
| queue = []; | |
| }, | |
| }; | |
| } | |
| // The worklets run uncompiled, so keys that cross to them are quoted. | |
| function workletOptions(holds) { | |
| return { | |
| 'numberOfInputs': 0, | |
| 'numberOfOutputs': 1, | |
| 'outputChannelCount': [2], | |
| 'processorOptions': { | |
| 'memory': host.memory(), | |
| 'table': host.exports['_rive_shared_table'](), | |
| 'counter': holds.buffer, | |
| }, | |
| }; | |
| } | |
| const newHolds = () => new Int32Array(new SharedArrayBuffer(kHoldWords * 4)); | |
| // Frees the lock and lane word a worklet that is surely gone left held. | |
| const releaseLane = (holds) => | |
| releaseSharedLane( | |
| () => host.memory().buffer, | |
| host.exports['_rive_shared_table'](), | |
| holds | |
| ); | |
| function failOwners(text) { | |
| for (const id of [...audio.owners.keys()]) { | |
| audioEvent({ 'id': id, 'kind': 'failed', 'text': text }); | |
| } | |
| } | |
| // Calls end with why once the worklet stops counting blocks for | |
| // stallChecks while processors wait on it, or once context closes. | |
| function watchBlocks(context, holds, readyChecks, stallChecks, end, closed = end) { | |
| let ready = false; | |
| let seen = -1; | |
| let stalled = 0; | |
| const timer = setInterval(() => { | |
| if (context.state === 'closed') { | |
| clearInterval(timer); | |
| closed(kContextClosed); | |
| return; | |
| } | |
| const now = Atomics.load(holds, kHoldBlocks); | |
| // A suspended context renders nothing without being stuck. A | |
| // stall outlives the stop of the processor that caused it. | |
| const waiting = | |
| (audio.owners.size > 0 || stalled > 0) && context.state === 'running'; | |
| stalled = now === seen && waiting ? stalled + 1 : 0; | |
| seen = now; | |
| const limit = !ready | |
| ? readyChecks | |
| : Atomics.load(holds, kHoldStarting) !== 0 | |
| ? kStartStallChecks | |
| : stallChecks; | |
| if (stalled >= limit) { | |
| clearInterval(timer); | |
| end(ready ? 'processor stalled the audio thread' : 'script audio worklet never answered'); | |
| } | |
| }, kStallCheckMs); | |
| return { | |
| ready() { | |
| ready = true; | |
| stalled = 0; | |
| }, | |
| stop: () => clearInterval(timer), | |
| }; | |
| } | |
| // An output the host's worklet runs. sent: the modules it has the bytes | |
| // of, so each crosses once; a worklet that lost them asks again. | |
| function audioOutputOf(context, queue) { | |
| return { context, post: queue.post, sent: new Set(), queue }; | |
| } | |
| // An output that failed or was ended: what it still queued fails, and the | |
| // next start makes a fresh one. Ends the context when it was ours. | |
| function dropOutput(output, text, close = true) { | |
| output.queue.fail(text); | |
| if (audio.output === output) { | |
| audio.output = null; | |
| } | |
| if (close && runner['audioContext'] === undefined) { | |
| output.context.close?.(); | |
| } | |
| } | |
| const noWorklet = (error) => | |
| 'script audio has no worklet: ' + errorText(error); | |
| // A browser context's worklet keeps one lane word until the context | |
| // closes, unless it stalled, as a stalled worklet may yet run. | |
| const contextHolds = new WeakMap(); | |
| function browserHolds(context) { | |
| let holds = contextHolds.get(context); | |
| if (holds === undefined) { | |
| holds = { words: newHolds(), stalled: false }; | |
| contextHolds.set(context, holds); | |
| context.addEventListener('statechange', () => { | |
| if (context.state === 'closed' && !holds.stalled) { | |
| releaseLane(holds.words); | |
| } | |
| }); | |
| } | |
| return holds; | |
| } | |
| // Browsers start audio only after a gesture, so a context only the runner | |
| // holds resumes on the page's first one, and warns once while it waits. | |
| function ownContext() { | |
| // iOS mutes the default ambient session at the silent switch, which | |
| // video plays through. | |
| const session = globalThis.navigator?.['audioSession']; | |
| if (session?.['type'] === 'auto') { | |
| session['type'] = 'playback'; | |
| } | |
| const context = new AudioContext(); | |
| const gestures = ['pointerdown', 'pointerup', 'keydown', 'touchend']; | |
| const resume = () => context.resume(); | |
| const waiting = setTimeout( | |
| () => console.warn('script audio waits for a click, tap or key press on the page'), | |
| kGestureWaitMs | |
| ); | |
| const started = () => { | |
| if (context.state === 'running' || context.state === 'closed') { | |
| clearTimeout(waiting); | |
| context.removeEventListener('statechange', started); | |
| for (const gesture of gestures) { | |
| globalThis.removeEventListener(gesture, resume, { capture: true }); | |
| } | |
| } | |
| }; | |
| for (const gesture of gestures) { | |
| globalThis.addEventListener(gesture, resume, { capture: true }); | |
| } | |
| context.addEventListener('statechange', started); | |
| started(); | |
| return context; | |
| } | |
| function browserOutput() { | |
| const context = runner['audioContext'] ?? ownContext(); | |
| const queue = audioQueue(); | |
| const output = audioOutputOf(context, queue); | |
| const holds = browserHolds(context); | |
| let node = null; | |
| const closed = (text) => { | |
| if (audio.output === output) { | |
| watch.stop(); | |
| failOwners(text); | |
| dropOutput(output, text, false); | |
| } | |
| }; | |
| // Nothing ends a worklet stuck in a block, so its processors fail and the node | |
| // leaves the mix in case it returns. Chrome's close would wait on that thread. | |
| const stalled = (text) => { | |
| holds.stalled = true; | |
| node.port.onmessage = null; | |
| node.port.postMessage({ 'kind': 'end' }); | |
| node.disconnect(); | |
| failOwners(text); | |
| dropOutput(output, text, false); | |
| }; | |
| const watch = watchBlocks( | |
| context, | |
| holds.words, | |
| Infinity, | |
| kBrowserStallChecks, | |
| stalled, | |
| closed | |
| ); | |
| context.addEventListener('statechange', () => { | |
| if (context.state === 'closed') { | |
| closed(kContextClosed); | |
| } | |
| }); | |
| context.audioWorklet | |
| .addModule(workletUrl()) | |
| .then(() => { | |
| node = new AudioWorkletNode( | |
| context, | |
| kProcessorNode, | |
| workletOptions(holds.words) | |
| ); | |
| node.port.onmessage = (event) => audioEvent(event.data); | |
| node.connect(context.destination); | |
| watch.ready(); | |
| queue.open((message) => node.port.postMessage(message)); | |
| }) | |
| .catch((error) => { | |
| watch.stop(); | |
| dropOutput(output, noWorklet(error)); | |
| }); | |
| return output; | |
| } | |
| // NRDP's worklet has no addModule: init binds a thread of ours to the | |
| // context, which runs the bundled script and adds the processor. | |
| function nrdpOutput() { | |
| const url = runner['audioWorkletUrl']; | |
| let context = runner['audioContext']; | |
| if (context === undefined) { | |
| // A context made before the output opens never renders. | |
| nrdp()['audio']['output']['open'](); | |
| context = new AudioContext(); | |
| } | |
| context['forceStart']?.(); | |
| const queue = audioQueue(); | |
| const output = audioOutputOf(context, queue); | |
| const holds = newHolds(); | |
| let thread = null; | |
| let ready = false; | |
| let ended = false; | |
| // A processor stuck in a block freezes every context; ending the | |
| // thread lets sample playback resume. | |
| const end = (text) => { | |
| if (ended) { | |
| return; | |
| } | |
| ended = true; | |
| watch.stop(); | |
| thread?.['terminate'](); | |
| if (ready) { | |
| // Waits here, where librive cannot meanwhile spin on a lock | |
| // the ended thread left held. | |
| for (const until = monotonicNow() + kEndedThreadMs; monotonicNow() < until; ) {} | |
| releaseLane(holds); | |
| failOwners(text); | |
| } | |
| dropOutput(output, text); | |
| }; | |
| const watch = watchBlocks(context, holds, kReadyChecks, kStallChecks, end); | |
| // A throw in a callback NRDP runs would escape the fetch's catch. | |
| const guard = | |
| (fn) => | |
| (...args) => { | |
| try { | |
| fn(...args); | |
| } catch (error) { | |
| end(noWorklet(error)); | |
| } | |
| }; | |
| const onReady = guard(() => { | |
| const node = new AudioWorkletNode( | |
| context, | |
| kProcessorNode, | |
| workletOptions(holds) | |
| ); | |
| node.connect(context.destination); | |
| ready = true; | |
| watch.ready(); | |
| queue.open((message) => thread['send'](message)); | |
| }); | |
| fetch(url) | |
| .then((response) => { | |
| if (!response.ok) { | |
| throw new Error(url + ' answered HTTP ' + response.status); | |
| } | |
| return response.text(); | |
| }) | |
| .then((source) => { | |
| if (ended) { | |
| return; | |
| } | |
| const worklet = context.audioWorklet; | |
| worklet['active'] = true; | |
| worklet['init']( | |
| guard(() => { | |
| if (ended) { | |
| return; | |
| } | |
| thread = nrdp()['thread']['start']({ | |
| 'url': url, | |
| 'source': source, | |
| 'audio': context, | |
| }); | |
| thread.addEventListener('raw-message', (message) => | |
| message['kind'] === 'ready' ? onReady() : audioEvent(message) | |
| ); | |
| }) | |
| ); | |
| }) | |
| .catch((error) => end(noWorklet(error))); | |
| return output; | |
| } | |
| function audioOutput() { | |
| audio.output ??= onNrdp() ? nrdpOutput() : browserOutput(); | |
| return audio.output; | |
| } | |
| // Forgets the oldest modules no processor runs, past the cache's size. | |
| function forgetModules(output) { | |
| const running = new Set([...audio.owners.values()].map((o) => o.moduleId)); | |
| for (const moduleId of output.sent) { | |
| if (output.sent.size <= kLaneModuleCache) { | |
| return; | |
| } | |
| if (!running.has(moduleId)) { | |
| output.sent.delete(moduleId); | |
| output.post({ 'kind': 'forget', 'moduleId': moduleId }); | |
| } | |
| } | |
| } | |
| // Bytes rather than the compiled module: a browser's worklet may sit in | |
| // another agent cluster, where a module cannot cross. | |
| function postStart(output, owned, withBytes) { | |
| const compiled = owned.compiled; | |
| output.sent.add(owned.moduleId); | |
| output.post({ | |
| ...owned.start, | |
| 'bytes': withBytes ? compiled.bytes : null, | |
| }); | |
| } | |
| // owner names the processor to librive when the worklet answers. | |
| function audioStart(owner, moduleId, bytes, entry, input, format, hardBlocks, sharedOwner) { | |
| const compiled = laneModule(moduleId, bytes, 'processor'); | |
| if (compiled.error !== null) { | |
| return { ok: false, error: compiled.error }; | |
| } | |
| const output = audioOutput(); | |
| const id = audio.next++; | |
| const owned = { | |
| owner, | |
| moduleId, | |
| compiled, | |
| start: { | |
| 'kind': 'start', | |
| 'id': id, | |
| 'moduleId': moduleId, | |
| 'entry': entry, | |
| 'input': input, | |
| 'format': { | |
| 'sampleRate': format.sampleRate, | |
| 'maxFrames': format.maxFrames, | |
| 'channels': format.channels, | |
| }, | |
| 'hardBlocks': hardBlocks, | |
| 'sharedOwner': sharedOwner, | |
| }, | |
| }; | |
| audio.owners.set(id, owned); | |
| postStart(output, owned, !output.sent.has(moduleId)); | |
| forgetModules(output); | |
| return { ok: true, id }; | |
| } | |
| function audioStop(id) { | |
| audio.owners.delete(id); | |
| if (audio.output !== null) { | |
| audio.output.post({ 'kind': 'stop', 'id': id }); | |
| forgetModules(audio.output); | |
| } | |
| } | |
| // The LaneState a processor reached, or a console line. | |
| const kProcessorEvents = { | |
| 'running': kLaneStates['running'], | |
| 'failed': kLaneStates['failed'], | |
| 'log': kProcessorEventLog, | |
| }; | |
| function audioEvent(event) { | |
| const owned = audio.owners.get(event['id']); | |
| if (owned === undefined) { | |
| return; | |
| } | |
| if (event['kind'] === 'resend') { | |
| if (audio.output !== null) { | |
| postStart(audio.output, owned, true); | |
| } | |
| return; | |
| } | |
| host.processorEvent(owned.owner, kProcessorEvents[event['kind']], event['text'] ?? ''); | |
| } | |
| function processorEnd(processor) { | |
| processors.delete(processor); | |
| } | |
| const runner = { | |
| attach(primitives) { | |
| if (host !== null) { | |
| return; | |
| } | |
| host = primitives; | |
| // Zero where the engine has no timeOrigin. | |
| const offset = performance.timeOrigin - host.pageOrigin || 0; | |
| laneNow = () => performance.now() + offset; | |
| }, | |
| attachThreads(workers, workerOf) { | |
| threads = workers; | |
| teamWorkerOf = workerOf; | |
| }, | |
| register(vm, bytes) { | |
| const copy = bytes.slice(); | |
| vms.set(vm, { | |
| ctx: { vm, raised: null, hostFault: false, counters }, | |
| bytes: copy, | |
| instance: null, | |
| memory: null, | |
| parallelMemory: null, | |
| parallelSize: null, | |
| parallel: null, | |
| preparing: null, | |
| error: missingSimd(copy), | |
| names: new Map(), | |
| }); | |
| }, | |
| release(vm) { | |
| const entry = vms.get(vm); | |
| if (entry) { | |
| // A module still instantiating may call imports afterwards. | |
| entry.ctx.vm = 0; | |
| vms.delete(vm); | |
| if (entry.parallel !== null) { | |
| parallel.release(entry.parallel); | |
| } | |
| } | |
| }, | |
| // The team a parallel call runs on, for tests to report. | |
| parallelState() { | |
| return parallel.state(); | |
| }, | |
| prepare() { | |
| const pending = []; | |
| for (const entry of vms.values()) { | |
| if (entry.instance === null && entry.error === null) { | |
| entry.preparing ??= prepareEntry(entry); | |
| pending.push(entry.preparing); | |
| } | |
| } | |
| return Promise.all(pending); | |
| }, | |
| // Returns null when the VM has an instance, else the error. | |
| start(vm) { | |
| const entry = vms.get(vm); | |
| if (!entry) { | |
| return 'script module was never registered'; | |
| } | |
| if (entry.instance === null && entry.error === null) { | |
| if (entry.preparing !== null) { | |
| return 'script module is still being prepared'; | |
| } | |
| try { | |
| const lifted = liftStart(withMemory(entry)); | |
| const module = new WebAssembly.Module(lifted); | |
| announceExports(entry, module); | |
| prepareLanes(module, true); | |
| adopt( | |
| entry, | |
| new WebAssembly.Instance(module, importsFor(entry, module)) | |
| ); | |
| // Members start in the background; calls before they | |
| // do get fewer parts. | |
| adoptMembers(entry, memberBytes(entry, lifted)); | |
| } catch (error) { | |
| entry.error = errorText(error); | |
| } | |
| } | |
| return entry.error; | |
| }, | |
| preparing(vm) { | |
| const entry = vms.get(vm); | |
| return entry?.instance === null && | |
| entry.error === null && | |
| entry.preparing !== null | |
| ? 1 | |
| : 0; | |
| }, | |
| hasExport(vm, namePtr) { | |
| const entry = vms.get(vm); | |
| return typeof entry?.instance?.exports[host.utf8(namePtr)] === | |
| 'function' | |
| ? 1 | |
| : 0; | |
| }, | |
| // Args arrive as doubles: a u32 is exact in one and the engine | |
| // converts each to the export's own parameter type. | |
| call(vm, namePtr, argc, argv, resultPtr, trapBuffer, trapCapacity) { | |
| const entry = vms.get(vm); | |
| if (!entry || entry.instance === null) { | |
| return kMissing; | |
| } | |
| // Export names reach librive's call seam as string literals, so | |
| // the pointer identifies the name. | |
| let fn = entry.names.get(namePtr); | |
| if (fn === undefined) { | |
| fn = entry.instance.exports[host.utf8(namePtr)] ?? null; | |
| entry.names.set(namePtr, fn); | |
| } | |
| if (typeof fn !== 'function') { | |
| return kMissing; | |
| } | |
| const callState = entry.callState; | |
| const saved = entry.callSaved; | |
| const base = saved.length; | |
| for (let i = 0; i < callState.length; i++) { | |
| saved.push(callState[i].value); | |
| } | |
| try { | |
| const result = callExport(fn, host.heapF64(), argv >> 3, argc); | |
| host.heapF64()[resultPtr >> 3] = | |
| typeof result === 'number' ? result : 0; | |
| return kOk; | |
| } catch (error) { | |
| entry.ctx.raised = null; | |
| host.writeUtf8( | |
| errorText(error), | |
| trapBuffer, | |
| trapCapacity | |
| ); | |
| return entry.ctx.hostFault ? kHostFault : kTrapped; | |
| } finally { | |
| for (let i = 0; i < callState.length; i++) { | |
| callState[i].value = saved[base + i]; | |
| } | |
| saved.length = base; | |
| } | |
| }, | |
| raise(vm, messagePtr) { | |
| const entry = vms.get(vm); | |
| if (entry) { | |
| entry.ctx.raised = host.utf8(messagePtr); | |
| } | |
| }, | |
| read(vm, appAddr, dst, size) { | |
| const memory = vms.get(vm)?.memory; | |
| if (!memory || appAddr + size > memory.buffer.byteLength) { | |
| return 0; | |
| } | |
| host.heapU8().set(new Uint8Array(memory.buffer, appAddr, size), dst); | |
| if (counters.on) counters.bytesRead += size; | |
| return 1; | |
| }, | |
| write(vm, appAddr, src, size) { | |
| const memory = vms.get(vm)?.memory; | |
| if (!memory || appAddr + size > memory.buffer.byteLength) { | |
| return 0; | |
| } | |
| new Uint8Array(memory.buffer, appAddr, size).set( | |
| host.heapU8().subarray(src, src + size) | |
| ); | |
| if (counters.on) counters.bytesWritten += size; | |
| return 1; | |
| }, | |
| // Length of the zero terminated string at appAddr, or -1. | |
| stringLength(vm, appAddr) { | |
| const memory = vms.get(vm)?.memory; | |
| if (!memory || appAddr >= memory.buffer.byteLength) { | |
| return -1; | |
| } | |
| const end = new Uint8Array(memory.buffer).indexOf(0, appAddr); | |
| return end < 0 ? -1 : end - appAddr; | |
| }, | |
| pages(vm) { | |
| const memory = vms.get(vm)?.memory; | |
| // Not >>> 16, which reads a full 4 GiB memory as none. | |
| return memory ? memory.buffer.byteLength / 65536 : 0; | |
| }, | |
| // File::frameBoundary for every live VM, for hosts that keep no list | |
| // of their files. Returns the warnings they raised. | |
| frameBoundary() { | |
| const warnings = []; | |
| for (const vm of vms.keys()) { | |
| const text = host.exports['_rive_web_vm_frame_boundary'](vm); | |
| if (text !== 0) { | |
| warnings.push(host.utf8(text)); | |
| } | |
| } | |
| return warnings; | |
| }, | |
| // Starts or stops tallying the bridge traffic, from zero. | |
| countHostCalls(on) { | |
| counters.on = !!on; | |
| counters.hostCalls = 0; | |
| counters.bytesStaged = 0; | |
| counters.bytesCopiedOut = 0; | |
| counters.bytesRead = 0; | |
| counters.bytesWritten = 0; | |
| }, | |
| // Calls into librive, bytes staged into its heap and copied back, and | |
| // bytes librive read and wrote through its memory seam. | |
| hostCallCounts() { | |
| return { | |
| 'hostCalls': counters.hostCalls, | |
| 'bytesStaged': counters.bytesStaged, | |
| 'bytesCopiedOut': counters.bytesCopiedOut, | |
| 'bytesRead': counters.bytesRead, | |
| 'bytesWritten': counters.bytesWritten, | |
| }; | |
| }, | |
| }; | |
| runner['runJob'] = runJob; | |
| runner['workerStart'] = workerStart; | |
| runner['workerWake'] = workerWake; | |
| runner['workerCollect'] = workerCollect; | |
| runner['workerEnd'] = workerEnd; | |
| runner['processorStart'] = processorStart; | |
| runner['processorRender'] = processorRender; | |
| runner['processorEnd'] = processorEnd; | |
| runner['audioRefusal'] = audioRefusal; | |
| runner['audioSampleRate'] = () => audioOutput().context.sampleRate; | |
| runner['audioStart'] = audioStart; | |
| runner['audioStop'] = audioStop; | |
| // For hosts and tests: where the real time output stands. | |
| runner['audioState'] = () => ({ | |
| 'context': audio.output?.context.state ?? 'none', | |
| 'processors': audio.owners.size, | |
| }); | |
| // The entries hosts call from outside this script. | |
| runner['prepare'] = runner.prepare; | |
| runner['frameBoundary'] = runner.frameBoundary; | |
| runner['countHostCalls'] = runner.countHostCalls; | |
| runner['hostCallCounts'] = runner.hostCallCounts; | |
| Module['riveScripting'] = runner; | |
| return runner; | |
| } | |
| installRiveScripting(Module); | |
| })(); |