-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathenum_parser.mjs
309 lines (301 loc) · 12.8 KB
/
enum_parser.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
// All constants of the parser itself (parser.mjs) that can be inlined should go in here
// At dev time many of these constants are distinguishable object references.
// In a prod build these are all scrubbed to generic booleans or numbers.
// This file is used as a way to decide which constants to inline. As such be careful to only make primitives `const`
// because the inlining is unconditional beyond being a const in this file.
import {ASSERT} from "./utils.mjs";
const VERSION_EXPONENTIATION = 7; // ES2016
const VERSION_ASYNC = 8; // ES2017
const VERSION_TRAILING_FUNC_COMMAS = 8; // ES2017
const VERSION_ASYNC_GEN = 9; // ES2018
const VERSION_OBJECTSPREAD = 9; // ES2018
const VERSION_TAGGED_TEMPLATE_BAD_ESCAPES = 9; // ES2018
const VERSION_OPTIONAL_CATCH = 10; // ES2019
const VERSION_DYNAMIC_IMPORT = 11; // ES2020
const VERSION_EXPORT_STAR_AS = 11; // ES2020
const VERSION_WHATEVER = Infinity;
const IS_ASYNC = DEVONLY() ? {IS_ASYNC: 1} : true;
const NOT_ASYNC = DEVONLY() ? {_ASYNC: 1} : false;
const IS_ASYNC_PREFIXED = DEVONLY() ? {IS_ASYNC_PREFIXED: 1} : true;
const NOT_ASYNC_PREFIXED = DEVONLY() ? {NOT_ASYNC_PREFIXED: 1} : false;
const UNDEF_STATIC = DEVONLY() ? {UNDEF_STATIC: 1, get str(){ASSERT(false)}} : undefined;
const UNDEF_ASYNC = DEVONLY() ? {UNDEF_ASYNC: 1, get str(){ASSERT(false)}} : undefined;
const UNDEF_STAR = DEVONLY() ? {UNDEF_STAR: 1, get str(){ASSERT(false)}} : undefined;
const UNDEF_GET = DEVONLY() ? {UNDEF_GET: 1, get str(){ASSERT(false)}} : undefined;
const UNDEF_SET = DEVONLY() ? {UNDEF_SET: 1, get str(){ASSERT(false)}} : undefined;
const IS_FUNC_DECL = DEVONLY() ? {IS_FUNC_DECL: 1} : true;
const NOT_FUNC_DECL = DEVONLY() ? {NOT_FUNC_DECL: 1} : false;
const IS_FUNC_EXPR = DEVONLY() ? {IS_FUNC_EXPR: 1} : true;
const NOT_FUNC_EXPR = DEVONLY() ? {NOT_FUNC_EXPR: 1} : false;
const IDENT_OPTIONAL = DEVONLY() ? {IDENT_OPTIONAL: 1} : true;
const IDENT_REQUIRED = DEVONLY() ? {IDENT_REQUIRED: 1} : false;
const PARSE_VALUE_MAYBE = DEVONLY() ? {PARSE_VALUE_MAYBE: 1} : true;
const PARSE_VALUE_MUST = DEVONLY() ? {PARSE_VALUE_MUST: 1} : false;
const YIELD_WITHOUT_VALUE = DEVONLY() ? {YIELD_WITHOUT_VALUE: 1} : 0;
const WITH_ASSIGNABLE = DEVONLY() ? {WITH_ASSIGNABLE: 1} : 1;
const WITH_NON_ASSIGNABLE = DEVONLY() ? {WITH_NON_ASSIGNABLE: 1} : 2;
const IS_ARROW = DEVONLY() ? {IS_ARROW: 1} : true;
const NOT_ARROW = DEVONLY() ? {NOT_ARROW: 1} : false;
const FROM_STATEMENT_START = DEVONLY() ? {FROM_STATEMENT_START: 1} : 1;
const FROM_FOR_HEADER = DEVONLY() ? {FROM_FOR_HEADER: 1} : 2;
const FROM_EXPORT_DECL = DEVONLY() ? {FROM_EXPORT_DECL: 1} : 3;
const FROM_CATCH = DEVONLY() ? {FROM_CATCH: 1} : 4;
const FROM_ASYNC_ARG = DEVONLY() ? {FROM_ASYNC_ARG: 1} : 5;
const FROM_OTHER_FUNC_ARG = DEVONLY() ? {FROM_OTHER_FUNC_ARG: 1} : 6;
const COAL_SEEN_NEITHER = 0;
const COAL_SEEN_NULLISH = 1;
const COAL_SEEN_LOGICAL = 2;
const ASSIGNMENT_IS_INIT = DEVONLY() ? {ASSIGNMENT_IS_INIT: 1} : true; // var foo = bar; (not to be parsed by parseBinding
const ASSIGNMENT_IS_DEFAULT = DEVONLY() ? {ASSIGNMENT_IS_DEFAULT: 1} : false; // (foo = bar) => foo (parsed by parseBinding)
const IS_EXPRESSION = DEVONLY() ? {IS_EXPRESSION: 1} : 1;
const IS_STATEMENT = DEVONLY() ? {IS_STATEMENT: 1} : 2;
const IS_NEW_ARG = DEVONLY() ? {IS_NEW_ARG: 1} : 3;
const NOT_NEW_ARG = DEVONLY() ? {NOT_NEW_ARG: 1} : 4;
const IS_OPTIONAL = DEVONLY() ? {IS_OPTIONAL: 1} : 1;
const NOT_OPTIONAL = DEVONLY() ? {NOT_OPTIONAL: 1} : 2;
const MIGHT_DESTRUCT = 0; // any kind of destructuring or lack thereof is okay
const CANT_DESTRUCT = 1 << 0; // it is impossible to destructure this
const DESTRUCT_ASSIGN_ONLY = 1 << 1; // the only way this can destruct is by assignment
const MUST_DESTRUCT = 1 << 2; // something that is an error if it doesnt lead to destructurig like `({a=b})`
const ASSIGNABLE_UNDETERMINED = 1 << 3;
const NOT_ASSIGNABLE = 1 << 4;
const IS_ASSIGNABLE = 1 << 5;
const PIGGY_BACK_SAW_AWAIT = 1 << 6; // parsed an expression containing `await` as varname or keyword
const PIGGY_BACK_SAW_YIELD = 1 << 7; // parsed an expression containing `yield` as varname or keyword
const PIGGY_BACK_WAS_CONSTRUCTOR = 1 << 8; // signal having found a constructor (special case)
const PIGGY_BACK_WAS_PROTO = 1 << 9; // signal that a `__proto__: x` was parsed (do detect double occurrence)
const PIGGY_BACK_WAS_ARROW = 1 << 10; // signal that double proto was found on object; error in web compat outside of arrow headers
const NO_SPREAD = DEVONLY() ? {NO_SPREAD: 1} : 0;
const LAST_SPREAD = DEVONLY() ? {LAST_SPREAD: 1} : 1;
const MID_SPREAD = DEVONLY() ? {MID_SPREAD: 1} : 2;
const PARSE_INIT = DEVONLY() ? {PARSE_INIT: 1} : true;
const SKIP_INIT = DEVONLY() ? {SKIP_INIT: 1} : false;
const IS_EXPORT = DEVONLY() ? {IS_EXPORT: 1} : true;
const NOT_EXPORT = DEVONLY() ? {NOT_EXPORT: 1} : false;
const IS_QUASI_TAIL = DEVONLY() ? {IS_QUASI_TAIL: 1} : true;
const NOT_QUASI_TAIL = DEVONLY() ? {NOT_QUASI_TAIL: 1} : false;
const PARAM_UNDETERMINED = DEVONLY() ? {PARAM_UNDETERMINED: 1} : 0;
const PARAM_WAS_SIMPLE = DEVONLY() ? {PARAM_WAS_SIMPLE: 1} : 1;
const PARAM_WAS_NON_STRICT_SIMPLE = DEVONLY() ? {PARAM_WAS_NON_STRICT_SIMPLE: 1} : 2; // like a future reserved word, `(package) => {"use strict"}`
const PARAM_WAS_COMPLEX = DEVONLY() ? {PARAM_WAS_COMPLEX: 1} : 3;
const PARAM_WAS_COMPLEX_HAD_INIT = DEVONLY() ? {PARAM_WAS_COMPLEX_HAD_INIT: 1} : 4;
const PARAMS_ALL_SIMPLE = DEVONLY() ? {PARAMS_ALL_SIMPLE: 1} : 1;
const PARAMS_SOME_NONSTRICT = DEVONLY() ? {PARAMS_SOME_NONSTRICT: 1} : 2;
const PARAMS_SOME_COMPLEX = DEVONLY() ? {PARAMS_SOME_COMPLEX: 1} : 3;
const IS_CONSTRUCTOR = DEVONLY() ? {IS_CONSTRUCTOR: 1} : true;
const NOT_CONSTRUCTOR = DEVONLY() ? {NOT_CONSTRUCTOR: 1} : false;
const IS_METHOD = DEVONLY() ? {IS_METHOD: 1} : true;
const NOT_METHOD = DEVONLY() ? {NOT_METHOD: 1} : false;
const ASSIGN_EXPR_IS_OK = DEVONLY() ? {ASSIGN_EXPR_IS_OK: 1} : true; // fine to parse assignments, arrows, yield, ternary
const ASSIGN_EXPR_IS_ERROR = DEVONLY() ? {ASSIGN_EXPR_IS_ERROR: 1} : false; // throw on actual assignments, but also arrows, yield, await, ternary
const NO_ID_TO_VERIFY = DEVONLY() ? {NO_ID_TO_VERIFY: 1} : undefined;
const NO_DUPE_PARAMS = DEVONLY() ? {NO_DUPE_PARAMS: 1} : 0;
const DO_NOT_BIND = DEVONLY() ? {DO_NOT_BIND: 1} : null;
const UNDEF_EXPORTS = DEVONLY() ? {UNDEF_EXPORTS: 1} : undefined;
const FDS_ILLEGAL = DEVONLY() ? {FDS_ILLEGAL: 1} : 1; // function declaration not allowed, period
const FDS_IFELSE = DEVONLY() ? {FDS_IFELSE: 2} : 2; // if-else specific webcompat exception would apply to a function declaration
const FDS_LEX = DEVONLY() ? {FDS_LEX: 3} : 3; // a function declaration would be a lexical binding
const FDS_VAR = DEVONLY() ? {FDS_VAR: 4} : 4; // a function declaration would be a var binding
const IS_GLOBAL_TOPLEVEL = DEVONLY() ? {IS_GLOBAL_TOPLEVEL: 1} : true;
const NOT_GLOBAL_TOPLEVEL = DEVONLY() ? {NOT_GLOBAL_TOPLEVEL: 1} : false;
const IS_LABELLED = DEVONLY() ? {IS_LABELLED: 1} : true;
const NOT_LABELLED = DEVONLY() ? {NOT_LABELLED: 1} : false;
const NOT_LHSE = DEVONLY() ? {NOT_LHSE: 1} : false; // not requiring a "LeftHandExpression". This is currently only used for class `extends`.
const ONLY_LHSE = DEVONLY() ? {ONLY_LHSE: 1} : true; // restrict value to conform to a "LeftHandExpression" production.
const PARENT_NOT_LABEL = null; // when the parent statement was not a label statement
const EMPTY_LABEL_SET = null;
// The scope constants are exported so make them `let` so they don't get scrubbed entirely
// TODO: also means they won't be inlined so this may require a slightly more granular system
let BINDING_TYPE_NONE = DEVONLY() ? {BINDING_TYPE_NONE: 1} : 0;
let BINDING_TYPE_ARG = DEVONLY() ? {BINDING_TYPE_ARG: 1} : 1;
let BINDING_TYPE_VAR = DEVONLY() ? {BINDING_TYPE_VAR: 1} : 2;
let BINDING_TYPE_FUNC_VAR = DEVONLY() ? {BINDING_TYPE_FUNC_VAR: 1} : 3;
let BINDING_TYPE_FUNC_STMT = DEVONLY() ? {BINDING_TYPE_FUNC_STMT: 1} : 4; // A func decl inside a block or switch (for webcompat mode)
let BINDING_TYPE_FUNC_LEX = DEVONLY() ? {BINDING_TYPE_FUNC_LEX: 1} : 5;
let BINDING_TYPE_LET = DEVONLY() ? {BINDING_TYPE_LET: 1} : 6;
let BINDING_TYPE_CONST = DEVONLY() ? {BINDING_TYPE_CONST: 1} : 7;
let BINDING_TYPE_CLASS = DEVONLY() ? {BINDING_TYPE_CLASS: 1} : 8;
let BINDING_TYPE_CATCH_IDENT = DEVONLY() ? {BINDING_TYPE_CATCH_IDENT: 1} : 9;
let BINDING_TYPE_CATCH_OTHER = DEVONLY() ? {BINDING_TYPE_CATCH_OTHER: 1} : 10;
let HAS_NO_BINDINGS = DEVONLY() ? {HAS_NO_BINDINGS: 1} : null;
let SCOPE_LAYER_GLOBAL = DEVONLY() ? {SCOPE_LAYER_GLOBAL: 1} : 0;
let SCOPE_LAYER_FOR_HEADER = DEVONLY() ? {SCOPE_LAYER_FOR_HEADER: 1} : 1;
let SCOPE_LAYER_BLOCK = DEVONLY() ? {SCOPE_LAYER_BLOCK: 1} : 2;
let SCOPE_LAYER_FUNC_PARAMS = DEVONLY() ? {SCOPE_LAYER_FUNC_PARAMS: 1} : 3;
let SCOPE_LAYER_CATCH_HEAD = DEVONLY() ? {SCOPE_LAYER_CATCH_HEAD: 1} : 5;
let SCOPE_LAYER_CATCH_BODY = DEVONLY() ? {SCOPE_LAYER_CATCH_BODY: 1} : 6;
let SCOPE_LAYER_FINALLY = DEVONLY() ? {SCOPE_LAYER_FINALLY: 1} : 7;
let SCOPE_LAYER_SWITCH = DEVONLY() ? {SCOPE_LAYER_SWITCH: 1} : 8;
let SCOPE_LAYER_FUNC_ROOT = DEVONLY() ? {SCOPE_LAYER_FUNC_ROOT: 1} : 9;
let SCOPE_LAYER_FUNC_BODY = DEVONLY() ? {SCOPE_LAYER_FUNC_BODY: 1} : 10;
let SCOPE_LAYER_ARROW_PARAMS = DEVONLY() ? {SCOPE_LAYER_ARROW_PARAMS: 1} : 11;
let SCOPE_LAYER_FAKE_BLOCK = DEVONLY() ? {SCOPE_LAYER_FAKE_BLOCK: 1} : 12;
// This `DEVONLY` function is only used to set objects for enum in a dev build. In a prod build these are stripped entirely
// The "dsl" for this function is assuming usage in a ternary (`DEVONLY() ? devstuff : prodstuff`). Any other use is at the mercy of the DCE of the minifier.
function DEVONLY() {
let dev = false;
// A build will eliminate this ASSERT call. A minifier will inline the `true` and then eliminate it. Hopefully.
ASSERT(dev = true);
return dev;
}
const PIGGIES = (0
| PIGGY_BACK_SAW_AWAIT
| PIGGY_BACK_SAW_YIELD
| PIGGY_BACK_WAS_CONSTRUCTOR
| PIGGY_BACK_WAS_PROTO
| PIGGY_BACK_WAS_ARROW
);
function copyPiggies(output, input) {
return output | (input & PIGGIES);
}
function P(f, arr) {
if (f & PIGGY_BACK_WAS_CONSTRUCTOR) {
arr.push('PIGGY_BACK_WAS_CONSTRUCTOR');
f ^= PIGGY_BACK_WAS_CONSTRUCTOR;
}
if (f & PIGGY_BACK_WAS_PROTO) {
arr.push('PIGGY_BACK_WAS_PROTO');
f ^= PIGGY_BACK_WAS_PROTO;
}
if (f & PIGGY_BACK_SAW_AWAIT) {
arr.push('PIGGY_BACK_SAW_AWAIT');
f ^= PIGGY_BACK_SAW_AWAIT;
}
if (f & PIGGY_BACK_SAW_YIELD) {
arr.push('PIGGY_BACK_SAW_YIELD');
f ^= PIGGY_BACK_SAW_YIELD;
}
if (f & PIGGY_BACK_WAS_ARROW) {
arr.push('PIGGY_BACK_WAS_ARROW');
f ^= PIGGY_BACK_WAS_ARROW;
}
return f;
}
export {
VERSION_EXPONENTIATION,
VERSION_ASYNC,
VERSION_TRAILING_FUNC_COMMAS,
VERSION_ASYNC_GEN,
VERSION_OBJECTSPREAD,
VERSION_TAGGED_TEMPLATE_BAD_ESCAPES,
VERSION_OPTIONAL_CATCH,
VERSION_DYNAMIC_IMPORT,
VERSION_EXPORT_STAR_AS,
VERSION_WHATEVER,
IS_ASYNC,
NOT_ASYNC,
IS_ASYNC_PREFIXED,
NOT_ASYNC_PREFIXED,
UNDEF_STATIC,
UNDEF_ASYNC,
UNDEF_STAR,
UNDEF_GET,
UNDEF_SET,
IS_FUNC_DECL,
NOT_FUNC_DECL,
IS_FUNC_EXPR,
NOT_FUNC_EXPR,
IDENT_OPTIONAL,
IDENT_REQUIRED,
PARSE_VALUE_MAYBE,
PARSE_VALUE_MUST,
YIELD_WITHOUT_VALUE,
WITH_ASSIGNABLE,
WITH_NON_ASSIGNABLE,
IS_ARROW,
NOT_ARROW,
FROM_STATEMENT_START,
FROM_FOR_HEADER,
FROM_EXPORT_DECL,
FROM_CATCH,
FROM_ASYNC_ARG,
FROM_OTHER_FUNC_ARG,
COAL_SEEN_NEITHER,
COAL_SEEN_NULLISH,
COAL_SEEN_LOGICAL,
BINDING_TYPE_NONE,
BINDING_TYPE_ARG,
BINDING_TYPE_VAR,
BINDING_TYPE_LET,
BINDING_TYPE_CONST,
BINDING_TYPE_CLASS,
BINDING_TYPE_FUNC_VAR,
BINDING_TYPE_FUNC_LEX,
BINDING_TYPE_FUNC_STMT,
BINDING_TYPE_CATCH_IDENT,
BINDING_TYPE_CATCH_OTHER,
HAS_NO_BINDINGS,
ASSIGNMENT_IS_INIT,
ASSIGNMENT_IS_DEFAULT,
IS_EXPRESSION,
IS_STATEMENT,
IS_NEW_ARG,
NOT_NEW_ARG,
IS_OPTIONAL,
NOT_OPTIONAL,
MIGHT_DESTRUCT,
CANT_DESTRUCT,
DESTRUCT_ASSIGN_ONLY,
MUST_DESTRUCT,
ASSIGNABLE_UNDETERMINED,
NOT_ASSIGNABLE,
IS_ASSIGNABLE,
PIGGY_BACK_SAW_AWAIT,
PIGGY_BACK_SAW_YIELD,
PIGGY_BACK_WAS_CONSTRUCTOR,
PIGGY_BACK_WAS_PROTO,
PIGGY_BACK_WAS_ARROW,
NO_SPREAD,
LAST_SPREAD,
MID_SPREAD,
PARSE_INIT,
SKIP_INIT,
IS_EXPORT,
NOT_EXPORT,
IS_QUASI_TAIL,
NOT_QUASI_TAIL,
PARAM_UNDETERMINED,
PARAM_WAS_SIMPLE,
PARAM_WAS_NON_STRICT_SIMPLE,
PARAM_WAS_COMPLEX,
PARAM_WAS_COMPLEX_HAD_INIT,
PARAMS_ALL_SIMPLE,
PARAMS_SOME_NONSTRICT,
PARAMS_SOME_COMPLEX,
IS_CONSTRUCTOR,
NOT_CONSTRUCTOR,
IS_METHOD,
NOT_METHOD,
ASSIGN_EXPR_IS_OK,
ASSIGN_EXPR_IS_ERROR,
NO_ID_TO_VERIFY,
NO_DUPE_PARAMS,
SCOPE_LAYER_GLOBAL,
SCOPE_LAYER_FOR_HEADER,
SCOPE_LAYER_BLOCK,
SCOPE_LAYER_FUNC_PARAMS,
SCOPE_LAYER_CATCH_HEAD,
SCOPE_LAYER_CATCH_BODY,
SCOPE_LAYER_FINALLY,
SCOPE_LAYER_SWITCH,
SCOPE_LAYER_FUNC_ROOT,
SCOPE_LAYER_FUNC_BODY,
SCOPE_LAYER_ARROW_PARAMS,
SCOPE_LAYER_FAKE_BLOCK,
DO_NOT_BIND,
UNDEF_EXPORTS,
FDS_ILLEGAL,
FDS_IFELSE,
FDS_LEX,
FDS_VAR,
IS_GLOBAL_TOPLEVEL,
NOT_GLOBAL_TOPLEVEL,
IS_LABELLED,
NOT_LABELLED,
NOT_LHSE,
ONLY_LHSE,
PARENT_NOT_LABEL,
EMPTY_LABEL_SET,
copyPiggies,
P,
};