Skip to content

Detect Babel reexports with conflict filter for other exports #39

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ EXPORT_STAR_LIB: `Object.keys(` IDENTIFIER$1 `).forEach(function (` IDENTIFIER$2
`if (` IDENTIFIER$2 `===` ( `'default'` | `"default"` ) `||` IDENTIFIER$2 `===` ( '__esModule' | `"__esModule"` ) `) return` `;`? |
`if (` IDENTIFIER$2 `!==` ( `'default'` | `"default"` ) `)`
)
(
`if (Object.prototype.hasOwnProperty.call(` IDENTIFIER `, ` IDENTIFIER$2 `)) return` `;`?
)?
(
`if (` IDENTIFIER$2 `in` EXPORTS_IDENTIFIER `&&` EXPORTS_IDENTIFIER `[` IDENTIFIER$2 `] ===` IDENTIFIER$1 `[` IDENTIFIER$2 `]) return` `;`?
)?
Expand Down
1 change: 1 addition & 0 deletions include-wasm/cjs-module-lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ bool str_eq4 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4)
bool str_eq5 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4, uint16_t c5);
bool str_eq6 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6);
bool str_eq7 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6, uint16_t c7);
bool str_eq8 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6, uint16_t c7, uint16_t c8);
bool str_eq9 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6, uint16_t c7, uint16_t c8, uint16_t c9);
bool str_eq10 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6, uint16_t c7, uint16_t c8, uint16_t c9, uint16_t c10);
bool str_eq13 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6, uint16_t c7, uint16_t c8, uint16_t c9, uint16_t c10, uint16_t c11, uint16_t c12, uint16_t c13);
Expand Down
68 changes: 67 additions & 1 deletion lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,73 @@ function tryParseObjectDefineOrKeys (keys) {
}
else break;

// `if (Object.prototype.hasOwnProperty.call(` IDENTIFIER `, ` IDENTIFIER$2 `)) return` `;`?
currentIfStatement: if (ch === 105/*i*/ && source.charCodeAt(pos + 1) === 102/*f*/) {
let ifStartPos = pos;

pos += 2;
ch = commentWhitespace();
if (ch !== 40/*(*/) break;
pos++;
ch = commentWhitespace();
if (ch !== 79/*O*/ || !source.startsWith('bject', pos + 1)) {
// Revert parsing the current optional if statement, but don't bail
// out since we can try parse the next possible if statement.
pos = ifStartPos;
ch = 105/*i*/;
break currentIfStatement;
}
pos += 6;
ch = commentWhitespace();
if (ch !== 46/*.*/) {
// Revert parsing the current optional if statement, but don't bail
// out since we can try parse the next possible if statement.
pos = ifStartPos;
ch = 105/*i*/;
break currentIfStatement;
}
pos++;
ch = commentWhitespace();
if (ch !== 112/*p*/ || !source.startsWith('rototype', pos + 1)) break;
pos += 9;
ch = commentWhitespace();
if (ch !== 46/*.*/) break;
pos++;
ch = commentWhitespace();
if (ch !== 104/*h*/ || !source.startsWith('asOwnProperty', pos + 1)) break;
pos += 14;
ch = commentWhitespace();
if (ch !== 46/*.*/) break;
pos++;
ch = commentWhitespace();
if (ch !== 99/*c*/ || !source.startsWith('all', pos + 1)) break;
pos += 4;
ch = commentWhitespace();
if (ch !== 40/*(*/) break;
pos++;
ch = commentWhitespace();
if (!identifier()) break;
ch = commentWhitespace();
if (ch !== 44/*,*/) break;
pos++;
ch = commentWhitespace();
if (!source.startsWith(it_id, pos)) break;
pos += it_id.length;
ch = commentWhitespace();
if (ch !== 41/*)*/) break;
pos++;
ch = commentWhitespace();
if (ch !== 41/*)*/) break;
pos++;
ch = commentWhitespace();
if (ch !== 114/*r*/ || !source.startsWith('eturn', pos + 1)) break;
pos += 6;
ch = commentWhitespace();
if (ch === 59/*;*/)
pos++;
ch = commentWhitespace();
}

