From 2755c16df4d0c7a19c0a830da1f4fd939bc0d352 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Mon, 28 Mar 2022 02:43:28 -0300 Subject: [PATCH 01/27] Implement unparenthesized REPL object literals --- src/repl.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/repl.ts b/src/repl.ts index ae48c7816..650149b23 100644 --- a/src/repl.ts +++ b/src/repl.ts @@ -509,6 +509,7 @@ function appendCompileAndEvalInput(options: { service: Service; state: EvalState; input: string; + wrappedErr?: unknown; /** Enable top-level await but only if the TSNode service allows it. */ enableTopLevelAwait?: boolean; context: Context | undefined; @@ -516,10 +517,22 @@ function appendCompileAndEvalInput(options: { const { service, state, - input, + wrappedErr, enableTopLevelAwait = false, context, } = options; + let { input } = options; + + // It's confusing for `{ a: 1 }` to be interpreted as a block statement + // rather than an object literal. So, we first try to wrap it in + // parentheses, so that it will be interpreted as an expression. + // Based on https://github.com/nodejs/node/blob/c2e6822153bad023ab7ebd30a6117dcc049e475c/lib/repl.js#L413-L422 + let wrappedCmd = false; + if (!wrappedErr && /^\s*{/.test(input) && !/;\s*$/.test(input)) { + input = `(${input.trim()})\n`; + wrappedCmd = true; + } + const lines = state.lines; const isCompletion = !/\n$/.test(input); const undo = appendToEvalState(state, input); @@ -536,6 +549,16 @@ function appendCompileAndEvalInput(options: { output = service.compile(state.input, state.path, -lines); } catch (err) { undo(); + + if (wrappedCmd) { + // Unwrap and try again + return appendCompileAndEvalInput({ + ...options, + wrappedErr: err + }); + } + + if (wrappedErr) throw wrappedErr; throw err; } @@ -689,6 +712,10 @@ const RECOVERY_CODES: Map | null> = new Map([ [1005, null], // "')' expected.", "'}' expected." [1109, null], // "Expression expected." [1126, null], // "Unexpected end of text." + [ + 1136, // "Property assignment expected." + new Set([1005]), // happens when typing out an object literal or block scope across multiple lines: '{ foo: 123,' + ], [1160, null], // "Unterminated template literal." [1161, null], // "Unterminated regular expression literal." [2355, null], // "A function whose declared type is neither 'void' nor 'any' must return a value." From 908ada84e68daea309ead85982532dd9fef26693 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Mon, 28 Mar 2022 02:52:56 -0300 Subject: [PATCH 02/27] Fix property access error inconsistency --- src/repl.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/repl.ts b/src/repl.ts index 650149b23..4a34134f9 100644 --- a/src/repl.ts +++ b/src/repl.ts @@ -551,6 +551,10 @@ function appendCompileAndEvalInput(options: { undo(); if (wrappedCmd) { + if (err instanceof TSError && err.diagnosticCodes[0] === 2339) { + // Ensure consistent and more sane behavior between { a: 1 }['b'] and ({ a: 1 }['b']) + throw err; + } // Unwrap and try again return appendCompileAndEvalInput({ ...options, From 87329cde7115507f4e68b6ef184cfc26c1d7014a Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:15:04 -0300 Subject: [PATCH 03/27] Run prettier on src/repl.ts --- src/repl.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/repl.ts b/src/repl.ts index 4a34134f9..8fff58b6e 100644 --- a/src/repl.ts +++ b/src/repl.ts @@ -558,7 +558,7 @@ function appendCompileAndEvalInput(options: { // Unwrap and try again return appendCompileAndEvalInput({ ...options, - wrappedErr: err + wrappedErr: err, }); } @@ -719,7 +719,7 @@ const RECOVERY_CODES: Map | null> = new Map([ [ 1136, // "Property assignment expected." new Set([1005]), // happens when typing out an object literal or block scope across multiple lines: '{ foo: 123,' - ], + ], [1160, null], // "Unterminated template literal." [1161, null], // "Unterminated regular expression literal." [2355, null], // "A function whose declared type is neither 'void' nor 'any' must return a value." From e45f27fb5c9a3d660e74d135e10aa3b9321a7d71 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Mon, 28 Mar 2022 04:40:56 -0300 Subject: [PATCH 04/27] Add cross-env as dev dependency --- package-lock.json | 9 +++++++++ package.json | 1 + 2 files changed, 10 insertions(+) diff --git a/package-lock.json b/package-lock.json index 19319b310..0d129c392 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1885,6 +1885,15 @@ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.0.tgz", "integrity": "sha512-yEFVS7dQjDXp5iOEtWisN4uFmL+pUTyIaEizKda9Eb77XX58p6pgFOLAPaBCP+IR6ZPZ1jgJLAuf+ABk0zXYBQ==" }, + "cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, "cross-spawn": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", diff --git a/package.json b/package.json index 1f158f1fb..d5ca71149 100644 --- a/package.json +++ b/package.json @@ -126,6 +126,7 @@ "ava": "^3.15.0", "axios": "^0.21.1", "chai": "^4.0.1", + "cross-env": "^7.0.3", "expect": "^27.0.2", "get-stream": "^6.0.0", "lodash": "^4.17.15", From ca24458a6b5648487284ed35ec636508432ed603 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Mon, 28 Mar 2022 05:00:42 -0300 Subject: [PATCH 05/27] Fix issue preventing tests from running on envs with NODE_PATH set --- ava.config.cjs | 9 ++++++++- package.json | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ava.config.cjs b/ava.config.cjs index aa04b33bf..790ab3d4c 100644 --- a/ava.config.cjs +++ b/ava.config.cjs @@ -21,7 +21,14 @@ module.exports = { /* * Tests *must* install and use our most recent ts-node tarball. * We must prevent them from accidentally require-ing a different version of - * ts-node, from either node_modules or tests/node_modules + * ts-node, from either node_modules or tests/node_modules. + * + * Another possibility of interference is NODE_PATH environment variable being set, + * and ts-node being installed globally or in any of the paths in NODE_PATH, to fix this, + * we must remove NODE_PATH from the environment variables *BEFORE* running ava, + * as seen in the test-spec npm script using cross-env for interop between OS'es. + * This is not a breaking change, as calling ava directly with NODE_PATH unset will also still work, + * it is only strictly required for environments where NODE_PATH is set to folders containing ts-node. */ const { existsSync } = require('fs'); diff --git a/package.json b/package.json index d5ca71149..e4ed2fe4e 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "build-tsc": "tsc", "build-configSchema": "typescript-json-schema --topRef --refs --validationKeywords allOf --out tsconfig.schema.json tsconfig.build-schema.json TsConfigSchema && node --require ./register ./scripts/create-merged-schema", "build-pack": "node ./scripts/build-pack.js", - "test-spec": "ava", + "test-spec": "cross-env NODE_PATH='' ava", "test-cov": "nyc ava", "test": "npm run build && npm run lint && npm run test-cov --", "test-local": "npm run lint-fix && npm run build-tsc && npm run build-pack && npm run test-spec --", From 713ae2ee4dbb8de97db5912c3e77af982d92486d Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Mon, 28 Mar 2022 05:10:26 -0300 Subject: [PATCH 06/27] Silence deprecation warning spam on tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e4ed2fe4e..ae6c2126c 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "build-tsc": "tsc", "build-configSchema": "typescript-json-schema --topRef --refs --validationKeywords allOf --out tsconfig.schema.json tsconfig.build-schema.json TsConfigSchema && node --require ./register ./scripts/create-merged-schema", "build-pack": "node ./scripts/build-pack.js", - "test-spec": "cross-env NODE_PATH='' ava", + "test-spec": "cross-env NODE_PATH='' ava --node-arguments='--no-deprecation'", "test-cov": "nyc ava", "test": "npm run build && npm run lint && npm run test-cov --", "test-local": "npm run lint-fix && npm run build-tsc && npm run build-pack && npm run test-spec --", From 3dacbd3ed9d1570311904fb1c9bc19f304c7ef01 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Mon, 28 Mar 2022 05:29:37 -0300 Subject: [PATCH 07/27] Single quotes caused some cli bugs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae6c2126c..2303eabb6 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "build-tsc": "tsc", "build-configSchema": "typescript-json-schema --topRef --refs --validationKeywords allOf --out tsconfig.schema.json tsconfig.build-schema.json TsConfigSchema && node --require ./register ./scripts/create-merged-schema", "build-pack": "node ./scripts/build-pack.js", - "test-spec": "cross-env NODE_PATH='' ava --node-arguments='--no-deprecation'", + "test-spec": "cross-env NODE_PATH= ava --node-arguments=--no-deprecation", "test-cov": "nyc ava", "test": "npm run build && npm run lint && npm run test-cov --", "test-local": "npm run lint-fix && npm run build-tsc && npm run build-pack && npm run test-spec --", From db5ebb3f5680e1a01ff424027a6ec2e688fc5e18 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Mon, 28 Mar 2022 06:32:31 -0300 Subject: [PATCH 08/27] Add REPL object literal tests --- src/test/repl/repl.spec.ts | 115 +++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/src/test/repl/repl.spec.ts b/src/test/repl/repl.spec.ts index d23ed445e..4e7a50703 100644 --- a/src/test/repl/repl.spec.ts +++ b/src/test/repl/repl.spec.ts @@ -537,3 +537,118 @@ test.suite('REPL declares types for node built-ins within REPL', (test) => { expect(stderr).toBe(''); }); }); + +test.suite( + 'REPL treats object literals and block scopes correctly', + (test) => { + test('repl should treat { key: 123 } as object literal', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }\n', + }); + expect(stdout).toContain('{ key: 123 }'); + }); + test('repl should treat ({ key: 123 }) as object literal', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '({ key: 123 })\n', + }); + expect(stdout).toContain('{ key: 123 }'); + }); + test('repl should treat ({ let v = 0; v; }) as object literal and error', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '({ let v = 0; v; })\n', + }); + expect(stderr).toContain('No value exists in scope for the shorthand property'); + }); + test('repl should treat { let v = 0; v; } as block scope', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ let v = 0; v; }\n', + }); + expect(stdout).toContain('0'); + }); + test('repl should treat { key: 123 }; as block scope', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 };\n', + }); + expect(stdout).toContain('123'); + }); + test.suite('multiline', (test) => { + test('repl should treat {\\nkey: 123\\n} as object literal', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{\nkey: 123\n}\n', + }); + expect(stdout).toContain('{ key: 123 }'); + }); + test('repl should treat ({\\nkey: 123\\n}) as object literal', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '({\nkey: 123\n})\n', + }); + expect(stdout).toContain('{ key: 123 }'); + }); + test('repl should treat ({\\nlet v = 0;\\nv;\\n}) as object literal and error', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '({\nlet v = 0;\nv;\n})\n', + }); + expect(stderr).toContain('No value exists in scope for the shorthand property'); + }); + test('repl should treat {\\nlet v = 0;\\nv;\\n} as block scope', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{\nlet v = 0;\nv;\n}\n', + }); + expect(stdout).toContain('0'); + }); + test('repl should treat { key: 123 }; as block scope', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{\nkey: 123\n};\n', + }); + expect(stdout).toContain('123'); + }); + }); + test.suite('property access', (test) => { + test('repl should treat { key: 123 }.key as object literal property access', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }.key\n', + }); + expect(stdout).toContain('123'); + }); + test('repl should treat { key: 123 }["key"] as object literal indexed access', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }["key"]\n', + }); + expect(stdout).toContain('123'); + }); + test('repl should treat { key: 123 }.foo as object literal non-existent property access', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }.foo\n', + }); + expect(stderr).toContain('Property \'foo\' does not exist on type'); + }); + test('repl should treat { key: 123 }["foo"] as object literal non-existent indexed access', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }["foo"]\n', + }); + expect(stderr).toContain('Property \'foo\' does not exist on type'); + }); + test('repl should treat { key: 123 }[] as block scope (edge case)', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }[]\n', + }); + expect(stdout).toContain('[]'); + }); + }); + } +); From a183bb5a3839923c335fc917c53024e266d186fe Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 01:36:55 -0300 Subject: [PATCH 09/27] remove cross-env --- ava.config.cjs | 8 +++----- package-lock.json | 9 --------- package.json | 3 +-- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/ava.config.cjs b/ava.config.cjs index 790ab3d4c..06d173d25 100644 --- a/ava.config.cjs +++ b/ava.config.cjs @@ -24,11 +24,9 @@ module.exports = { * ts-node, from either node_modules or tests/node_modules. * * Another possibility of interference is NODE_PATH environment variable being set, - * and ts-node being installed globally or in any of the paths in NODE_PATH, to fix this, - * we must remove NODE_PATH from the environment variables *BEFORE* running ava, - * as seen in the test-spec npm script using cross-env for interop between OS'es. - * This is not a breaking change, as calling ava directly with NODE_PATH unset will also still work, - * it is only strictly required for environments where NODE_PATH is set to folders containing ts-node. + * and ts-node being installed in any of the paths listed in NODE_PATH, to fix this, + * the NODE_PATH variable must be removed from the environment *BEFORE* running ava. + * An error will be thrown when trying to run tests with NODE_PATH set to paths with ts-node installed. */ const { existsSync } = require('fs'); diff --git a/package-lock.json b/package-lock.json index 0d129c392..19319b310 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1885,15 +1885,6 @@ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.0.tgz", "integrity": "sha512-yEFVS7dQjDXp5iOEtWisN4uFmL+pUTyIaEizKda9Eb77XX58p6pgFOLAPaBCP+IR6ZPZ1jgJLAuf+ABk0zXYBQ==" }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - } - }, "cross-spawn": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", diff --git a/package.json b/package.json index 2303eabb6..2b6272673 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "build-tsc": "tsc", "build-configSchema": "typescript-json-schema --topRef --refs --validationKeywords allOf --out tsconfig.schema.json tsconfig.build-schema.json TsConfigSchema && node --require ./register ./scripts/create-merged-schema", "build-pack": "node ./scripts/build-pack.js", - "test-spec": "cross-env NODE_PATH= ava --node-arguments=--no-deprecation", + "test-spec": "ava --node-arguments=--no-deprecation", "test-cov": "nyc ava", "test": "npm run build && npm run lint && npm run test-cov --", "test-local": "npm run lint-fix && npm run build-tsc && npm run build-pack && npm run test-spec --", @@ -126,7 +126,6 @@ "ava": "^3.15.0", "axios": "^0.21.1", "chai": "^4.0.1", - "cross-env": "^7.0.3", "expect": "^27.0.2", "get-stream": "^6.0.0", "lodash": "^4.17.15", From 20bc6ec94e39352f956c78b9ac5ffbefee494c03 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 03:19:25 -0300 Subject: [PATCH 10/27] Add NODE_PATH check and warning to tests runner See: https://github.com/TypeStrong/ts-node/issues/1697#issuecomment-1080258594 --- ava.config.cjs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/ava.config.cjs b/ava.config.cjs index 06d173d25..1c42b9143 100644 --- a/ava.config.cjs +++ b/ava.config.cjs @@ -24,22 +24,40 @@ module.exports = { * ts-node, from either node_modules or tests/node_modules. * * Another possibility of interference is NODE_PATH environment variable being set, - * and ts-node being installed in any of the paths listed in NODE_PATH, to fix this, + * and ts-node being installed in any of the paths listed on NODE_PATH, to fix this, * the NODE_PATH variable must be removed from the environment *BEFORE* running ava. * An error will be thrown when trying to run tests with NODE_PATH set to paths with ts-node installed. */ - const { existsSync } = require('fs'); + const { existsSync, realpathSync } = require('fs'); const rimraf = require('rimraf'); - const { resolve } = require('path'); + const { resolve, delimiter } = require('path'); remove(resolve(__dirname, 'node_modules/ts-node')); remove(resolve(__dirname, 'tests/node_modules/ts-node')); // Prove that we did it correctly - expect(() => {createRequire(resolve(__dirname, 'tests/foo.js')).resolve('ts-node')}).toThrow(); + let resolved; + try { + expect(() => { resolved = createRequire(resolve(__dirname, 'tests/foo.js')).resolve('ts-node'); }).toThrow(); + } catch (err) { + err.message = err.message.split('\n').slice(0, -1).join('\n') + `\nts-node unexpectedly resolved to external location: ${resolved}`; + + // Check for NODE_PATH interference. See comment on line 26. + if (process.env.NODE_PATH) { + const NODE_PATH = process.env.NODE_PATH.split(delimiter).filter(f => f).map(f => realpathSync(resolve(__dirname, f))); + for (const path of NODE_PATH) { + if (resolved.includes(path)) { + err.message += `\n! WARNING: NODE_PATH is set and contains ts-node at ${path}`; + err.message += `\n! This can cause problems with tests. Please clear the NODE_PATH environment variable before running tests.\n`; + } + } + } + + throw err; + } function remove(p) { - if(existsSync(p)) rimraf.sync(p, {recursive: true}) + if (existsSync(p)) rimraf.sync(p, {recursive: true}); } } From 0435f05a51a2ab5a23a893ed37c2da7f4a0534c8 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 03:52:25 -0300 Subject: [PATCH 11/27] Run prettier on repl.spec.ts --- src/test/repl/repl.spec.ts | 165 +++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 82 deletions(-) diff --git a/src/test/repl/repl.spec.ts b/src/test/repl/repl.spec.ts index 4e7a50703..2daafb07d 100644 --- a/src/test/repl/repl.spec.ts +++ b/src/test/repl/repl.spec.ts @@ -538,117 +538,118 @@ test.suite('REPL declares types for node built-ins within REPL', (test) => { }); }); -test.suite( - 'REPL treats object literals and block scopes correctly', - (test) => { - test('repl should treat { key: 123 } as object literal', async (t) => { +test.suite('REPL treats object literals and block scopes correctly', (test) => { + test('repl should treat { key: 123 } as object literal', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }\n', + }); + expect(stdout).toContain('{ key: 123 }'); + }); + test('repl should treat ({ key: 123 }) as object literal', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '({ key: 123 })\n', + }); + expect(stdout).toContain('{ key: 123 }'); + }); + test('repl should treat ({ let v = 0; v; }) as object literal and error', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '({ let v = 0; v; })\n', + }); + expect(stderr).toContain( + 'No value exists in scope for the shorthand property' + ); + }); + test('repl should treat { let v = 0; v; } as block scope', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ let v = 0; v; }\n', + }); + expect(stdout).toContain('0'); + }); + test('repl should treat { key: 123 }; as block scope', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 };\n', + }); + expect(stdout).toContain('123'); + }); + test.suite('multiline', (test) => { + test('repl should treat {\\nkey: 123\\n} as object literal', async (t) => { const { stdout, stderr } = await execTester({ flags: '-i', - stdin: '{ key: 123 }\n', + stdin: '{\nkey: 123\n}\n', }); expect(stdout).toContain('{ key: 123 }'); }); - test('repl should treat ({ key: 123 }) as object literal', async (t) => { + test('repl should treat ({\\nkey: 123\\n}) as object literal', async (t) => { const { stdout, stderr } = await execTester({ flags: '-i', - stdin: '({ key: 123 })\n', + stdin: '({\nkey: 123\n})\n', }); expect(stdout).toContain('{ key: 123 }'); }); - test('repl should treat ({ let v = 0; v; }) as object literal and error', async (t) => { + test('repl should treat ({\\nlet v = 0;\\nv;\\n}) as object literal and error', async (t) => { const { stdout, stderr } = await execTester({ flags: '-i', - stdin: '({ let v = 0; v; })\n', + stdin: '({\nlet v = 0;\nv;\n})\n', }); - expect(stderr).toContain('No value exists in scope for the shorthand property'); + expect(stderr).toContain( + 'No value exists in scope for the shorthand property' + ); }); - test('repl should treat { let v = 0; v; } as block scope', async (t) => { + test('repl should treat {\\nlet v = 0;\\nv;\\n} as block scope', async (t) => { const { stdout, stderr } = await execTester({ flags: '-i', - stdin: '{ let v = 0; v; }\n', + stdin: '{\nlet v = 0;\nv;\n}\n', }); expect(stdout).toContain('0'); }); test('repl should treat { key: 123 }; as block scope', async (t) => { const { stdout, stderr } = await execTester({ flags: '-i', - stdin: '{ key: 123 };\n', + stdin: '{\nkey: 123\n};\n', }); expect(stdout).toContain('123'); }); - test.suite('multiline', (test) => { - test('repl should treat {\\nkey: 123\\n} as object literal', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{\nkey: 123\n}\n', - }); - expect(stdout).toContain('{ key: 123 }'); - }); - test('repl should treat ({\\nkey: 123\\n}) as object literal', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '({\nkey: 123\n})\n', - }); - expect(stdout).toContain('{ key: 123 }'); - }); - test('repl should treat ({\\nlet v = 0;\\nv;\\n}) as object literal and error', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '({\nlet v = 0;\nv;\n})\n', - }); - expect(stderr).toContain('No value exists in scope for the shorthand property'); - }); - test('repl should treat {\\nlet v = 0;\\nv;\\n} as block scope', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{\nlet v = 0;\nv;\n}\n', - }); - expect(stdout).toContain('0'); - }); - test('repl should treat { key: 123 }; as block scope', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{\nkey: 123\n};\n', - }); - expect(stdout).toContain('123'); + }); + test.suite('property access', (test) => { + test('repl should treat { key: 123 }.key as object literal property access', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }.key\n', }); + expect(stdout).toContain('123'); }); - test.suite('property access', (test) => { - test('repl should treat { key: 123 }.key as object literal property access', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }.key\n', - }); - expect(stdout).toContain('123'); - }); - test('repl should treat { key: 123 }["key"] as object literal indexed access', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }["key"]\n', - }); - expect(stdout).toContain('123'); + test('repl should treat { key: 123 }["key"] as object literal indexed access', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }["key"]\n', }); - test('repl should treat { key: 123 }.foo as object literal non-existent property access', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }.foo\n', - }); - expect(stderr).toContain('Property \'foo\' does not exist on type'); + expect(stdout).toContain('123'); + }); + test('repl should treat { key: 123 }.foo as object literal non-existent property access', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }.foo\n', }); - test('repl should treat { key: 123 }["foo"] as object literal non-existent indexed access', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }["foo"]\n', - }); - expect(stderr).toContain('Property \'foo\' does not exist on type'); + expect(stderr).toContain("Property 'foo' does not exist on type"); + }); + test('repl should treat { key: 123 }["foo"] as object literal non-existent indexed access', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }["foo"]\n', }); - test('repl should treat { key: 123 }[] as block scope (edge case)', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }[]\n', - }); - expect(stdout).toContain('[]'); + expect(stderr).toContain("Property 'foo' does not exist on type"); + }); + test('repl should treat { key: 123 }[] as block scope (edge case)', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }[]\n', }); + expect(stdout).toContain('[]'); }); - } -); + }); +}); From 3aa1f33010cfac8e5e59c7449d089fce1396a611 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 04:26:49 -0300 Subject: [PATCH 12/27] node nightly tests fail because of unexpected custom ESM loaders warnings so fix that i guess? --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b6272673..8656278f6 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "build-tsc": "tsc", "build-configSchema": "typescript-json-schema --topRef --refs --validationKeywords allOf --out tsconfig.schema.json tsconfig.build-schema.json TsConfigSchema && node --require ./register ./scripts/create-merged-schema", "build-pack": "node ./scripts/build-pack.js", - "test-spec": "ava --node-arguments=--no-deprecation", + "test-spec": "ava --node-arguments=\"--no-deprecation --no-warnings\"", "test-cov": "nyc ava", "test": "npm run build && npm run lint && npm run test-cov --", "test-local": "npm run lint-fix && npm run build-tsc && npm run build-pack && npm run test-spec --", From 358163d5845bc25b1c49e1094368b5a18fc47cb5 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 05:31:29 -0300 Subject: [PATCH 13/27] fix tests on TS 2.7 --- src/test/repl/repl.spec.ts | 55 +++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/test/repl/repl.spec.ts b/src/test/repl/repl.spec.ts index 2daafb07d..82952140f 100644 --- a/src/test/repl/repl.spec.ts +++ b/src/test/repl/repl.spec.ts @@ -559,7 +559,9 @@ test.suite('REPL treats object literals and block scopes correctly', (test) => { stdin: '({ let v = 0; v; })\n', }); expect(stderr).toContain( - 'No value exists in scope for the shorthand property' + semver.satisfies(ts.version, '2.7') + ? 'error TS2304' + : 'No value exists in scope for the shorthand property' ); }); test('repl should treat { let v = 0; v; } as block scope', async (t) => { @@ -569,12 +571,29 @@ test.suite('REPL treats object literals and block scopes correctly', (test) => { }); expect(stdout).toContain('0'); }); - test('repl should treat { key: 123 }; as block scope', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 };\n', + test.suite('extra', (test) => { + test.skipIf(semver.satisfies(ts.version, '2.7')); + test('repl should treat { key: 123 }; as block scope', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 };\n', + }); + expect(stdout).toContain('123'); + }); + test('repl should treat {\\nkey: 123\\n}; as block scope', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{\nkey: 123\n};\n', + }); + expect(stdout).toContain('123'); + }); + test('repl should treat { key: 123 }[] as block scope (edge case)', async (t) => { + const { stdout, stderr } = await execTester({ + flags: '-i', + stdin: '{ key: 123 }[]\n', + }); + expect(stdout).toContain('[]'); }); - expect(stdout).toContain('123'); }); test.suite('multiline', (test) => { test('repl should treat {\\nkey: 123\\n} as object literal', async (t) => { @@ -597,7 +616,9 @@ test.suite('REPL treats object literals and block scopes correctly', (test) => { stdin: '({\nlet v = 0;\nv;\n})\n', }); expect(stderr).toContain( - 'No value exists in scope for the shorthand property' + semver.satisfies(ts.version, '2.7') + ? 'error TS2304' + : 'No value exists in scope for the shorthand property' ); }); test('repl should treat {\\nlet v = 0;\\nv;\\n} as block scope', async (t) => { @@ -607,13 +628,6 @@ test.suite('REPL treats object literals and block scopes correctly', (test) => { }); expect(stdout).toContain('0'); }); - test('repl should treat { key: 123 }; as block scope', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{\nkey: 123\n};\n', - }); - expect(stdout).toContain('123'); - }); }); test.suite('property access', (test) => { test('repl should treat { key: 123 }.key as object literal property access', async (t) => { @@ -642,14 +656,11 @@ test.suite('REPL treats object literals and block scopes correctly', (test) => { flags: '-i', stdin: '{ key: 123 }["foo"]\n', }); - expect(stderr).toContain("Property 'foo' does not exist on type"); - }); - test('repl should treat { key: 123 }[] as block scope (edge case)', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }[]\n', - }); - expect(stdout).toContain('[]'); + expect(stderr).toContain( + semver.satisfies(ts.version, '2.7') + ? 'error TS7017' + : "Property 'foo' does not exist on type" + ); }); }); }); From 68c3d86ef4a0b22ae384725a358aaf7ce357ae59 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 06:41:11 -0300 Subject: [PATCH 14/27] node nightly tests still failed, fix attempt 2 --- src/test/esm-loader.spec.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index cc673e544..8f61dc2fe 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -334,14 +334,20 @@ test.suite('esm', (test) => { test.runIf(nodeSupportsSpawningChildProcess); basic('ts-node-esm executable', () => - exec(`${BIN_ESM_PATH} ./esm-child-process/via-flag/index.ts foo bar`) + exec(`${BIN_ESM_PATH} ./esm-child-process/via-flag/index.ts foo bar`, { + env: { NODE_OPTIONS: '--no-warnings' }, + }) ); basic('ts-node --esm flag', () => - exec(`${BIN_PATH} --esm ./esm-child-process/via-flag/index.ts foo bar`) + exec( + `${BIN_PATH} --esm ./esm-child-process/via-flag/index.ts foo bar`, + { env: { NODE_OPTIONS: '--no-warnings' } } + ) ); basic('ts-node w/tsconfig esm:true', () => exec( - `${BIN_PATH} --esm ./esm-child-process/via-tsconfig/index.ts foo bar` + `${BIN_PATH} --esm ./esm-child-process/via-tsconfig/index.ts foo bar`, + { env: { NODE_OPTIONS: '--no-warnings' } } ) ); @@ -365,6 +371,7 @@ test.suite('esm', (test) => { const childP = spawn([ // exec lets us run the shims on windows; spawn does not process.execPath, + '--no-warnings', BIN_PATH_JS, `./esm-child-process/via-tsconfig/sleep.ts`, ]); From bd6a3ed2f1a6275c659e313982c9db89018447de Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 07:26:40 -0300 Subject: [PATCH 15/27] append instead of overriding NODE_OPTIONS --- src/test/esm-loader.spec.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index 8f61dc2fe..b8bc07764 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -335,19 +335,29 @@ test.suite('esm', (test) => { basic('ts-node-esm executable', () => exec(`${BIN_ESM_PATH} ./esm-child-process/via-flag/index.ts foo bar`, { - env: { NODE_OPTIONS: '--no-warnings' }, + env: { + NODE_OPTIONS: (process.env.NODE_OPTIONS ?? '') + '--no-warnings', + }, }) ); basic('ts-node --esm flag', () => exec( `${BIN_PATH} --esm ./esm-child-process/via-flag/index.ts foo bar`, - { env: { NODE_OPTIONS: '--no-warnings' } } + { + env: { + NODE_OPTIONS: (process.env.NODE_OPTIONS ?? '') + '--no-warnings', + }, + } ) ); basic('ts-node w/tsconfig esm:true', () => exec( `${BIN_PATH} --esm ./esm-child-process/via-tsconfig/index.ts foo bar`, - { env: { NODE_OPTIONS: '--no-warnings' } } + { + env: { + NODE_OPTIONS: (process.env.NODE_OPTIONS ?? '') + '--no-warnings', + }, + } ) ); From 6fa789ee9ff05faa5336c90692d1d451b7b765fb Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 08:09:51 -0300 Subject: [PATCH 16/27] accept warning-only stderr on nightly test --- src/test/esm-loader.spec.ts | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index b8bc07764..14cbd65f9 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -334,30 +334,14 @@ test.suite('esm', (test) => { test.runIf(nodeSupportsSpawningChildProcess); basic('ts-node-esm executable', () => - exec(`${BIN_ESM_PATH} ./esm-child-process/via-flag/index.ts foo bar`, { - env: { - NODE_OPTIONS: (process.env.NODE_OPTIONS ?? '') + '--no-warnings', - }, - }) + exec(`${BIN_ESM_PATH} ./esm-child-process/via-flag/index.ts foo bar`) ); basic('ts-node --esm flag', () => - exec( - `${BIN_PATH} --esm ./esm-child-process/via-flag/index.ts foo bar`, - { - env: { - NODE_OPTIONS: (process.env.NODE_OPTIONS ?? '') + '--no-warnings', - }, - } - ) + exec(`${BIN_PATH} --esm ./esm-child-process/via-flag/index.ts foo bar`) ); basic('ts-node w/tsconfig esm:true', () => exec( - `${BIN_PATH} --esm ./esm-child-process/via-tsconfig/index.ts foo bar`, - { - env: { - NODE_OPTIONS: (process.env.NODE_OPTIONS ?? '') + '--no-warnings', - }, - } + `${BIN_PATH} --esm ./esm-child-process/via-tsconfig/index.ts foo bar` ) ); @@ -366,7 +350,16 @@ test.suite('esm', (test) => { const { err, stdout, stderr } = await cb(); expect(err).toBe(null); expect(stdout.trim()).toBe('CLI args: foo bar'); - expect(stderr).toBe(''); + if (stderr && process.version.includes('nightly')) { + // Nightly builds of Node.js might randomly start spitting out warnings, + // which would cause the tests to fail despite actually working, so we + // should check if stderr is a warning and consider it a pass if it is. + expect(stderr).toMatch( + /^\(node:\d+?\) .*?Warning: .+?(?:\n\(Use `node --trace-(?:deprecation|warnings) \.{3}`.+?\))?\n?$/ + ); + } else { + expect(stderr).toBe(''); + } }); } From d03380ba6821cd2d77bf02c351af174c84ee2c2c Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 08:28:30 -0300 Subject: [PATCH 17/27] if check didnt fire --- src/test/esm-loader.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index 14cbd65f9..07371ab62 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -350,7 +350,7 @@ test.suite('esm', (test) => { const { err, stdout, stderr } = await cb(); expect(err).toBe(null); expect(stdout.trim()).toBe('CLI args: foo bar'); - if (stderr && process.version.includes('nightly')) { + if (stderr) { // Nightly builds of Node.js might randomly start spitting out warnings, // which would cause the tests to fail despite actually working, so we // should check if stderr is a warning and consider it a pass if it is. From 3aee6b1b1457f92e67c9824a83d8e69b9097bb85 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 08:33:19 -0300 Subject: [PATCH 18/27] maybe the regex is broken --- src/test/esm-loader.spec.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index 07371ab62..6b90d0f7c 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -354,9 +354,7 @@ test.suite('esm', (test) => { // Nightly builds of Node.js might randomly start spitting out warnings, // which would cause the tests to fail despite actually working, so we // should check if stderr is a warning and consider it a pass if it is. - expect(stderr).toMatch( - /^\(node:\d+?\) .*?Warning: .+?(?:\n\(Use `node --trace-(?:deprecation|warnings) \.{3}`.+?\))?\n?$/ - ); + expect(stderr).toContain('Warnig:'); } else { expect(stderr).toBe(''); } From 6e82b71dc74ad5a03046f9099c10390531ef5fc7 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 08:48:08 -0300 Subject: [PATCH 19/27] am i even editing the right lines --- src/test/esm-loader.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index 6b90d0f7c..90818342b 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -354,9 +354,9 @@ test.suite('esm', (test) => { // Nightly builds of Node.js might randomly start spitting out warnings, // which would cause the tests to fail despite actually working, so we // should check if stderr is a warning and consider it a pass if it is. - expect(stderr).toContain('Warnig:'); + expect(stderr).toContain('Warning:'); } else { - expect(stderr).toBe(''); + //expect(stderr).toBe(''); } }); } From 2a93a1fe3b5e0f3561d24165c2509bd7f4a83ff5 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 08:58:01 -0300 Subject: [PATCH 20/27] make test-cov match test-spec --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8656278f6..6cbd7e98e 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "build-configSchema": "typescript-json-schema --topRef --refs --validationKeywords allOf --out tsconfig.schema.json tsconfig.build-schema.json TsConfigSchema && node --require ./register ./scripts/create-merged-schema", "build-pack": "node ./scripts/build-pack.js", "test-spec": "ava --node-arguments=\"--no-deprecation --no-warnings\"", - "test-cov": "nyc ava", + "test-cov": "nyc ava --node-arguments=\"--no-deprecation --no-warnings\"", "test": "npm run build && npm run lint && npm run test-cov --", "test-local": "npm run lint-fix && npm run build-tsc && npm run build-pack && npm run test-spec --", "pre-debug": "npm run build-tsc && npm run build-pack", From 4572135055ca98fee3635164a992282978ef2437 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 09:06:26 -0300 Subject: [PATCH 21/27] try checking for nightly again... --- src/test/esm-loader.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index 90818342b..d4be5f0c7 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -407,7 +407,8 @@ test.suite('esm', (test) => { `child registered signal handlers\nchild received signal: ${signal}\nchild exiting` ); } - expect(stderr).toBe(''); + t.log(process.version); + if (!process.version.includes('nightly')) expect(stderr).toBe(''); }); } }); From 1723c567705842fb17d71343c49bd32c6da816ea Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 09:20:05 -0300 Subject: [PATCH 22/27] tests work! clean them up now, please don't break --- package.json | 4 ++-- src/test/esm-loader.spec.ts | 17 +++++++---------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 6cbd7e98e..449a6f5b5 100644 --- a/package.json +++ b/package.json @@ -69,8 +69,8 @@ "build-tsc": "tsc", "build-configSchema": "typescript-json-schema --topRef --refs --validationKeywords allOf --out tsconfig.schema.json tsconfig.build-schema.json TsConfigSchema && node --require ./register ./scripts/create-merged-schema", "build-pack": "node ./scripts/build-pack.js", - "test-spec": "ava --node-arguments=\"--no-deprecation --no-warnings\"", - "test-cov": "nyc ava --node-arguments=\"--no-deprecation --no-warnings\"", + "test-spec": "ava --node-arguments=--no-deprecation", + "test-cov": "nyc ava --node-arguments=--no-deprecation", "test": "npm run build && npm run lint && npm run test-cov --", "test-local": "npm run lint-fix && npm run build-tsc && npm run build-pack && npm run test-spec --", "pre-debug": "npm run build-tsc && npm run build-pack", diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index d4be5f0c7..9a51d16a1 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -350,14 +350,10 @@ test.suite('esm', (test) => { const { err, stdout, stderr } = await cb(); expect(err).toBe(null); expect(stdout.trim()).toBe('CLI args: foo bar'); - if (stderr) { - // Nightly builds of Node.js might randomly start spitting out warnings, - // which would cause the tests to fail despite actually working, so we - // should check if stderr is a warning and consider it a pass if it is. - expect(stderr).toContain('Warning:'); - } else { - //expect(stderr).toBe(''); - } + // Nightly builds of Node.js might randomly start printing warnings, + // which would cause this test to fail despite actually working, + // so we should ignore stderr when testing on Node.js nightly. + if (!process.version.includes('nightly')) expect(stderr).toBe(''); }); } @@ -372,7 +368,6 @@ test.suite('esm', (test) => { const childP = spawn([ // exec lets us run the shims on windows; spawn does not process.execPath, - '--no-warnings', BIN_PATH_JS, `./esm-child-process/via-tsconfig/sleep.ts`, ]); @@ -407,7 +402,9 @@ test.suite('esm', (test) => { `child registered signal handlers\nchild received signal: ${signal}\nchild exiting` ); } - t.log(process.version); + // Nightly builds of Node.js might randomly start printing warnings, + // which would cause this test to fail despite actually working, + // so we should ignore stderr when testing on Node.js nightly. if (!process.version.includes('nightly')) expect(stderr).toBe(''); }); } From 228c4ed932fbd0dd6ed20ff2fe0834cc28ebe888 Mon Sep 17 00:00:00 2001 From: jhmaster2000 <32803471+jhmaster2000@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:52:09 -0300 Subject: [PATCH 23/27] Remove node nightly tests warning checks (superseded by #1701) --- package.json | 4 ++-- src/test/esm-loader.spec.ts | 10 ++-------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 449a6f5b5..1f158f1fb 100644 --- a/package.json +++ b/package.json @@ -69,8 +69,8 @@ "build-tsc": "tsc", "build-configSchema": "typescript-json-schema --topRef --refs --validationKeywords allOf --out tsconfig.schema.json tsconfig.build-schema.json TsConfigSchema && node --require ./register ./scripts/create-merged-schema", "build-pack": "node ./scripts/build-pack.js", - "test-spec": "ava --node-arguments=--no-deprecation", - "test-cov": "nyc ava --node-arguments=--no-deprecation", + "test-spec": "ava", + "test-cov": "nyc ava", "test": "npm run build && npm run lint && npm run test-cov --", "test-local": "npm run lint-fix && npm run build-tsc && npm run build-pack && npm run test-spec --", "pre-debug": "npm run build-tsc && npm run build-pack", diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index 9a51d16a1..cc673e544 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -350,10 +350,7 @@ test.suite('esm', (test) => { const { err, stdout, stderr } = await cb(); expect(err).toBe(null); expect(stdout.trim()).toBe('CLI args: foo bar'); - // Nightly builds of Node.js might randomly start printing warnings, - // which would cause this test to fail despite actually working, - // so we should ignore stderr when testing on Node.js nightly. - if (!process.version.includes('nightly')) expect(stderr).toBe(''); + expect(stderr).toBe(''); }); } @@ -402,10 +399,7 @@ test.suite('esm', (test) => { `child registered signal handlers\nchild received signal: ${signal}\nchild exiting` ); } - // Nightly builds of Node.js might randomly start printing warnings, - // which would cause this test to fail despite actually working, - // so we should ignore stderr when testing on Node.js nightly. - if (!process.version.includes('nightly')) expect(stderr).toBe(''); + expect(stderr).toBe(''); }); } }); From 4d474604ab91feae1d0840e861bf0b3f3ae87029 Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Mon, 18 Apr 2022 17:38:51 -0400 Subject: [PATCH 24/27] simplify NODE_PATH check --- ava.config.cjs | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/ava.config.cjs b/ava.config.cjs index 1c42b9143..420163fb2 100644 --- a/ava.config.cjs +++ b/ava.config.cjs @@ -11,6 +11,7 @@ module.exports = { // This avoids passing it to spawned processes under test, which would negatively affect // their behavior. FORCE_COLOR: '3', + NODE_PATH: '' }, require: ['./src/test/remove-env-var-force-color.js'], timeout: '300s', @@ -22,7 +23,7 @@ module.exports = { * Tests *must* install and use our most recent ts-node tarball. * We must prevent them from accidentally require-ing a different version of * ts-node, from either node_modules or tests/node_modules. - * + * * Another possibility of interference is NODE_PATH environment variable being set, * and ts-node being installed in any of the paths listed on NODE_PATH, to fix this, * the NODE_PATH variable must be removed from the environment *BEFORE* running ava. @@ -31,31 +32,26 @@ module.exports = { const { existsSync, realpathSync } = require('fs'); const rimraf = require('rimraf'); - const { resolve, delimiter } = require('path'); + const { resolve } = require('path'); remove(resolve(__dirname, 'node_modules/ts-node')); remove(resolve(__dirname, 'tests/node_modules/ts-node')); // Prove that we did it correctly - let resolved; - try { - expect(() => { resolved = createRequire(resolve(__dirname, 'tests/foo.js')).resolve('ts-node'); }).toThrow(); - } catch (err) { - err.message = err.message.split('\n').slice(0, -1).join('\n') + `\nts-node unexpectedly resolved to external location: ${resolved}`; - - // Check for NODE_PATH interference. See comment on line 26. - if (process.env.NODE_PATH) { - const NODE_PATH = process.env.NODE_PATH.split(delimiter).filter(f => f).map(f => realpathSync(resolve(__dirname, f))); - for (const path of NODE_PATH) { - if (resolved.includes(path)) { - err.message += `\n! WARNING: NODE_PATH is set and contains ts-node at ${path}`; - err.message += `\n! This can cause problems with tests. Please clear the NODE_PATH environment variable before running tests.\n`; - } - } + (() => { + let resolved; + try { + resolved = createRequire(resolve(__dirname, 'tests/foo.js')).resolve('ts-node'); + } catch(err) {return} + + // require.resolve() found ts-node; this should not happen. + let errorMessage = `require.resolve('ts-node') unexpectedly resolved to ${resolved}\n`; + // Check for NODE_PATH interference. See comments above. + if(process.env.NODE_PATH) { + errorMessage += `NODE_PATH environment variable is set. This test suite does not support running with NODE_PATH. Unset it before running the tests.`; } - - throw err; - } + throw new Error(errorMessage); + })(); function remove(p) { if (existsSync(p)) rimraf.sync(p, {recursive: true}); From 44743321a147af3015573ea29bf5b9dec6b5653c Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Mon, 18 Apr 2022 18:20:20 -0400 Subject: [PATCH 25/27] attempt at running new repl tests in-process for speed --- src/test/repl/repl.spec.ts | 232 ++++++++++++++++++------------------- 1 file changed, 114 insertions(+), 118 deletions(-) diff --git a/src/test/repl/repl.spec.ts b/src/test/repl/repl.spec.ts index 82952140f..bec93ebd4 100644 --- a/src/test/repl/repl.spec.ts +++ b/src/test/repl/repl.spec.ts @@ -1,4 +1,4 @@ -import { _test, expect } from '../testlib'; +import { context, expect } from '../testlib'; import { resetNodeEnvironment, ts } from '../helpers'; import semver = require('semver'); import { @@ -12,7 +12,8 @@ import { upstreamTopLevelAwaitTests } from './node-repl-tla'; import { contextReplHelpers, replMacros } from './helpers'; import { promisify } from 'util'; -const test = _test.context(contextTsNodeUnderTest).context(contextReplHelpers); +const test = context(contextTsNodeUnderTest).context(contextReplHelpers); +test.runSerially(); test.beforeEach(async (t) => { t.teardown(() => { resetNodeEnvironment(); @@ -539,128 +540,123 @@ test.suite('REPL declares types for node built-ins within REPL', (test) => { }); test.suite('REPL treats object literals and block scopes correctly', (test) => { - test('repl should treat { key: 123 } as object literal', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }\n', - }); - expect(stdout).toContain('{ key: 123 }'); - }); - test('repl should treat ({ key: 123 }) as object literal', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '({ key: 123 })\n', - }); - expect(stdout).toContain('{ key: 123 }'); + const basic = test.macro( + (input: string, output?: string, errorOutput?: string) => async (t) => { + const { stdout, stderr } = await t.context.executeInRepl(`${input}\n`, { + registerHooks: true, + waitPattern: output ?? errorOutput, + waitMs: 5000, + startInternalOptions: { useGlobal: false }, + }); + if (output) expect(stdout).toContain(output); + if (errorOutput) expect(stderr).toContain(errorOutput); + } + ); + test( + 'FOOBAR repl should treat { key: 123 } as object literal', + basic, + '{ key: 123 }', + '{ key: 123 }' + ); + test( + 'repl should treat ({ key: 123 }) as object literal', + basic, + '({ key: 123 })', + '{ key: 123 }' + ); + test( + 'repl should treat ({ let v = 0; v; }) as object literal and error', + basic, + '({ let v = 0; v; })', + undefined, + semver.satisfies(ts.version, '2.7') + ? 'error TS2304' + : 'No value exists in scope for the shorthand property' + ); + test( + 'repl should treat { let v = 0; v; } as block scope', + basic, + '{ let v = 0; v; }', + '0' + ); + test.suite('extra', (test) => { + test.skipIf(semver.satisfies(ts.version, '2.7')); + test( + 'repl should treat { key: 123 }; as block scope', + basic, + '{ key: 123 };', + '123' + ); + test( + 'repl should treat {\\nkey: 123\\n}; as block scope', + basic, + '{\nkey: 123\n};', + '123' + ); + test( + 'repl should treat { key: 123 }[] as block scope (edge case)', + basic, + '{ key: 123 }[]', + '[]' + ); }); - test('repl should treat ({ let v = 0; v; }) as object literal and error', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '({ let v = 0; v; })\n', - }); - expect(stderr).toContain( + test.suite('multiline', (test) => { + test( + 'repl should treat {\\nkey: 123\\n} as object literal', + basic, + '{\nkey: 123\n}', + '{ key: 123 }' + ); + test( + 'repl should treat ({\\nkey: 123\\n}) as object literal', + basic, + '({\nkey: 123\n})', + '{ key: 123 }' + ); + test( + 'repl should treat ({\\nlet v = 0;\\nv;\\n}) as object literal and error', + basic, + '({\nlet v = 0;\nv;\n})', + undefined, semver.satisfies(ts.version, '2.7') ? 'error TS2304' : 'No value exists in scope for the shorthand property' ); - }); - test('repl should treat { let v = 0; v; } as block scope', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ let v = 0; v; }\n', - }); - expect(stdout).toContain('0'); - }); - test.suite('extra', (test) => { - test.skipIf(semver.satisfies(ts.version, '2.7')); - test('repl should treat { key: 123 }; as block scope', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 };\n', - }); - expect(stdout).toContain('123'); - }); - test('repl should treat {\\nkey: 123\\n}; as block scope', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{\nkey: 123\n};\n', - }); - expect(stdout).toContain('123'); - }); - test('repl should treat { key: 123 }[] as block scope (edge case)', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }[]\n', - }); - expect(stdout).toContain('[]'); - }); - }); - test.suite('multiline', (test) => { - test('repl should treat {\\nkey: 123\\n} as object literal', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{\nkey: 123\n}\n', - }); - expect(stdout).toContain('{ key: 123 }'); - }); - test('repl should treat ({\\nkey: 123\\n}) as object literal', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '({\nkey: 123\n})\n', - }); - expect(stdout).toContain('{ key: 123 }'); - }); - test('repl should treat ({\\nlet v = 0;\\nv;\\n}) as object literal and error', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '({\nlet v = 0;\nv;\n})\n', - }); - expect(stderr).toContain( - semver.satisfies(ts.version, '2.7') - ? 'error TS2304' - : 'No value exists in scope for the shorthand property' - ); - }); - test('repl should treat {\\nlet v = 0;\\nv;\\n} as block scope', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{\nlet v = 0;\nv;\n}\n', - }); - expect(stdout).toContain('0'); - }); + test( + 'repl should treat {\\nlet v = 0;\\nv;\\n} as block scope', + basic, + '{\nlet v = 0;\nv;\n}', + '0' + ); }); test.suite('property access', (test) => { - test('repl should treat { key: 123 }.key as object literal property access', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }.key\n', - }); - expect(stdout).toContain('123'); - }); - test('repl should treat { key: 123 }["key"] as object literal indexed access', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }["key"]\n', - }); - expect(stdout).toContain('123'); - }); - test('repl should treat { key: 123 }.foo as object literal non-existent property access', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }.foo\n', - }); - expect(stderr).toContain("Property 'foo' does not exist on type"); - }); - test('repl should treat { key: 123 }["foo"] as object literal non-existent indexed access', async (t) => { - const { stdout, stderr } = await execTester({ - flags: '-i', - stdin: '{ key: 123 }["foo"]\n', - }); - expect(stderr).toContain( - semver.satisfies(ts.version, '2.7') - ? 'error TS7017' - : "Property 'foo' does not exist on type" - ); - }); + test( + 'repl should treat { key: 123 }.key as object literal property access', + basic, + '{ key: 123 }.key', + '123' + ); + test( + 'repl should treat { key: 123 }["key"] as object literal indexed access', + basic, + '{ key: 123 }["key"]', + '123' + ); + test( + 'repl should treat { key: 123 }.foo as object literal non-existent property access', + basic, + '{ key: 123 }.foo', + undefined, + "Property 'foo' does not exist on type" + ); + test( + 'repl should treat { key: 123 }["foo"] as object literal non-existent indexed access', + basic, + '{ key: 123 }["foo"]', + undefined, + semver.satisfies(ts.version, '2.7') + ? 'error TS7017' + : "Property 'foo' does not exist on type" + ); }); }); From 7295ad05a46bfe1656a3de2d12a35b1a3fc19991 Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Tue, 19 Apr 2022 16:03:05 -0400 Subject: [PATCH 26/27] switch tests to run in-process using existing macros --- package.json | 3 ++ src/test/helpers.ts | 26 ++++++++------ src/test/repl/repl.spec.ts | 70 +++++++++++++------------------------- 3 files changed, 42 insertions(+), 57 deletions(-) diff --git a/package.json b/package.json index 670ce54fe..74fbac852 100644 --- a/package.json +++ b/package.json @@ -173,6 +173,9 @@ "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, + "prettier": { + "singleQuote": true + }, "volta": { "node": "17.5.0", "npm": "6.14.15" diff --git a/src/test/helpers.ts b/src/test/helpers.ts index c7466849f..ae9ebc3ba 100644 --- a/src/test/helpers.ts +++ b/src/test/helpers.ts @@ -197,7 +197,8 @@ export function getStream(stream: Readable, waitForPattern?: string | RegExp) { //#region Reset node environment const defaultRequireExtensions = captureObjectState(require.extensions); -const defaultProcess = captureObjectState(process); +// Avoid node deprecation warning for accessing _channel +const defaultProcess = captureObjectState(process, ['_channel']); const defaultModule = captureObjectState(require('module')); const defaultError = captureObjectState(Error); const defaultGlobal = captureObjectState(global); @@ -209,15 +210,20 @@ const defaultGlobal = captureObjectState(global); * Must also play nice with `nyc`'s environmental mutations. */ export function resetNodeEnvironment() { + const sms = + require('@cspotcode/source-map-support') as typeof import('@cspotcode/source-map-support'); // We must uninstall so that it resets its internal state; otherwise it won't know it needs to reinstall in the next test. - require('@cspotcode/source-map-support').uninstall(); + sms.uninstall(); + // Must remove handlers to avoid a memory leak + sms.resetRetrieveHandlers(); // Modified by ts-node hooks resetObject(require.extensions, defaultRequireExtensions); // ts-node attaches a property when it registers an instance // source-map-support monkey-patches the emit function - resetObject(process, defaultProcess); + // Avoid node deprecation warnings for setting process.config or accessing _channel + resetObject(process, defaultProcess, undefined, ['_channel'], ['config']); // source-map-support swaps out the prepareStackTrace function resetObject(Error, defaultError); @@ -230,11 +236,10 @@ export function resetNodeEnvironment() { resetObject(global, defaultGlobal, ['__coverage__']); } -function captureObjectState(object: any) { +function captureObjectState(object: any, avoidGetters: string[] = []) { const descriptors = Object.getOwnPropertyDescriptors(object); const values = mapValues(descriptors, (_d, key) => { - // Avoid node deprecation warning for accessing _channel - if (object === process && key === '_channel') return descriptors[key].value; + if (avoidGetters.includes(key)) return descriptors[key].value; return object[key]; }); return { @@ -246,7 +251,9 @@ function captureObjectState(object: any) { function resetObject( object: any, state: ReturnType, - doNotDeleteTheseKeys: string[] = [] + doNotDeleteTheseKeys: string[] = [], + doNotSetTheseKeys: string[] = [], + avoidSetterIfUnchanged: string[] = [] ) { const currentDescriptors = Object.getOwnPropertyDescriptors(object); for (const key of Object.keys(currentDescriptors)) { @@ -257,9 +264,8 @@ function resetObject( // Trigger nyc's setter functions for (const [key, value] of Object.entries(state.values)) { try { - // Avoid node deprecation warnings for setting process.config or accessing _channel - if (object === process && key === '_channel') continue; - if (object === process && key === 'config' && object[key] === value) + if (doNotSetTheseKeys.includes(key)) continue; + if (avoidSetterIfUnchanged.includes(key) && object[key] === value) continue; object[key] = value; } catch {} diff --git a/src/test/repl/repl.spec.ts b/src/test/repl/repl.spec.ts index 408c64d05..5a29cee49 100644 --- a/src/test/repl/repl.spec.ts +++ b/src/test/repl/repl.spec.ts @@ -17,6 +17,9 @@ test.runSerially(); test.beforeEach(async (t) => { t.teardown(() => { resetNodeEnvironment(); + // Useful for debugging memory leaks. Leaving in case I need it again. + // global.gc(); // Requires adding nodeArguments: ['--expose-gc'] to ava config + // console.dir(process.memoryUsage().heapUsed / 1000 / 1000); }); }); @@ -540,120 +543,93 @@ test.suite('REPL declares types for node built-ins within REPL', (test) => { }); test.suite('REPL treats object literals and block scopes correctly', (test) => { - const basic = test.macro( - (input: string, output?: string, errorOutput?: string) => async (t) => { - const { stdout, stderr } = await t.context.executeInRepl(`${input}\n`, { - registerHooks: true, - waitPattern: output ?? errorOutput, - waitMs: 5000, - startInternalOptions: { useGlobal: false }, - }); - if (output) expect(stdout).toContain(output); - if (errorOutput) expect(stderr).toContain(errorOutput); - } - ); - test( - 'FOOBAR repl should treat { key: 123 } as object literal', - basic, + const macros = replMacros(test); + macros.noErrorsAndStdoutContains( + 'repl should treat { key: 123 } as object literal', '{ key: 123 }', '{ key: 123 }' ); - test( + macros.noErrorsAndStdoutContains( 'repl should treat ({ key: 123 }) as object literal', - basic, '({ key: 123 })', '{ key: 123 }' ); - test( + macros.stderrContains( 'repl should treat ({ let v = 0; v; }) as object literal and error', - basic, '({ let v = 0; v; })', - undefined, semver.satisfies(ts.version, '2.7') ? 'error TS2304' : 'No value exists in scope for the shorthand property' ); - test( + macros.noErrorsAndStdoutContains( 'repl should treat { let v = 0; v; } as block scope', - basic, '{ let v = 0; v; }', '0' ); test.suite('extra', (test) => { test.skipIf(semver.satisfies(ts.version, '2.7')); - test( + const macros = replMacros(test); + macros.noErrorsAndStdoutContains( 'repl should treat { key: 123 }; as block scope', - basic, '{ key: 123 };', '123' ); - test( + macros.noErrorsAndStdoutContains( 'repl should treat {\\nkey: 123\\n}; as block scope', - basic, '{\nkey: 123\n};', '123' ); - test( + macros.noErrorsAndStdoutContains( 'repl should treat { key: 123 }[] as block scope (edge case)', - basic, '{ key: 123 }[]', '[]' ); }); test.suite('multiline', (test) => { - test( + const macros = replMacros(test); + macros.noErrorsAndStdoutContains( 'repl should treat {\\nkey: 123\\n} as object literal', - basic, '{\nkey: 123\n}', '{ key: 123 }' ); - test( + macros.noErrorsAndStdoutContains( 'repl should treat ({\\nkey: 123\\n}) as object literal', - basic, '({\nkey: 123\n})', '{ key: 123 }' ); - test( + macros.stderrContains( 'repl should treat ({\\nlet v = 0;\\nv;\\n}) as object literal and error', - basic, '({\nlet v = 0;\nv;\n})', - undefined, semver.satisfies(ts.version, '2.7') ? 'error TS2304' : 'No value exists in scope for the shorthand property' ); - test( + macros.noErrorsAndStdoutContains( 'repl should treat {\\nlet v = 0;\\nv;\\n} as block scope', - basic, '{\nlet v = 0;\nv;\n}', '0' ); }); test.suite('property access', (test) => { - test( + const macros = replMacros(test); + macros.noErrorsAndStdoutContains( 'repl should treat { key: 123 }.key as object literal property access', - basic, '{ key: 123 }.key', '123' ); - test( + macros.noErrorsAndStdoutContains( 'repl should treat { key: 123 }["key"] as object literal indexed access', - basic, '{ key: 123 }["key"]', '123' ); - test( + macros.stderrContains( 'repl should treat { key: 123 }.foo as object literal non-existent property access', - basic, '{ key: 123 }.foo', - undefined, "Property 'foo' does not exist on type" ); - test( + macros.stderrContains( 'repl should treat { key: 123 }["foo"] as object literal non-existent indexed access', - basic, '{ key: 123 }["foo"]', - undefined, semver.satisfies(ts.version, '2.7') ? 'error TS7017' : "Property 'foo' does not exist on type" From 6e9a5f66b2de2422bf83516d6311c5c73c8c2345 Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Tue, 19 Apr 2022 19:54:02 -0400 Subject: [PATCH 27/27] finish changes to run tests in-process --- src/test/repl/repl.spec.ts | 49 +++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/test/repl/repl.spec.ts b/src/test/repl/repl.spec.ts index 7d519d199..55f49cb68 100644 --- a/src/test/repl/repl.spec.ts +++ b/src/test/repl/repl.spec.ts @@ -546,92 +546,103 @@ test.suite('REPL declares types for node built-ins within REPL', (test) => { }); test.suite('REPL treats object literals and block scopes correctly', (test) => { - const macros = replMacros(test); - macros.noErrorsAndStdoutContains( + test( 'repl should treat { key: 123 } as object literal', + macroReplNoErrorsAndStdoutContains, '{ key: 123 }', '{ key: 123 }' ); - macros.noErrorsAndStdoutContains( + test( 'repl should treat ({ key: 123 }) as object literal', + macroReplNoErrorsAndStdoutContains, '({ key: 123 })', '{ key: 123 }' ); - macros.stderrContains( + test( 'repl should treat ({ let v = 0; v; }) as object literal and error', + macroReplStderrContains, '({ let v = 0; v; })', semver.satisfies(ts.version, '2.7') ? 'error TS2304' : 'No value exists in scope for the shorthand property' ); - macros.noErrorsAndStdoutContains( + test( 'repl should treat { let v = 0; v; } as block scope', + macroReplNoErrorsAndStdoutContains, '{ let v = 0; v; }', '0' ); test.suite('extra', (test) => { test.skipIf(semver.satisfies(ts.version, '2.7')); - const macros = replMacros(test); - macros.noErrorsAndStdoutContains( + test( 'repl should treat { key: 123 }; as block scope', + macroReplNoErrorsAndStdoutContains, '{ key: 123 };', '123' ); - macros.noErrorsAndStdoutContains( + test( 'repl should treat {\\nkey: 123\\n}; as block scope', + macroReplNoErrorsAndStdoutContains, '{\nkey: 123\n};', '123' ); - macros.noErrorsAndStdoutContains( + test( 'repl should treat { key: 123 }[] as block scope (edge case)', + macroReplNoErrorsAndStdoutContains, '{ key: 123 }[]', '[]' ); }); test.suite('multiline', (test) => { - const macros = replMacros(test); - macros.noErrorsAndStdoutContains( + test( 'repl should treat {\\nkey: 123\\n} as object literal', + macroReplNoErrorsAndStdoutContains, '{\nkey: 123\n}', '{ key: 123 }' ); - macros.noErrorsAndStdoutContains( + test( 'repl should treat ({\\nkey: 123\\n}) as object literal', + macroReplNoErrorsAndStdoutContains, '({\nkey: 123\n})', '{ key: 123 }' ); - macros.stderrContains( + test( 'repl should treat ({\\nlet v = 0;\\nv;\\n}) as object literal and error', + macroReplStderrContains, '({\nlet v = 0;\nv;\n})', semver.satisfies(ts.version, '2.7') ? 'error TS2304' : 'No value exists in scope for the shorthand property' ); - macros.noErrorsAndStdoutContains( + test( 'repl should treat {\\nlet v = 0;\\nv;\\n} as block scope', + macroReplNoErrorsAndStdoutContains, '{\nlet v = 0;\nv;\n}', '0' ); }); test.suite('property access', (test) => { - const macros = replMacros(test); - macros.noErrorsAndStdoutContains( + test( 'repl should treat { key: 123 }.key as object literal property access', + macroReplNoErrorsAndStdoutContains, '{ key: 123 }.key', '123' ); - macros.noErrorsAndStdoutContains( + test( 'repl should treat { key: 123 }["key"] as object literal indexed access', + macroReplNoErrorsAndStdoutContains, '{ key: 123 }["key"]', '123' ); - macros.stderrContains( + test( 'repl should treat { key: 123 }.foo as object literal non-existent property access', + macroReplStderrContains, '{ key: 123 }.foo', "Property 'foo' does not exist on type" ); - macros.stderrContains( + test( 'repl should treat { key: 123 }["foo"] as object literal non-existent indexed access', + macroReplStderrContains, '{ key: 123 }["foo"]', semver.satisfies(ts.version, '2.7') ? 'error TS7017'