diff --git a/.yarn/cache/meriyah-npm-4.3.7-18d2504ccb-537fed1981.zip b/.yarn/cache/meriyah-npm-4.3.7-18d2504ccb-537fed1981.zip deleted file mode 100644 index f75dac6d..00000000 Binary files a/.yarn/cache/meriyah-npm-4.3.7-18d2504ccb-537fed1981.zip and /dev/null differ diff --git a/.yarn/cache/meriyah-npm-5.0.0-2cc74cfe0a-bdd628ab95.zip b/.yarn/cache/meriyah-npm-5.0.0-2cc74cfe0a-bdd628ab95.zip new file mode 100644 index 00000000..4200bdac Binary files /dev/null and b/.yarn/cache/meriyah-npm-5.0.0-2cc74cfe0a-bdd628ab95.zip differ diff --git a/package.json b/package.json index 9839bd92..61320f16 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "astring": "^1.8.6", "chalk": "<5", "json5": "^2.2.3", - "meriyah": "^4.3.7", + "meriyah": "^5.0.0", "source-map-js": "^1.0.2", "stack-utils": "^2.0.6", "yaml": "^2.3.4" diff --git a/src/config.ts b/src/config.ts index ed959f8d..b4f63c06 100644 --- a/src/config.ts +++ b/src/config.ts @@ -128,6 +128,10 @@ export class Config { }; } + // For easily toggling features/fixes for testing. + readonly addJsonImportAttributes = true; + readonly fixJsonImportAssertions = true; + migrate() { if (!this.migrationPending) return; diff --git a/src/loader.ts b/src/loader.ts index 6b68cfd1..ca1ac13b 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -48,7 +48,17 @@ export const load: NodeLoaderHooksAPI2["load"] = async function load(url, contex const original = await defaultLoad(url, context, defaultLoad); if (original.source) { - const xformed = transform(original.source.toString(), new URL(url)); + let xformed = transform(original.source.toString(), new URL(url)); + + if (config.addJsonImportAttributes) { + // Add import attributes to json imports if they don't have it. + // Import-attributes is lost after generating the instrumented + // code from the AST with the Astring library. + const regex = /(import\s+\w+\s+from\s+['"][^'"]+\.json['"])\s*;/g; + xformed = xformed.replace(regex, (match, importPart) => { + return `${importPart} with {type: "json"};`; + }); + } return { shortCircuit: false, diff --git a/src/transform.ts b/src/transform.ts index 860b2803..c8844700 100644 --- a/src/transform.ts +++ b/src/transform.ts @@ -14,6 +14,7 @@ import * as mocha from "./hooks/mocha"; import * as next from "./hooks/next"; import * as vitest from "./hooks/vitest"; import { warn } from "./message"; +import config from "./config"; const debug = debuglog("appmap"); const treeDebug = debuglog("appmap-tree"); @@ -41,6 +42,14 @@ export default function transform(code: string, url: URL, hooks = defaultHooks): if (hooks.some((h) => h.shouldIgnore?.(url))) return code; + if (config.fixJsonImportAssertions) { + // Meriyah does not support old import-assertions. + // Replace import-assertions with the import-attributes syntax + // for json imports. + const regex = /assert\s*\{\s*type\s*:\s*"json"\s*\}/g; + code = code.replace(regex, 'with {type: "json"}'); + } + try { const comments: ESTree.Comment[] = []; const tree = parse(code, { diff --git a/test/__snapshots__/simple.test.ts.snap b/test/__snapshots__/simple.test.ts.snap index 00d03c66..f8908ab5 100644 --- a/test/__snapshots__/simple.test.ts.snap +++ b/test/__snapshots__/simple.test.ts.snap @@ -277,6 +277,70 @@ exports[`mapping a custom Error class with a message property 1`] = ` } `; +exports[`mapping a script with import attributes/assertions 1`] = ` +{ + "classMap": [ + { + "children": [ + { + "children": [ + { + "location": "importAttributes.mjs:3", + "name": "helloWorld", + "static": true, + "type": "function", + }, + ], + "name": "importAttributes", + "type": "class", + }, + ], + "name": "simple", + "type": "package", + }, + ], + "events": [ + { + "defined_class": "importAttributes", + "event": "call", + "id": 1, + "lineno": 3, + "method_id": "helloWorld", + "parameters": [], + "path": "importAttributes.mjs", + "static": true, + "thread_id": 0, + }, + { + "elapsed": 31.337, + "event": "return", + "id": 2, + "parent_id": 1, + "thread_id": 0, + }, + ], + "metadata": { + "app": "simple", + "client": { + "name": "appmap-node", + "url": "https://github.com/getappmap/appmap-node", + "version": "test node-appmap version", + }, + "language": { + "engine": "Node.js", + "name": "javascript", + "version": "test node version", + }, + "name": "test process recording", + "recorder": { + "name": "process", + "type": "process", + }, + }, + "version": "1.12", +} +`; + exports[`mapping a simple script 1`] = ` { "classMap": [ diff --git a/test/simple.test.ts b/test/simple.test.ts index ff1a421a..63c628a3 100644 --- a/test/simple.test.ts +++ b/test/simple.test.ts @@ -27,6 +27,11 @@ integrationTest("mapping an mjs script", () => { expect(readAppmap()).toMatchSnapshot(); }); +integrationTest("mapping a script with import attributes/assertions", () => { + expect(runAppmapNode("importAttributes.mjs").status).toBe(0); + expect(readAppmap()).toMatchSnapshot(); +}); + integrationTest("mapping js class methods and constructors containing super keyword", () => { expect(runAppmapNode("class.js").status).toBe(0); expect(readAppmap()).toMatchSnapshot(); diff --git a/test/simple/importAttributes.json b/test/simple/importAttributes.json new file mode 100644 index 00000000..b42e2f20 --- /dev/null +++ b/test/simple/importAttributes.json @@ -0,0 +1,3 @@ +{ + "content": "This is for the import attributes test" +} \ No newline at end of file diff --git a/test/simple/importAttributes.mjs b/test/simple/importAttributes.mjs new file mode 100644 index 00000000..3be46bf8 --- /dev/null +++ b/test/simple/importAttributes.mjs @@ -0,0 +1,7 @@ +import importedJson from "./importAttributes.json" assert { type: "json" }; + +export function helloWorld() { + console.log(importedJson); +} + +helloWorld(); diff --git a/yarn.lock b/yarn.lock index 0b593205..3fce350c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2774,7 +2774,7 @@ __metadata: fast-glob: ^3.3.1 jest: ^29.6.2 json5: ^2.2.3 - meriyah: ^4.3.7 + meriyah: ^5.0.0 mongodb: ^6.3.0 next: ^14.0.4 prettier: ^3.0.2 @@ -6854,10 +6854,10 @@ __metadata: languageName: node linkType: hard -"meriyah@npm:^4.3.7": - version: 4.3.7 - resolution: "meriyah@npm:4.3.7" - checksum: 537fed1981bb4c2dc5fffa0c2d159fc169bff252e7a31c8b15ce3ddb9e91d8b66cacf5c932d7fc31bd522dd70d9b007e19131ac40172cd3bd27feee79c447041 +"meriyah@npm:^5.0.0": + version: 5.0.0 + resolution: "meriyah@npm:5.0.0" + checksum: bdd628ab956fca90d44334cc4538cdcde73bff5cf64c32aee3ddce808fe77591fcd6e6c141ec0fc5a6451776f55f6600cdcc53643b106a9e09974f169c697961 languageName: node linkType: hard