Buckets:
| // Copyright 2012 The Emscripten Authors. All rights reserved. | |
| // Emscripten is available under two separate licenses, the MIT license and the | |
| // University of Illinois/NCSA Open Source License. Both these licenses can be | |
| // found in the LICENSE file. | |
| // Number of handles reserved for non-use (0) or common values w/o refcount. | |
| {{{ | |
| const EMVAL_RESERVED_HANDLES = 5; | |
| const EMVAL_LAST_RESERVED_HANDLE = EMVAL_RESERVED_HANDLES * 2 - 1; | |
| }}} | |
| var LibraryEmVal = { | |
| // Stack of handles available for reuse. | |
| $emval_freelist: [], | |
| #if !DISABLE_EXCEPTION_CATCHING || WASM_EXCEPTIONS | |
| $emval_exception_decrefs: [], | |
| #endif | |
| // Array of alternating pairs (value, refcount). | |
| // reserve 0 and some special values. These never get de-allocated. | |
| $emval_handles: [ | |
| 0, 1, | |
| undefined, 1, | |
| null, 1, | |
| true, 1, | |
| false, 1, | |
| ], | |
| #if ASSERTIONS | |
| $emval_handles__postset: 'assert(emval_handles.length === {{{ EMVAL_RESERVED_HANDLES }}} * 2)', | |
| #endif | |
| $emval_symbols: {}, // address -> string | |
| $count_emval_handles__deps: ['$emval_freelist', '$emval_handles'], | |
| $count_emval_handles: () => { | |
| return emval_handles.length / 2 - {{{ EMVAL_RESERVED_HANDLES }}} - emval_freelist.length; | |
| }, | |
| _emval_register_symbol__deps: ['$emval_symbols', '$AsciiToString'], | |
| _emval_register_symbol: (address) => { | |
| emval_symbols[address] = AsciiToString(address); | |
| }, | |
| $getStringOrSymbol__deps: ['$emval_symbols', '$AsciiToString'], | |
| $getStringOrSymbol: (address) => { | |
| var symbol = emval_symbols[address]; | |
| if (symbol === undefined) { | |
| return AsciiToString(address); | |
| } | |
| return symbol; | |
| }, | |
| $Emval__deps: ['$emval_freelist', '$emval_handles', '$throwBindingError'], | |
| $Emval: { | |
| toValue: (handle) => { | |
| if (!handle) { | |
| throwBindingError(`Cannot use deleted val. handle = ${handle}`); | |
| } | |
| #if ASSERTIONS | |
| // handle 2 is supposed to be `undefined`. | |
| assert(handle === 2 || emval_handles[handle] !== undefined && handle % 2 === 0, `invalid handle: ${handle}`); | |
| #endif | |
| return emval_handles[handle]; | |
| }, | |
| toHandle: (value) => { | |
| switch (value) { | |
| case undefined: return 2; | |
| case null: return 4; | |
| case true: return 6; | |
| case false: return 8; | |
| default:{ | |
| const handle = emval_freelist.pop() || emval_handles.length; | |
| emval_handles[handle] = value; | |
| emval_handles[handle + 1] = 1; | |
| return handle; | |
| } | |
| } | |
| } | |
| }, | |
| _emval_incref__deps: ['$emval_handles'], | |
| _emval_incref: (handle) => { | |
| if (handle > {{{ EMVAL_LAST_RESERVED_HANDLE }}}) { | |
| emval_handles[handle + 1] += 1; | |
| } | |
| }, | |
| _emval_decref__deps: ['$emval_freelist', '$emval_handles', | |
| #if !DISABLE_EXCEPTION_CATCHING || WASM_EXCEPTIONS | |
| '$emval_exception_decrefs', | |
| #endif | |
| ], | |
| _emval_decref: (handle) => { | |
| if (handle > {{{ EMVAL_LAST_RESERVED_HANDLE }}} && 0 === --emval_handles[handle + 1]) { | |
| #if ASSERTIONS | |
| assert(emval_handles[handle] !== undefined, `decref for unallocated handle`); | |
| #endif | |
| var value = emval_handles[handle]; | |
| emval_handles[handle] = undefined; | |
| #if !DISABLE_EXCEPTION_CATCHING || WASM_EXCEPTIONS | |
| // In case the value is a C++ exception, decrement the refcount, so the | |
| // memory can be freed correctly | |
| var destructor = emval_exception_decrefs[handle]; | |
| if (destructor) { | |
| emval_exception_decrefs[handle] = undefined; | |
| destructor(value); | |
| } | |
| #endif | |
| emval_freelist.push(handle); | |
| } | |
| }, | |
| _emval_run_destructors__deps: ['_emval_decref', '$Emval', '$runDestructors'], | |
| _emval_run_destructors: (handle) => { | |
| var destructors = Emval.toValue(handle); | |
| runDestructors(destructors); | |
| __emval_decref(handle); | |
| }, | |
| _emval_new_array__deps: ['$Emval'], | |
| _emval_new_array: () => Emval.toHandle([]), | |
| #if !SUPPORT_BIG_ENDIAN | |
| _emval_new_array_from_memory_view__deps: ['$Emval'], | |
| _emval_new_array_from_memory_view: (view) => { | |
| view = Emval.toValue(view); | |
| // using for..loop is faster than Array.from | |
| var a = new Array(view.length); | |
| for (var i = 0; i < view.length; i++) a[i] = view[i]; | |
| return Emval.toHandle(a); | |
| }, | |
| _emval_array_to_memory_view__deps: ['$Emval'], | |
| _emval_array_to_memory_view: (dst, src) => { | |
| dst = Emval.toValue(dst); | |
| src = Emval.toValue(src); | |
| dst.set(src); | |
| }, | |
| #else | |
| _emval_new_array_from_memory_view__deps: ['$Emval'], | |
| _emval_new_array_from_memory_view: (view) => { | |
| view = Emval.toValue(view); | |
| const dv = new DataView(view.buffer, view.byteOffset); | |
| const reader = { | |
| Int8Array: dv.getInt8, | |
| Uint8Array: dv.getUint8, | |
| Int16Array: dv.getInt16, | |
| Uint16Array: dv.getUint16, | |
| Int32Array: dv.getInt32, | |
| Uint32Array: dv.getUint32, | |
| BigInt64Array: dv.getBigInt64, | |
| BigUint64Array: dv.getBigUint64, | |
| Float32Array: dv.getFloat32, | |
| Float64Array: dv.getFloat64, | |
| }[view[Symbol.toStringTag]]; | |
| var a = new Array(view.length); | |
| for (var i = 0; i < view.length; i++) a[i] = reader.call(dv, i * view.BYTES_PER_ELEMENT, true); | |
| return Emval.toHandle(a); | |
| }, | |
| _emval_array_to_memory_view__deps: ['$Emval'], | |
| _emval_array_to_memory_view: (dst, src) => { | |
| dst = Emval.toValue(dst); | |
| src = Emval.toValue(src); | |
| const dv = new DataView(dst.buffer, dst.byteOffset); | |
| const writer = { | |
| Int8Array: dv.setInt8, | |
| Uint8Array: dv.setUint8, | |
| Int16Array: dv.setInt16, | |
| Uint16Array: dv.setUint16, | |
| Int32Array: dv.setInt32, | |
| Uint32Array: dv.setUint32, | |
| BigInt64Array: dv.setBigInt64, | |
| BigUint64Array: dv.setBigUint64, | |
| Float32Array: dv.setFloat32, | |
| Float64Array: dv.setFloat64, | |
| }[dst[Symbol.toStringTag]]; | |
| for (var i = 0; i < src.length; i++) writer.call(dv, i * dst.BYTES_PER_ELEMENT, src[i], true); | |
| }, | |
| #endif | |
| _emval_new_object__deps: ['$Emval'], | |
| _emval_new_object: () => Emval.toHandle({}), | |
| _emval_new_cstring__deps: ['$getStringOrSymbol', '$Emval'], | |
| _emval_new_cstring: (v) => Emval.toHandle(getStringOrSymbol(v)), | |
| _emval_new_u8string__deps: ['$Emval'], | |
| _emval_new_u8string: (v) => Emval.toHandle(UTF8ToString(v)), | |
| _emval_new_u16string__deps: ['$Emval'], | |
| _emval_new_u16string: (v) => Emval.toHandle(UTF16ToString(v)), | |
| _emval_get_global__deps: ['$Emval', '$getStringOrSymbol'], | |
| _emval_get_global: (name) => { | |
| if (!name) { | |
| return Emval.toHandle(globalThis); | |
| } | |
| name = getStringOrSymbol(name); | |
| return Emval.toHandle(globalThis[name]); | |
| }, | |
| _emval_get_module_property__deps: ['$getStringOrSymbol', '$Emval'], | |
| _emval_get_module_property: (name) => { | |
| name = getStringOrSymbol(name); | |
| return Emval.toHandle(Module[name]); | |
| }, | |
| _emval_get_property__deps: ['$Emval'], | |
| _emval_get_property: (handle, key) => { | |
| handle = Emval.toValue(handle); | |
| key = Emval.toValue(key); | |
| return Emval.toHandle(handle[key]); | |
| }, | |
| _emval_set_property__deps: ['$Emval'], | |
| _emval_set_property: (handle, key, value) => { | |
| handle = Emval.toValue(handle); | |
| key = Emval.toValue(key); | |
| value = Emval.toValue(value); | |
| handle[key] = value; | |
| }, | |
| $emval_returnValue__deps: ['$Emval'], | |
| $emval_returnValue: (toReturnWire, destructorsRef, handle) => { | |
| var destructors = []; | |
| var result = toReturnWire(destructors, handle); | |
| if (destructors.length) { | |
| // void, primitives and any other types w/o destructors don't need to allocate a handle | |
| {{{ makeSetValue('destructorsRef', '0', 'Emval.toHandle(destructors)', '*') }}}; | |
| } | |
| return result; | |
| }, | |
| _emval_equals__deps: ['$Emval'], | |
| _emval_equals: (first, second) => { | |
| first = Emval.toValue(first); | |
| second = Emval.toValue(second); | |
| return first == second; | |
| }, | |
| _emval_strictly_equals__deps: ['$Emval'], | |
| _emval_strictly_equals: (first, second) => { | |
| first = Emval.toValue(first); | |
| second = Emval.toValue(second); | |
| return first === second; | |
| }, | |
| _emval_greater_than__deps: ['$Emval'], | |
| _emval_greater_than: (first, second) => { | |
| first = Emval.toValue(first); | |
| second = Emval.toValue(second); | |
| return first > second; | |
| }, | |
| _emval_less_than__deps: ['$Emval'], | |
| _emval_less_than: (first, second) => { | |
| first = Emval.toValue(first); | |
| second = Emval.toValue(second); | |
| return first < second; | |
| }, | |
| _emval_not__deps: ['$Emval'], | |
| _emval_not: (object) => { | |
| object = Emval.toValue(object); | |
| return !object; | |
| }, | |
| $emval_lookupTypes__deps: ['$requireRegisteredType'], | |
| $emval_lookupTypes: (argCount, argTypes) => { | |
| var a = new Array(argCount); | |
| for (var i = 0; i < argCount; ++i) { | |
| a[i] = requireRegisteredType({{{ makeGetValue('argTypes', `i*${POINTER_SIZE}`, '*') }}}, | |
| `parameter ${i}`); | |
| } | |
| return a; | |
| }, | |
| // Leave id 0 undefined. It's not a big deal, but might be confusing | |
| // to have null be a valid method caller. | |
| $emval_methodCallers: [undefined], | |
| $emval_addMethodCaller__deps: ['$emval_methodCallers'], | |
| $emval_addMethodCaller: (caller) => { | |
| var id = emval_methodCallers.length; | |
| emval_methodCallers.push(caller); | |
| return id; | |
| }, | |
| _emval_create_invoker__deps: [ | |
| '$emval_addMethodCaller', '$emval_lookupTypes', | |
| '$createNamedFunction', '$emval_returnValue', | |
| '$Emval', '$getStringOrSymbol', | |
| ], | |
| _emval_create_invoker: (argCount, argTypesPtr, kind) => { | |
| var GenericWireTypeSize = {{{ 2 * POINTER_SIZE }}}; | |
| var [retType, ...argTypes] = emval_lookupTypes(argCount, argTypesPtr); | |
| var toReturnWire = retType.toWireType.bind(retType); | |
| var argFromPtr = argTypes.map(type => type.readValueFromPointer.bind(type)); | |
| argCount--; // remove the extracted return type | |
| #if DYNAMIC_EXECUTION | |
| var captures = {'toValue': Emval.toValue}; | |
| var args = argFromPtr.map((argFromPtr, i) => { | |
| var captureName = `argFromPtr${i}`; | |
| captures[captureName] = argFromPtr; | |
| return `${captureName}(args${i ? '+' + i * GenericWireTypeSize : ''})`; | |
| }); | |
| var functionBody; | |
| switch (kind){ | |
| case {{{ cDefs['internal::EM_INVOKER_KIND::FUNCTION'] }}}: | |
| functionBody = 'toValue(handle)'; | |
| break; | |
| case {{{ cDefs['internal::EM_INVOKER_KIND::CONSTRUCTOR'] }}}: | |
| functionBody = 'new (toValue(handle))'; | |
| break; | |
| case {{{ cDefs['internal::EM_INVOKER_KIND::CAST'] }}}: | |
| functionBody = ''; | |
| break; | |
| case {{{ cDefs['internal::EM_INVOKER_KIND::METHOD'] }}}: | |
| captures['getStringOrSymbol'] = getStringOrSymbol; | |
| functionBody = 'toValue(handle)[getStringOrSymbol(methodName)]'; | |
| break; | |
| } | |
| functionBody += `(${args})`; | |
| if (!retType.isVoid) { | |
| captures['toReturnWire'] = toReturnWire; | |
| captures['emval_returnValue'] = emval_returnValue; | |
| functionBody = `return emval_returnValue(toReturnWire, destructorsRef, ${functionBody})`; | |
| } | |
| functionBody = `return function (handle, methodName, destructorsRef, args) { | |
| ${functionBody} | |
| }`; | |
| var invokerFunction = new Function(Object.keys(captures), functionBody)(...Object.values(captures)); | |
| #else | |
| var argN = new Array(argCount); | |
| var invokerFunction = (handle, methodName, destructorsRef, args) => { | |
| var offset = 0; | |
| for (var i = 0; i < argCount; ++i) { | |
| argN[i] = argFromPtr[i](args + offset); | |
| offset += GenericWireTypeSize; | |
| } | |
| var rv; | |
| switch (kind) { | |
| case {{{ cDefs['internal::EM_INVOKER_KIND::FUNCTION'] }}}: | |
| rv = Emval.toValue(handle).apply(null, argN); | |
| break; | |
| case {{{ cDefs['internal::EM_INVOKER_KIND::CONSTRUCTOR'] }}}: | |
| rv = Reflect.construct(Emval.toValue(handle), argN); | |
| break; | |
| case {{{ cDefs['internal::EM_INVOKER_KIND::CAST'] }}}: | |
| // no-op, just return the argument | |
| rv = argN[0]; | |
| break; | |
| case {{{ cDefs['internal::EM_INVOKER_KIND::METHOD'] }}}: | |
| rv = Emval.toValue(handle)[getStringOrSymbol(methodName)](...argN); | |
| break; | |
| } | |
| return emval_returnValue(toReturnWire, destructorsRef, rv); | |
| }; | |
| #endif | |
| var functionName = `methodCaller<(${argTypes.map(t => t.name)}) => ${retType.name}>`; | |
| return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction)); | |
| }, | |
| _emval_invoke__deps: ['$getStringOrSymbol', '$emval_methodCallers', '$Emval'], | |
| _emval_invoke: (caller, handle, methodName, destructorsRef, args) => { | |
| return emval_methodCallers[caller](handle, methodName, destructorsRef, args); | |
| }, | |
| // Same as `_emval_invoke`, just imported into Wasm under a different return type. | |
| // TODO: remove this if/when https://github.com/emscripten-core/emscripten/issues/20478 is fixed. | |
| _emval_invoke_i64: '_emval_invoke', | |
| _emval_typeof__deps: ['$Emval'], | |
| _emval_typeof: (handle) => { | |
| handle = Emval.toValue(handle); | |
| return Emval.toHandle(typeof handle); | |
| }, | |
| _emval_instanceof__deps: ['$Emval'], | |
| _emval_instanceof: (object, constructor) => { | |
| object = Emval.toValue(object); | |
| constructor = Emval.toValue(constructor); | |
| return object instanceof constructor; | |
| }, | |
| _emval_is_number__deps: ['$Emval'], | |
| _emval_is_number: (handle) => { | |
| handle = Emval.toValue(handle); | |
| return typeof handle == 'number'; | |
| }, | |
| _emval_is_string__deps: ['$Emval'], | |
| _emval_is_string: (handle) => { | |
| handle = Emval.toValue(handle); | |
| return typeof handle == 'string'; | |
| }, | |
| _emval_in__deps: ['$Emval'], | |
| _emval_in: (item, object) => { | |
| item = Emval.toValue(item); | |
| object = Emval.toValue(object); | |
| return item in object; | |
| }, | |
| _emval_delete__deps: ['$Emval'], | |
| _emval_delete: (object, property) => { | |
| object = Emval.toValue(object); | |
| property = Emval.toValue(property); | |
| return delete object[property]; | |
| }, | |
| #if !DISABLE_EXCEPTION_CATCHING || WASM_EXCEPTIONS | |
| $isCppExceptionObject__deps: ['$Emval'], | |
| $isCppExceptionObject: (object) => { | |
| #if !DISABLE_EXCEPTION_CATCHING | |
| return object instanceof CppException; | |
| #else // WASM_EXCEPTIONS | |
| return object instanceof WebAssembly.Exception; | |
| #endif | |
| }, | |
| #endif | |
| _emval_throw__deps: ['$Emval', | |
| #if !DISABLE_EXCEPTION_CATCHING || WASM_EXCEPTIONS | |
| #if !DISABLE_EXCEPTION_CATCHING | |
| '$exceptionLast', | |
| '$ExceptionInfo', | |
| #endif | |
| '$incrementExceptionRefcount', | |
| '$incrementUncaughtExceptionCount', | |
| '$isCppExceptionObject', | |
| #endif | |
| ], | |
| _emval_throw: (object) => { | |
| object = Emval.toValue(object); | |
| #if !DISABLE_EXCEPTION_CATCHING || WASM_EXCEPTIONS | |
| if (isCppExceptionObject(object)) { | |
| #if !DISABLE_EXCEPTION_CATCHING | |
| var info = new ExceptionInfo(object.excPtr); | |
| info.set_caught(false); | |
| info.set_rethrown(false); | |
| exceptionLast = object; | |
| #endif | |
| incrementUncaughtExceptionCount(); | |
| incrementExceptionRefcount(object); | |
| } | |
| #endif | |
| throw object; | |
| }, | |
| #if ASYNCIFY | |
| _emval_await__deps: ['$Emval', '$Asyncify'], | |
| _emval_await__async: 'auto', | |
| _emval_await: async (promise) => { | |
| var value = await Emval.toValue(promise); | |
| return Emval.toHandle(value); | |
| }, | |
| #endif | |
| _emval_iter_begin__deps: ['$Emval'], | |
| _emval_iter_begin: (iterable) => { | |
| iterable = Emval.toValue(iterable); | |
| return Emval.toHandle(iterable[Symbol.iterator]()); | |
| }, | |
| _emval_iter_next__deps: ['$Emval'], | |
| _emval_iter_next: (iterator) => { | |
| iterator = Emval.toValue(iterator); | |
| var result = iterator.next(); | |
| return result.done ? 0 : Emval.toHandle(result.value); | |
| }, | |
| _emval_coro_suspend__deps: ['$Emval', '_emval_coro_resume', '_emval_coro_reject'], | |
| _emval_coro_suspend: (promiseHandle, awaiterPtr) => { | |
| Emval.toValue(promiseHandle) | |
| .then((result) => __emval_coro_resume(awaiterPtr, Emval.toHandle(result)), | |
| (error) => __emval_coro_reject(awaiterPtr, Emval.toHandle(error))); | |
| }, | |
| _emval_coro_make_promise__deps: ['$Emval'], | |
| _emval_coro_make_promise: (resolveHandlePtr, rejectHandlePtr) => { | |
| return Emval.toHandle(new Promise((resolve, reject) => { | |
| {{{ makeSetValue('resolveHandlePtr', '0', 'Emval.toHandle(resolve)', '*') }}}; | |
| {{{ makeSetValue('rejectHandlePtr', '0', 'Emval.toHandle(reject)', '*') }}}; | |
| })); | |
| }, | |
| _emval_from_current_cxa_exception__deps: ['$Emval', '__cxa_rethrow', | |
| #if !DISABLE_EXCEPTION_THROWING || WASM_EXCEPTIONS | |
| '$decrementUncaughtExceptionCount', | |
| #endif | |
| #if !DISABLE_EXCEPTION_CATCHING || WASM_EXCEPTIONS | |
| '$decrementExceptionRefcount', | |
| '$emval_exception_decrefs', | |
| #endif | |
| ], | |
| _emval_from_current_cxa_exception: () => { | |
| try { | |
| // Use __cxa_rethrow which already has mechanism for generating | |
| // user-friendly error message and stacktrace from C++ exception | |
| // if EXCEPTION_STACK_TRACES is enabled and numeric exception | |
| // with metadata optimised out otherwise. | |
| ___cxa_rethrow(); | |
| } catch (e) { | |
| #if !DISABLE_EXCEPTION_THROWING || WASM_EXCEPTIONS | |
| // ___cxa_rethrow incremented uncaughtExceptionCount. | |
| // Since we caught it in JS, we need to manually decrement it to balance. | |
| decrementUncaughtExceptionCount(); | |
| #endif | |
| var handle = Emval.toHandle(e); | |
| #if !DISABLE_EXCEPTION_CATCHING || WASM_EXCEPTIONS | |
| emval_exception_decrefs[handle] = decrementExceptionRefcount; | |
| #endif | |
| return handle; | |
| } | |
| }, | |
| }; | |
| addToLibrary(LibraryEmVal); | |
Xet Storage Details
- Size:
- 17.2 kB
- Xet hash:
- d349be62231dcb9fbd095834449dd6e7b04fa2fb9958b6c8280bbe33aecbe773
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.