Skip to content

Commit 279682c

Browse files
authored
feat: consistent esm syntax err (#90)
1 parent 182e276 commit 279682c

File tree

10 files changed

+2441
-2466
lines changed

10 files changed

+2441
-2466
lines changed

build.js

+3
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,7 @@ const minified = MINIFY && terser.minify(jsSourceProcessed, {
1919
}
2020
});
2121

22+
if (minified.error)
23+
throw minified.error;
24+
2225
fs.writeFileSync('./dist/lexer.mjs', minified ? minified.code : jsSourceProcessed);

include-wasm/cjs-module-lexer.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ bool ru () {
117117
return true;
118118
}
119119

120-
bool parse (uint32_t point);
121-
122120
void _addExport (const uint16_t* start, const uint16_t* end) {
123121
Slice* export = (Slice*)(analysis_head);
124122
analysis_head = analysis_head + sizeof(Slice);
@@ -163,7 +161,7 @@ void (*addExport)(const uint16_t*, const uint16_t*) = &_addExport;
163161
void (*addReexport)(const uint16_t*, const uint16_t*) = &_addReexport;
164162
void (*addUnsafeGetter)(const uint16_t*, const uint16_t*) = &_addUnsafeGetter;
165163
void (*clearReexports)() = &_clearReexports;
166-
bool parseCJS (uint16_t* source, uint32_t sourceLen, void (*addExport)(const uint16_t* start, const uint16_t* end), void (*addReexport)(const uint16_t* start, const uint16_t* end), void (*addUnsafeGetter)(const uint16_t*, const uint16_t*), void (*clearReexports)());
164+
uint32_t parseCJS (uint16_t* source, uint32_t sourceLen, void (*addExport)(const uint16_t* start, const uint16_t* end), void (*addReexport)(const uint16_t* start, const uint16_t* end), void (*addUnsafeGetter)(const uint16_t*, const uint16_t*), void (*clearReexports)());
167165

168166
enum RequireType {
169167
Import,
@@ -237,4 +235,4 @@ void nextChar (uint16_t ch);
237235
void nextCharSurrogate (uint16_t ch);
238236
uint16_t readChar ();
239237

240-
void syntaxError ();
238+
void syntaxError (uint32_t code);

lexer.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,10 @@ function codePointAtLast (bPos) {
11491149
return ch;
11501150
}
11511151

1152+
function esmSyntaxErr (msg) {
1153+
return Object.assign(new Error(msg), { code: 'ERR_LEXER_ESM_SYNTAX' });
1154+
}
1155+
11521156
function throwIfImportStatement () {
11531157
const startPos = pos;
11541158
pos += 6;
@@ -1160,7 +1164,7 @@ function throwIfImportStatement () {
11601164
return;
11611165
// import.meta
11621166
case 46/*.*/:
1163-
throw new Error('Unexpected import.meta in CJS module.');
1167+
throw esmSyntaxErr('Unexpected import.meta in CJS module.');
11641168

11651169
default:
11661170
// no space after "import" -> not an import keyword
@@ -1176,7 +1180,7 @@ function throwIfImportStatement () {
11761180
return;
11771181
}
11781182
// import statements are a syntax error in CommonJS
1179-
throw new Error('Unexpected import statement in CJS module.');
1183+
throw esmSyntaxErr('Unexpected import statement in CJS module.');
11801184
}
11811185
}
11821186

@@ -1186,7 +1190,7 @@ function throwIfExportStatement () {
11861190
const ch = commentWhitespace();
11871191
if (pos === curPos && !isPunctuator(ch))
11881192
return;
1189-
throw new Error('Unexpected export statement in CJS module.');
1193+
throw esmSyntaxErr('Unexpected export statement in CJS module.');
11901194
}
11911195

11921196
function commentWhitespace () {

lib/lexer.wasm

-246 Bytes
Binary file not shown.

lib/lexer.wat

+2,287-2,430
Large diffs are not rendered by default.

package-lock.json

+65-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
"types": "lexer.d.ts",
1414
"scripts": {
1515
"test-js": "mocha -b -u tdd test/*.js",
16-
"test-wasm": "WASM=1 mocha -b -u tdd test/*.js",
16+
"test-wasm": "cross-env WASM=1 mocha -b -u tdd test/*.js",
1717
"test": "npm run test-wasm && npm run test-js",
1818
"bench": "node --expose-gc bench/index.mjs",
19-
"build": "node build.js && babel dist/lexer.mjs | terser -o dist/lexer.js",
19+
"build": "node build.js ; babel dist/lexer.mjs -o dist/lexer.js ; terser dist/lexer.js -o dist/lexer.js",
2020
"build-wasm": "make lib/lexer.wasm && node build.js",
2121
"prepublishOnly": "make && npm run build",
2222
"footprint": "npm run build && cat dist/lexer.js | gzip -9f | wc -c"
@@ -27,6 +27,7 @@
2727
"@babel/cli": "^7.5.5",
2828
"@babel/core": "^7.5.5",
2929
"@babel/plugin-transform-modules-commonjs": "^7.5.0",
30+
"cross-env": "^7.0.3",
3031
"kleur": "^2.0.2",
3132
"mocha": "^9.1.3",
3233
"terser": "^4.1.4"

src/lexer.c

+23-23
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ uint16_t* lastReexportEnd;
3030
// -> source
3131
// -> analysis starts after source
3232
uint32_t parse_error;
33-
bool has_error = false;
33+
uint32_t error = 0;
3434
uint32_t sourceLen;
3535

3636
uint16_t templateStack_[STACK_DEPTH];
@@ -45,7 +45,7 @@ void (*addUnsafeGetter)(const uint16_t*, const uint16_t*);
4545
void (*clearReexports)();
4646

4747
// Note: parsing is based on the _assumption_ that the source is already valid
48-
bool parseCJS (uint16_t* _source, uint32_t _sourceLen, void (*_addExport)(const uint16_t*, const uint16_t*), void (*_addReexport)(const uint16_t*, const uint16_t*), void (*_addUnsafeGetter)(const uint16_t*, const uint16_t*), void (*_clearReexports)()) {
48+
uint32_t parseCJS (uint16_t* _source, uint32_t _sourceLen, void (*_addExport)(const uint16_t*, const uint16_t*), void (*_addReexport)(const uint16_t*, const uint16_t*), void (*_addUnsafeGetter)(const uint16_t*, const uint16_t*), void (*_clearReexports)()) {
4949
source = _source;
5050
sourceLen = _sourceLen;
5151
if (_addExport)
@@ -61,7 +61,7 @@ bool parseCJS (uint16_t* _source, uint32_t _sourceLen, void (*_addExport)(const
6161
lastTokenPos = (uint16_t*)EMPTY_CHAR;
6262
lastSlashWasDivision = false;
6363
parse_error = 0;
64-
has_error = false;
64+
error = 0;
6565
templateStack = &templateStack_[0];
6666
openTokenPosStack = &openTokenPosStack_[0];
6767
starExportStack = &starExportStack_[0];
@@ -74,7 +74,7 @@ bool parseCJS (uint16_t* _source, uint32_t _sourceLen, void (*_addExport)(const
7474
// Handle #!
7575
if (*source == '#' && *(source + 1) == '!') {
7676
if (sourceLen == 2)
77-
return true;
77+
return 0;
7878
pos += 2;
7979
while (pos++ < end) {
8080
ch = *pos;
@@ -155,7 +155,7 @@ bool parseCJS (uint16_t* _source, uint32_t _sourceLen, void (*_addExport)(const
155155
break;
156156
case ')':
157157
if (openTokenDepth == 0)
158-
return syntaxError(), false;
158+
return syntaxError(8), error;
159159
openTokenDepth--;
160160
break;
161161
case '{':
@@ -165,14 +165,14 @@ bool parseCJS (uint16_t* _source, uint32_t _sourceLen, void (*_addExport)(const
165165
break;
166166
case '}':
167167
if (openTokenDepth == 0)
168-
return syntaxError(), false;
168+
return syntaxError(2), false;
169169
if (openTokenDepth-- == templateDepth) {
170170
templateDepth = templateStack[--templateStackDepth];
171171
templateString();
172172
}
173173
else {
174174
if (templateDepth != UINT16_MAX && openTokenDepth < templateDepth)
175-
return syntaxError(), false;
175+
return syntaxError(3), error;
176176
}
177177
break;
178178
case '<':
@@ -219,18 +219,18 @@ bool parseCJS (uint16_t* _source, uint32_t _sourceLen, void (*_addExport)(const
219219
}
220220
case '`':
221221
if (templateDepth == UINT16_MAX - 1)
222-
return syntaxError(), false;
222+
return syntaxError(4), error;
223223
templateString();
224224
break;
225225
}
226226
lastTokenPos = pos;
227227
}
228228

229-
if (templateDepth != UINT16_MAX || openTokenDepth || has_error)
230-
return false;
229+
if (templateDepth != UINT16_MAX || openTokenDepth || error)
230+
return error;
231231

232232
// success
233-
return true;
233+
return 0;
234234
}
235235

236236
void tryBacktrackAddStarExportBinding (uint16_t* bPos) {
@@ -1154,7 +1154,7 @@ void throwIfImportStatement () {
11541154
return;
11551155
// import.meta
11561156
case '.':
1157-
syntaxError();
1157+
syntaxError(5);
11581158
return;
11591159

11601160
default:
@@ -1171,7 +1171,7 @@ void throwIfImportStatement () {
11711171
return;
11721172
}
11731173
// import statements are a syntax error in CommonJS
1174-
syntaxError();
1174+
syntaxError(6);
11751175
}
11761176
}
11771177

@@ -1181,7 +1181,7 @@ void throwIfExportStatement () {
11811181
uint16_t ch = commentWhitespace();
11821182
if (pos == curPos && !isPunctuator(ch))
11831183
return;
1184-
syntaxError();
1184+
syntaxError(7);
11851185
}
11861186

11871187
uint16_t commentWhitespace () {
@@ -1218,7 +1218,7 @@ void templateString () {
12181218
if (ch == '\\')
12191219
pos++;
12201220
}
1221-
syntaxError();
1221+
syntaxError(8);
12221222
}
12231223

12241224
void blockComment () {
@@ -1253,7 +1253,7 @@ void stringLiteral (uint16_t quote) {
12531253
else if (isBr(ch))
12541254
break;
12551255
}
1256-
syntaxError();
1256+
syntaxError(9);
12571257
}
12581258

12591259
uint16_t regexCharacterClass () {
@@ -1266,7 +1266,7 @@ uint16_t regexCharacterClass () {
12661266
else if (ch == '\n' || ch == '\r')
12671267
break;
12681268
}
1269-
syntaxError();
1269+
syntaxError(10);
12701270
return '\0';
12711271
}
12721272

@@ -1282,7 +1282,7 @@ void regularExpression () {
12821282
else if (ch == '\n' || ch == '\r')
12831283
break;
12841284
}
1285-
syntaxError();
1285+
syntaxError(11);
12861286
}
12871287

12881288
uint16_t readToWsOrPunctuator (uint16_t ch) {
@@ -1503,14 +1503,14 @@ bool isExpressionTerminator (uint16_t* curPos) {
15031503
return false;
15041504
}
15051505

1506-
void bail (uint32_t error) {
1507-
has_error = true;
1508-
parse_error = error;
1506+
void bail (uint32_t err) {
1507+
error = 1;
1508+
parse_error = err;
15091509
pos = end + 1;
15101510
}
15111511

1512-
void syntaxError () {
1513-
has_error = true;
1512+
void syntaxError (uint32_t code) {
1513+
if (error == 0) error = code;
15141514
parse_error = pos - source;
15151515
pos = end + 1;
15161516
}

src/lexer.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,15 @@ export function parse (source, name = '@') {
1616
const addr = wasm.sa(len);
1717
(isLE ? copyLE : copyBE)(source, new Uint16Array(wasm.memory.buffer, addr, len));
1818

19-
if (!wasm.parseCJS(addr, source.length, 0, 0, 0))
20-
throw Object.assign(new Error(`Parse error ${name}${wasm.e()}:${source.slice(0, wasm.e()).split('\n').length}:${wasm.e() - source.lastIndexOf('\n', wasm.e() - 1)}`), { idx: wasm.e() });
19+
const err_code = wasm.parseCJS(addr, source.length, 0, 0, 0);
20+
21+
if (err_code) {
22+
const err = new Error(`Parse error ${name}${wasm.e()}:${source.slice(0, wasm.e()).split('\n').length}:${wasm.e() - source.lastIndexOf('\n', wasm.e() - 1)}`);
23+
Object.assign(err, { idx: wasm.e() });
24+
if (err_code === 5 || err_code === 6 || err_code === 7)
25+
Object.assign(err, { code: 'ERR_LEXER_ESM_SYNTAX' });
26+
throw err;
27+
}
2128

2229
let exports = new Set(), reexports = new Set(), unsafeGetters = new Set();
2330

0 commit comments

Comments
 (0)