@sentry/wasm 10.53.1 → 10.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/npm/cjs/index.js +31 -116
- package/build/npm/cjs/index.js.map +1 -1
- package/build/npm/cjs/patchWebAssembly.js +12 -21
- package/build/npm/cjs/patchWebAssembly.js.map +1 -1
- package/build/npm/cjs/registry.js +9 -39
- package/build/npm/cjs/registry.js.map +1 -1
- package/build/npm/esm/index.js +31 -116
- package/build/npm/esm/index.js.map +1 -1
- package/build/npm/esm/package.json +1 -1
- package/build/npm/esm/patchWebAssembly.js +12 -21
- package/build/npm/esm/patchWebAssembly.js.map +1 -1
- package/build/npm/esm/registry.js +9 -39
- package/build/npm/esm/registry.js.map +1 -1
- package/package.json +3 -3
package/build/npm/cjs/index.js
CHANGED
|
@@ -4,22 +4,9 @@ const core = require('@sentry/core');
|
|
|
4
4
|
const patchWebAssembly = require('./patchWebAssembly.js');
|
|
5
5
|
const registry = require('./registry.js');
|
|
6
6
|
|
|
7
|
-
const INTEGRATION_NAME =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// recognizes WASM frames as first-party code without needing modifications.
|
|
11
|
-
const BUNDLER_PLUGIN_APP_KEY_PREFIX = '_sentryBundlerPluginAppKey:';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Minimal interface for DedicatedWorkerGlobalScope.
|
|
15
|
-
* We can't use the actual type because it breaks everyone who doesn't have {"lib": ["WebWorker"]}
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
// Access WINDOW with proper typing for _sentryWasmImages
|
|
19
|
-
const WINDOW = core.GLOBAL_OBJ
|
|
20
|
-
|
|
21
|
-
;
|
|
22
|
-
|
|
7
|
+
const INTEGRATION_NAME = "Wasm";
|
|
8
|
+
const BUNDLER_PLUGIN_APP_KEY_PREFIX = "_sentryBundlerPluginAppKey:";
|
|
9
|
+
const WINDOW = core.GLOBAL_OBJ;
|
|
23
10
|
const _wasmIntegration = ((options = {}) => {
|
|
24
11
|
return {
|
|
25
12
|
name: INTEGRATION_NAME,
|
|
@@ -28,86 +15,50 @@ const _wasmIntegration = ((options = {}) => {
|
|
|
28
15
|
},
|
|
29
16
|
processEvent(event) {
|
|
30
17
|
let hasAtLeastOneWasmFrameWithImage = false;
|
|
31
|
-
|
|
32
18
|
const existingImagesCount = event.debug_meta?.images?.length || 0;
|
|
33
|
-
|
|
34
19
|
if (event.exception?.values) {
|
|
35
|
-
event.exception.values.forEach(exception => {
|
|
20
|
+
event.exception.values.forEach((exception) => {
|
|
36
21
|
if (exception.stacktrace?.frames) {
|
|
37
|
-
hasAtLeastOneWasmFrameWithImage =
|
|
38
|
-
hasAtLeastOneWasmFrameWithImage ||
|
|
39
|
-
patchFrames(exception.stacktrace.frames, options.applicationKey, existingImagesCount);
|
|
22
|
+
hasAtLeastOneWasmFrameWithImage = hasAtLeastOneWasmFrameWithImage || patchFrames(exception.stacktrace.frames, options.applicationKey, existingImagesCount);
|
|
40
23
|
}
|
|
41
24
|
});
|
|
42
25
|
}
|
|
43
|
-
|
|
44
26
|
if (hasAtLeastOneWasmFrameWithImage) {
|
|
45
27
|
event.debug_meta = event.debug_meta || {};
|
|
46
28
|
const mainThreadImages = registry.getImages();
|
|
47
29
|
const workerImages = WINDOW._sentryWasmImages || [];
|
|
48
|
-
event.debug_meta.images = [...
|
|
30
|
+
event.debug_meta.images = [...event.debug_meta.images || [], ...mainThreadImages, ...workerImages];
|
|
49
31
|
}
|
|
50
|
-
|
|
51
32
|
return event;
|
|
52
|
-
}
|
|
33
|
+
}
|
|
53
34
|
};
|
|
54
|
-
})
|
|
55
|
-
|
|
35
|
+
});
|
|
56
36
|
const wasmIntegration = core.defineIntegration(_wasmIntegration);
|
|
57
|
-
|
|
58
37
|
const PARSER_REGEX = /^(.*?):wasm-function\[\d+\]:(0x[a-fA-F0-9]+)$/;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Patches a list of stackframes with wasm data needed for server-side symbolication
|
|
62
|
-
* if applicable. Returns true if the provided list of stack frames had at least one
|
|
63
|
-
* matching registered image.
|
|
64
|
-
*
|
|
65
|
-
* @param frames - Stack frames to patch
|
|
66
|
-
* @param applicationKey - Optional key for third-party error filtering
|
|
67
|
-
* @param existingImagesOffset - Number of existing debug images that will be prepended
|
|
68
|
-
* to the final images array (used to calculate correct addr_mode indices)
|
|
69
|
-
*/
|
|
70
|
-
// Only exported for tests
|
|
71
|
-
function patchFrames(
|
|
72
|
-
frames,
|
|
73
|
-
applicationKey,
|
|
74
|
-
existingImagesOffset = 0,
|
|
75
|
-
) {
|
|
38
|
+
function patchFrames(frames, applicationKey, existingImagesOffset = 0) {
|
|
76
39
|
let hasAtLeastOneWasmFrameWithImage = false;
|
|
77
|
-
frames.forEach(frame => {
|
|
40
|
+
frames.forEach((frame) => {
|
|
78
41
|
if (!frame.filename) {
|
|
79
42
|
return;
|
|
80
43
|
}
|
|
81
|
-
|
|
82
|
-
const split = frame.filename.split('(');
|
|
83
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
44
|
+
const split = frame.filename.split("(");
|
|
84
45
|
const lastSplit = split[split.length - 1];
|
|
85
|
-
|
|
86
|
-
// Let's call this first match a "messy match".
|
|
87
|
-
// The browser stacktrace parser spits out frames that have a filename like this: "int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb"
|
|
88
|
-
// It contains some leftover mess because wasm stack frames are more complicated than our parser can handle: "at MyClass::bar(int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb)"
|
|
89
|
-
// This first match simply tries to mitigate the mess up until the first opening parens.
|
|
90
|
-
// The match afterwards is a sensible fallback
|
|
91
|
-
let match = lastSplit.match(PARSER_REGEX) ;
|
|
92
|
-
|
|
46
|
+
let match = lastSplit.match(PARSER_REGEX);
|
|
93
47
|
if (!match) {
|
|
94
|
-
match = frame.filename.match(PARSER_REGEX)
|
|
48
|
+
match = frame.filename.match(PARSER_REGEX);
|
|
95
49
|
}
|
|
96
|
-
|
|
97
50
|
if (match) {
|
|
98
51
|
const index = registry.getImage(match[1]);
|
|
99
52
|
const workerImageIndex = getWorkerImage(match[1]);
|
|
100
53
|
frame.instruction_addr = match[2];
|
|
101
54
|
frame.filename = match[1];
|
|
102
|
-
frame.platform =
|
|
103
|
-
|
|
55
|
+
frame.platform = "native";
|
|
104
56
|
if (applicationKey) {
|
|
105
57
|
frame.module_metadata = {
|
|
106
58
|
...frame.module_metadata,
|
|
107
|
-
[`${BUNDLER_PLUGIN_APP_KEY_PREFIX}${applicationKey}`]: true
|
|
59
|
+
[`${BUNDLER_PLUGIN_APP_KEY_PREFIX}${applicationKey}`]: true
|
|
108
60
|
};
|
|
109
61
|
}
|
|
110
|
-
|
|
111
62
|
if (index >= 0) {
|
|
112
63
|
frame.addr_mode = `rel:${existingImagesOffset + index}`;
|
|
113
64
|
hasAtLeastOneWasmFrameWithImage = true;
|
|
@@ -118,87 +69,51 @@ function patchFrames(
|
|
|
118
69
|
}
|
|
119
70
|
}
|
|
120
71
|
});
|
|
121
|
-
|
|
122
72
|
return hasAtLeastOneWasmFrameWithImage;
|
|
123
73
|
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Looks up an image by URL in worker images.
|
|
127
|
-
*/
|
|
128
74
|
function getWorkerImage(url) {
|
|
129
75
|
const workerImages = WINDOW._sentryWasmImages || [];
|
|
130
|
-
return workerImages.findIndex(image => {
|
|
131
|
-
return image.type ===
|
|
76
|
+
return workerImages.findIndex((image) => {
|
|
77
|
+
return image.type === "wasm" && image.code_file === url;
|
|
132
78
|
});
|
|
133
79
|
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Use this function to register WASM support in a web worker.
|
|
137
|
-
*
|
|
138
|
-
* This function will:
|
|
139
|
-
* - Patch WebAssembly.instantiateStreaming and WebAssembly.compileStreaming in the worker
|
|
140
|
-
* - Forward WASM debug images to the parent thread for symbolication
|
|
141
|
-
*
|
|
142
|
-
* @param options {RegisterWebWorkerWasmOptions} Options:
|
|
143
|
-
* - `self`: The worker's global scope (self).
|
|
144
|
-
*/
|
|
145
80
|
function registerWebWorkerWasm({ self }) {
|
|
146
81
|
patchWebAssemblyWithForwarding(self);
|
|
147
82
|
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Patches the WebAssembly object in the worker scope and forwards
|
|
151
|
-
* registered modules to the parent thread.
|
|
152
|
-
*/
|
|
153
83
|
function patchWebAssemblyWithForwarding(workerSelf) {
|
|
154
|
-
if (
|
|
84
|
+
if ("instantiateStreaming" in WebAssembly) {
|
|
155
85
|
const origInstantiateStreaming = WebAssembly.instantiateStreaming;
|
|
156
|
-
WebAssembly.instantiateStreaming = function instantiateStreaming(
|
|
157
|
-
response
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return origInstantiateStreaming(response, importObject).then(rv => {
|
|
162
|
-
if (response.url) {
|
|
163
|
-
registerModuleAndForward(rv.module, response.url, workerSelf);
|
|
86
|
+
WebAssembly.instantiateStreaming = function instantiateStreaming(response, importObject) {
|
|
87
|
+
return Promise.resolve(response).then((response2) => {
|
|
88
|
+
return origInstantiateStreaming(response2, importObject).then((rv) => {
|
|
89
|
+
if (response2.url) {
|
|
90
|
+
registerModuleAndForward(rv.module, response2.url, workerSelf);
|
|
164
91
|
}
|
|
165
92
|
return rv;
|
|
166
93
|
});
|
|
167
94
|
});
|
|
168
|
-
}
|
|
95
|
+
};
|
|
169
96
|
}
|
|
170
|
-
|
|
171
|
-
if ('compileStreaming' in WebAssembly) {
|
|
97
|
+
if ("compileStreaming" in WebAssembly) {
|
|
172
98
|
const origCompileStreaming = WebAssembly.compileStreaming;
|
|
173
|
-
WebAssembly.compileStreaming = function compileStreaming(
|
|
174
|
-
source
|
|
175
|
-
|
|
176
|
-
return Promise.resolve(source).then(response => {
|
|
177
|
-
return origCompileStreaming(response).then(module => {
|
|
99
|
+
WebAssembly.compileStreaming = function compileStreaming(source) {
|
|
100
|
+
return Promise.resolve(source).then((response) => {
|
|
101
|
+
return origCompileStreaming(response).then((module) => {
|
|
178
102
|
if (response.url) {
|
|
179
103
|
registerModuleAndForward(module, response.url, workerSelf);
|
|
180
104
|
}
|
|
181
105
|
return module;
|
|
182
106
|
});
|
|
183
107
|
});
|
|
184
|
-
}
|
|
108
|
+
};
|
|
185
109
|
}
|
|
186
110
|
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Registers a WASM module and forwards its debug image to the parent thread.
|
|
190
|
-
*/
|
|
191
|
-
function registerModuleAndForward(
|
|
192
|
-
module,
|
|
193
|
-
url,
|
|
194
|
-
workerSelf,
|
|
195
|
-
) {
|
|
111
|
+
function registerModuleAndForward(module, url, workerSelf) {
|
|
196
112
|
const image = registry.registerModule(module, url);
|
|
197
|
-
|
|
198
113
|
if (image) {
|
|
199
114
|
workerSelf.postMessage({
|
|
200
115
|
_sentryMessage: true,
|
|
201
|
-
_sentryWasmImages: [image]
|
|
116
|
+
_sentryWasmImages: [image]
|
|
202
117
|
});
|
|
203
118
|
}
|
|
204
119
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/index.ts"],"sourcesContent":["import type { DebugImage, Event, IntegrationFn, StackFrame } from '@sentry/core';\nimport { defineIntegration, GLOBAL_OBJ } from '@sentry/core';\nimport { patchWebAssembly } from './patchWebAssembly';\nimport { getImage, getImages, registerModule } from './registry';\n\nconst INTEGRATION_NAME = 'Wasm';\n\n// We use the same prefix as bundler plugins so that thirdPartyErrorFilterIntegration\n// recognizes WASM frames as first-party code without needing modifications.\nconst BUNDLER_PLUGIN_APP_KEY_PREFIX = '_sentryBundlerPluginAppKey:';\n\n/**\n * Minimal interface for DedicatedWorkerGlobalScope.\n * We can't use the actual type because it breaks everyone who doesn't have {\"lib\": [\"WebWorker\"]}\n */\ninterface MinimalDedicatedWorkerGlobalScope {\n postMessage: (message: unknown) => void;\n}\n\ninterface RegisterWebWorkerWasmOptions {\n self: MinimalDedicatedWorkerGlobalScope;\n}\n\ninterface WasmIntegrationOptions {\n /**\n * Key to identify this application for third-party error filtering.\n * This key should match one of the keys provided to the `filterKeys` option\n * of the `thirdPartyErrorFilterIntegration`.\n */\n applicationKey?: string;\n}\n\n// Access WINDOW with proper typing for _sentryWasmImages\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n _sentryWasmImages?: Array<DebugImage>;\n};\n\nconst _wasmIntegration = ((options: WasmIntegrationOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n patchWebAssembly();\n },\n processEvent(event: Event): Event {\n let hasAtLeastOneWasmFrameWithImage = false;\n\n const existingImagesCount = event.debug_meta?.images?.length || 0;\n\n if (event.exception?.values) {\n event.exception.values.forEach(exception => {\n if (exception.stacktrace?.frames) {\n hasAtLeastOneWasmFrameWithImage =\n hasAtLeastOneWasmFrameWithImage ||\n patchFrames(exception.stacktrace.frames, options.applicationKey, existingImagesCount);\n }\n });\n }\n\n if (hasAtLeastOneWasmFrameWithImage) {\n event.debug_meta = event.debug_meta || {};\n const mainThreadImages = getImages();\n const workerImages = WINDOW._sentryWasmImages || [];\n event.debug_meta.images = [...(event.debug_meta.images || []), ...mainThreadImages, ...workerImages];\n }\n\n return event;\n },\n };\n}) satisfies IntegrationFn;\n\nexport const wasmIntegration = defineIntegration(_wasmIntegration);\n\nconst PARSER_REGEX = /^(.*?):wasm-function\\[\\d+\\]:(0x[a-fA-F0-9]+)$/;\n\n/**\n * Patches a list of stackframes with wasm data needed for server-side symbolication\n * if applicable. Returns true if the provided list of stack frames had at least one\n * matching registered image.\n *\n * @param frames - Stack frames to patch\n * @param applicationKey - Optional key for third-party error filtering\n * @param existingImagesOffset - Number of existing debug images that will be prepended\n * to the final images array (used to calculate correct addr_mode indices)\n */\n// Only exported for tests\nexport function patchFrames(\n frames: Array<StackFrame>,\n applicationKey?: string,\n existingImagesOffset: number = 0,\n): boolean {\n let hasAtLeastOneWasmFrameWithImage = false;\n frames.forEach(frame => {\n if (!frame.filename) {\n return;\n }\n\n const split = frame.filename.split('(');\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSplit = split[split.length - 1]!;\n\n // Let's call this first match a \"messy match\".\n // The browser stacktrace parser spits out frames that have a filename like this: \"int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb\"\n // It contains some leftover mess because wasm stack frames are more complicated than our parser can handle: \"at MyClass::bar(int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb)\"\n // This first match simply tries to mitigate the mess up until the first opening parens.\n // The match afterwards is a sensible fallback\n let match = lastSplit.match(PARSER_REGEX) as null | [string, string, string];\n\n if (!match) {\n match = frame.filename.match(PARSER_REGEX) as null | [string, string, string];\n }\n\n if (match) {\n const index = getImage(match[1]);\n const workerImageIndex = getWorkerImage(match[1]);\n frame.instruction_addr = match[2];\n frame.filename = match[1];\n frame.platform = 'native';\n\n if (applicationKey) {\n frame.module_metadata = {\n ...frame.module_metadata,\n [`${BUNDLER_PLUGIN_APP_KEY_PREFIX}${applicationKey}`]: true,\n };\n }\n\n if (index >= 0) {\n frame.addr_mode = `rel:${existingImagesOffset + index}`;\n hasAtLeastOneWasmFrameWithImage = true;\n } else if (workerImageIndex >= 0) {\n const mainThreadImagesCount = getImages().length;\n frame.addr_mode = `rel:${existingImagesOffset + mainThreadImagesCount + workerImageIndex}`;\n hasAtLeastOneWasmFrameWithImage = true;\n }\n }\n });\n\n return hasAtLeastOneWasmFrameWithImage;\n}\n\n/**\n * Looks up an image by URL in worker images.\n */\nfunction getWorkerImage(url: string): number {\n const workerImages = WINDOW._sentryWasmImages || [];\n return workerImages.findIndex(image => {\n return image.type === 'wasm' && image.code_file === url;\n });\n}\n\n/**\n * Use this function to register WASM support in a web worker.\n *\n * This function will:\n * - Patch WebAssembly.instantiateStreaming and WebAssembly.compileStreaming in the worker\n * - Forward WASM debug images to the parent thread for symbolication\n *\n * @param options {RegisterWebWorkerWasmOptions} Options:\n * - `self`: The worker's global scope (self).\n */\nexport function registerWebWorkerWasm({ self }: RegisterWebWorkerWasmOptions): void {\n patchWebAssemblyWithForwarding(self);\n}\n\n/**\n * Patches the WebAssembly object in the worker scope and forwards\n * registered modules to the parent thread.\n */\nfunction patchWebAssemblyWithForwarding(workerSelf: MinimalDedicatedWorkerGlobalScope): void {\n if ('instantiateStreaming' in WebAssembly) {\n const origInstantiateStreaming = WebAssembly.instantiateStreaming;\n WebAssembly.instantiateStreaming = function instantiateStreaming(\n response: Response | PromiseLike<Response>,\n importObject: WebAssembly.Imports,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(response).then(response => {\n return origInstantiateStreaming(response, importObject).then(rv => {\n if (response.url) {\n registerModuleAndForward(rv.module, response.url, workerSelf);\n }\n return rv;\n });\n });\n } as typeof WebAssembly.instantiateStreaming;\n }\n\n if ('compileStreaming' in WebAssembly) {\n const origCompileStreaming = WebAssembly.compileStreaming;\n WebAssembly.compileStreaming = function compileStreaming(\n source: Response | Promise<Response>,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(source).then(response => {\n return origCompileStreaming(response).then(module => {\n if (response.url) {\n registerModuleAndForward(module, response.url, workerSelf);\n }\n return module;\n });\n });\n } as typeof WebAssembly.compileStreaming;\n }\n}\n\n/**\n * Registers a WASM module and forwards its debug image to the parent thread.\n */\nfunction registerModuleAndForward(\n module: WebAssembly.Module,\n url: string,\n workerSelf: MinimalDedicatedWorkerGlobalScope,\n): void {\n const image = registerModule(module, url);\n\n if (image) {\n workerSelf.postMessage({\n _sentryMessage: true,\n _sentryWasmImages: [image],\n });\n }\n}\n"],"names":["GLOBAL_OBJ","patchWebAssembly","getImages","defineIntegration","getImage","registerModule"],"mappings":";;;;;;AAKA,MAAM,gBAAA,GAAmB,MAAM;;AAE/B;AACA;AACA,MAAM,6BAAA,GAAgC,6BAA6B;;AAEnE;AACA;AACA;AACA;;AAkBA;AACA,MAAM,MAAA,GAASA;;AAEf;;AAEA,MAAM,gBAAA,IAAoB,CAAC,OAAO,GAA2B,EAAE,KAAK;AACpE,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,SAAS,GAAG;AAChB,MAAMC,iCAAgB,EAAE;AACxB,IAAI,CAAC;AACL,IAAI,YAAY,CAAC,KAAK,EAAgB;AACtC,MAAM,IAAI,+BAAA,GAAkC,KAAK;;AAEjD,MAAM,MAAM,mBAAA,GAAsB,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,MAAA,IAAU,CAAC;;AAEvE,MAAM,IAAI,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE;AACnC,QAAQ,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,SAAA,IAAa;AACpD,UAAU,IAAI,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE;AAC5C,YAAY,+BAAA;AACZ,cAAc,+BAAA;AACd,cAAc,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,EAAE,mBAAmB,CAAC;AACnG,UAAU;AACV,QAAQ,CAAC,CAAC;AACV,MAAM;;AAEN,MAAM,IAAI,+BAA+B,EAAE;AAC3C,QAAQ,KAAK,CAAC,UAAA,GAAa,KAAK,CAAC,UAAA,IAAc,EAAE;AACjD,QAAQ,MAAM,gBAAA,GAAmBC,kBAAS,EAAE;AAC5C,QAAQ,MAAM,eAAe,MAAM,CAAC,iBAAA,IAAqB,EAAE;AAC3D,QAAQ,KAAK,CAAC,UAAU,CAAC,MAAA,GAAS,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,MAAA,IAAU,EAAE,CAAC,EAAE,GAAG,gBAAgB,EAAE,GAAG,YAAY,CAAC;AAC5G,MAAM;;AAEN,MAAM,OAAO,KAAK;AAClB,IAAI,CAAC;AACL,GAAG;AACH,CAAC,CAAA;;MAEY,eAAA,GAAkBC,sBAAiB,CAAC,gBAAgB;;AAEjE,MAAM,YAAA,GAAe,+CAA+C;;AAEpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,WAAW;AAC3B,EAAE,MAAM;AACR,EAAE,cAAc;AAChB,EAAE,oBAAoB,GAAW,CAAC;AAClC,EAAW;AACX,EAAE,IAAI,+BAAA,GAAkC,KAAK;AAC7C,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;AAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;AACzB,MAAM;AACN,IAAI;;AAEJ,IAAI,MAAM,KAAA,GAAQ,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;AAC3C;AACA,IAAI,MAAM,SAAA,GAAY,KAAK,CAAC,KAAK,CAAC,MAAA,GAAS,CAAC,CAAC;;AAE7C;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,QAAQ,SAAS,CAAC,KAAK,CAAC,YAAY,CAAA;;AAE5C,IAAI,IAAI,CAAC,KAAK,EAAE;AAChB,MAAM,KAAA,GAAQ,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAA;AAC/C,IAAI;;AAEJ,IAAI,IAAI,KAAK,EAAE;AACf,MAAM,MAAM,QAAQC,iBAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtC,MAAM,MAAM,mBAAmB,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvD,MAAM,KAAK,CAAC,gBAAA,GAAmB,KAAK,CAAC,CAAC,CAAC;AACvC,MAAM,KAAK,CAAC,QAAA,GAAW,KAAK,CAAC,CAAC,CAAC;AAC/B,MAAM,KAAK,CAAC,QAAA,GAAW,QAAQ;;AAE/B,MAAM,IAAI,cAAc,EAAE;AAC1B,QAAQ,KAAK,CAAC,eAAA,GAAkB;AAChC,UAAU,GAAG,KAAK,CAAC,eAAe;AAClC,UAAU,CAAC,CAAC,EAAA,6BAAA,CAAA,EAAA,cAAA,CAAA,CAAA,GAAA,IAAA;AACA,SAAA;AACA,MAAA;;AAEA,MAAA,IAAA,KAAA,IAAA,CAAA,EAAA;AACA,QAAA,KAAA,CAAA,SAAA,GAAA,CAAA,IAAA,EAAA,oBAAA,GAAA,KAAA,CAAA,CAAA;AACA,QAAA,+BAAA,GAAA,IAAA;AACA,MAAA,CAAA,MAAA,IAAA,gBAAA,IAAA,CAAA,EAAA;AACA,QAAA,MAAA,qBAAA,GAAAF,kBAAA,EAAA,CAAA,MAAA;AACA,QAAA,KAAA,CAAA,SAAA,GAAA,CAAA,IAAA,EAAA,oBAAA,GAAA,qBAAA,GAAA,gBAAA,CAAA,CAAA;AACA,QAAA,+BAAA,GAAA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA,CAAA,CAAA;;AAEA,EAAA,OAAA,+BAAA;AACA;;AAEA;AACA;AACA;AACA,SAAA,cAAA,CAAA,GAAA,EAAA;AACA,EAAA,MAAA,YAAA,GAAA,MAAA,CAAA,iBAAA,IAAA,EAAA;AACA,EAAA,OAAA,YAAA,CAAA,SAAA,CAAA,KAAA,IAAA;AACA,IAAA,OAAA,KAAA,CAAA,IAAA,KAAA,MAAA,IAAA,KAAA,CAAA,SAAA,KAAA,GAAA;AACA,EAAA,CAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,qBAAA,CAAA,EAAA,IAAA,EAAA,EAAA;AACA,EAAA,8BAAA,CAAA,IAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAA,8BAAA,CAAA,UAAA,EAAA;AACA,EAAA,IAAA,sBAAA,IAAA,WAAA,EAAA;AACA,IAAA,MAAA,wBAAA,GAAA,WAAA,CAAA,oBAAA;AACA,IAAA,WAAA,CAAA,oBAAA,GAAA,SAAA,oBAAA;AACA,MAAA,QAAA;AACA,MAAA,YAAA;AACA,MAAA;AACA,MAAA,OAAA,OAAA,CAAA,OAAA,CAAA,QAAA,CAAA,CAAA,IAAA,CAAA,QAAA,IAAA;AACA,QAAA,OAAA,wBAAA,CAAA,QAAA,EAAA,YAAA,CAAA,CAAA,IAAA,CAAA,EAAA,IAAA;AACA,UAAA,IAAA,QAAA,CAAA,GAAA,EAAA;AACA,YAAA,wBAAA,CAAA,EAAA,CAAA,MAAA,EAAA,QAAA,CAAA,GAAA,EAAA,UAAA,CAAA;AACA,UAAA;AACA,UAAA,OAAA,EAAA;AACA,QAAA,CAAA,CAAA;AACA,MAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,EAAA;;AAEA,EAAA,IAAA,kBAAA,IAAA,WAAA,EAAA;AACA,IAAA,MAAA,oBAAA,GAAA,WAAA,CAAA,gBAAA;AACA,IAAA,WAAA,CAAA,gBAAA,GAAA,SAAA,gBAAA;AACA,MAAA,MAAA;AACA,MAAA;AACA,MAAA,OAAA,OAAA,CAAA,OAAA,CAAA,MAAA,CAAA,CAAA,IAAA,CAAA,QAAA,IAAA;AACA,QAAA,OAAA,oBAAA,CAAA,QAAA,CAAA,CAAA,IAAA,CAAA,MAAA,IAAA;AACA,UAAA,IAAA,QAAA,CAAA,GAAA,EAAA;AACA,YAAA,wBAAA,CAAA,MAAA,EAAA,QAAA,CAAA,GAAA,EAAA,UAAA,CAAA;AACA,UAAA;AACA,UAAA,OAAA,MAAA;AACA,QAAA,CAAA,CAAA;AACA,MAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,EAAA;AACA;;AAEA;AACA;AACA;AACA,SAAA,wBAAA;AACA,EAAA,MAAA;AACA,EAAA,GAAA;AACA,EAAA,UAAA;AACA,EAAA;AACA,EAAA,MAAA,KAAA,GAAAG,uBAAA,CAAA,MAAA,EAAA,GAAA,CAAA;;AAEA,EAAA,IAAA,KAAA,EAAA;AACA,IAAA,UAAA,CAAA,WAAA,CAAA;AACA,MAAA,cAAA,EAAA,IAAA;AACA,MAAA,iBAAA,EAAA,CAAA,KAAA,CAAA;AACA,KAAA,CAAA;AACA,EAAA;AACA;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/index.ts"],"sourcesContent":["import type { DebugImage, Event, IntegrationFn, StackFrame } from '@sentry/core';\nimport { defineIntegration, GLOBAL_OBJ } from '@sentry/core';\nimport { patchWebAssembly } from './patchWebAssembly';\nimport { getImage, getImages, registerModule } from './registry';\n\nconst INTEGRATION_NAME = 'Wasm';\n\n// We use the same prefix as bundler plugins so that thirdPartyErrorFilterIntegration\n// recognizes WASM frames as first-party code without needing modifications.\nconst BUNDLER_PLUGIN_APP_KEY_PREFIX = '_sentryBundlerPluginAppKey:';\n\n/**\n * Minimal interface for DedicatedWorkerGlobalScope.\n * We can't use the actual type because it breaks everyone who doesn't have {\"lib\": [\"WebWorker\"]}\n */\ninterface MinimalDedicatedWorkerGlobalScope {\n postMessage: (message: unknown) => void;\n}\n\ninterface RegisterWebWorkerWasmOptions {\n self: MinimalDedicatedWorkerGlobalScope;\n}\n\ninterface WasmIntegrationOptions {\n /**\n * Key to identify this application for third-party error filtering.\n * This key should match one of the keys provided to the `filterKeys` option\n * of the `thirdPartyErrorFilterIntegration`.\n */\n applicationKey?: string;\n}\n\n// Access WINDOW with proper typing for _sentryWasmImages\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n _sentryWasmImages?: Array<DebugImage>;\n};\n\nconst _wasmIntegration = ((options: WasmIntegrationOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n patchWebAssembly();\n },\n processEvent(event: Event): Event {\n let hasAtLeastOneWasmFrameWithImage = false;\n\n const existingImagesCount = event.debug_meta?.images?.length || 0;\n\n if (event.exception?.values) {\n event.exception.values.forEach(exception => {\n if (exception.stacktrace?.frames) {\n hasAtLeastOneWasmFrameWithImage =\n hasAtLeastOneWasmFrameWithImage ||\n patchFrames(exception.stacktrace.frames, options.applicationKey, existingImagesCount);\n }\n });\n }\n\n if (hasAtLeastOneWasmFrameWithImage) {\n event.debug_meta = event.debug_meta || {};\n const mainThreadImages = getImages();\n const workerImages = WINDOW._sentryWasmImages || [];\n event.debug_meta.images = [...(event.debug_meta.images || []), ...mainThreadImages, ...workerImages];\n }\n\n return event;\n },\n };\n}) satisfies IntegrationFn;\n\nexport const wasmIntegration = defineIntegration(_wasmIntegration);\n\nconst PARSER_REGEX = /^(.*?):wasm-function\\[\\d+\\]:(0x[a-fA-F0-9]+)$/;\n\n/**\n * Patches a list of stackframes with wasm data needed for server-side symbolication\n * if applicable. Returns true if the provided list of stack frames had at least one\n * matching registered image.\n *\n * @param frames - Stack frames to patch\n * @param applicationKey - Optional key for third-party error filtering\n * @param existingImagesOffset - Number of existing debug images that will be prepended\n * to the final images array (used to calculate correct addr_mode indices)\n */\n// Only exported for tests\nexport function patchFrames(\n frames: Array<StackFrame>,\n applicationKey?: string,\n existingImagesOffset: number = 0,\n): boolean {\n let hasAtLeastOneWasmFrameWithImage = false;\n frames.forEach(frame => {\n if (!frame.filename) {\n return;\n }\n\n const split = frame.filename.split('(');\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSplit = split[split.length - 1]!;\n\n // Let's call this first match a \"messy match\".\n // The browser stacktrace parser spits out frames that have a filename like this: \"int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb\"\n // It contains some leftover mess because wasm stack frames are more complicated than our parser can handle: \"at MyClass::bar(int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb)\"\n // This first match simply tries to mitigate the mess up until the first opening parens.\n // The match afterwards is a sensible fallback\n let match = lastSplit.match(PARSER_REGEX) as null | [string, string, string];\n\n if (!match) {\n match = frame.filename.match(PARSER_REGEX) as null | [string, string, string];\n }\n\n if (match) {\n const index = getImage(match[1]);\n const workerImageIndex = getWorkerImage(match[1]);\n frame.instruction_addr = match[2];\n frame.filename = match[1];\n frame.platform = 'native';\n\n if (applicationKey) {\n frame.module_metadata = {\n ...frame.module_metadata,\n [`${BUNDLER_PLUGIN_APP_KEY_PREFIX}${applicationKey}`]: true,\n };\n }\n\n if (index >= 0) {\n frame.addr_mode = `rel:${existingImagesOffset + index}`;\n hasAtLeastOneWasmFrameWithImage = true;\n } else if (workerImageIndex >= 0) {\n const mainThreadImagesCount = getImages().length;\n frame.addr_mode = `rel:${existingImagesOffset + mainThreadImagesCount + workerImageIndex}`;\n hasAtLeastOneWasmFrameWithImage = true;\n }\n }\n });\n\n return hasAtLeastOneWasmFrameWithImage;\n}\n\n/**\n * Looks up an image by URL in worker images.\n */\nfunction getWorkerImage(url: string): number {\n const workerImages = WINDOW._sentryWasmImages || [];\n return workerImages.findIndex(image => {\n return image.type === 'wasm' && image.code_file === url;\n });\n}\n\n/**\n * Use this function to register WASM support in a web worker.\n *\n * This function will:\n * - Patch WebAssembly.instantiateStreaming and WebAssembly.compileStreaming in the worker\n * - Forward WASM debug images to the parent thread for symbolication\n *\n * @param options {RegisterWebWorkerWasmOptions} Options:\n * - `self`: The worker's global scope (self).\n */\nexport function registerWebWorkerWasm({ self }: RegisterWebWorkerWasmOptions): void {\n patchWebAssemblyWithForwarding(self);\n}\n\n/**\n * Patches the WebAssembly object in the worker scope and forwards\n * registered modules to the parent thread.\n */\nfunction patchWebAssemblyWithForwarding(workerSelf: MinimalDedicatedWorkerGlobalScope): void {\n if ('instantiateStreaming' in WebAssembly) {\n const origInstantiateStreaming = WebAssembly.instantiateStreaming;\n WebAssembly.instantiateStreaming = function instantiateStreaming(\n response: Response | PromiseLike<Response>,\n importObject: WebAssembly.Imports,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(response).then(response => {\n return origInstantiateStreaming(response, importObject).then(rv => {\n if (response.url) {\n registerModuleAndForward(rv.module, response.url, workerSelf);\n }\n return rv;\n });\n });\n } as typeof WebAssembly.instantiateStreaming;\n }\n\n if ('compileStreaming' in WebAssembly) {\n const origCompileStreaming = WebAssembly.compileStreaming;\n WebAssembly.compileStreaming = function compileStreaming(\n source: Response | Promise<Response>,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(source).then(response => {\n return origCompileStreaming(response).then(module => {\n if (response.url) {\n registerModuleAndForward(module, response.url, workerSelf);\n }\n return module;\n });\n });\n } as typeof WebAssembly.compileStreaming;\n }\n}\n\n/**\n * Registers a WASM module and forwards its debug image to the parent thread.\n */\nfunction registerModuleAndForward(\n module: WebAssembly.Module,\n url: string,\n workerSelf: MinimalDedicatedWorkerGlobalScope,\n): void {\n const image = registerModule(module, url);\n\n if (image) {\n workerSelf.postMessage({\n _sentryMessage: true,\n _sentryWasmImages: [image],\n });\n }\n}\n"],"names":["GLOBAL_OBJ","patchWebAssembly","getImages","defineIntegration","getImage","response","registerModule"],"mappings":"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"}
|
|
@@ -2,41 +2,32 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
|
|
3
3
|
const registry = require('./registry.js');
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Patches the web assembly runtime.
|
|
7
|
-
*/
|
|
8
5
|
function patchWebAssembly() {
|
|
9
|
-
if (
|
|
6
|
+
if ("instantiateStreaming" in WebAssembly) {
|
|
10
7
|
const origInstantiateStreaming = WebAssembly.instantiateStreaming;
|
|
11
|
-
WebAssembly.instantiateStreaming = function instantiateStreaming(
|
|
12
|
-
response
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return origInstantiateStreaming(response, importObject).then(rv => {
|
|
17
|
-
if (response.url) {
|
|
18
|
-
registry.registerModule(rv.module, response.url);
|
|
8
|
+
WebAssembly.instantiateStreaming = function instantiateStreaming(response, importObject) {
|
|
9
|
+
return Promise.resolve(response).then((response2) => {
|
|
10
|
+
return origInstantiateStreaming(response2, importObject).then((rv) => {
|
|
11
|
+
if (response2.url) {
|
|
12
|
+
registry.registerModule(rv.module, response2.url);
|
|
19
13
|
}
|
|
20
14
|
return rv;
|
|
21
15
|
});
|
|
22
16
|
});
|
|
23
|
-
}
|
|
17
|
+
};
|
|
24
18
|
}
|
|
25
|
-
|
|
26
|
-
if ('compileStreaming' in WebAssembly) {
|
|
19
|
+
if ("compileStreaming" in WebAssembly) {
|
|
27
20
|
const origCompileStreaming = WebAssembly.compileStreaming;
|
|
28
|
-
WebAssembly.compileStreaming = function compileStreaming(
|
|
29
|
-
source
|
|
30
|
-
|
|
31
|
-
return Promise.resolve(source).then(response => {
|
|
32
|
-
return origCompileStreaming(response).then(module => {
|
|
21
|
+
WebAssembly.compileStreaming = function compileStreaming(source) {
|
|
22
|
+
return Promise.resolve(source).then((response) => {
|
|
23
|
+
return origCompileStreaming(response).then((module) => {
|
|
33
24
|
if (response.url) {
|
|
34
25
|
registry.registerModule(module, response.url);
|
|
35
26
|
}
|
|
36
27
|
return module;
|
|
37
28
|
});
|
|
38
29
|
});
|
|
39
|
-
}
|
|
30
|
+
};
|
|
40
31
|
}
|
|
41
32
|
}
|
|
42
33
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patchWebAssembly.js","sources":["../../../src/patchWebAssembly.ts"],"sourcesContent":["import { registerModule } from './registry';\n\n/**\n * Patches the web assembly runtime.\n */\nexport function patchWebAssembly(): void {\n if ('instantiateStreaming' in WebAssembly) {\n const origInstantiateStreaming = WebAssembly.instantiateStreaming;\n WebAssembly.instantiateStreaming = function instantiateStreaming(\n response: Response | PromiseLike<Response>,\n importObject: WebAssembly.Imports,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(response).then(response => {\n return origInstantiateStreaming(response, importObject).then(rv => {\n if (response.url) {\n registerModule(rv.module, response.url);\n }\n return rv;\n });\n });\n } as typeof WebAssembly.instantiateStreaming;\n }\n\n if ('compileStreaming' in WebAssembly) {\n const origCompileStreaming = WebAssembly.compileStreaming;\n WebAssembly.compileStreaming = function compileStreaming(\n source: Response | Promise<Response>,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(source).then(response => {\n return origCompileStreaming(response).then(module => {\n if (response.url) {\n registerModule(module, response.url);\n }\n return module;\n });\n });\n } as typeof WebAssembly.compileStreaming;\n }\n}\n"],"names":["registerModule"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"patchWebAssembly.js","sources":["../../../src/patchWebAssembly.ts"],"sourcesContent":["import { registerModule } from './registry';\n\n/**\n * Patches the web assembly runtime.\n */\nexport function patchWebAssembly(): void {\n if ('instantiateStreaming' in WebAssembly) {\n const origInstantiateStreaming = WebAssembly.instantiateStreaming;\n WebAssembly.instantiateStreaming = function instantiateStreaming(\n response: Response | PromiseLike<Response>,\n importObject: WebAssembly.Imports,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(response).then(response => {\n return origInstantiateStreaming(response, importObject).then(rv => {\n if (response.url) {\n registerModule(rv.module, response.url);\n }\n return rv;\n });\n });\n } as typeof WebAssembly.instantiateStreaming;\n }\n\n if ('compileStreaming' in WebAssembly) {\n const origCompileStreaming = WebAssembly.compileStreaming;\n WebAssembly.compileStreaming = function compileStreaming(\n source: Response | Promise<Response>,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(source).then(response => {\n return origCompileStreaming(response).then(module => {\n if (response.url) {\n registerModule(module, response.url);\n }\n return module;\n });\n });\n } as typeof WebAssembly.compileStreaming;\n }\n}\n"],"names":["response","registerModule"],"mappings":";;;;AAKO,SAAS,gBAAA,GAAyB;AACvC,EAAA,IAAI,0BAA0B,WAAA,EAAa;AACzC,IAAA,MAAM,2BAA2B,WAAA,CAAY,oBAAA;AAC7C,IAAA,WAAA,CAAY,oBAAA,GAAuB,SAAS,oBAAA,CAC1C,QAAA,EACA,YAAA,EAC6B;AAC7B,MAAA,OAAO,QAAQ,OAAA,CAAQ,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAAA,SAAAA,KAAY;AAChD,QAAA,OAAO,wBAAA,CAAyBA,SAAAA,EAAU,YAAY,CAAA,CAAE,KAAK,CAAA,EAAA,KAAM;AACjE,UAAA,IAAIA,UAAS,GAAA,EAAK;AAChB,YAAAC,uBAAA,CAAe,EAAA,CAAG,MAAA,EAAQD,SAAAA,CAAS,GAAG,CAAA;AAAA,UACxC;AACA,UAAA,OAAO,EAAA;AAAA,QACT,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAEA,EAAA,IAAI,sBAAsB,WAAA,EAAa;AACrC,IAAA,MAAM,uBAAuB,WAAA,CAAY,gBAAA;AACzC,IAAA,WAAA,CAAY,gBAAA,GAAmB,SAAS,gBAAA,CACtC,MAAA,EAC6B;AAC7B,MAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA,CAAE,KAAK,CAAA,QAAA,KAAY;AAC9C,QAAA,OAAO,oBAAA,CAAqB,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAA,MAAA,KAAU;AACnD,UAAA,IAAI,SAAS,GAAA,EAAK;AAChB,YAAAC,uBAAA,CAAe,MAAA,EAAQ,SAAS,GAAG,CAAA;AAAA,UACrC;AACA,UAAA,OAAO,MAAA;AAAA,QACT,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AACF;;;;"}
|
|
@@ -1,88 +1,58 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const IMAGES = [];
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Returns the extracted meta information from a web assembly module that
|
|
7
|
-
* Sentry uses to identify debug images.
|
|
8
|
-
*
|
|
9
|
-
* @param module
|
|
10
|
-
*/
|
|
11
4
|
function getModuleInfo(module) {
|
|
12
|
-
const buildIds = WebAssembly.Module.customSections(module,
|
|
5
|
+
const buildIds = WebAssembly.Module.customSections(module, "build_id");
|
|
13
6
|
let buildId = null;
|
|
14
7
|
let debugFile = null;
|
|
15
|
-
|
|
16
8
|
const buildId0 = buildIds[0];
|
|
17
9
|
if (buildId0) {
|
|
18
10
|
const firstBuildId = new Uint8Array(buildId0);
|
|
19
11
|
buildId = Array.from(firstBuildId).reduce((acc, x) => {
|
|
20
|
-
return acc + x.toString(16).padStart(2,
|
|
21
|
-
},
|
|
12
|
+
return acc + x.toString(16).padStart(2, "0");
|
|
13
|
+
}, "");
|
|
22
14
|
}
|
|
23
|
-
|
|
24
|
-
const externalDebugInfo = WebAssembly.Module.customSections(module, 'external_debug_info');
|
|
15
|
+
const externalDebugInfo = WebAssembly.Module.customSections(module, "external_debug_info");
|
|
25
16
|
const externalDebugInfo0 = externalDebugInfo[0];
|
|
26
17
|
if (externalDebugInfo0) {
|
|
27
18
|
const firstExternalDebugInfo = new Uint8Array(externalDebugInfo0);
|
|
28
|
-
const decoder = new TextDecoder(
|
|
19
|
+
const decoder = new TextDecoder("utf-8");
|
|
29
20
|
debugFile = decoder.decode(firstExternalDebugInfo);
|
|
30
21
|
}
|
|
31
|
-
|
|
32
22
|
return { buildId, debugFile };
|
|
33
23
|
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Records a module and returns the created debug image.
|
|
37
|
-
*/
|
|
38
24
|
function registerModule(module, url) {
|
|
39
25
|
const { buildId, debugFile } = getModuleInfo(module);
|
|
40
26
|
if (!buildId) {
|
|
41
27
|
return null;
|
|
42
28
|
}
|
|
43
|
-
|
|
44
29
|
const oldIdx = getImage(url);
|
|
45
30
|
if (oldIdx >= 0) {
|
|
46
31
|
IMAGES.splice(oldIdx, 1);
|
|
47
32
|
}
|
|
48
|
-
|
|
49
33
|
let debugFileUrl = null;
|
|
50
34
|
if (debugFile) {
|
|
51
35
|
try {
|
|
52
36
|
debugFileUrl = new URL(debugFile, url).href;
|
|
53
37
|
} catch {
|
|
54
|
-
// debugFile could be a blob URL which causes the URL constructor to throw
|
|
55
|
-
// for now we just ignore this case
|
|
56
38
|
}
|
|
57
39
|
}
|
|
58
|
-
|
|
59
40
|
const image = {
|
|
60
|
-
type:
|
|
41
|
+
type: "wasm",
|
|
61
42
|
code_id: buildId,
|
|
62
43
|
code_file: url,
|
|
63
44
|
debug_file: debugFileUrl,
|
|
64
|
-
debug_id: `${buildId.padEnd(32,
|
|
45
|
+
debug_id: `${buildId.padEnd(32, "0").slice(0, 32)}0`
|
|
65
46
|
};
|
|
66
|
-
|
|
67
47
|
IMAGES.push(image);
|
|
68
48
|
return image;
|
|
69
49
|
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Returns all known images.
|
|
73
|
-
*/
|
|
74
50
|
function getImages() {
|
|
75
51
|
return IMAGES;
|
|
76
52
|
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Looks up an image by URL.
|
|
80
|
-
*
|
|
81
|
-
* @param url the URL of the WebAssembly module.
|
|
82
|
-
*/
|
|
83
53
|
function getImage(url) {
|
|
84
|
-
return IMAGES.findIndex(image => {
|
|
85
|
-
return image.type ===
|
|
54
|
+
return IMAGES.findIndex((image) => {
|
|
55
|
+
return image.type === "wasm" && image.code_file === url;
|
|
86
56
|
});
|
|
87
57
|
}
|
|
88
58
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sources":["../../../src/registry.ts"],"sourcesContent":["import type { DebugImage } from '@sentry/core';\n\nexport const IMAGES: Array<DebugImage> = [];\n\nexport interface ModuleInfo {\n buildId: string | null;\n debugFile: string | null;\n}\n\n/**\n * Returns the extracted meta information from a web assembly module that\n * Sentry uses to identify debug images.\n *\n * @param module\n */\nexport function getModuleInfo(module: WebAssembly.Module): ModuleInfo {\n const buildIds = WebAssembly.Module.customSections(module, 'build_id');\n let buildId = null;\n let debugFile = null;\n\n const buildId0 = buildIds[0];\n if (buildId0) {\n const firstBuildId = new Uint8Array(buildId0);\n buildId = Array.from(firstBuildId).reduce((acc, x) => {\n return acc + x.toString(16).padStart(2, '0');\n }, '');\n }\n\n const externalDebugInfo = WebAssembly.Module.customSections(module, 'external_debug_info');\n const externalDebugInfo0 = externalDebugInfo[0];\n if (externalDebugInfo0) {\n const firstExternalDebugInfo = new Uint8Array(externalDebugInfo0);\n const decoder = new TextDecoder('utf-8');\n debugFile = decoder.decode(firstExternalDebugInfo);\n }\n\n return { buildId, debugFile };\n}\n\n/**\n * Records a module and returns the created debug image.\n */\nexport function registerModule(module: WebAssembly.Module, url: string): DebugImage | null {\n const { buildId, debugFile } = getModuleInfo(module);\n if (!buildId) {\n return null;\n }\n\n const oldIdx = getImage(url);\n if (oldIdx >= 0) {\n IMAGES.splice(oldIdx, 1);\n }\n\n let debugFileUrl = null;\n if (debugFile) {\n try {\n debugFileUrl = new URL(debugFile, url).href;\n } catch {\n // debugFile could be a blob URL which causes the URL constructor to throw\n // for now we just ignore this case\n }\n }\n\n const image: DebugImage = {\n type: 'wasm',\n code_id: buildId,\n code_file: url,\n debug_file: debugFileUrl,\n debug_id: `${buildId.padEnd(32, '0').slice(0, 32)}0`,\n };\n\n IMAGES.push(image);\n return image;\n}\n\n/**\n * Returns all known images.\n */\nexport function getImages(): Array<DebugImage> {\n return IMAGES;\n}\n\n/**\n * Looks up an image by URL.\n *\n * @param url the URL of the WebAssembly module.\n */\nexport function getImage(url: string): number {\n return IMAGES.findIndex(image => {\n return image.type === 'wasm' && image.code_file === url;\n });\n}\n"],"names":[],"mappings":";;AAEO,MAAM,
|
|
1
|
+
{"version":3,"file":"registry.js","sources":["../../../src/registry.ts"],"sourcesContent":["import type { DebugImage } from '@sentry/core';\n\nexport const IMAGES: Array<DebugImage> = [];\n\nexport interface ModuleInfo {\n buildId: string | null;\n debugFile: string | null;\n}\n\n/**\n * Returns the extracted meta information from a web assembly module that\n * Sentry uses to identify debug images.\n *\n * @param module\n */\nexport function getModuleInfo(module: WebAssembly.Module): ModuleInfo {\n const buildIds = WebAssembly.Module.customSections(module, 'build_id');\n let buildId = null;\n let debugFile = null;\n\n const buildId0 = buildIds[0];\n if (buildId0) {\n const firstBuildId = new Uint8Array(buildId0);\n buildId = Array.from(firstBuildId).reduce((acc, x) => {\n return acc + x.toString(16).padStart(2, '0');\n }, '');\n }\n\n const externalDebugInfo = WebAssembly.Module.customSections(module, 'external_debug_info');\n const externalDebugInfo0 = externalDebugInfo[0];\n if (externalDebugInfo0) {\n const firstExternalDebugInfo = new Uint8Array(externalDebugInfo0);\n const decoder = new TextDecoder('utf-8');\n debugFile = decoder.decode(firstExternalDebugInfo);\n }\n\n return { buildId, debugFile };\n}\n\n/**\n * Records a module and returns the created debug image.\n */\nexport function registerModule(module: WebAssembly.Module, url: string): DebugImage | null {\n const { buildId, debugFile } = getModuleInfo(module);\n if (!buildId) {\n return null;\n }\n\n const oldIdx = getImage(url);\n if (oldIdx >= 0) {\n IMAGES.splice(oldIdx, 1);\n }\n\n let debugFileUrl = null;\n if (debugFile) {\n try {\n debugFileUrl = new URL(debugFile, url).href;\n } catch {\n // debugFile could be a blob URL which causes the URL constructor to throw\n // for now we just ignore this case\n }\n }\n\n const image: DebugImage = {\n type: 'wasm',\n code_id: buildId,\n code_file: url,\n debug_file: debugFileUrl,\n debug_id: `${buildId.padEnd(32, '0').slice(0, 32)}0`,\n };\n\n IMAGES.push(image);\n return image;\n}\n\n/**\n * Returns all known images.\n */\nexport function getImages(): Array<DebugImage> {\n return IMAGES;\n}\n\n/**\n * Looks up an image by URL.\n *\n * @param url the URL of the WebAssembly module.\n */\nexport function getImage(url: string): number {\n return IMAGES.findIndex(image => {\n return image.type === 'wasm' && image.code_file === url;\n });\n}\n"],"names":[],"mappings":";;AAEO,MAAM,SAA4B;AAalC,SAAS,cAAc,MAAA,EAAwC;AACpE,EAAA,MAAM,QAAA,GAAW,WAAA,CAAY,MAAA,CAAO,cAAA,CAAe,QAAQ,UAAU,CAAA;AACrE,EAAA,IAAI,OAAA,GAAU,IAAA;AACd,EAAA,IAAI,SAAA,GAAY,IAAA;AAEhB,EAAA,MAAM,QAAA,GAAW,SAAS,CAAC,CAAA;AAC3B,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,MAAM,YAAA,GAAe,IAAI,UAAA,CAAW,QAAQ,CAAA;AAC5C,IAAA,OAAA,GAAU,MAAM,IAAA,CAAK,YAAY,EAAE,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM;AACpD,MAAA,OAAO,MAAM,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAAA,IAC7C,GAAG,EAAE,CAAA;AAAA,EACP;AAEA,EAAA,MAAM,iBAAA,GAAoB,WAAA,CAAY,MAAA,CAAO,cAAA,CAAe,QAAQ,qBAAqB,CAAA;AACzF,EAAA,MAAM,kBAAA,GAAqB,kBAAkB,CAAC,CAAA;AAC9C,EAAA,IAAI,kBAAA,EAAoB;AACtB,IAAA,MAAM,sBAAA,GAAyB,IAAI,UAAA,CAAW,kBAAkB,CAAA;AAChE,IAAA,MAAM,OAAA,GAAU,IAAI,WAAA,CAAY,OAAO,CAAA;AACvC,IAAA,SAAA,GAAY,OAAA,CAAQ,OAAO,sBAAsB,CAAA;AAAA,EACnD;AAEA,EAAA,OAAO,EAAE,SAAS,SAAA,EAAU;AAC9B;AAKO,SAAS,cAAA,CAAe,QAA4B,GAAA,EAAgC;AACzF,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAU,GAAI,cAAc,MAAM,CAAA;AACnD,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,MAAA,GAAS,SAAS,GAAG,CAAA;AAC3B,EAAA,IAAI,UAAU,CAAA,EAAG;AACf,IAAA,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAC,CAAA;AAAA,EACzB;AAEA,EAAA,IAAI,YAAA,GAAe,IAAA;AACnB,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,IAAI;AACF,MAAA,YAAA,GAAe,IAAI,GAAA,CAAI,SAAA,EAAW,GAAG,CAAA,CAAE,IAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AAAA,IAGR;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAoB;AAAA,IACxB,IAAA,EAAM,MAAA;AAAA,IACN,OAAA,EAAS,OAAA;AAAA,IACT,SAAA,EAAW,GAAA;AAAA,IACX,UAAA,EAAY,YAAA;AAAA,IACZ,QAAA,EAAU,CAAA,EAAG,OAAA,CAAQ,MAAA,CAAO,EAAA,EAAI,GAAG,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,CAAA;AAAA,GACnD;AAEA,EAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,EAAA,OAAO,KAAA;AACT;AAKO,SAAS,SAAA,GAA+B;AAC7C,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,SAAS,GAAA,EAAqB;AAC5C,EAAA,OAAO,MAAA,CAAO,UAAU,CAAA,KAAA,KAAS;AAC/B,IAAA,OAAO,KAAA,CAAM,IAAA,KAAS,MAAA,IAAU,KAAA,CAAM,SAAA,KAAc,GAAA;AAAA,EACtD,CAAC,CAAA;AACH;;;;;;;;"}
|
package/build/npm/esm/index.js
CHANGED
|
@@ -2,22 +2,9 @@ import { defineIntegration, GLOBAL_OBJ } from '@sentry/core';
|
|
|
2
2
|
import { patchWebAssembly } from './patchWebAssembly.js';
|
|
3
3
|
import { getImage, getImages, registerModule } from './registry.js';
|
|
4
4
|
|
|
5
|
-
const INTEGRATION_NAME =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// recognizes WASM frames as first-party code without needing modifications.
|
|
9
|
-
const BUNDLER_PLUGIN_APP_KEY_PREFIX = '_sentryBundlerPluginAppKey:';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Minimal interface for DedicatedWorkerGlobalScope.
|
|
13
|
-
* We can't use the actual type because it breaks everyone who doesn't have {"lib": ["WebWorker"]}
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
// Access WINDOW with proper typing for _sentryWasmImages
|
|
17
|
-
const WINDOW = GLOBAL_OBJ
|
|
18
|
-
|
|
19
|
-
;
|
|
20
|
-
|
|
5
|
+
const INTEGRATION_NAME = "Wasm";
|
|
6
|
+
const BUNDLER_PLUGIN_APP_KEY_PREFIX = "_sentryBundlerPluginAppKey:";
|
|
7
|
+
const WINDOW = GLOBAL_OBJ;
|
|
21
8
|
const _wasmIntegration = ((options = {}) => {
|
|
22
9
|
return {
|
|
23
10
|
name: INTEGRATION_NAME,
|
|
@@ -26,86 +13,50 @@ const _wasmIntegration = ((options = {}) => {
|
|
|
26
13
|
},
|
|
27
14
|
processEvent(event) {
|
|
28
15
|
let hasAtLeastOneWasmFrameWithImage = false;
|
|
29
|
-
|
|
30
16
|
const existingImagesCount = event.debug_meta?.images?.length || 0;
|
|
31
|
-
|
|
32
17
|
if (event.exception?.values) {
|
|
33
|
-
event.exception.values.forEach(exception => {
|
|
18
|
+
event.exception.values.forEach((exception) => {
|
|
34
19
|
if (exception.stacktrace?.frames) {
|
|
35
|
-
hasAtLeastOneWasmFrameWithImage =
|
|
36
|
-
hasAtLeastOneWasmFrameWithImage ||
|
|
37
|
-
patchFrames(exception.stacktrace.frames, options.applicationKey, existingImagesCount);
|
|
20
|
+
hasAtLeastOneWasmFrameWithImage = hasAtLeastOneWasmFrameWithImage || patchFrames(exception.stacktrace.frames, options.applicationKey, existingImagesCount);
|
|
38
21
|
}
|
|
39
22
|
});
|
|
40
23
|
}
|
|
41
|
-
|
|
42
24
|
if (hasAtLeastOneWasmFrameWithImage) {
|
|
43
25
|
event.debug_meta = event.debug_meta || {};
|
|
44
26
|
const mainThreadImages = getImages();
|
|
45
27
|
const workerImages = WINDOW._sentryWasmImages || [];
|
|
46
|
-
event.debug_meta.images = [...
|
|
28
|
+
event.debug_meta.images = [...event.debug_meta.images || [], ...mainThreadImages, ...workerImages];
|
|
47
29
|
}
|
|
48
|
-
|
|
49
30
|
return event;
|
|
50
|
-
}
|
|
31
|
+
}
|
|
51
32
|
};
|
|
52
|
-
})
|
|
53
|
-
|
|
33
|
+
});
|
|
54
34
|
const wasmIntegration = defineIntegration(_wasmIntegration);
|
|
55
|
-
|
|
56
35
|
const PARSER_REGEX = /^(.*?):wasm-function\[\d+\]:(0x[a-fA-F0-9]+)$/;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Patches a list of stackframes with wasm data needed for server-side symbolication
|
|
60
|
-
* if applicable. Returns true if the provided list of stack frames had at least one
|
|
61
|
-
* matching registered image.
|
|
62
|
-
*
|
|
63
|
-
* @param frames - Stack frames to patch
|
|
64
|
-
* @param applicationKey - Optional key for third-party error filtering
|
|
65
|
-
* @param existingImagesOffset - Number of existing debug images that will be prepended
|
|
66
|
-
* to the final images array (used to calculate correct addr_mode indices)
|
|
67
|
-
*/
|
|
68
|
-
// Only exported for tests
|
|
69
|
-
function patchFrames(
|
|
70
|
-
frames,
|
|
71
|
-
applicationKey,
|
|
72
|
-
existingImagesOffset = 0,
|
|
73
|
-
) {
|
|
36
|
+
function patchFrames(frames, applicationKey, existingImagesOffset = 0) {
|
|
74
37
|
let hasAtLeastOneWasmFrameWithImage = false;
|
|
75
|
-
frames.forEach(frame => {
|
|
38
|
+
frames.forEach((frame) => {
|
|
76
39
|
if (!frame.filename) {
|
|
77
40
|
return;
|
|
78
41
|
}
|
|
79
|
-
|
|
80
|
-
const split = frame.filename.split('(');
|
|
81
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
42
|
+
const split = frame.filename.split("(");
|
|
82
43
|
const lastSplit = split[split.length - 1];
|
|
83
|
-
|
|
84
|
-
// Let's call this first match a "messy match".
|
|
85
|
-
// The browser stacktrace parser spits out frames that have a filename like this: "int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb"
|
|
86
|
-
// It contains some leftover mess because wasm stack frames are more complicated than our parser can handle: "at MyClass::bar(int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb)"
|
|
87
|
-
// This first match simply tries to mitigate the mess up until the first opening parens.
|
|
88
|
-
// The match afterwards is a sensible fallback
|
|
89
|
-
let match = lastSplit.match(PARSER_REGEX) ;
|
|
90
|
-
|
|
44
|
+
let match = lastSplit.match(PARSER_REGEX);
|
|
91
45
|
if (!match) {
|
|
92
|
-
match = frame.filename.match(PARSER_REGEX)
|
|
46
|
+
match = frame.filename.match(PARSER_REGEX);
|
|
93
47
|
}
|
|
94
|
-
|
|
95
48
|
if (match) {
|
|
96
49
|
const index = getImage(match[1]);
|
|
97
50
|
const workerImageIndex = getWorkerImage(match[1]);
|
|
98
51
|
frame.instruction_addr = match[2];
|
|
99
52
|
frame.filename = match[1];
|
|
100
|
-
frame.platform =
|
|
101
|
-
|
|
53
|
+
frame.platform = "native";
|
|
102
54
|
if (applicationKey) {
|
|
103
55
|
frame.module_metadata = {
|
|
104
56
|
...frame.module_metadata,
|
|
105
|
-
[`${BUNDLER_PLUGIN_APP_KEY_PREFIX}${applicationKey}`]: true
|
|
57
|
+
[`${BUNDLER_PLUGIN_APP_KEY_PREFIX}${applicationKey}`]: true
|
|
106
58
|
};
|
|
107
59
|
}
|
|
108
|
-
|
|
109
60
|
if (index >= 0) {
|
|
110
61
|
frame.addr_mode = `rel:${existingImagesOffset + index}`;
|
|
111
62
|
hasAtLeastOneWasmFrameWithImage = true;
|
|
@@ -116,87 +67,51 @@ function patchFrames(
|
|
|
116
67
|
}
|
|
117
68
|
}
|
|
118
69
|
});
|
|
119
|
-
|
|
120
70
|
return hasAtLeastOneWasmFrameWithImage;
|
|
121
71
|
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Looks up an image by URL in worker images.
|
|
125
|
-
*/
|
|
126
72
|
function getWorkerImage(url) {
|
|
127
73
|
const workerImages = WINDOW._sentryWasmImages || [];
|
|
128
|
-
return workerImages.findIndex(image => {
|
|
129
|
-
return image.type ===
|
|
74
|
+
return workerImages.findIndex((image) => {
|
|
75
|
+
return image.type === "wasm" && image.code_file === url;
|
|
130
76
|
});
|
|
131
77
|
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Use this function to register WASM support in a web worker.
|
|
135
|
-
*
|
|
136
|
-
* This function will:
|
|
137
|
-
* - Patch WebAssembly.instantiateStreaming and WebAssembly.compileStreaming in the worker
|
|
138
|
-
* - Forward WASM debug images to the parent thread for symbolication
|
|
139
|
-
*
|
|
140
|
-
* @param options {RegisterWebWorkerWasmOptions} Options:
|
|
141
|
-
* - `self`: The worker's global scope (self).
|
|
142
|
-
*/
|
|
143
78
|
function registerWebWorkerWasm({ self }) {
|
|
144
79
|
patchWebAssemblyWithForwarding(self);
|
|
145
80
|
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Patches the WebAssembly object in the worker scope and forwards
|
|
149
|
-
* registered modules to the parent thread.
|
|
150
|
-
*/
|
|
151
81
|
function patchWebAssemblyWithForwarding(workerSelf) {
|
|
152
|
-
if (
|
|
82
|
+
if ("instantiateStreaming" in WebAssembly) {
|
|
153
83
|
const origInstantiateStreaming = WebAssembly.instantiateStreaming;
|
|
154
|
-
WebAssembly.instantiateStreaming = function instantiateStreaming(
|
|
155
|
-
response
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return origInstantiateStreaming(response, importObject).then(rv => {
|
|
160
|
-
if (response.url) {
|
|
161
|
-
registerModuleAndForward(rv.module, response.url, workerSelf);
|
|
84
|
+
WebAssembly.instantiateStreaming = function instantiateStreaming(response, importObject) {
|
|
85
|
+
return Promise.resolve(response).then((response2) => {
|
|
86
|
+
return origInstantiateStreaming(response2, importObject).then((rv) => {
|
|
87
|
+
if (response2.url) {
|
|
88
|
+
registerModuleAndForward(rv.module, response2.url, workerSelf);
|
|
162
89
|
}
|
|
163
90
|
return rv;
|
|
164
91
|
});
|
|
165
92
|
});
|
|
166
|
-
}
|
|
93
|
+
};
|
|
167
94
|
}
|
|
168
|
-
|
|
169
|
-
if ('compileStreaming' in WebAssembly) {
|
|
95
|
+
if ("compileStreaming" in WebAssembly) {
|
|
170
96
|
const origCompileStreaming = WebAssembly.compileStreaming;
|
|
171
|
-
WebAssembly.compileStreaming = function compileStreaming(
|
|
172
|
-
source
|
|
173
|
-
|
|
174
|
-
return Promise.resolve(source).then(response => {
|
|
175
|
-
return origCompileStreaming(response).then(module => {
|
|
97
|
+
WebAssembly.compileStreaming = function compileStreaming(source) {
|
|
98
|
+
return Promise.resolve(source).then((response) => {
|
|
99
|
+
return origCompileStreaming(response).then((module) => {
|
|
176
100
|
if (response.url) {
|
|
177
101
|
registerModuleAndForward(module, response.url, workerSelf);
|
|
178
102
|
}
|
|
179
103
|
return module;
|
|
180
104
|
});
|
|
181
105
|
});
|
|
182
|
-
}
|
|
106
|
+
};
|
|
183
107
|
}
|
|
184
108
|
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Registers a WASM module and forwards its debug image to the parent thread.
|
|
188
|
-
*/
|
|
189
|
-
function registerModuleAndForward(
|
|
190
|
-
module,
|
|
191
|
-
url,
|
|
192
|
-
workerSelf,
|
|
193
|
-
) {
|
|
109
|
+
function registerModuleAndForward(module, url, workerSelf) {
|
|
194
110
|
const image = registerModule(module, url);
|
|
195
|
-
|
|
196
111
|
if (image) {
|
|
197
112
|
workerSelf.postMessage({
|
|
198
113
|
_sentryMessage: true,
|
|
199
|
-
_sentryWasmImages: [image]
|
|
114
|
+
_sentryWasmImages: [image]
|
|
200
115
|
});
|
|
201
116
|
}
|
|
202
117
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/index.ts"],"sourcesContent":["import type { DebugImage, Event, IntegrationFn, StackFrame } from '@sentry/core';\nimport { defineIntegration, GLOBAL_OBJ } from '@sentry/core';\nimport { patchWebAssembly } from './patchWebAssembly';\nimport { getImage, getImages, registerModule } from './registry';\n\nconst INTEGRATION_NAME = 'Wasm';\n\n// We use the same prefix as bundler plugins so that thirdPartyErrorFilterIntegration\n// recognizes WASM frames as first-party code without needing modifications.\nconst BUNDLER_PLUGIN_APP_KEY_PREFIX = '_sentryBundlerPluginAppKey:';\n\n/**\n * Minimal interface for DedicatedWorkerGlobalScope.\n * We can't use the actual type because it breaks everyone who doesn't have {\"lib\": [\"WebWorker\"]}\n */\ninterface MinimalDedicatedWorkerGlobalScope {\n postMessage: (message: unknown) => void;\n}\n\ninterface RegisterWebWorkerWasmOptions {\n self: MinimalDedicatedWorkerGlobalScope;\n}\n\ninterface WasmIntegrationOptions {\n /**\n * Key to identify this application for third-party error filtering.\n * This key should match one of the keys provided to the `filterKeys` option\n * of the `thirdPartyErrorFilterIntegration`.\n */\n applicationKey?: string;\n}\n\n// Access WINDOW with proper typing for _sentryWasmImages\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n _sentryWasmImages?: Array<DebugImage>;\n};\n\nconst _wasmIntegration = ((options: WasmIntegrationOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n patchWebAssembly();\n },\n processEvent(event: Event): Event {\n let hasAtLeastOneWasmFrameWithImage = false;\n\n const existingImagesCount = event.debug_meta?.images?.length || 0;\n\n if (event.exception?.values) {\n event.exception.values.forEach(exception => {\n if (exception.stacktrace?.frames) {\n hasAtLeastOneWasmFrameWithImage =\n hasAtLeastOneWasmFrameWithImage ||\n patchFrames(exception.stacktrace.frames, options.applicationKey, existingImagesCount);\n }\n });\n }\n\n if (hasAtLeastOneWasmFrameWithImage) {\n event.debug_meta = event.debug_meta || {};\n const mainThreadImages = getImages();\n const workerImages = WINDOW._sentryWasmImages || [];\n event.debug_meta.images = [...(event.debug_meta.images || []), ...mainThreadImages, ...workerImages];\n }\n\n return event;\n },\n };\n}) satisfies IntegrationFn;\n\nexport const wasmIntegration = defineIntegration(_wasmIntegration);\n\nconst PARSER_REGEX = /^(.*?):wasm-function\\[\\d+\\]:(0x[a-fA-F0-9]+)$/;\n\n/**\n * Patches a list of stackframes with wasm data needed for server-side symbolication\n * if applicable. Returns true if the provided list of stack frames had at least one\n * matching registered image.\n *\n * @param frames - Stack frames to patch\n * @param applicationKey - Optional key for third-party error filtering\n * @param existingImagesOffset - Number of existing debug images that will be prepended\n * to the final images array (used to calculate correct addr_mode indices)\n */\n// Only exported for tests\nexport function patchFrames(\n frames: Array<StackFrame>,\n applicationKey?: string,\n existingImagesOffset: number = 0,\n): boolean {\n let hasAtLeastOneWasmFrameWithImage = false;\n frames.forEach(frame => {\n if (!frame.filename) {\n return;\n }\n\n const split = frame.filename.split('(');\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSplit = split[split.length - 1]!;\n\n // Let's call this first match a \"messy match\".\n // The browser stacktrace parser spits out frames that have a filename like this: \"int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb\"\n // It contains some leftover mess because wasm stack frames are more complicated than our parser can handle: \"at MyClass::bar(int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb)\"\n // This first match simply tries to mitigate the mess up until the first opening parens.\n // The match afterwards is a sensible fallback\n let match = lastSplit.match(PARSER_REGEX) as null | [string, string, string];\n\n if (!match) {\n match = frame.filename.match(PARSER_REGEX) as null | [string, string, string];\n }\n\n if (match) {\n const index = getImage(match[1]);\n const workerImageIndex = getWorkerImage(match[1]);\n frame.instruction_addr = match[2];\n frame.filename = match[1];\n frame.platform = 'native';\n\n if (applicationKey) {\n frame.module_metadata = {\n ...frame.module_metadata,\n [`${BUNDLER_PLUGIN_APP_KEY_PREFIX}${applicationKey}`]: true,\n };\n }\n\n if (index >= 0) {\n frame.addr_mode = `rel:${existingImagesOffset + index}`;\n hasAtLeastOneWasmFrameWithImage = true;\n } else if (workerImageIndex >= 0) {\n const mainThreadImagesCount = getImages().length;\n frame.addr_mode = `rel:${existingImagesOffset + mainThreadImagesCount + workerImageIndex}`;\n hasAtLeastOneWasmFrameWithImage = true;\n }\n }\n });\n\n return hasAtLeastOneWasmFrameWithImage;\n}\n\n/**\n * Looks up an image by URL in worker images.\n */\nfunction getWorkerImage(url: string): number {\n const workerImages = WINDOW._sentryWasmImages || [];\n return workerImages.findIndex(image => {\n return image.type === 'wasm' && image.code_file === url;\n });\n}\n\n/**\n * Use this function to register WASM support in a web worker.\n *\n * This function will:\n * - Patch WebAssembly.instantiateStreaming and WebAssembly.compileStreaming in the worker\n * - Forward WASM debug images to the parent thread for symbolication\n *\n * @param options {RegisterWebWorkerWasmOptions} Options:\n * - `self`: The worker's global scope (self).\n */\nexport function registerWebWorkerWasm({ self }: RegisterWebWorkerWasmOptions): void {\n patchWebAssemblyWithForwarding(self);\n}\n\n/**\n * Patches the WebAssembly object in the worker scope and forwards\n * registered modules to the parent thread.\n */\nfunction patchWebAssemblyWithForwarding(workerSelf: MinimalDedicatedWorkerGlobalScope): void {\n if ('instantiateStreaming' in WebAssembly) {\n const origInstantiateStreaming = WebAssembly.instantiateStreaming;\n WebAssembly.instantiateStreaming = function instantiateStreaming(\n response: Response | PromiseLike<Response>,\n importObject: WebAssembly.Imports,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(response).then(response => {\n return origInstantiateStreaming(response, importObject).then(rv => {\n if (response.url) {\n registerModuleAndForward(rv.module, response.url, workerSelf);\n }\n return rv;\n });\n });\n } as typeof WebAssembly.instantiateStreaming;\n }\n\n if ('compileStreaming' in WebAssembly) {\n const origCompileStreaming = WebAssembly.compileStreaming;\n WebAssembly.compileStreaming = function compileStreaming(\n source: Response | Promise<Response>,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(source).then(response => {\n return origCompileStreaming(response).then(module => {\n if (response.url) {\n registerModuleAndForward(module, response.url, workerSelf);\n }\n return module;\n });\n });\n } as typeof WebAssembly.compileStreaming;\n }\n}\n\n/**\n * Registers a WASM module and forwards its debug image to the parent thread.\n */\nfunction registerModuleAndForward(\n module: WebAssembly.Module,\n url: string,\n workerSelf: MinimalDedicatedWorkerGlobalScope,\n): void {\n const image = registerModule(module, url);\n\n if (image) {\n workerSelf.postMessage({\n _sentryMessage: true,\n _sentryWasmImages: [image],\n });\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/index.ts"],"sourcesContent":["import type { DebugImage, Event, IntegrationFn, StackFrame } from '@sentry/core';\nimport { defineIntegration, GLOBAL_OBJ } from '@sentry/core';\nimport { patchWebAssembly } from './patchWebAssembly';\nimport { getImage, getImages, registerModule } from './registry';\n\nconst INTEGRATION_NAME = 'Wasm';\n\n// We use the same prefix as bundler plugins so that thirdPartyErrorFilterIntegration\n// recognizes WASM frames as first-party code without needing modifications.\nconst BUNDLER_PLUGIN_APP_KEY_PREFIX = '_sentryBundlerPluginAppKey:';\n\n/**\n * Minimal interface for DedicatedWorkerGlobalScope.\n * We can't use the actual type because it breaks everyone who doesn't have {\"lib\": [\"WebWorker\"]}\n */\ninterface MinimalDedicatedWorkerGlobalScope {\n postMessage: (message: unknown) => void;\n}\n\ninterface RegisterWebWorkerWasmOptions {\n self: MinimalDedicatedWorkerGlobalScope;\n}\n\ninterface WasmIntegrationOptions {\n /**\n * Key to identify this application for third-party error filtering.\n * This key should match one of the keys provided to the `filterKeys` option\n * of the `thirdPartyErrorFilterIntegration`.\n */\n applicationKey?: string;\n}\n\n// Access WINDOW with proper typing for _sentryWasmImages\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n _sentryWasmImages?: Array<DebugImage>;\n};\n\nconst _wasmIntegration = ((options: WasmIntegrationOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n patchWebAssembly();\n },\n processEvent(event: Event): Event {\n let hasAtLeastOneWasmFrameWithImage = false;\n\n const existingImagesCount = event.debug_meta?.images?.length || 0;\n\n if (event.exception?.values) {\n event.exception.values.forEach(exception => {\n if (exception.stacktrace?.frames) {\n hasAtLeastOneWasmFrameWithImage =\n hasAtLeastOneWasmFrameWithImage ||\n patchFrames(exception.stacktrace.frames, options.applicationKey, existingImagesCount);\n }\n });\n }\n\n if (hasAtLeastOneWasmFrameWithImage) {\n event.debug_meta = event.debug_meta || {};\n const mainThreadImages = getImages();\n const workerImages = WINDOW._sentryWasmImages || [];\n event.debug_meta.images = [...(event.debug_meta.images || []), ...mainThreadImages, ...workerImages];\n }\n\n return event;\n },\n };\n}) satisfies IntegrationFn;\n\nexport const wasmIntegration = defineIntegration(_wasmIntegration);\n\nconst PARSER_REGEX = /^(.*?):wasm-function\\[\\d+\\]:(0x[a-fA-F0-9]+)$/;\n\n/**\n * Patches a list of stackframes with wasm data needed for server-side symbolication\n * if applicable. Returns true if the provided list of stack frames had at least one\n * matching registered image.\n *\n * @param frames - Stack frames to patch\n * @param applicationKey - Optional key for third-party error filtering\n * @param existingImagesOffset - Number of existing debug images that will be prepended\n * to the final images array (used to calculate correct addr_mode indices)\n */\n// Only exported for tests\nexport function patchFrames(\n frames: Array<StackFrame>,\n applicationKey?: string,\n existingImagesOffset: number = 0,\n): boolean {\n let hasAtLeastOneWasmFrameWithImage = false;\n frames.forEach(frame => {\n if (!frame.filename) {\n return;\n }\n\n const split = frame.filename.split('(');\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSplit = split[split.length - 1]!;\n\n // Let's call this first match a \"messy match\".\n // The browser stacktrace parser spits out frames that have a filename like this: \"int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb\"\n // It contains some leftover mess because wasm stack frames are more complicated than our parser can handle: \"at MyClass::bar(int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb)\"\n // This first match simply tries to mitigate the mess up until the first opening parens.\n // The match afterwards is a sensible fallback\n let match = lastSplit.match(PARSER_REGEX) as null | [string, string, string];\n\n if (!match) {\n match = frame.filename.match(PARSER_REGEX) as null | [string, string, string];\n }\n\n if (match) {\n const index = getImage(match[1]);\n const workerImageIndex = getWorkerImage(match[1]);\n frame.instruction_addr = match[2];\n frame.filename = match[1];\n frame.platform = 'native';\n\n if (applicationKey) {\n frame.module_metadata = {\n ...frame.module_metadata,\n [`${BUNDLER_PLUGIN_APP_KEY_PREFIX}${applicationKey}`]: true,\n };\n }\n\n if (index >= 0) {\n frame.addr_mode = `rel:${existingImagesOffset + index}`;\n hasAtLeastOneWasmFrameWithImage = true;\n } else if (workerImageIndex >= 0) {\n const mainThreadImagesCount = getImages().length;\n frame.addr_mode = `rel:${existingImagesOffset + mainThreadImagesCount + workerImageIndex}`;\n hasAtLeastOneWasmFrameWithImage = true;\n }\n }\n });\n\n return hasAtLeastOneWasmFrameWithImage;\n}\n\n/**\n * Looks up an image by URL in worker images.\n */\nfunction getWorkerImage(url: string): number {\n const workerImages = WINDOW._sentryWasmImages || [];\n return workerImages.findIndex(image => {\n return image.type === 'wasm' && image.code_file === url;\n });\n}\n\n/**\n * Use this function to register WASM support in a web worker.\n *\n * This function will:\n * - Patch WebAssembly.instantiateStreaming and WebAssembly.compileStreaming in the worker\n * - Forward WASM debug images to the parent thread for symbolication\n *\n * @param options {RegisterWebWorkerWasmOptions} Options:\n * - `self`: The worker's global scope (self).\n */\nexport function registerWebWorkerWasm({ self }: RegisterWebWorkerWasmOptions): void {\n patchWebAssemblyWithForwarding(self);\n}\n\n/**\n * Patches the WebAssembly object in the worker scope and forwards\n * registered modules to the parent thread.\n */\nfunction patchWebAssemblyWithForwarding(workerSelf: MinimalDedicatedWorkerGlobalScope): void {\n if ('instantiateStreaming' in WebAssembly) {\n const origInstantiateStreaming = WebAssembly.instantiateStreaming;\n WebAssembly.instantiateStreaming = function instantiateStreaming(\n response: Response | PromiseLike<Response>,\n importObject: WebAssembly.Imports,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(response).then(response => {\n return origInstantiateStreaming(response, importObject).then(rv => {\n if (response.url) {\n registerModuleAndForward(rv.module, response.url, workerSelf);\n }\n return rv;\n });\n });\n } as typeof WebAssembly.instantiateStreaming;\n }\n\n if ('compileStreaming' in WebAssembly) {\n const origCompileStreaming = WebAssembly.compileStreaming;\n WebAssembly.compileStreaming = function compileStreaming(\n source: Response | Promise<Response>,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(source).then(response => {\n return origCompileStreaming(response).then(module => {\n if (response.url) {\n registerModuleAndForward(module, response.url, workerSelf);\n }\n return module;\n });\n });\n } as typeof WebAssembly.compileStreaming;\n }\n}\n\n/**\n * Registers a WASM module and forwards its debug image to the parent thread.\n */\nfunction registerModuleAndForward(\n module: WebAssembly.Module,\n url: string,\n workerSelf: MinimalDedicatedWorkerGlobalScope,\n): void {\n const image = registerModule(module, url);\n\n if (image) {\n workerSelf.postMessage({\n _sentryMessage: true,\n _sentryWasmImages: [image],\n });\n }\n}\n"],"names":["response"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"10.
|
|
1
|
+
{"type":"module","version":"10.54.0","sideEffects":false}
|
|
@@ -1,40 +1,31 @@
|
|
|
1
1
|
import { registerModule } from './registry.js';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Patches the web assembly runtime.
|
|
5
|
-
*/
|
|
6
3
|
function patchWebAssembly() {
|
|
7
|
-
if (
|
|
4
|
+
if ("instantiateStreaming" in WebAssembly) {
|
|
8
5
|
const origInstantiateStreaming = WebAssembly.instantiateStreaming;
|
|
9
|
-
WebAssembly.instantiateStreaming = function instantiateStreaming(
|
|
10
|
-
response
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return origInstantiateStreaming(response, importObject).then(rv => {
|
|
15
|
-
if (response.url) {
|
|
16
|
-
registerModule(rv.module, response.url);
|
|
6
|
+
WebAssembly.instantiateStreaming = function instantiateStreaming(response, importObject) {
|
|
7
|
+
return Promise.resolve(response).then((response2) => {
|
|
8
|
+
return origInstantiateStreaming(response2, importObject).then((rv) => {
|
|
9
|
+
if (response2.url) {
|
|
10
|
+
registerModule(rv.module, response2.url);
|
|
17
11
|
}
|
|
18
12
|
return rv;
|
|
19
13
|
});
|
|
20
14
|
});
|
|
21
|
-
}
|
|
15
|
+
};
|
|
22
16
|
}
|
|
23
|
-
|
|
24
|
-
if ('compileStreaming' in WebAssembly) {
|
|
17
|
+
if ("compileStreaming" in WebAssembly) {
|
|
25
18
|
const origCompileStreaming = WebAssembly.compileStreaming;
|
|
26
|
-
WebAssembly.compileStreaming = function compileStreaming(
|
|
27
|
-
source
|
|
28
|
-
|
|
29
|
-
return Promise.resolve(source).then(response => {
|
|
30
|
-
return origCompileStreaming(response).then(module => {
|
|
19
|
+
WebAssembly.compileStreaming = function compileStreaming(source) {
|
|
20
|
+
return Promise.resolve(source).then((response) => {
|
|
21
|
+
return origCompileStreaming(response).then((module) => {
|
|
31
22
|
if (response.url) {
|
|
32
23
|
registerModule(module, response.url);
|
|
33
24
|
}
|
|
34
25
|
return module;
|
|
35
26
|
});
|
|
36
27
|
});
|
|
37
|
-
}
|
|
28
|
+
};
|
|
38
29
|
}
|
|
39
30
|
}
|
|
40
31
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patchWebAssembly.js","sources":["../../../src/patchWebAssembly.ts"],"sourcesContent":["import { registerModule } from './registry';\n\n/**\n * Patches the web assembly runtime.\n */\nexport function patchWebAssembly(): void {\n if ('instantiateStreaming' in WebAssembly) {\n const origInstantiateStreaming = WebAssembly.instantiateStreaming;\n WebAssembly.instantiateStreaming = function instantiateStreaming(\n response: Response | PromiseLike<Response>,\n importObject: WebAssembly.Imports,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(response).then(response => {\n return origInstantiateStreaming(response, importObject).then(rv => {\n if (response.url) {\n registerModule(rv.module, response.url);\n }\n return rv;\n });\n });\n } as typeof WebAssembly.instantiateStreaming;\n }\n\n if ('compileStreaming' in WebAssembly) {\n const origCompileStreaming = WebAssembly.compileStreaming;\n WebAssembly.compileStreaming = function compileStreaming(\n source: Response | Promise<Response>,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(source).then(response => {\n return origCompileStreaming(response).then(module => {\n if (response.url) {\n registerModule(module, response.url);\n }\n return module;\n });\n });\n } as typeof WebAssembly.compileStreaming;\n }\n}\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"patchWebAssembly.js","sources":["../../../src/patchWebAssembly.ts"],"sourcesContent":["import { registerModule } from './registry';\n\n/**\n * Patches the web assembly runtime.\n */\nexport function patchWebAssembly(): void {\n if ('instantiateStreaming' in WebAssembly) {\n const origInstantiateStreaming = WebAssembly.instantiateStreaming;\n WebAssembly.instantiateStreaming = function instantiateStreaming(\n response: Response | PromiseLike<Response>,\n importObject: WebAssembly.Imports,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(response).then(response => {\n return origInstantiateStreaming(response, importObject).then(rv => {\n if (response.url) {\n registerModule(rv.module, response.url);\n }\n return rv;\n });\n });\n } as typeof WebAssembly.instantiateStreaming;\n }\n\n if ('compileStreaming' in WebAssembly) {\n const origCompileStreaming = WebAssembly.compileStreaming;\n WebAssembly.compileStreaming = function compileStreaming(\n source: Response | Promise<Response>,\n ): Promise<WebAssembly.Module> {\n return Promise.resolve(source).then(response => {\n return origCompileStreaming(response).then(module => {\n if (response.url) {\n registerModule(module, response.url);\n }\n return module;\n });\n });\n } as typeof WebAssembly.compileStreaming;\n }\n}\n"],"names":["response"],"mappings":";;AAKO,SAAS,gBAAA,GAAyB;AACvC,EAAA,IAAI,0BAA0B,WAAA,EAAa;AACzC,IAAA,MAAM,2BAA2B,WAAA,CAAY,oBAAA;AAC7C,IAAA,WAAA,CAAY,oBAAA,GAAuB,SAAS,oBAAA,CAC1C,QAAA,EACA,YAAA,EAC6B;AAC7B,MAAA,OAAO,QAAQ,OAAA,CAAQ,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAAA,SAAAA,KAAY;AAChD,QAAA,OAAO,wBAAA,CAAyBA,SAAAA,EAAU,YAAY,CAAA,CAAE,KAAK,CAAA,EAAA,KAAM;AACjE,UAAA,IAAIA,UAAS,GAAA,EAAK;AAChB,YAAA,cAAA,CAAe,EAAA,CAAG,MAAA,EAAQA,SAAAA,CAAS,GAAG,CAAA;AAAA,UACxC;AACA,UAAA,OAAO,EAAA;AAAA,QACT,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAEA,EAAA,IAAI,sBAAsB,WAAA,EAAa;AACrC,IAAA,MAAM,uBAAuB,WAAA,CAAY,gBAAA;AACzC,IAAA,WAAA,CAAY,gBAAA,GAAmB,SAAS,gBAAA,CACtC,MAAA,EAC6B;AAC7B,MAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA,CAAE,KAAK,CAAA,QAAA,KAAY;AAC9C,QAAA,OAAO,oBAAA,CAAqB,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAA,MAAA,KAAU;AACnD,UAAA,IAAI,SAAS,GAAA,EAAK;AAChB,YAAA,cAAA,CAAe,MAAA,EAAQ,SAAS,GAAG,CAAA;AAAA,UACrC;AACA,UAAA,OAAO,MAAA;AAAA,QACT,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AACF;;;;"}
|
|
@@ -1,86 +1,56 @@
|
|
|
1
1
|
const IMAGES = [];
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Returns the extracted meta information from a web assembly module that
|
|
5
|
-
* Sentry uses to identify debug images.
|
|
6
|
-
*
|
|
7
|
-
* @param module
|
|
8
|
-
*/
|
|
9
2
|
function getModuleInfo(module) {
|
|
10
|
-
const buildIds = WebAssembly.Module.customSections(module,
|
|
3
|
+
const buildIds = WebAssembly.Module.customSections(module, "build_id");
|
|
11
4
|
let buildId = null;
|
|
12
5
|
let debugFile = null;
|
|
13
|
-
|
|
14
6
|
const buildId0 = buildIds[0];
|
|
15
7
|
if (buildId0) {
|
|
16
8
|
const firstBuildId = new Uint8Array(buildId0);
|
|
17
9
|
buildId = Array.from(firstBuildId).reduce((acc, x) => {
|
|
18
|
-
return acc + x.toString(16).padStart(2,
|
|
19
|
-
},
|
|
10
|
+
return acc + x.toString(16).padStart(2, "0");
|
|
11
|
+
}, "");
|
|
20
12
|
}
|
|
21
|
-
|
|
22
|
-
const externalDebugInfo = WebAssembly.Module.customSections(module, 'external_debug_info');
|
|
13
|
+
const externalDebugInfo = WebAssembly.Module.customSections(module, "external_debug_info");
|
|
23
14
|
const externalDebugInfo0 = externalDebugInfo[0];
|
|
24
15
|
if (externalDebugInfo0) {
|
|
25
16
|
const firstExternalDebugInfo = new Uint8Array(externalDebugInfo0);
|
|
26
|
-
const decoder = new TextDecoder(
|
|
17
|
+
const decoder = new TextDecoder("utf-8");
|
|
27
18
|
debugFile = decoder.decode(firstExternalDebugInfo);
|
|
28
19
|
}
|
|
29
|
-
|
|
30
20
|
return { buildId, debugFile };
|
|
31
21
|
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Records a module and returns the created debug image.
|
|
35
|
-
*/
|
|
36
22
|
function registerModule(module, url) {
|
|
37
23
|
const { buildId, debugFile } = getModuleInfo(module);
|
|
38
24
|
if (!buildId) {
|
|
39
25
|
return null;
|
|
40
26
|
}
|
|
41
|
-
|
|
42
27
|
const oldIdx = getImage(url);
|
|
43
28
|
if (oldIdx >= 0) {
|
|
44
29
|
IMAGES.splice(oldIdx, 1);
|
|
45
30
|
}
|
|
46
|
-
|
|
47
31
|
let debugFileUrl = null;
|
|
48
32
|
if (debugFile) {
|
|
49
33
|
try {
|
|
50
34
|
debugFileUrl = new URL(debugFile, url).href;
|
|
51
35
|
} catch {
|
|
52
|
-
// debugFile could be a blob URL which causes the URL constructor to throw
|
|
53
|
-
// for now we just ignore this case
|
|
54
36
|
}
|
|
55
37
|
}
|
|
56
|
-
|
|
57
38
|
const image = {
|
|
58
|
-
type:
|
|
39
|
+
type: "wasm",
|
|
59
40
|
code_id: buildId,
|
|
60
41
|
code_file: url,
|
|
61
42
|
debug_file: debugFileUrl,
|
|
62
|
-
debug_id: `${buildId.padEnd(32,
|
|
43
|
+
debug_id: `${buildId.padEnd(32, "0").slice(0, 32)}0`
|
|
63
44
|
};
|
|
64
|
-
|
|
65
45
|
IMAGES.push(image);
|
|
66
46
|
return image;
|
|
67
47
|
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Returns all known images.
|
|
71
|
-
*/
|
|
72
48
|
function getImages() {
|
|
73
49
|
return IMAGES;
|
|
74
50
|
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Looks up an image by URL.
|
|
78
|
-
*
|
|
79
|
-
* @param url the URL of the WebAssembly module.
|
|
80
|
-
*/
|
|
81
51
|
function getImage(url) {
|
|
82
|
-
return IMAGES.findIndex(image => {
|
|
83
|
-
return image.type ===
|
|
52
|
+
return IMAGES.findIndex((image) => {
|
|
53
|
+
return image.type === "wasm" && image.code_file === url;
|
|
84
54
|
});
|
|
85
55
|
}
|
|
86
56
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sources":["../../../src/registry.ts"],"sourcesContent":["import type { DebugImage } from '@sentry/core';\n\nexport const IMAGES: Array<DebugImage> = [];\n\nexport interface ModuleInfo {\n buildId: string | null;\n debugFile: string | null;\n}\n\n/**\n * Returns the extracted meta information from a web assembly module that\n * Sentry uses to identify debug images.\n *\n * @param module\n */\nexport function getModuleInfo(module: WebAssembly.Module): ModuleInfo {\n const buildIds = WebAssembly.Module.customSections(module, 'build_id');\n let buildId = null;\n let debugFile = null;\n\n const buildId0 = buildIds[0];\n if (buildId0) {\n const firstBuildId = new Uint8Array(buildId0);\n buildId = Array.from(firstBuildId).reduce((acc, x) => {\n return acc + x.toString(16).padStart(2, '0');\n }, '');\n }\n\n const externalDebugInfo = WebAssembly.Module.customSections(module, 'external_debug_info');\n const externalDebugInfo0 = externalDebugInfo[0];\n if (externalDebugInfo0) {\n const firstExternalDebugInfo = new Uint8Array(externalDebugInfo0);\n const decoder = new TextDecoder('utf-8');\n debugFile = decoder.decode(firstExternalDebugInfo);\n }\n\n return { buildId, debugFile };\n}\n\n/**\n * Records a module and returns the created debug image.\n */\nexport function registerModule(module: WebAssembly.Module, url: string): DebugImage | null {\n const { buildId, debugFile } = getModuleInfo(module);\n if (!buildId) {\n return null;\n }\n\n const oldIdx = getImage(url);\n if (oldIdx >= 0) {\n IMAGES.splice(oldIdx, 1);\n }\n\n let debugFileUrl = null;\n if (debugFile) {\n try {\n debugFileUrl = new URL(debugFile, url).href;\n } catch {\n // debugFile could be a blob URL which causes the URL constructor to throw\n // for now we just ignore this case\n }\n }\n\n const image: DebugImage = {\n type: 'wasm',\n code_id: buildId,\n code_file: url,\n debug_file: debugFileUrl,\n debug_id: `${buildId.padEnd(32, '0').slice(0, 32)}0`,\n };\n\n IMAGES.push(image);\n return image;\n}\n\n/**\n * Returns all known images.\n */\nexport function getImages(): Array<DebugImage> {\n return IMAGES;\n}\n\n/**\n * Looks up an image by URL.\n *\n * @param url the URL of the WebAssembly module.\n */\nexport function getImage(url: string): number {\n return IMAGES.findIndex(image => {\n return image.type === 'wasm' && image.code_file === url;\n });\n}\n"],"names":[],"mappings":"AAEO,MAAM,
|
|
1
|
+
{"version":3,"file":"registry.js","sources":["../../../src/registry.ts"],"sourcesContent":["import type { DebugImage } from '@sentry/core';\n\nexport const IMAGES: Array<DebugImage> = [];\n\nexport interface ModuleInfo {\n buildId: string | null;\n debugFile: string | null;\n}\n\n/**\n * Returns the extracted meta information from a web assembly module that\n * Sentry uses to identify debug images.\n *\n * @param module\n */\nexport function getModuleInfo(module: WebAssembly.Module): ModuleInfo {\n const buildIds = WebAssembly.Module.customSections(module, 'build_id');\n let buildId = null;\n let debugFile = null;\n\n const buildId0 = buildIds[0];\n if (buildId0) {\n const firstBuildId = new Uint8Array(buildId0);\n buildId = Array.from(firstBuildId).reduce((acc, x) => {\n return acc + x.toString(16).padStart(2, '0');\n }, '');\n }\n\n const externalDebugInfo = WebAssembly.Module.customSections(module, 'external_debug_info');\n const externalDebugInfo0 = externalDebugInfo[0];\n if (externalDebugInfo0) {\n const firstExternalDebugInfo = new Uint8Array(externalDebugInfo0);\n const decoder = new TextDecoder('utf-8');\n debugFile = decoder.decode(firstExternalDebugInfo);\n }\n\n return { buildId, debugFile };\n}\n\n/**\n * Records a module and returns the created debug image.\n */\nexport function registerModule(module: WebAssembly.Module, url: string): DebugImage | null {\n const { buildId, debugFile } = getModuleInfo(module);\n if (!buildId) {\n return null;\n }\n\n const oldIdx = getImage(url);\n if (oldIdx >= 0) {\n IMAGES.splice(oldIdx, 1);\n }\n\n let debugFileUrl = null;\n if (debugFile) {\n try {\n debugFileUrl = new URL(debugFile, url).href;\n } catch {\n // debugFile could be a blob URL which causes the URL constructor to throw\n // for now we just ignore this case\n }\n }\n\n const image: DebugImage = {\n type: 'wasm',\n code_id: buildId,\n code_file: url,\n debug_file: debugFileUrl,\n debug_id: `${buildId.padEnd(32, '0').slice(0, 32)}0`,\n };\n\n IMAGES.push(image);\n return image;\n}\n\n/**\n * Returns all known images.\n */\nexport function getImages(): Array<DebugImage> {\n return IMAGES;\n}\n\n/**\n * Looks up an image by URL.\n *\n * @param url the URL of the WebAssembly module.\n */\nexport function getImage(url: string): number {\n return IMAGES.findIndex(image => {\n return image.type === 'wasm' && image.code_file === url;\n });\n}\n"],"names":[],"mappings":"AAEO,MAAM,SAA4B;AAalC,SAAS,cAAc,MAAA,EAAwC;AACpE,EAAA,MAAM,QAAA,GAAW,WAAA,CAAY,MAAA,CAAO,cAAA,CAAe,QAAQ,UAAU,CAAA;AACrE,EAAA,IAAI,OAAA,GAAU,IAAA;AACd,EAAA,IAAI,SAAA,GAAY,IAAA;AAEhB,EAAA,MAAM,QAAA,GAAW,SAAS,CAAC,CAAA;AAC3B,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,MAAM,YAAA,GAAe,IAAI,UAAA,CAAW,QAAQ,CAAA;AAC5C,IAAA,OAAA,GAAU,MAAM,IAAA,CAAK,YAAY,EAAE,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM;AACpD,MAAA,OAAO,MAAM,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAAA,IAC7C,GAAG,EAAE,CAAA;AAAA,EACP;AAEA,EAAA,MAAM,iBAAA,GAAoB,WAAA,CAAY,MAAA,CAAO,cAAA,CAAe,QAAQ,qBAAqB,CAAA;AACzF,EAAA,MAAM,kBAAA,GAAqB,kBAAkB,CAAC,CAAA;AAC9C,EAAA,IAAI,kBAAA,EAAoB;AACtB,IAAA,MAAM,sBAAA,GAAyB,IAAI,UAAA,CAAW,kBAAkB,CAAA;AAChE,IAAA,MAAM,OAAA,GAAU,IAAI,WAAA,CAAY,OAAO,CAAA;AACvC,IAAA,SAAA,GAAY,OAAA,CAAQ,OAAO,sBAAsB,CAAA;AAAA,EACnD;AAEA,EAAA,OAAO,EAAE,SAAS,SAAA,EAAU;AAC9B;AAKO,SAAS,cAAA,CAAe,QAA4B,GAAA,EAAgC;AACzF,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAU,GAAI,cAAc,MAAM,CAAA;AACnD,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,MAAA,GAAS,SAAS,GAAG,CAAA;AAC3B,EAAA,IAAI,UAAU,CAAA,EAAG;AACf,IAAA,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAC,CAAA;AAAA,EACzB;AAEA,EAAA,IAAI,YAAA,GAAe,IAAA;AACnB,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,IAAI;AACF,MAAA,YAAA,GAAe,IAAI,GAAA,CAAI,SAAA,EAAW,GAAG,CAAA,CAAE,IAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AAAA,IAGR;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAoB;AAAA,IACxB,IAAA,EAAM,MAAA;AAAA,IACN,OAAA,EAAS,OAAA;AAAA,IACT,SAAA,EAAW,GAAA;AAAA,IACX,UAAA,EAAY,YAAA;AAAA,IACZ,QAAA,EAAU,CAAA,EAAG,OAAA,CAAQ,MAAA,CAAO,EAAA,EAAI,GAAG,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,CAAA;AAAA,GACnD;AAEA,EAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,EAAA,OAAO,KAAA;AACT;AAKO,SAAS,SAAA,GAA+B;AAC7C,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,SAAS,GAAA,EAAqB;AAC5C,EAAA,OAAO,MAAA,CAAO,UAAU,CAAA,KAAA,KAAS;AAC/B,IAAA,OAAO,KAAA,CAAM,IAAA,KAAS,MAAA,IAAU,KAAA,CAAM,SAAA,KAAc,GAAA;AAAA,EACtD,CAAC,CAAA;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/wasm",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.54.0",
|
|
4
4
|
"description": "Support for WASM.",
|
|
5
5
|
"repository": "git://github.com/getsentry/sentry-javascript.git",
|
|
6
6
|
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/wasm",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@sentry/browser": "10.
|
|
43
|
-
"@sentry/core": "10.
|
|
42
|
+
"@sentry/browser": "10.54.0",
|
|
43
|
+
"@sentry/core": "10.54.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "run-p build:transpile build:bundle build:types",
|