@contrast/rewriter 1.39.0 → 1.40.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/lib/cache.js CHANGED
@@ -141,52 +141,6 @@ module.exports.Cache = class Cache {
141
141
  }
142
142
  }
143
143
 
144
- /**
145
- * Asynchronously looks up and returns the source map for a previously rewritten file.
146
- * @param {string} filename
147
- * @returns {Promise<string | undefined>}
148
- */
149
- async readMap(filename) {
150
- const filenameCached = this.getCachedFilename(filename);
151
- const sourceMap = `${filenameCached}.map`;
152
-
153
- try {
154
- return fsPromises.readFile(sourceMap, 'utf8');
155
- } catch (err) {
156
- // @ts-expect-error ts treats errors poorly.
157
- if (err.code !== 'ENOENT') {
158
- this.logger.warn(
159
- { err, filename, filenameCached, sourceMap },
160
- 'An unexpected error occurred finding source map.'
161
- );
162
- }
163
- return undefined;
164
- }
165
- }
166
-
167
-
168
- /**
169
- * Synchronously looks up and returns the source map for a previously rewritten file.
170
- * @param {string} filename
171
- * @returns {string | undefined}
172
- */
173
- readMapSync(filename) {
174
- const filenameCached = this.getCachedFilename(filename);
175
- const sourceMap = `${filenameCached}.map`;
176
- try {
177
- return fs.readFileSync(sourceMap, 'utf8');
178
- } catch (err) {
179
- // @ts-expect-error ts treats errors poorly.
180
- if (err.code !== 'ENOENT') {
181
- this.logger.warn(
182
- { err, filename, filenameCached, sourceMap },
183
- 'An unexpected error occurred finding source map.'
184
- );
185
- }
186
- return undefined;
187
- }
188
- }
189
-
190
144
  /**
191
145
  * Looks up and returns the string content of a previously rewritten file
192
146
  * synchronously. Used when we need to block on cache lookups.
package/lib/index.js CHANGED
@@ -15,8 +15,7 @@
15
15
  // @ts-check
16
16
  'use strict';
17
17
  const { arch, platform } = require('node:os');
18
- // @ts-expect-error
19
- const { SourceMapConsumer: SourceMapConsumerSync } = require('@contrast/synchronous-source-maps');
18
+ const { findSourceMap } = require('node:module');
20
19
  const { parseSync, transform, transformSync } = require('@swc/core');
21
20
  // @ts-expect-error `@contrast/agent-swc-plugin` .d.ts file doesn't exist.
22
21
  const { defaultRewriter, defaultUnwriter } = require('@contrast/agent-swc-plugin');
@@ -70,7 +69,7 @@ class Rewriter {
70
69
  */