// `if (` IDENTIFIER$2 `in` EXPORTS_IDENTIFIER `&&` EXPORTS_IDENTIFIER `[` IDENTIFIER$2 `] ===` IDENTIFIER$1 `[` IDENTIFIER$2 `]) return` `;`?
if (ch === 105/*i*/ && source.charCodeAt(pos + 1) === 102/*f*/) {
pos += 2;
Expand Down Expand Up @@ -1039,7 +1106,6 @@ function throwIfImportStatement () {
// import.meta
case 46/*.*/:
throw new Error('Unexpected import.meta in CJS module.');
return;

default:
// no space after "import" -> not an import keyword
Expand Down
Binary file modified lib/lexer.wasm
Binary file not shown.
73 changes: 73 additions & 0 deletions src/lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,75 @@ void tryParseObjectDefineOrKeys (bool keys) {
else break;


// `if (Object.prototype.hasOwnProperty.call(` IDENTIFIER `, ` IDENTIFIER$2 `)) return` `;`?
if (ch == 'i' && *(pos + 1) == 'f') {
uint16_t *ifStartPos = pos;

pos += 2;
ch = commentWhitespace();
if (ch != '(') break;
pos++;
ch = commentWhitespace();
if (ch != 'O' || !str_eq5(pos + 1, 'b', 'j', 'e', 'c', 't')) {
// Revert parsing the current optional if statement, but don't bail
// out since we can try parse the next possible if statement.
pos = ifStartPos;
ch = 'i';
goto currentIfStatementEnd;
}
pos += 6;
ch = commentWhitespace();
if (ch != '.') {
// Revert parsing the current optional if statement, but don't bail
// out since we can try parse the next possible if statement.
pos = ifStartPos;
ch = 'i';
goto currentIfStatementEnd;
}
pos++;
ch = commentWhitespace();
if (ch != 'p' || !str_eq8(pos + 1, 'r', 'o', 't', 'o', 't', 'y', 'p', 'e')) break;
pos += 9;
ch = commentWhitespace();
if (ch != '.') break;
pos++;
ch = commentWhitespace();
if (ch != 'h' || !str_eq13(pos + 1, 'a', 's', 'O', 'w', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'y')) break;
pos += 14;
ch = commentWhitespace();
if (ch != '.') break;
pos++;
ch = commentWhitespace();
if (ch != 'c' || !str_eq3(pos + 1, 'a', 'l', 'l')) break;
pos += 4;
ch = commentWhitespace();
if (ch != '(') break;
pos++;
ch = commentWhitespace();
if (!identifier(ch)) break;
ch = commentWhitespace();
if (ch != ',') break;
pos++;
ch = commentWhitespace();
if (memcmp(pos, it_id_start, it_id_len * sizeof(uint16_t)) != 0) break;
pos += it_id_len;
ch = commentWhitespace();
if (ch != ')') break;
pos++;
ch = commentWhitespace();
if (ch != ')') break;
pos++;
ch = commentWhitespace();
if (ch != 'r' || !str_eq5(pos + 1, 'e', 't', 'u', 'r', 'n')) break;
pos += 6;
ch = commentWhitespace();
if (ch == ';')
pos++;
ch = commentWhitespace();
}
currentIfStatementEnd:;


// `if (` IDENTIFIER$2 `in` EXPORTS_IDENTIFIER `&&` EXPORTS_IDENTIFIER `[` IDENTIFIER$2 `] ===` IDENTIFIER$1 `[` IDENTIFIER$2 `]) return` `;`?
if (ch == 'i' && *(pos + 1) == 'f') {
pos += 2;
Expand Down Expand Up @@ -1257,6 +1326,10 @@ bool str_eq7 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4,
return *pos == c1 && *(pos + 1) == c2 && *(pos + 2) == c3 && *(pos + 3) == c4 && *(pos + 4) == c5 && *(pos + 5) == c6 && *(pos + 6) == c7;
}

bool str_eq8 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6, uint16_t c7, uint16_t c8) {
return *pos == c1 && *(pos + 1) == c2 && *(pos + 2) == c3 && *(pos + 3) == c4 && *(pos + 4) == c5 && *(pos + 5) == c6 && *(pos + 6) == c7 && *(pos + 7) == c8;
}

bool str_eq9 (uint16_t* pos, uint16_t c1, uint16_t c2, uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6, uint16_t c7, uint16_t c8, uint16_t c9) {
return *pos == c1 && *(pos + 1) == c2 && *(pos + 2) == c3 && *(pos + 3) == c4 && *(pos + 4) == c5 && *(pos + 5) == c6 && *(pos + 6) == c7 && *(pos + 7) == c8 && *(pos + 8) == c9;
}
Expand Down
41 changes: 34 additions & 7 deletions test/_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,19 @@ suite('Lexer', () => {
exports[key] = _external001[key];
});

var _external003 = require("external003");

// Babel >=7.12.0, loose mode, reexports conflicts filter
Object.keys(_external003).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _external003[key]) return;
exports[key] = _external003[key];
});

var _external002 = require("external002");

// Babel >=7.12.0, loose mode
// Babel >=7.12.0
Object.keys(_external002).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _external002[key]) return;
Expand All @@ -158,6 +168,21 @@ suite('Lexer', () => {
});
});

var _external004 = require("external004");

// Babel >=7.12.0, reexports conflict filter
Object.keys(_external004).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _external004[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _external004[key];
}
});
});

let external3 = require('external3');
const external4 = require('external4');

Expand Down Expand Up @@ -285,15 +310,17 @@ suite('Lexer', () => {
`);
assert.equal(exports.length, 1);
assert.equal(exports[0], '__esModule');
assert.equal(reexports.length, 8);
assert.equal(reexports.length, 10);
assert.equal(reexports[0], 'external');
assert.equal(reexports[1], 'external2');
assert.equal(reexports[2], 'external001');
assert.equal(reexports[3], 'external002');
assert.equal(reexports[4], 'external3');
assert.equal(reexports[5], 'external4');
assert.equal(reexports[6], 'external😃');
assert.equal(reexports[7], 'external𤭢');
assert.equal(reexports[3], 'external003');
assert.equal(reexports[4], 'external002');
assert.equal(reexports[5], 'external004');
assert.equal(reexports[6], 'external3');
assert.equal(reexports[7], 'external4');
assert.equal(reexports[8], 'external😃');
assert.equal(reexports[9], 'external𤭢');
});

test('invalid exports cases', () => {
Expand Down