mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-20 15:01:46 +02:00
test(carriers): pin CommonJS require candidates, regex after a block, and non-import from
Review on dd14493e found four more ways the closure gate misjudges a
carrier, each reproduced against that head:
- require('./helper') resolves when only helper.cjs or helper.mjs is
planned, but Node's CommonJS search tries only .js, .json and .node.
- In `if (ok) {} /"/.test(text); require(...)` the regex after the block
is read as division and its quote swallows the require.
- `obj.\nif(x) / 2` is a method call, but the condition check only saw
the character immediately before `if`, so the division read as a regex
and swallowed a later require. Introduced by the previous fix.
- A tagged template named `from` was recorded as an import; with exact
import resolution it now fails a carrier that never loads that path.
Introduced by the previous fix.
Controls: an extensionless require still resolves to a .json file, and a
template literal passed to import() is still a dependency.
This commit is contained in:
@@ -118,6 +118,32 @@ test('an extensionless require still resolves through the CommonJS extension sea
|
||||
assert.equal(result.status, 'success', JSON.stringify(result.failures));
|
||||
}));
|
||||
|
||||
// An extensionless require searches only .js, .json and .node, then a
|
||||
// directory's index; .cjs and .mjs must be named explicitly.
|
||||
for (const extension of ['cjs', 'mjs']) {
|
||||
test(`an extensionless require does not resolve to a .${extension} file`, () => withFixture(root => {
|
||||
write(root, `skills/ecc-guide/scripts/helper.${extension}`, 'module.exports = 1;\n');
|
||||
plantSkillScript(root, "module.exports = require('./helper');\n");
|
||||
const result = validator().validate(root);
|
||||
assert.equal(result.status, 'failure');
|
||||
assert.ok(result.failures.every(failure => failure.reason === 'unplanned-target'));
|
||||
}));
|
||||
}
|
||||
|
||||
test('an extensionless require resolves to a .json file', () => withFixture(root => {
|
||||
write(root, 'skills/ecc-guide/scripts/helper.json', '{}\n');
|
||||
plantSkillScript(root, "module.exports = require('./helper');\n");
|
||||
const result = validator().validate(root);
|
||||
assert.equal(result.status, 'success', JSON.stringify(result.failures));
|
||||
}));
|
||||
|
||||
test('a tagged template named from is not an import', () => withFixture(root => {
|
||||
plantSkillScript(root, 'const from = parts => parts[0];\nmodule.exports = from`./helper`;\n');
|
||||
const result = validator().validate(root);
|
||||
assert.equal(result.status, 'success', JSON.stringify(result.failures));
|
||||
assert.deepEqual(result.warnings, []);
|
||||
}));
|
||||
|
||||
test('a backslash-separated relative require fails: Linux and macOS read it as one filename', () => withFixture(root => {
|
||||
write(root, 'skills/ecc-guide/scripts/lib/helper.js', 'module.exports = 1;\n');
|
||||
plantSkillScript(root, "module.exports = require('./lib\\\\helper.js');\n");
|
||||
@@ -188,6 +214,13 @@ const SCANNER_CASES = [
|
||||
['regex after a while condition', "while (more) /\"/.test(s); require('./after-while');", ['./after-while']],
|
||||
['division after a method named if', "const v = a.if(x) / 2, q = \"/\"; require('./after-method');", ['./after-method']],
|
||||
['division after a call inside a condition', "if (f(a) / 2 > 1) { q = \"/\"; } require('./after-nested');", ['./after-nested']],
|
||||
['regex after a block', "if (ok) {} /\"/.test(text); require('./after-block');", ['./after-block']],
|
||||
['division after a method named if across a line break',
|
||||
"const n = obj.\nif(x) / 2, q = \"/\"; require('./after-spaced-method');", ['./after-spaced-method']],
|
||||
['division after an optional-chained method named while',
|
||||
"const n = obj?. while(x) / 2, q = \"/\"; require('./after-optional');", ['./after-optional']],
|
||||
['a tagged template named from', 'const from = p => p[0]; const s = from`./helper`;', []],
|
||||
['a template import() is still a dependency', 'import(`./templated`);', ['./templated']],
|
||||
];
|
||||
|
||||
for (const [label, source, expected] of SCANNER_CASES) {
|
||||
|
||||
Reference in New Issue
Block a user