71
70
  swcOptions(opts) {
72
71
  const nodeCfg = this.core.config.agent.node;
73
- const sourceMaps = nodeCfg.source_maps.enable;
72
+ const sourceMaps = nodeCfg.source_maps.inline ? 'inline' : nodeCfg.source_maps.enable;
74
73
  const minify = opts.minify && nodeCfg.source_maps.enable && nodeCfg.rewrite.minify;
75
74
  opts.minify = minify;
76
75
  return {
@@ -110,22 +109,23 @@ class Rewriter {
110
109
  * - result.map.sources array
111
110
  * @param {RewriteOpts} rewriteOpts
112
111
  * @param {import('@swc/core').Output} result
112
+ * @returns {import('@swc/core').Output}
113
113
  */
114
- adjustMap(rewriteOpts, result) {
114
+ adjustResult(rewriteOpts, result) {
115
115
  if (rewriteOpts.filename && result.map) {
116
116
  const map = JSON.parse(result.map);
117
117
  const cachedFilename = this.cache.getCachedFilename(rewriteOpts.filename);
118
- const absoluteCachedMapName = `${cachedFilename}.map`;
119
- const origMapURL = `${primordials.PathBasename(rewriteOpts.filename)}.map`;
120
- const comment = `${MAGIC_COMMENT_PREFIX}${origMapURL}`;
121
118
 
122
119
  // 1) magic comment
123
120
  // https://github.com/nodejs/node/blob/main/lib/internal/source_map/source_map_cache.js#L134-L136
124
- const i = result.code.lastIndexOf(comment);
121
+ const i = result.code.lastIndexOf(MAGIC_COMMENT_PREFIX);
125
122
  if (i >= 0) {
126
123
  let code = primordials.StringPrototypeSubstr.call(result.code, 0, i);
127
- code += `${MAGIC_COMMENT_PREFIX}${absoluteCachedMapName}`;
124
+ code += `${MAGIC_COMMENT_PREFIX}${cachedFilename}.map`;
128
125
  result.code = code;
126
+ } else {
127
+ // if the comment is missing entirely, add it
128
+ result.code += `${MAGIC_COMMENT_PREFIX}${cachedFilename}.map`;
129
129
  }
130
130
  // 2) map.sources array
131
131
  for (let i = 0; i < map.sources?.length; i++) {
@@ -140,6 +140,8 @@ class Rewriter {
140
140
  // reasign modified map
141
141
  result.map = primordials.JSONStringify(map);
142
142
  }
143
+
144
+ return result;
143
145
  }
144
146
 
145
147
  /**
@@ -153,9 +155,8 @@ class Rewriter {
153
155
  async rewrite(content, opts = {}) {
154
156
  const rewriteOpts = this.swcOptions(opts);
155
157
  this.logger.trace({ opts }, 'rewriting %s', opts.filename);
156
- const ret = await transform(content, rewriteOpts);
157
- this.adjustMap(rewriteOpts, ret);
158
- return ret;
158
+ const result = await transform(content, rewriteOpts);
159
+ return this.adjustResult(rewriteOpts, result);
159
160
  }
160
161
 
161
162
  /**
@@ -171,8 +172,7 @@ class Rewriter {
171
172
  const rewriteOpts = this.swcOptions(opts);
172
173
  this.logger.trace({ opts }, 'rewriting %s', opts.filename);
173
174
  const result = transformSync(content, rewriteOpts);
174
- this.adjustMap(rewriteOpts, result);
175
- return result;
175
+ return this.adjustResult(rewriteOpts, result);
176
176
  }
177
177
 
178
178
  /**
@@ -198,18 +198,11 @@ class Rewriter {
198
198
  }
199
199
 
200
200
  /**
201
- * TODO implement for async scenarios using newer versions of source-map
202
- * @param {function} func
203
- */
204
- async funcInfo(func) {
205
- throw new Error('funcInfo is not implemented');
206
- }
207
-
208
- /**
209
- * @param {function} func
201
+ * @param {Function} func
202
+ * @returns {any} replace with {import('@contrast/fn-inspect').FuncInfo} once exported from fn-inspect
210
203
  */
211
204
  funcInfoSync(func) {
212
- /** @type any */
205
+ /** @type {any} {import('@contrast/fn-inspect').FuncInfo} */
213
206
  const fnInfo = funcInfo(func);
214
207
 
215
208
  if (
@@ -219,17 +212,20 @@ class Rewriter {
219
212
  !this.core.config.agent.node.source_maps.enable
220
213
  ) return fnInfo;
221
214
 
222
- const map = this.cache.readMapSync(fnInfo.file);
223
- if (!map) return fnInfo;
215
+ try {
216
+ const map = findSourceMap(fnInfo.file);
217
+ if (!map) return fnInfo;
224
218
 
225
- const orig = new SourceMapConsumerSync(map).originalPositionFor({
226
- line: fnInfo.lineNumber + 1,
227
- column: fnInfo.column,
228
- });
229
- if (orig) {
230
- fnInfo.file = orig.source ? primordials.PathResolve(fnInfo.file, '..', orig.source) : fnInfo.file;
231
- fnInfo.lineNumber = orig.line;
232
- fnInfo.column = orig.column;
219
+ const entry = map.findEntry(fnInfo.lineNumber, fnInfo.column);
220
+ if (entry) {
221
+ fnInfo.file = entry.originalSource ? primordials.PathResolve(fnInfo.file, '..', entry.originalSource) : fnInfo.file;
222
+
223
+ // fn-inspect and source map entries are 0 indexed, but stack traces display 1-indexed lines and columns.
224
+ fnInfo.lineNumber = entry.originalLine + 1;
225
+ fnInfo.column = entry.originalColumn + 1;
226
+ }
227
+ } catch (err) {
228
+ this.logger.debug({ err, fnInfo }, 'findSourceMap failed for %s', fnInfo.file);
233
229
  }
234
230
 
235
231
  return fnInfo;
@@ -60,12 +60,20 @@ const DEADZONED_PATHS = [
60
60
  'moment-timezone',
61
61
  'node-forge',
62
62
  'node-webpack',
63
+ `@opentelemetry${sep}api`,
64
+ `@opentelemetry${sep}core`,
65
+ `@opentelemetry${sep}instrumentation`,
66
+ `@opentelemetry${sep}resources`,
67
+ `@opentelemetry${sep}sdk-metrics`,
68
+ `@opentelemetry${sep}sdk-trace-base`,
69
+ `@opentelemetry${sep}sdk-trace-node`,
63
70
  'pem',
64
71
  'react',
65
72
  'react-dom', // doesn't this cover the next line?
66
73
  //'react-dom/server',
67
74
  'requirejs',
68
75
  'semver',
76
+ '@sentry',
69
77
  'strong-remoting',
70
78
  'type-is',
71
79
  'uglify-js',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/rewriter",
3
- "version": "1.39.0",
3
+ "version": "1.40.0",
4
4
  "description": "A transpilation tool mainly used for instrumentation",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
@@ -21,12 +21,11 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@contrast/agent-swc-plugin": "3.2.0",
24
- "@contrast/common": "1.41.0",
25
- "@contrast/config": "1.57.0",
26
- "@contrast/core": "1.62.0",
24
+ "@contrast/common": "1.41.1",
25
+ "@contrast/config": "1.58.0",
26
+ "@contrast/core": "1.63.0",
27
27
  "@contrast/fn-inspect": "^5.0.2",
28
- "@contrast/logger": "1.35.0",
29
- "@contrast/synchronous-source-maps": "^1.1.5",
28
+ "@contrast/logger": "1.36.0",
30
29
  "@swc/core": "1.13.3"
31
30
  }
32
31
  }