зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1615066 - Add support for new profiler-get-symbols version which supports partial file reading. r=canaltinova
Differential Revision: https://phabricator.services.mozilla.com/D117938
This commit is contained in:
Родитель
a2997cb1c6
Коммит
124dd3228f
|
@ -544,3 +544,16 @@ export type SymbolicationWorkerReplyData<R> =
|
|||
| {
|
||||
error: SymbolicationWorkerError;
|
||||
};
|
||||
|
||||
// This type is used in the symbolication worker for the return type of the
|
||||
// FileAndPathHelper's readFile method.
|
||||
// FIXME: Or rather, this type *would* be used if the worker code was checked
|
||||
// by TypeScript.
|
||||
export interface FileHandle {
|
||||
// Return the length of the file in bytes.
|
||||
getLength: () => number;
|
||||
// Synchronously read the bytes at offset `offset` into the array `dest`.
|
||||
readBytesInto: (dest: Uint8Array, offset: number) => void;
|
||||
// Called when the file is no longer needed, to allow closing the file.
|
||||
drop: () => void;
|
||||
}
|
||||
|
|
|
@ -6,213 +6,32 @@
|
|||
// THIS FILE IS AUTOGENERATED by wasm-bindgen.
|
||||
//
|
||||
// Generated from:
|
||||
// https://github.com/mstange/profiler-get-symbols/commit/90ee39f1d18d2727f07dc57bd93cff6bc73ce8a0
|
||||
// https://github.com/mstange/profiler-get-symbols/commit/c1dca28a2a506df40f0a6f32c12ba51ec54b02be
|
||||
// by following the instructions in that repository's Readme.md
|
||||
//
|
||||
|
||||
let wasm_bindgen;
|
||||
(function() {
|
||||
const __exports = {};
|
||||
let wasm;
|
||||
|
||||
let cachegetInt32Memory = null;
|
||||
function getInt32Memory() {
|
||||
if (cachegetInt32Memory === null || cachegetInt32Memory.buffer !== wasm.memory.buffer) {
|
||||
cachegetInt32Memory = new Int32Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetInt32Memory;
|
||||
}
|
||||
|
||||
let cachegetUint32Memory = null;
|
||||
function getUint32Memory() {
|
||||
if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== wasm.memory.buffer) {
|
||||
cachegetUint32Memory = new Uint32Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetUint32Memory;
|
||||
}
|
||||
|
||||
function getArrayU32FromWasm(ptr, len) {
|
||||
return getUint32Memory().subarray(ptr / 4, ptr / 4 + len);
|
||||
}
|
||||
|
||||
let cachegetUint8Memory = null;
|
||||
function getUint8Memory() {
|
||||
if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== wasm.memory.buffer) {
|
||||
cachegetUint8Memory = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetUint8Memory;
|
||||
}
|
||||
|
||||
function getArrayU8FromWasm(ptr, len) {
|
||||
return getUint8Memory().subarray(ptr / 1, ptr / 1 + len);
|
||||
}
|
||||
|
||||
const heap = new Array(32);
|
||||
|
||||
heap.fill(undefined);
|
||||
const heap = new Array(32).fill(undefined);
|
||||
|
||||
heap.push(undefined, null, true, false);
|
||||
|
||||
let stack_pointer = 32;
|
||||
|
||||
function addBorrowedObject(obj) {
|
||||
if (stack_pointer == 1) throw new Error('out of js stack');
|
||||
heap[--stack_pointer] = obj;
|
||||
return stack_pointer;
|
||||
}
|
||||
|
||||
function _assertClass(instance, klass) {
|
||||
if (!(instance instanceof klass)) {
|
||||
throw new Error(`expected instance of ${klass.name}`);
|
||||
}
|
||||
return instance.ptr;
|
||||
}
|
||||
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
let cachedTextEncoder = new TextEncoder('utf-8');
|
||||
|
||||
let passStringToWasm;
|
||||
if (typeof cachedTextEncoder.encodeInto === 'function') {
|
||||
passStringToWasm = function(arg) {
|
||||
|
||||
|
||||
let size = arg.length;
|
||||
let ptr = wasm.__wbindgen_malloc(size);
|
||||
let offset = 0;
|
||||
{
|
||||
const mem = getUint8Memory();
|
||||
for (; offset < arg.length; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset !== arg.length) {
|
||||
arg = arg.slice(offset);
|
||||
ptr = wasm.__wbindgen_realloc(ptr, size, size = offset + arg.length * 3);
|
||||
const view = getUint8Memory().subarray(ptr + offset, ptr + size);
|
||||
const ret = cachedTextEncoder.encodeInto(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
}
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
};
|
||||
} else {
|
||||
passStringToWasm = function(arg) {
|
||||
|
||||
|
||||
let size = arg.length;
|
||||
let ptr = wasm.__wbindgen_malloc(size);
|
||||
let offset = 0;
|
||||
{
|
||||
const mem = getUint8Memory();
|
||||
for (; offset < arg.length; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset !== arg.length) {
|
||||
const buf = cachedTextEncoder.encode(arg.slice(offset));
|
||||
ptr = wasm.__wbindgen_realloc(ptr, size, size = offset + buf.length);
|
||||
getUint8Memory().set(buf, ptr + offset);
|
||||
offset += buf.length;
|
||||
}
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @param {WasmMemBuffer} binary_data
|
||||
* @param {WasmMemBuffer} debug_data
|
||||
* @param {string} breakpad_id
|
||||
* @returns {CompactSymbolTable}
|
||||
*/
|
||||
__exports.get_compact_symbol_table = function(binary_data, debug_data, breakpad_id) {
|
||||
_assertClass(binary_data, WasmMemBuffer);
|
||||
_assertClass(debug_data, WasmMemBuffer);
|
||||
const ret = wasm.get_compact_symbol_table(binary_data.ptr, debug_data.ptr, passStringToWasm(breakpad_id), WASM_VECTOR_LEN);
|
||||
return CompactSymbolTable.__wrap(ret);
|
||||
};
|
||||
|
||||
function getObject(idx) { return heap[idx]; }
|
||||
|
||||
function debugString(val) {
|
||||
// primitive types
|
||||
const type = typeof val;
|
||||
if (type == 'number' || type == 'boolean' || val == null) {
|
||||
return `${val}`;
|
||||
}
|
||||
if (type == 'string') {
|
||||
return `"${val}"`;
|
||||
}
|
||||
if (type == 'symbol') {
|
||||
const description = val.description;
|
||||
if (description == null) {
|
||||
return 'Symbol';
|
||||
} else {
|
||||
return `Symbol(${description})`;
|
||||
}
|
||||
}
|
||||
if (type == 'function') {
|
||||
const name = val.name;
|
||||
if (typeof name == 'string' && name.length > 0) {
|
||||
return `Function(${name})`;
|
||||
} else {
|
||||
return 'Function';
|
||||
}
|
||||
}
|
||||
// objects
|
||||
if (Array.isArray(val)) {
|
||||
const length = val.length;
|
||||
let debug = '[';
|
||||
if (length > 0) {
|
||||
debug += debugString(val[0]);
|
||||
}
|
||||
for(let i = 1; i < length; i++) {
|
||||
debug += ', ' + debugString(val[i]);
|
||||
}
|
||||
debug += ']';
|
||||
return debug;
|
||||
}
|
||||
// Test for built-in
|
||||
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
||||
let className;
|
||||
if (builtInMatches.length > 1) {
|
||||
className = builtInMatches[1];
|
||||
} else {
|
||||
// Failed to match the standard '[object ClassName]'
|
||||
return toString.call(val);
|
||||
}
|
||||
if (className == 'Object') {
|
||||
// we're a user defined class or Object
|
||||
// JSON.stringify avoids problems with cycles, and is generally much
|
||||
// easier than looping through ownProperties of `val`.
|
||||
try {
|
||||
return 'Object(' + JSON.stringify(val) + ')';
|
||||
} catch (_) {
|
||||
return 'Object';
|
||||
}
|
||||
}
|
||||
// errors
|
||||
if (val instanceof Error) {
|
||||
return `${val.name}: ${val.message}\n${val.stack}`;
|
||||
}
|
||||
// TODO we could test for more things here, like `Set`s and `Map`s.
|
||||
return className;
|
||||
}
|
||||
|
||||
let cachedTextDecoder = new TextDecoder('utf-8');
|
||||
|
||||
function getStringFromWasm(ptr, len) {
|
||||
return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));
|
||||
}
|
||||
|
||||
let heap_next = heap.length;
|
||||
|
||||
function addHeapObject(obj) {
|
||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||
const idx = heap_next;
|
||||
heap_next = heap[idx];
|
||||
|
||||
heap[idx] = obj;
|
||||
return idx;
|
||||
}
|
||||
|
||||
function dropObject(idx) {
|
||||
if (idx < 36) return;
|
||||
heap[idx] = heap_next;
|
||||
|
@ -225,202 +44,413 @@ function takeObject(idx) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
function addHeapObject(obj) {
|
||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||
const idx = heap_next;
|
||||
heap_next = heap[idx];
|
||||
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||
|
||||
heap[idx] = obj;
|
||||
return idx;
|
||||
cachedTextDecoder.decode();
|
||||
|
||||
let cachegetUint8Memory0 = null;
|
||||
function getUint8Memory0() {
|
||||
if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
|
||||
cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetUint8Memory0;
|
||||
}
|
||||
|
||||
function handleError(e) {
|
||||
wasm.__wbindgen_exn_store(addHeapObject(e));
|
||||
function getStringFromWasm0(ptr, len) {
|
||||
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
|
||||
}
|
||||
/**
|
||||
*/
|
||||
class CompactSymbolTable {
|
||||
|
||||
static __wrap(ptr) {
|
||||
const obj = Object.create(CompactSymbolTable.prototype);
|
||||
obj.ptr = ptr;
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
return obj;
|
||||
}
|
||||
let cachedTextEncoder = new TextEncoder('utf-8');
|
||||
|
||||
free() {
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
|
||||
wasm.__wbg_compactsymboltable_free(ptr);
|
||||
}
|
||||
/**
|
||||
* @returns {CompactSymbolTable}
|
||||
*/
|
||||
constructor() {
|
||||
const ret = wasm.compactsymboltable_new();
|
||||
return CompactSymbolTable.__wrap(ret);
|
||||
}
|
||||
/**
|
||||
* @returns {Uint32Array}
|
||||
*/
|
||||
take_addr() {
|
||||
const retptr = 8;
|
||||
const ret = wasm.compactsymboltable_take_addr(retptr, this.ptr);
|
||||
const memi32 = getInt32Memory();
|
||||
const v0 = getArrayU32FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
|
||||
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 4);
|
||||
return v0;
|
||||
}
|
||||
/**
|
||||
* @returns {Uint32Array}
|
||||
*/
|
||||
take_index() {
|
||||
const retptr = 8;
|
||||
const ret = wasm.compactsymboltable_take_index(retptr, this.ptr);
|
||||
const memi32 = getInt32Memory();
|
||||
const v0 = getArrayU32FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
|
||||
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 4);
|
||||
return v0;
|
||||
}
|
||||
/**
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
take_buffer() {
|
||||
const retptr = 8;
|
||||
const ret = wasm.compactsymboltable_take_buffer(retptr, this.ptr);
|
||||
const memi32 = getInt32Memory();
|
||||
const v0 = getArrayU8FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
|
||||
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 1);
|
||||
return v0;
|
||||
}
|
||||
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
||||
? function (arg, view) {
|
||||
return cachedTextEncoder.encodeInto(arg, view);
|
||||
}
|
||||
__exports.CompactSymbolTable = CompactSymbolTable;
|
||||
/**
|
||||
* WasmMemBuffer lets you allocate a chunk of memory on the wasm heap and
|
||||
* directly initialize it from JS without a copy. The constructor takes the
|
||||
* allocation size and a callback function which does the initialization.
|
||||
* This is useful if you need to get very large amounts of data from JS into
|
||||
* wasm (for example, the contents of a 1.7GB libxul.so).
|
||||
*/
|
||||
class WasmMemBuffer {
|
||||
: function (arg, view) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
view.set(buf);
|
||||
return {
|
||||
read: arg.length,
|
||||
written: buf.length
|
||||
};
|
||||
});
|
||||
|
||||
static __wrap(ptr) {
|
||||
const obj = Object.create(WasmMemBuffer.prototype);
|
||||
obj.ptr = ptr;
|
||||
function passStringToWasm0(arg, malloc, realloc) {
|
||||
|
||||
return obj;
|
||||
if (realloc === undefined) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
const ptr = malloc(buf.length);
|
||||
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||
WASM_VECTOR_LEN = buf.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
free() {
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
let len = arg.length;
|
||||
let ptr = malloc(len);
|
||||
|
||||
wasm.__wbg_wasmmembuffer_free(ptr);
|
||||
const mem = getUint8Memory0();
|
||||
|
||||
let offset = 0;
|
||||
|
||||
for (; offset < len; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
/**
|
||||
* Create the buffer and initialize it synchronously in the callback function.
|
||||
* f is called with one argument: the Uint8Array that wraps our buffer.
|
||||
* f should not return anything; its return value is ignored.
|
||||
* f must not call any exported wasm functions! Anything that causes the
|
||||
* wasm heap to resize will invalidate the typed array\'s internal buffer!
|
||||
* Do not hold on to the array that is passed to f after f completes.
|
||||
* @param {number} byte_length
|
||||
* @param {any} f
|
||||
* @returns {WasmMemBuffer}
|
||||
*/
|
||||
constructor(byte_length, f) {
|
||||
|
||||
if (offset !== len) {
|
||||
if (offset !== 0) {
|
||||
arg = arg.slice(offset);
|
||||
}
|
||||
ptr = realloc(ptr, len, len = offset + arg.length * 3);
|
||||
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
|
||||
const ret = encodeString(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
}
|
||||
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function isLikeNone(x) {
|
||||
return x === undefined || x === null;
|
||||
}
|
||||
|
||||
let cachegetInt32Memory0 = null;
|
||||
function getInt32Memory0() {
|
||||
if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
|
||||
cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetInt32Memory0;
|
||||
}
|
||||
|
||||
function makeMutClosure(arg0, arg1, dtor, f) {
|
||||
const state = { a: arg0, b: arg1, cnt: 1, dtor };
|
||||
const real = (...args) => {
|
||||
// First up with a closure we increment the internal reference
|
||||
// count. This ensures that the Rust closure environment won't
|
||||
// be deallocated while we're invoking it.
|
||||
state.cnt++;
|
||||
const a = state.a;
|
||||
state.a = 0;
|
||||
try {
|
||||
const ret = wasm.wasmmembuffer_new(byte_length, addBorrowedObject(f));
|
||||
return WasmMemBuffer.__wrap(ret);
|
||||
return f(a, state.b, ...args);
|
||||
} finally {
|
||||
heap[stack_pointer++] = undefined;
|
||||
if (--state.cnt === 0) {
|
||||
wasm.__wbindgen_export_2.get(state.dtor)(a, state.b);
|
||||
|
||||
} else {
|
||||
state.a = a;
|
||||
}
|
||||
}
|
||||
};
|
||||
real.original = state;
|
||||
|
||||
return real;
|
||||
}
|
||||
function __wbg_adapter_18(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h0f6e06591fd1eecd(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function handleError(f, args) {
|
||||
try {
|
||||
return f.apply(this, args);
|
||||
} catch (e) {
|
||||
wasm.__wbindgen_exn_store(addHeapObject(e));
|
||||
}
|
||||
}
|
||||
function __wbg_adapter_33(arg0, arg1, arg2, arg3) {
|
||||
wasm.wasm_bindgen__convert__closures__invoke2_mut__hb11591fa7d9b8977(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* ```js
|
||||
* async function getSymbolTable(debugName, breakpadId, libKeyToPathMap) {
|
||||
* const helper = {
|
||||
* getCandidatePathsForBinaryOrPdb: (debugName, breakpadId) => {
|
||||
* const path = libKeyToPathMap.get(`${debugName}/${breakpadId}`);
|
||||
* if (path !== undefined) {
|
||||
* return [path];
|
||||
* }
|
||||
* return [];
|
||||
* },
|
||||
* readFile: async (filename) => {
|
||||
* const byteLength = await getFileSizeInBytes(filename);
|
||||
* const fileHandle = getFileHandle(filename);
|
||||
* return {
|
||||
* getLength: () => byteLength,
|
||||
* readBytesInto: (array, offset) => {
|
||||
* syncReadFilePartIntoBuffer(fileHandle, array, offset);
|
||||
* },
|
||||
* drop: () => {},
|
||||
* };
|
||||
* },
|
||||
* };
|
||||
*
|
||||
* const [addr, index, buffer] = await getCompactSymbolTable(debugName, breakpadId, helper);
|
||||
* return [addr, index, buffer];
|
||||
* }
|
||||
* ```
|
||||
* @param {string} debug_name
|
||||
* @param {string} breakpad_id
|
||||
* @param {any} helper
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
__exports.getCompactSymbolTable = function(debug_name, breakpad_id, helper) {
|
||||
var ptr0 = passStringToWasm0(debug_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
var ptr1 = passStringToWasm0(breakpad_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len1 = WASM_VECTOR_LEN;
|
||||
var ret = wasm.getCompactSymbolTable(ptr0, len0, ptr1, len1, addHeapObject(helper));
|
||||
return takeObject(ret);
|
||||
};
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* ```js
|
||||
* async function getSymbolTable(url, requestJSONString, libKeyToPathMap) {
|
||||
* const helper = {
|
||||
* getCandidatePathsForBinaryOrPdb: (debugName, breakpadId) => {
|
||||
* const path = libKeyToPathMap.get(`${debugName}/${breakpadId}`);
|
||||
* if (path !== undefined) {
|
||||
* return [path];
|
||||
* }
|
||||
* return [];
|
||||
* },
|
||||
* readFile: async (filename) => {
|
||||
* const byteLength = await getFileSizeInBytes(filename);
|
||||
* const fileHandle = getFileHandle(filename);
|
||||
* return {
|
||||
* getLength: () => byteLength,
|
||||
* readBytesInto: (array, offset) => {
|
||||
* syncReadFilePartIntoBuffer(fileHandle, array, offset);
|
||||
* },
|
||||
* drop: () => {},
|
||||
* };
|
||||
* },
|
||||
* };
|
||||
*
|
||||
* const responseJSONString = await queryAPI(deburlugName, requestJSONString, helper);
|
||||
* return responseJSONString;
|
||||
* }
|
||||
* ```
|
||||
* @param {string} url
|
||||
* @param {string} request_json
|
||||
* @param {any} helper
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
__exports.queryAPI = function(url, request_json, helper) {
|
||||
var ptr0 = passStringToWasm0(url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
var ptr1 = passStringToWasm0(request_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len1 = WASM_VECTOR_LEN;
|
||||
var ret = wasm.queryAPI(ptr0, len0, ptr1, len1, addHeapObject(helper));
|
||||
return takeObject(ret);
|
||||
};
|
||||
|
||||
async function load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
|
||||
} catch (e) {
|
||||
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bytes = await module.arrayBuffer();
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
|
||||
} else {
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
return { instance, module };
|
||||
|
||||
} else {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
__exports.WasmMemBuffer = WasmMemBuffer;
|
||||
|
||||
function init(module) {
|
||||
|
||||
let result;
|
||||
async function init(input) {
|
||||
if (typeof input === 'undefined') {
|
||||
let src;
|
||||
if (typeof document === 'undefined') {
|
||||
src = location.href;
|
||||
} else {
|
||||
src = document.currentScript.src;
|
||||
}
|
||||
input = src.replace(/\.js$/, '_bg.wasm');
|
||||
}
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||
const ret = debugString(getObject(arg1));
|
||||
const ret0 = passStringToWasm(ret);
|
||||
const ret1 = WASM_VECTOR_LEN;
|
||||
getInt32Memory()[arg0 / 4 + 0] = ret0;
|
||||
getInt32Memory()[arg0 / 4 + 1] = ret1;
|
||||
};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm(arg0, arg1));
|
||||
};
|
||||
imports.wbg.__wbindgen_rethrow = function(arg0) {
|
||||
throw takeObject(arg0);
|
||||
};
|
||||
imports.wbg.__wbindgen_memory = function() {
|
||||
const ret = wasm.memory;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_buffer_aa8ebea80955a01a = function(arg0) {
|
||||
const ret = getObject(arg0).buffer;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_newwithbyteoffsetandlength_3e607c21646a8aef = function(arg0, arg1, arg2) {
|
||||
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
|
||||
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
|
||||
var ret = getObject(arg0);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_drop_6095f5f9a28379e4 = function() { return handleError(function (arg0) {
|
||||
getObject(arg0).drop();
|
||||
}, arguments) };
|
||||
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
||||
takeObject(arg0);
|
||||
};
|
||||
imports.wbg.__wbg_call_9c879b23724d007e = function(arg0, arg1, arg2) {
|
||||
try {
|
||||
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
|
||||
imports.wbg.__wbg_call_3fc07b7d5fc9022d = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
var ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
|
||||
return addHeapObject(ret);
|
||||
} catch (e) {
|
||||
handleError(e)
|
||||
}, arguments) };
|
||||
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
||||
var ret = getStringFromWasm0(arg0, arg1);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_readFile_1005cc171b90cf75 = function(arg0, arg1, arg2) {
|
||||
var ret = getObject(arg0).readFile(getStringFromWasm0(arg1, arg2));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_then_6c9a4bf55755f9b8 = function(arg0, arg1, arg2) {
|
||||
var ret = getObject(arg0).then(getObject(arg1), getObject(arg2));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_cb_drop = function(arg0) {
|
||||
const obj = takeObject(arg0).original;
|
||||
if (obj.cnt-- == 1) {
|
||||
obj.a = 0;
|
||||
return true;
|
||||
}
|
||||
var ret = false;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_getLength_83c461bbda972f3b = function() { return handleError(function (arg0) {
|
||||
var ret = getObject(arg0).getLength();
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_name_966f168ad0e59c92 = function(arg0) {
|
||||
var ret = getObject(arg0).name;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_message_e440fbd911a845a2 = function(arg0) {
|
||||
var ret = getObject(arg0).message;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_memory = function() {
|
||||
var ret = wasm.memory;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_buffer_9e184d6f785de5ed = function(arg0) {
|
||||
var ret = getObject(arg0).buffer;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_newwithbyteoffsetandlength_d92dfdd78c30c55a = function(arg0, arg1, arg2) {
|
||||
var ret = new Uint32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_new_71de2365d17503e7 = function(arg0) {
|
||||
var ret = new Uint32Array(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_newwithbyteoffsetandlength_e57ad1f2ce812c03 = function(arg0, arg1, arg2) {
|
||||
var ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_new_e8101319e4cf95fc = function(arg0) {
|
||||
var ret = new Uint8Array(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_of_7c797480f9ceac60 = function(arg0, arg1, arg2) {
|
||||
var ret = Array.of(getObject(arg0), getObject(arg1), getObject(arg2));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_json_parse = function(arg0, arg1) {
|
||||
const ret = JSON.parse(getStringFromWasm(arg0, arg1));
|
||||
var ret = JSON.parse(getStringFromWasm0(arg0, arg1));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_readBytesInto_02ee0cacc563822d = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
getObject(arg0).readBytesInto(takeObject(arg1), arg2);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_getCandidatePathsForBinaryOrPdb_6ff1ea4b13b7cbee = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
||||
var ret = getObject(arg0).getCandidatePathsForBinaryOrPdb(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_from_f4f6c9225e58242f = function(arg0) {
|
||||
var ret = Array.from(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_length_555f836564bf148d = function(arg0) {
|
||||
var ret = getObject(arg0).length;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_get_b7bbf50adcc94294 = function(arg0, arg1) {
|
||||
var ret = getObject(arg0)[arg1 >>> 0];
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_new_c143a4f563f78c4e = function(arg0, arg1) {
|
||||
try {
|
||||
var state0 = {a: arg0, b: arg1};
|
||||
var cb0 = (arg0, arg1) => {
|
||||
const a = state0.a;
|
||||
state0.a = 0;
|
||||
try {
|
||||
return __wbg_adapter_33(a, state0.b, arg0, arg1);
|
||||
} finally {
|
||||
state0.a = a;
|
||||
}
|
||||
};
|
||||
var ret = new Promise(cb0);
|
||||
return addHeapObject(ret);
|
||||
} finally {
|
||||
state0.a = state0.b = 0;
|
||||
}
|
||||
};
|
||||
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
|
||||
const obj = getObject(arg1);
|
||||
var ret = typeof(obj) === 'string' ? obj : undefined;
|
||||
var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
getInt32Memory0()[arg0 / 4 + 1] = len0;
|
||||
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
|
||||
};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
imports.wbg.__wbg_then_c2361a9d5c9a4fcb = function(arg0, arg1) {
|
||||
var ret = getObject(arg0).then(getObject(arg1));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_resolve_cae3d8f752f5db88 = function(arg0) {
|
||||
var ret = Promise.resolve(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper230 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 70, __wbg_adapter_18);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
|
||||
if (module instanceof URL || typeof module === 'string' || module instanceof Request) {
|
||||
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
||||
input = fetch(input);
|
||||
}
|
||||
|
||||
const response = fetch(module);
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
result = WebAssembly.instantiateStreaming(response, imports)
|
||||
.catch(e => {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
return response
|
||||
.then(r => r.arrayBuffer())
|
||||
.then(bytes => WebAssembly.instantiate(bytes, imports));
|
||||
});
|
||||
} else {
|
||||
result = response
|
||||
.then(r => r.arrayBuffer())
|
||||
.then(bytes => WebAssembly.instantiate(bytes, imports));
|
||||
}
|
||||
} else {
|
||||
|
||||
result = WebAssembly.instantiate(module, imports)
|
||||
.then(result => {
|
||||
if (result instanceof WebAssembly.Instance) {
|
||||
return { instance: result, module };
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
return result.then(({instance, module}) => {
|
||||
|
||||
const { instance, module } = await load(await input, imports);
|
||||
|
||||
wasm = instance.exports;
|
||||
init.__wbindgen_wasm_module = module;
|
||||
|
||||
return wasm;
|
||||
});
|
||||
}
|
||||
|
||||
self.wasm_bindgen = Object.assign(init, __exports);
|
||||
wasm_bindgen = Object.assign(init, __exports);
|
||||
|
||||
})();
|
||||
|
|
|
@ -19,6 +19,7 @@ importScripts(
|
|||
|
||||
/**
|
||||
* @typedef {import("./@types/perf").SymbolicationWorkerInitialMessage} SymbolicationWorkerInitialMessage
|
||||
* @typedef {import("./@types/perf").FileHandle} FileHandle
|
||||
*/
|
||||
|
||||
// This worker uses the wasm module that was generated from https://github.com/mstange/profiler-get-symbols.
|
||||
|
@ -29,60 +30,55 @@ importScripts(
|
|||
// itself.
|
||||
|
||||
/* eslint camelcase: 0*/
|
||||
const { WasmMemBuffer, get_compact_symbol_table } = wasm_bindgen;
|
||||
const { getCompactSymbolTable } = wasm_bindgen;
|
||||
|
||||
// Read an open OS.File instance into the Uint8Array dataBuf.
|
||||
function readFileInto(file, dataBuf) {
|
||||
// Ideally we'd be able to call file.readTo(dataBuf) here, but readTo no
|
||||
// longer exists.
|
||||
// So instead, we copy the file over into wasm memory in 4MB chunks. This
|
||||
// will take 425 invocations for a a 1.7GB file (such as libxul.so for a
|
||||
// Firefox for Android build) and not take up too much memory per call.
|
||||
const dataBufLen = dataBuf.byteLength;
|
||||
// Read parts of an open OS.File instance into the Uint8Array dataBuf.
|
||||
// This reads destBuf.byteLength bytes at offset offset.
|
||||
function readFileBytesInto(file, offset, destBuf) {
|
||||
file.setPosition(offset);
|
||||
// We read the file in 4MB chunks. This limits the amount of temporary
|
||||
// memory we use while we copy the file contents into wasm memory.
|
||||
const chunkSize = 4 * 1024 * 1024;
|
||||
let pos = 0;
|
||||
while (pos < dataBufLen) {
|
||||
const chunkData = file.read({ bytes: chunkSize });
|
||||
let posInDestBuf = 0;
|
||||
let remainingBytes = destBuf.byteLength;
|
||||
while (remainingBytes > 0) {
|
||||
const bytes = remainingBytes > chunkSize ? chunkSize : remainingBytes;
|
||||
const chunkData = file.read({ bytes });
|
||||
const chunkBytes = chunkData.byteLength;
|
||||
if (chunkBytes === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
dataBuf.set(chunkData, pos);
|
||||
pos += chunkBytes;
|
||||
destBuf.set(chunkData, posInDestBuf);
|
||||
posInDestBuf += chunkBytes;
|
||||
remainingBytes -= chunkBytes;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a plain object that is Structured Cloneable and has name and
|
||||
// description properties.
|
||||
// message properties.
|
||||
function createPlainErrorObject(e) {
|
||||
if (e instanceof OS.File.Error) {
|
||||
// OS.File.Error has an empty message property; it constructs the error
|
||||
// message on-demand in its toString() method. So we handle those errors
|
||||
// specially.
|
||||
if (!(e instanceof OS.File.Error)) {
|
||||
// Regular errors: just rewrap the object.
|
||||
if (e instanceof Error) {
|
||||
const { name, message, fileName, lineNumber } = e;
|
||||
return { name, message, fileName, lineNumber };
|
||||
}
|
||||
// The WebAssembly code throws errors with fields error_type and error_msg.
|
||||
if (e.error_type) {
|
||||
return {
|
||||
name: e.error_type,
|
||||
message: e.error_msg,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: e instanceof OS.File.Error ? "OSFileError" : "Error",
|
||||
name: "OSFileError",
|
||||
message: e.toString(),
|
||||
fileName: e.fileName,
|
||||
lineNumber: e.lineNumber,
|
||||
};
|
||||
}
|
||||
// Regular errors: just rewrap the object.
|
||||
const { name, message, fileName, lineNumber } = e;
|
||||
return { name, message, fileName, lineNumber };
|
||||
}
|
||||
|
||||
class PathHelper {
|
||||
/**
|
||||
* A FileAndPathHelper object is passed to getCompactSymbolTable, which calls
|
||||
* the methods `getCandidatePathsForBinaryOrPdb` and `readFile` on it.
|
||||
*/
|
||||
class FileAndPathHelper {
|
||||
constructor(libInfoMap, objdirs) {
|
||||
this._libInfoMap = libInfoMap;
|
||||
this._objdirs = objdirs;
|
||||
|
@ -90,12 +86,13 @@ class PathHelper {
|
|||
|
||||
/**
|
||||
* Enumerate all paths at which we could find files with symbol information.
|
||||
* This method is called by wasm code (via the bindings).
|
||||
*
|
||||
* @param {string} debugName
|
||||
* @param {string} breakpadId
|
||||
* @returns {Array<{ path: string, debugPath: string }>}
|
||||
* @returns {Array<string>}
|
||||
*/
|
||||
getCandidatePaths(debugName, breakpadId) {
|
||||
getCandidatePathsForBinaryOrPdb(debugName, breakpadId) {
|
||||
const key = `${debugName}:${breakpadId}`;
|
||||
const lib = this._libInfoMap.get(key);
|
||||
if (!lib) {
|
||||
|
@ -121,89 +118,64 @@ class PathHelper {
|
|||
// a system library.
|
||||
for (const objdirPath of this._objdirs) {
|
||||
// Binaries are usually expected to exist at objdir/dist/bin/filename.
|
||||
candidatePaths.push({
|
||||
path: OS.Path.join(objdirPath, "dist", "bin", name),
|
||||
debugPath: OS.Path.join(objdirPath, "dist", "bin", name),
|
||||
});
|
||||
candidatePaths.push(OS.Path.join(objdirPath, "dist", "bin", name));
|
||||
// Also search in the "objdir" directory itself (not just in dist/bin).
|
||||
// If, for some unforeseen reason, the relevant binary is not inside the
|
||||
// objdirs dist/bin/ directory, this provides a way out because it lets the
|
||||
// user specify the actual location.
|
||||
candidatePaths.push({
|
||||
path: OS.Path.join(objdirPath, name),
|
||||
debugPath: OS.Path.join(objdirPath, name),
|
||||
});
|
||||
candidatePaths.push(OS.Path.join(objdirPath, name));
|
||||
}
|
||||
|
||||
// Check the absolute paths of the library file(s) last.
|
||||
// Check the absolute paths of the library last.
|
||||
// We do this after the objdir search because the library's path may point
|
||||
// to a stripped binary, which will have fewer symbols than the original
|
||||
// binaries in the objdir.
|
||||
candidatePaths.push({ path, debugPath });
|
||||
if (debugPath !== path) {
|
||||
// We're on Windows, and debugPath points to a PDB file.
|
||||
// On non-Windows, path and debugPath are always the same.
|
||||
|
||||
// Check the PDB file before the binary because the PDB has the symbol
|
||||
// information. The binary is only used as a last-ditch fallback
|
||||
// for things like Windows system libraries (e.g. graphics drivers).
|
||||
candidatePaths.push(debugPath);
|
||||
}
|
||||
|
||||
// The location of the binary. If the profile was obtained on this machine
|
||||
// (and not, for example, on an Android device), this file should always
|
||||
// exist.
|
||||
candidatePaths.push(path);
|
||||
|
||||
return candidatePaths;
|
||||
}
|
||||
}
|
||||
|
||||
function getCompactSymbolTableFromPath(binaryPath, debugPath, breakpadId) {
|
||||
// Read the binary file into WASM memory.
|
||||
const binaryFile = OS.File.open(binaryPath, { read: true });
|
||||
const binaryData = new WasmMemBuffer(binaryFile.stat().size, array => {
|
||||
readFileInto(binaryFile, array);
|
||||
});
|
||||
binaryFile.close();
|
||||
|
||||
// Do the same for the debug file, if it is supplied and different from the
|
||||
// binary file. This is only the case on Windows.
|
||||
let debugData = binaryData;
|
||||
if (debugPath && debugPath !== binaryPath) {
|
||||
const debugFile = OS.File.open(debugPath, { read: true });
|
||||
debugData = new WasmMemBuffer(debugFile.stat().size, array => {
|
||||
readFileInto(debugFile, array);
|
||||
});
|
||||
debugFile.close();
|
||||
/**
|
||||
* Asynchronously prepare the file at `path` for synchronous reading.
|
||||
* This method is called by wasm code (via the bindings).
|
||||
*
|
||||
* @param {string} path
|
||||
* @returns {FileHandle}
|
||||
*/
|
||||
async readFile(path) {
|
||||
const file = OS.File.open(path, { read: true });
|
||||
const info = file.stat();
|
||||
if (info.isDir) {
|
||||
throw new Error(`Path "${path}" is a directory.`);
|
||||
}
|
||||
|
||||
try {
|
||||
const output = get_compact_symbol_table(binaryData, debugData, breakpadId);
|
||||
const result = [
|
||||
output.take_addr(),
|
||||
output.take_index(),
|
||||
output.take_buffer(),
|
||||
];
|
||||
output.free();
|
||||
return result;
|
||||
} finally {
|
||||
binaryData.free();
|
||||
if (debugData != binaryData) {
|
||||
debugData.free();
|
||||
}
|
||||
}
|
||||
}
|
||||
const fileSize = info.size;
|
||||
|
||||
function getSymbolTableInWorker(debugName, breakpadId, libInfoMap, objdirs) {
|
||||
const helper = new PathHelper(libInfoMap, objdirs);
|
||||
const candidatePaths = helper.getCandidatePaths(debugName, breakpadId);
|
||||
|
||||
const errors = [];
|
||||
for (const { path, debugPath } of candidatePaths) {
|
||||
try {
|
||||
return getCompactSymbolTableFromPath(path, debugPath, breakpadId);
|
||||
} catch (e) {
|
||||
// getCompactSymbolTableFromPath was unsuccessful. So either the
|
||||
// file wasn't parseable or its contents didn't match the specified
|
||||
// breakpadId, or some other error occurred.
|
||||
// Advance to the next candidate path.
|
||||
errors.push(e);
|
||||
// Create and return a FileHandle object. The methods of this object are
|
||||
// called by wasm code (via the bindings).
|
||||
return {
|
||||
getLength: () => fileSize,
|
||||
readBytesInto: (dest, offset) => {
|
||||
readFileBytesInto(file, offset, dest);
|
||||
},
|
||||
drop: () => {
|
||||
file.close();
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Could not obtain symbols for the library ${debugName} ${breakpadId} ` +
|
||||
`because there was no matching file at any of the candidate paths: ${JSON.stringify(
|
||||
candidatePaths
|
||||
)}. Errors: ${errors.map(e => e.message).join(", ")}`
|
||||
);
|
||||
}
|
||||
|
||||
/** @param {MessageEvent<SymbolicationWorkerInitialMessage>} e */
|
||||
|
@ -218,12 +190,8 @@ onmessage = async e => {
|
|||
// Instantiate the WASM module.
|
||||
await wasm_bindgen(module);
|
||||
|
||||
const result = getSymbolTableInWorker(
|
||||
debugName,
|
||||
breakpadId,
|
||||
libInfoMap,
|
||||
objdirs
|
||||
);
|
||||
const helper = new FileAndPathHelper(libInfoMap, objdirs);
|
||||
const result = await getCompactSymbolTable(debugName, breakpadId, helper);
|
||||
postMessage(
|
||||
{ result },
|
||||
result.map(r => r.buffer)
|
||||
|
|
|
@ -45,12 +45,15 @@ const global = this;
|
|||
// The hash check ensures that the contents of the wasm module are what we
|
||||
// expect them to be.
|
||||
// The source code is at https://github.com/mstange/profiler-get-symbols/ .
|
||||
// Documentation is at https://docs.rs/profiler-get-symbols/ .
|
||||
// The sha384 sum can be computed with the following command (tested on macOS):
|
||||
// shasum -b -a 384 profiler_get_symbols_wasm_bg.wasm | awk '{ print $1 }' | xxd -r -p | base64
|
||||
|
||||
// Generated from https://github.com/mstange/profiler-get-symbols/commit/90ee39f1d18d2727f07dc57bd93cff6bc73ce8a0
|
||||
// Generated from https://github.com/mstange/profiler-get-symbols/commit/c1dca28a2a506df40f0a6f32c12ba51ec54b02be
|
||||
const WASM_MODULE_URL =
|
||||
"https://zealous-rosalind-a98ce8.netlify.com/wasm/8f7ca2f70e1cd21b5a2dbe96545672752887bfbd4e7b3b9437e9fc7c3da0a3bedae4584ff734f0c9f08c642e6b66ffab.wasm";
|
||||
"https://storage.googleapis.com/firefox-profiler-get-symbols/c1dca28a2a506df40f0a6f32c12ba51ec54b02be.wasm";
|
||||
const WASM_MODULE_INTEGRITY =
|
||||
"sha384-j3yi9w4c0htaLb6WVFZydSiHv71OezuUN+n8fD2go77a5FhP9zTwyfCMZC5rZv+r";
|
||||
"sha384-ZWi2jwcKJr20rE2gmHjFQGHgsCF9CagkyPLsrIZfmf5QKD2oXgkLa8tMKHK6zPA1";
|
||||
|
||||
const EXPIRY_TIME_IN_MS = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче