jseption 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -3
- package/dist/bytecode.d.ts +6 -0
- package/dist/bytecode.js +1071 -0
- package/dist/bytecode.js.map +1 -0
- package/dist/interpreter.js +15 -4
- package/dist/interpreter.js.map +1 -1
- package/dist/jit.js +12 -4
- package/dist/jit.js.map +1 -1
- package/dist/jit_runtime.d.ts +2 -0
- package/dist/jit_runtime.js +11 -0
- package/dist/jit_runtime.js.map +1 -1
- package/dist/jseption.d.ts +6 -0
- package/dist/jseption.js +5 -0
- package/dist/jseption.js.map +1 -1
- package/dist/module.d.ts +28 -0
- package/dist/module.js +1166 -0
- package/dist/module.js.map +1 -0
- package/dist/opcodes.js +1 -1
- package/dist/opcodes.js.map +1 -1
- package/dist/parser.d.ts +31 -0
- package/dist/parser.js +2862 -62
- package/dist/parser.js.map +1 -1
- package/dist/qjs.js +86 -17
- package/dist/qjs.js.map +1 -1
- package/dist/quickjs.d.ts +8 -0
- package/dist/quickjs.js +21 -2
- package/dist/quickjs.js.map +1 -1
- package/dist/std.d.ts +2 -0
- package/dist/std.js +34 -0
- package/dist/std.js.map +1 -1
- package/dist/values.d.ts +78 -0
- package/dist/values.js +85 -0
- package/dist/values.js.map +1 -1
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/package.json +3 -2
package/dist/parser.js
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
* ("phase 2": resolve_variables) and a label resolution / peephole pass
|
|
11
11
|
* ("phase 3": resolve_labels).
|
|
12
12
|
*/
|
|
13
|
-
import { JS_ATOM_NULL, JS_EXCEPTION, JS_IsException, JSFunctionBytecode, JSVarDef, JSClosureVar, JS_MODE_STRICT, JS_MODE_BACKTRACE_BARRIER, JS_EVAL_TYPE_GLOBAL, JS_EVAL_TYPE_MODULE, JS_EVAL_TYPE_DIRECT, JS_EVAL_TYPE_INDIRECT, JS_EVAL_TYPE_MASK, JS_EVAL_FLAG_STRICT, JS_EVAL_FLAG_COMPILE_ONLY, JS_EVAL_FLAG_BACKTRACE_BARRIER, JS_EVAL_FLAG_ASYNC, JS_NewAtom, JS_AtomToString, JS_AtomGetStr, JS_ThrowSyntaxError, JS_ThrowError2, JS_Throw, JS_NewErrorNative, JS_DefinePropertyValue, JS_PROP_WRITABLE, JS_PROP_CONFIGURABLE, JS_SetErrorBacktraceDone, JS_ATOM_stack, JS_ATOM_lineNumber, JS_ATOM_columnNumber, JS_ATOM_fileName, hooks, JS_Call, JS_ATOM_empty_string, JS_ATOM_arguments, JS_ATOM_eval, JS_ATOM_this, JS_ATOM_new_target, JS_ATOM_home_object, JS_ATOM_this_active_func, JS_ATOM__eval_, JS_ATOM__ret_, JS_ATOM__var_, JS_ATOM__arg_var_, JS_ATOM_length, JS_ATOM_prototype, JS_ATOM_constructor, JS_ATOM_get, JS_ATOM_set, JS_ATOM_of, JS_ATOM___proto__, JS_ATOM_let, JS_ATOM_yield, JS_ATOM_await, JS_ATOM_async, JS_ATOM_static, JS_ATOM_target, JS_ATOM_meta, JS_ATOM_undefined, JS_ATOM_class_fields_init, JS_ATOM_computed_field, JS_ATOM_hash_constructor, JS_ATOM_raw, JS_ATOM_implements, JS_ATOM_null, JS_ATOM_default, JS_ATOM_function, JS_ATOM_done, JS_ATOM_value, JS_NewArray, JS_DefinePropertyValueUint32, JS_PROP_ENUMERABLE, JS_GetFunctionData, __JS_AtomIsTaggedInt, __JS_AtomFromUInt32, JS_GetException, JS_ATOM_super, JS_ATOM__with_, JS_ATOM_return, JS_ATOM__default_, } from "./quickjs.js";
|
|
13
|
+
import { JS_ATOM_NULL, JS_EXCEPTION, JS_IsException, JSFunctionBytecode, JSVarDef, JSClosureVar, JS_MODE_STRICT, JS_MODE_BACKTRACE_BARRIER, JS_EVAL_TYPE_GLOBAL, JS_EVAL_TYPE_MODULE, JS_EVAL_TYPE_DIRECT, JS_EVAL_TYPE_INDIRECT, JS_EVAL_TYPE_MASK, JS_EVAL_FLAG_STRICT, JS_EVAL_FLAG_COMPILE_ONLY, JS_EVAL_FLAG_BACKTRACE_BARRIER, JS_EVAL_FLAG_ASYNC, JS_EVAL_FLAG_STRIP_TYPES, JS_EVAL_FLAG_JSX, JS_NewAtom, JS_AtomToString, JS_AtomGetStr, JS_ThrowSyntaxError, JS_ThrowError2, JS_Throw, JS_NewErrorNative, JS_DefinePropertyValue, JS_PROP_WRITABLE, JS_PROP_CONFIGURABLE, JS_SetErrorBacktraceDone, JS_ATOM_stack, JS_ATOM_lineNumber, JS_ATOM_columnNumber, JS_ATOM_fileName, hooks, JS_Call, JS_ATOM_empty_string, JS_ATOM_arguments, JS_ATOM_eval, JS_ATOM_this, JS_ATOM_new_target, JS_ATOM_home_object, JS_ATOM_this_active_func, JS_ATOM__eval_, JS_ATOM__ret_, JS_ATOM__var_, JS_ATOM__arg_var_, JS_ATOM_length, JS_ATOM_prototype, JS_ATOM_constructor, JS_ATOM_get, JS_ATOM_set, JS_ATOM_of, JS_ATOM___proto__, JS_ATOM_let, JS_ATOM_yield, JS_ATOM_await, JS_ATOM_async, JS_ATOM_static, JS_ATOM_as, JS_ATOM_from, JS_ATOM_target, JS_ATOM_meta, JS_ATOM_undefined, JS_ATOM_class_fields_init, JS_ATOM_computed_field, JS_ATOM_hash_constructor, JS_ATOM_raw, JS_ATOM_implements, JS_ATOM_interface, JS_ATOM_private, JS_ATOM_protected, JS_ATOM_public, JS_ATOM_global, JS_ATOM_null, JS_ATOM_default, JS_ATOM_function, JS_ATOM_done, JS_ATOM_value, JS_NewArray, JS_DefinePropertyValueUint32, JS_PROP_ENUMERABLE, JS_GetFunctionData, __JS_AtomIsTaggedInt, __JS_AtomFromUInt32, JS_GetException, JS_HasException, JS_ATOM_super, JS_ATOM__with_, JS_ATOM_return, JS_ATOM__default_, JS_ATOM__star_, } from "./quickjs.js";
|
|
14
|
+
import { JSModuleDef, JSReqModuleEntry, JSExportEntry, JSStarExportEntry, JSImportEntry } from "./values.js";
|
|
14
15
|
import { opcode_info, short_opcode_info, OP_DEFINE_METHOD_METHOD, OP_DEFINE_METHOD_GETTER, OP_DEFINE_METHOD_ENUMERABLE, JS_DEFINE_CLASS_HAS_HERITAGE, JS_THROW_VAR_RO, JS_THROW_VAR_REDECL, JS_THROW_ERROR_DELETE_SUPER, JS_THROW_ERROR_ITERATOR_THROW, DEFINE_GLOBAL_LEX_VAR, DEFINE_GLOBAL_FUNC_VAR, get_u8, get_i8, get_u16, get_i16, get_u32, get_i32, put_u8, put_u16, put_u32 } from "./opcodes.js";
|
|
15
16
|
const TOK_FIRST_KEYWORD = -85 /* TOK.NULL */;
|
|
16
17
|
const TOK_LAST_KEYWORD = -40 /* TOK.AWAIT */;
|
|
@@ -224,6 +225,13 @@ export class JSParseState {
|
|
|
224
225
|
is_module = false; /* parsing a module */
|
|
225
226
|
allow_html_comments = false;
|
|
226
227
|
ext_json = false; /* true if accepting JSON superset */
|
|
228
|
+
/* TypeScript type stripping (JS_EVAL_FLAG_STRIP_TYPES) */
|
|
229
|
+
ts = false;
|
|
230
|
+
ts_cond_true = false; /* parsing the true branch of a conditional expression (arrow return type rule) */
|
|
231
|
+
ts_atoms = null;
|
|
232
|
+
/* JSX (JS_EVAL_FLAG_JSX) */
|
|
233
|
+
jsx = false;
|
|
234
|
+
jsx_runtime = null; /* decided at the first element */
|
|
227
235
|
/* line/col cache */
|
|
228
236
|
line_num = 1;
|
|
229
237
|
/* used for error reporting: position of the last token start */
|
|
@@ -1556,62 +1564,2058 @@ function js_parse_skip_parens_token(s, pbits, no_line_terminator) {
|
|
|
1556
1564
|
break;
|
|
1557
1565
|
case -86 /* TOK.EOF */:
|
|
1558
1566
|
break outer;
|
|
1567
|
+
case 60: /* < */
|
|
1568
|
+
if (s.jsx && is_regexp_allowed(last_tok) && jsx_try_skip(s)) {
|
|
1569
|
+
/* a JSX element */
|
|
1570
|
+
last_tok = 41;
|
|
1571
|
+
continue;
|
|
1572
|
+
}
|
|
1573
|
+
break;
|
|
1559
1574
|
case 59: /* ; */
|
|
1560
1575
|
if (level === 2)
|
|
1561
1576
|
bits |= SKIP_HAS_SEMI;
|
|
1562
1577
|
break;
|
|
1563
|
-
case -91 /* TOK.ELLIPSIS */:
|
|
1564
|
-
if (level === 2)
|
|
1565
|
-
bits |= SKIP_HAS_ELLIPSIS;
|
|
1578
|
+
case -91 /* TOK.ELLIPSIS */:
|
|
1579
|
+
if (level === 2)
|
|
1580
|
+
bits |= SKIP_HAS_ELLIPSIS;
|
|
1581
|
+
break;
|
|
1582
|
+
case 61: /* = */
|
|
1583
|
+
bits |= SKIP_HAS_ASSIGNMENT;
|
|
1584
|
+
break;
|
|
1585
|
+
case -122 /* TOK.DIV_ASSIGN */:
|
|
1586
|
+
case 47: /* / */
|
|
1587
|
+
if (is_regexp_allowed(last_tok)) {
|
|
1588
|
+
s.buf_ptr = s.token.ptr + 1;
|
|
1589
|
+
if (js_parse_regexp(s)) {
|
|
1590
|
+
/* clear the exception generated by js_parse_regexp */
|
|
1591
|
+
JS_GetException(s.ctx);
|
|
1592
|
+
break outer;
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
break;
|
|
1596
|
+
}
|
|
1597
|
+
/* last_tok is only used to recognize regexps */
|
|
1598
|
+
if (tv(s) === -125 /* TOK.IDENT */ && (token_is_pseudo_keyword(s, JS_ATOM_of) || token_is_pseudo_keyword(s, JS_ATOM_yield))) {
|
|
1599
|
+
last_tok = -39 /* TOK.OF */;
|
|
1600
|
+
}
|
|
1601
|
+
else {
|
|
1602
|
+
last_tok = tv(s);
|
|
1603
|
+
}
|
|
1604
|
+
const last_token_ptr = s.token.ptr;
|
|
1605
|
+
if (next_token(s)) {
|
|
1606
|
+
/* clear the exception generated by next_token() */
|
|
1607
|
+
JS_GetException(s.ctx);
|
|
1608
|
+
break;
|
|
1609
|
+
}
|
|
1610
|
+
if (level <= 1) {
|
|
1611
|
+
tok = tv(s);
|
|
1612
|
+
if (token_is_pseudo_keyword(s, JS_ATOM_of))
|
|
1613
|
+
tok = -39 /* TOK.OF */;
|
|
1614
|
+
if (no_line_terminator && has_lf_in_range(s, last_token_ptr, s.token.ptr))
|
|
1615
|
+
tok = 10;
|
|
1616
|
+
break;
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
if (pbits)
|
|
1620
|
+
pbits.bits = bits;
|
|
1621
|
+
/* restore the parser state */
|
|
1622
|
+
Object.assign(s.token, pos.token);
|
|
1623
|
+
s.buf_ptr = saved_ptr;
|
|
1624
|
+
s.got_lf = saved_got_lf;
|
|
1625
|
+
return tok;
|
|
1626
|
+
}
|
|
1627
|
+
const SKIP_HAS_SEMI = 1 << 0;
|
|
1628
|
+
const SKIP_HAS_ELLIPSIS = 1 << 1;
|
|
1629
|
+
const SKIP_HAS_ASSIGNMENT = 1 << 2;
|
|
1630
|
+
/* ---------------------------------------------------------------------
|
|
1631
|
+
TypeScript type stripping (JS_EVAL_FLAG_STRIP_TYPES)
|
|
1632
|
+
|
|
1633
|
+
Node's strip-only mode: the erasable TypeScript syntax (annotations,
|
|
1634
|
+
type declarations, generics, assertions, modifiers, overload
|
|
1635
|
+
signatures...) is consumed at the token level and never reaches the
|
|
1636
|
+
bytecode emitter, so the program compiles to exactly the bytecode of
|
|
1637
|
+
the JavaScript obtained by replacing the types with spaces, with the
|
|
1638
|
+
same source positions for errors, stacks and line tables. Constructs
|
|
1639
|
+
that need code generation (enum, namespaces with values, parameter
|
|
1640
|
+
properties, import =, export =) are rejected with a SyntaxError.
|
|
1641
|
+
|
|
1642
|
+
The ts_skip_* functions consume tokens and return true, or false on a
|
|
1643
|
+
token they cannot accept (a lexer error leaves an exception pending).
|
|
1644
|
+
They never emit bytecode, so they also run speculatively: ts_save and
|
|
1645
|
+
ts_restore rewind the lexer and drop any pending exception.
|
|
1646
|
+
See docs/TYPESCRIPT.md for the grammar and the ambiguity rules.
|
|
1647
|
+
--------------------------------------------------------------------- */
|
|
1648
|
+
class TSAtoms {
|
|
1649
|
+
type;
|
|
1650
|
+
declare;
|
|
1651
|
+
abstract;
|
|
1652
|
+
readonly;
|
|
1653
|
+
namespace;
|
|
1654
|
+
module;
|
|
1655
|
+
keyof;
|
|
1656
|
+
infer;
|
|
1657
|
+
is;
|
|
1658
|
+
asserts;
|
|
1659
|
+
satisfies;
|
|
1660
|
+
override;
|
|
1661
|
+
unique;
|
|
1662
|
+
out;
|
|
1663
|
+
assert;
|
|
1664
|
+
with_;
|
|
1665
|
+
constructor(ctx) {
|
|
1666
|
+
const a = (n) => JS_NewAtom(ctx, n);
|
|
1667
|
+
this.type = a('type');
|
|
1668
|
+
this.declare = a('declare');
|
|
1669
|
+
this.abstract = a('abstract');
|
|
1670
|
+
this.readonly = a('readonly');
|
|
1671
|
+
this.namespace = a('namespace');
|
|
1672
|
+
this.module = a('module');
|
|
1673
|
+
this.keyof = a('keyof');
|
|
1674
|
+
this.infer = a('infer');
|
|
1675
|
+
this.is = a('is');
|
|
1676
|
+
this.asserts = a('asserts');
|
|
1677
|
+
this.satisfies = a('satisfies');
|
|
1678
|
+
this.override = a('override');
|
|
1679
|
+
this.unique = a('unique');
|
|
1680
|
+
this.out = a('out');
|
|
1681
|
+
this.assert = a('assert');
|
|
1682
|
+
this.with_ = a('with');
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
function ts_atoms(s) {
|
|
1686
|
+
return s.ts_atoms ?? (s.ts_atoms = new TSAtoms(s.ctx));
|
|
1687
|
+
}
|
|
1688
|
+
/* the current token is the identifier or keyword `atom`, written without escapes */
|
|
1689
|
+
function ts_word(s, atom) {
|
|
1690
|
+
return s.token.atom === atom && !s.token.has_escape &&
|
|
1691
|
+
(tv(s) === -125 /* TOK.IDENT */ || (tv(s) >= TOK_FIRST_KEYWORD && tv(s) <= TOK_LAST_KEYWORD));
|
|
1692
|
+
}
|
|
1693
|
+
function ts_is_keyword(t) { return t >= TOK_FIRST_KEYWORD && t <= TOK_LAST_KEYWORD; }
|
|
1694
|
+
function ts_next(s) { return next_token(s) === 0; }
|
|
1695
|
+
function ts_save(s) {
|
|
1696
|
+
const t = new JSToken();
|
|
1697
|
+
Object.assign(t, s.token);
|
|
1698
|
+
return { token: t, buf_ptr: s.buf_ptr, got_lf: s.got_lf, last_ptr: s.last_ptr };
|
|
1699
|
+
}
|
|
1700
|
+
function ts_restore(s, p) {
|
|
1701
|
+
Object.assign(s.token, p.token);
|
|
1702
|
+
s.buf_ptr = p.buf_ptr;
|
|
1703
|
+
s.got_lf = p.got_lf;
|
|
1704
|
+
s.last_ptr = p.last_ptr;
|
|
1705
|
+
if (JS_HasException(s.ctx))
|
|
1706
|
+
JS_GetException(s.ctx);
|
|
1707
|
+
}
|
|
1708
|
+
function ts_peek(s) {
|
|
1709
|
+
const p = ts_save(s);
|
|
1710
|
+
const r = ts_next(s) ? { val: tv(s), atom: s.token.atom, lf: s.got_lf, escape: s.token.has_escape }
|
|
1711
|
+
: { val: -88 /* TOK.ERROR */, atom: JS_ATOM_NULL, lf: false, escape: false };
|
|
1712
|
+
ts_restore(s, p);
|
|
1713
|
+
return r;
|
|
1714
|
+
}
|
|
1715
|
+
function ts_peek_is_name(s) {
|
|
1716
|
+
const n = ts_peek(s);
|
|
1717
|
+
return !n.lf && (n.val === -125 /* TOK.IDENT */ || ts_is_keyword(n.val));
|
|
1718
|
+
}
|
|
1719
|
+
/* a skipper failed: report it unless the lexer already did */
|
|
1720
|
+
function ts_error(s, msg) {
|
|
1721
|
+
if (JS_HasException(s.ctx))
|
|
1722
|
+
return -1;
|
|
1723
|
+
return js_parse_error(s, msg);
|
|
1724
|
+
}
|
|
1725
|
+
/* Node's ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX */
|
|
1726
|
+
function ts_unsupported(s, what, pos) {
|
|
1727
|
+
return js_parse_error_pos(s, pos, `TypeScript ${what} is not supported in strip-only mode`);
|
|
1728
|
+
}
|
|
1729
|
+
/* '<' opening a type argument or parameter list ('<<' is split) */
|
|
1730
|
+
function ts_eat_lt(s) {
|
|
1731
|
+
if (tv(s) === 60)
|
|
1732
|
+
return ts_next(s);
|
|
1733
|
+
if (tv(s) === -106 /* TOK.SHL */) {
|
|
1734
|
+
s.buf_ptr = s.token.ptr + 1;
|
|
1735
|
+
return ts_next(s);
|
|
1736
|
+
}
|
|
1737
|
+
return false;
|
|
1738
|
+
}
|
|
1739
|
+
function ts_is_gt(t) {
|
|
1740
|
+
return t === 62 || t === -105 /* TOK.SAR */ || t === -104 /* TOK.SHR */ || t === -100 /* TOK.GTE */ || t === -117 /* TOK.SAR_ASSIGN */ || t === -116 /* TOK.SHR_ASSIGN */;
|
|
1741
|
+
}
|
|
1742
|
+
/* '>' closing a type list: '>>', '>>>', '>=', ... are split and the rest rescanned */
|
|
1743
|
+
function ts_eat_gt(s) {
|
|
1744
|
+
if (tv(s) === 62)
|
|
1745
|
+
return ts_next(s);
|
|
1746
|
+
if (!ts_is_gt(tv(s)))
|
|
1747
|
+
return false;
|
|
1748
|
+
s.buf_ptr = s.token.ptr + 1;
|
|
1749
|
+
return ts_next(s);
|
|
1750
|
+
}
|
|
1751
|
+
/* skip a balanced (...), [...], {...} or template literal, regexps, nested templates and JSX
|
|
1752
|
+
elements included; the token after it becomes current, or with lex_next false the position is
|
|
1753
|
+
just after its closing character. `info.ellipsis` records a '...' directly inside */
|
|
1754
|
+
function ts_skip_balanced(s, lex_next = true, info = null) {
|
|
1755
|
+
const stack = [];
|
|
1756
|
+
let last_tok = 0;
|
|
1757
|
+
for (;;) {
|
|
1758
|
+
const t = tv(s);
|
|
1759
|
+
switch (t) {
|
|
1760
|
+
case 60:
|
|
1761
|
+
if (s.jsx && is_regexp_allowed(last_tok) && jsx_try_skip(s)) {
|
|
1762
|
+
last_tok = 41; /* an operand */
|
|
1763
|
+
continue;
|
|
1764
|
+
}
|
|
1765
|
+
break;
|
|
1766
|
+
case -91 /* TOK.ELLIPSIS */:
|
|
1767
|
+
if (info !== null && stack.length === 1)
|
|
1768
|
+
info.ellipsis = true;
|
|
1769
|
+
break;
|
|
1770
|
+
case 40:
|
|
1771
|
+
case 91:
|
|
1772
|
+
case 123:
|
|
1773
|
+
stack.push(t);
|
|
1774
|
+
break;
|
|
1775
|
+
case 41:
|
|
1776
|
+
if (stack.pop() !== 40)
|
|
1777
|
+
return false;
|
|
1778
|
+
break;
|
|
1779
|
+
case 93:
|
|
1780
|
+
if (stack.pop() !== 91)
|
|
1781
|
+
return false;
|
|
1782
|
+
break;
|
|
1783
|
+
case 125: {
|
|
1784
|
+
const c = stack.pop();
|
|
1785
|
+
if (c === 96) {
|
|
1786
|
+
/* end of a template substitution: continue the template */
|
|
1787
|
+
s.got_lf = false;
|
|
1788
|
+
if (js_parse_template_part(s, s.buf_ptr))
|
|
1789
|
+
return false;
|
|
1790
|
+
if (s.token.sep !== 96)
|
|
1791
|
+
stack.push(96);
|
|
1792
|
+
}
|
|
1793
|
+
else if (c !== 123) {
|
|
1794
|
+
return false;
|
|
1795
|
+
}
|
|
1796
|
+
break;
|
|
1797
|
+
}
|
|
1798
|
+
case -126 /* TOK.TEMPLATE */:
|
|
1799
|
+
if (s.token.sep !== 96)
|
|
1800
|
+
stack.push(96);
|
|
1801
|
+
break;
|
|
1802
|
+
case -86 /* TOK.EOF */:
|
|
1803
|
+
return false;
|
|
1804
|
+
case -122 /* TOK.DIV_ASSIGN */:
|
|
1805
|
+
case 47:
|
|
1806
|
+
if (is_regexp_allowed(last_tok)) {
|
|
1807
|
+
s.buf_ptr = s.token.ptr + 1;
|
|
1808
|
+
if (js_parse_regexp(s))
|
|
1809
|
+
return false;
|
|
1810
|
+
}
|
|
1811
|
+
break;
|
|
1812
|
+
}
|
|
1813
|
+
last_tok = tv(s);
|
|
1814
|
+
if (stack.length === 0)
|
|
1815
|
+
return lex_next ? ts_next(s) : true;
|
|
1816
|
+
if (!ts_next(s))
|
|
1817
|
+
return false;
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
const TS_NO_COND = 1; /* conditional types are not allowed (the extends clause of a conditional type) */
|
|
1821
|
+
/* Type: function type, constructor type, or a union with an optional conditional part */
|
|
1822
|
+
function ts_skip_type(s, flags = 0) {
|
|
1823
|
+
const A = ts_atoms(s);
|
|
1824
|
+
if (tv(s) === 60) {
|
|
1825
|
+
/* generic function type: <T>(x: T) => T */
|
|
1826
|
+
return ts_skip_type_params(s) && ts_skip_fn_type_rest(s);
|
|
1827
|
+
}
|
|
1828
|
+
if (ts_word(s, A.abstract) && ts_peek(s).val === -74 /* TOK.NEW */) {
|
|
1829
|
+
if (!ts_next(s))
|
|
1830
|
+
return false;
|
|
1831
|
+
}
|
|
1832
|
+
if (tv(s) === -74 /* TOK.NEW */) {
|
|
1833
|
+
if (!ts_next(s))
|
|
1834
|
+
return false;
|
|
1835
|
+
if (tv(s) === 60 && !ts_skip_type_params(s))
|
|
1836
|
+
return false;
|
|
1837
|
+
return ts_skip_fn_type_rest(s);
|
|
1838
|
+
}
|
|
1839
|
+
if (tv(s) === 40) {
|
|
1840
|
+
/* function type, or a parenthesized type */
|
|
1841
|
+
const p = ts_save(s);
|
|
1842
|
+
if (ts_skip_balanced(s) && tv(s) === -92 /* TOK.ARROW */)
|
|
1843
|
+
return ts_next(s) && ts_skip_return_type(s);
|
|
1844
|
+
ts_restore(s, p);
|
|
1845
|
+
}
|
|
1846
|
+
if (!ts_skip_union(s, flags))
|
|
1847
|
+
return false;
|
|
1848
|
+
if (!(flags & TS_NO_COND) && tv(s) === -52 /* TOK.EXTENDS */ && !s.got_lf) {
|
|
1849
|
+
/* conditional type: C extends E ? T : F */
|
|
1850
|
+
if (!ts_next(s) || !ts_skip_type(s, TS_NO_COND))
|
|
1851
|
+
return false;
|
|
1852
|
+
if (tv(s) !== 63 || !ts_next(s) || !ts_skip_type(s))
|
|
1853
|
+
return false;
|
|
1854
|
+
if (tv(s) !== 58 || !ts_next(s))
|
|
1855
|
+
return false;
|
|
1856
|
+
return ts_skip_type(s);
|
|
1857
|
+
}
|
|
1858
|
+
return true;
|
|
1859
|
+
}
|
|
1860
|
+
/* '(' parameters ')' '=>' return type */
|
|
1861
|
+
function ts_skip_fn_type_rest(s) {
|
|
1862
|
+
if (tv(s) !== 40 || !ts_skip_balanced(s))
|
|
1863
|
+
return false;
|
|
1864
|
+
if (tv(s) !== -92 /* TOK.ARROW */ || !ts_next(s))
|
|
1865
|
+
return false;
|
|
1866
|
+
return ts_skip_return_type(s);
|
|
1867
|
+
}
|
|
1868
|
+
function ts_skip_union(s, flags) {
|
|
1869
|
+
if (tv(s) === 124 && !ts_next(s))
|
|
1870
|
+
return false;
|
|
1871
|
+
if (!ts_skip_intersection(s, flags))
|
|
1872
|
+
return false;
|
|
1873
|
+
while (tv(s) === 124) {
|
|
1874
|
+
if (!ts_next(s) || !ts_skip_intersection(s, flags))
|
|
1875
|
+
return false;
|
|
1876
|
+
}
|
|
1877
|
+
return true;
|
|
1878
|
+
}
|
|
1879
|
+
function ts_skip_intersection(s, flags) {
|
|
1880
|
+
if (tv(s) === 38 && !ts_next(s))
|
|
1881
|
+
return false;
|
|
1882
|
+
if (!ts_skip_type_operator(s, flags))
|
|
1883
|
+
return false;
|
|
1884
|
+
while (tv(s) === 38) {
|
|
1885
|
+
if (!ts_next(s) || !ts_skip_type_operator(s, flags))
|
|
1886
|
+
return false;
|
|
1887
|
+
}
|
|
1888
|
+
return true;
|
|
1889
|
+
}
|
|
1890
|
+
/* the next token can start the operand of a type operator */
|
|
1891
|
+
function ts_peek_starts_type(s) {
|
|
1892
|
+
const n = ts_peek(s);
|
|
1893
|
+
switch (n.val) {
|
|
1894
|
+
case 44:
|
|
1895
|
+
case 62:
|
|
1896
|
+
case 41:
|
|
1897
|
+
case 93:
|
|
1898
|
+
case 125:
|
|
1899
|
+
case 59:
|
|
1900
|
+
case 61:
|
|
1901
|
+
case 124:
|
|
1902
|
+
case 38:
|
|
1903
|
+
case 46:
|
|
1904
|
+
case 63:
|
|
1905
|
+
case 58:
|
|
1906
|
+
case -86 /* TOK.EOF */:
|
|
1907
|
+
case -92 /* TOK.ARROW */:
|
|
1908
|
+
case -52 /* TOK.EXTENDS */:
|
|
1909
|
+
case -88 /* TOK.ERROR */:
|
|
1910
|
+
case -105 /* TOK.SAR */:
|
|
1911
|
+
case -104 /* TOK.SHR */:
|
|
1912
|
+
case -100 /* TOK.GTE */:
|
|
1913
|
+
return false;
|
|
1914
|
+
}
|
|
1915
|
+
return true;
|
|
1916
|
+
}
|
|
1917
|
+
function ts_skip_type_operator(s, flags) {
|
|
1918
|
+
const A = ts_atoms(s);
|
|
1919
|
+
if ((ts_word(s, A.keyof) || ts_word(s, A.unique) || ts_word(s, A.readonly)) && ts_peek_starts_type(s)) {
|
|
1920
|
+
return ts_next(s) && ts_skip_type_operator(s, flags);
|
|
1921
|
+
}
|
|
1922
|
+
if (ts_word(s, A.infer) && ts_peek_is_name(s)) {
|
|
1923
|
+
if (!ts_next(s) || !ts_next(s))
|
|
1924
|
+
return false;
|
|
1925
|
+
if (tv(s) === -52 /* TOK.EXTENDS */ && !s.got_lf) {
|
|
1926
|
+
/* `infer U extends C`: a constraint, unless it reads as a conditional type */
|
|
1927
|
+
const p = ts_save(s);
|
|
1928
|
+
if (!(ts_next(s) && ts_skip_type(s, TS_NO_COND) && ((flags & TS_NO_COND) || tv(s) !== 63)))
|
|
1929
|
+
ts_restore(s, p);
|
|
1930
|
+
}
|
|
1931
|
+
return true;
|
|
1932
|
+
}
|
|
1933
|
+
return ts_skip_postfix_type(s);
|
|
1934
|
+
}
|
|
1935
|
+
function ts_skip_postfix_type(s) {
|
|
1936
|
+
if (!ts_skip_primary_type(s))
|
|
1937
|
+
return false;
|
|
1938
|
+
while (tv(s) === 91 && !s.got_lf) {
|
|
1939
|
+
/* T[] or T[K] */
|
|
1940
|
+
if (!ts_next(s))
|
|
1941
|
+
return false;
|
|
1942
|
+
if (tv(s) === 93) {
|
|
1943
|
+
if (!ts_next(s))
|
|
1944
|
+
return false;
|
|
1945
|
+
continue;
|
|
1946
|
+
}
|
|
1947
|
+
if (!ts_skip_type(s) || tv(s) !== 93 || !ts_next(s))
|
|
1948
|
+
return false;
|
|
1949
|
+
}
|
|
1950
|
+
return true;
|
|
1951
|
+
}
|
|
1952
|
+
/* identifiers and the keywords that name types */
|
|
1953
|
+
function ts_is_type_name(t) {
|
|
1954
|
+
return t === -125 /* TOK.IDENT */ || t === -76 /* TOK.VOID */ || t === -85 /* TOK.NULL */ || t === -78 /* TOK.THIS */ || t === -83 /* TOK.TRUE */ || t === -84 /* TOK.FALSE */ ||
|
|
1955
|
+
t === -47 /* TOK.LET */ || t === -41 /* TOK.YIELD */ || t === -40 /* TOK.AWAIT */ || t === -42 /* TOK.STATIC */ || t === -49 /* TOK.IMPLEMENTS */ ||
|
|
1956
|
+
t === -48 /* TOK.INTERFACE */ || t === -46 /* TOK.PACKAGE */ || t === -45 /* TOK.PRIVATE */ || t === -44 /* TOK.PROTECTED */ || t === -43 /* TOK.PUBLIC */;
|
|
1957
|
+
}
|
|
1958
|
+
function ts_skip_primary_type(s) {
|
|
1959
|
+
switch (tv(s)) {
|
|
1960
|
+
case 40: /* ( type ) */
|
|
1961
|
+
if (!ts_next(s) || !ts_skip_type(s))
|
|
1962
|
+
return false;
|
|
1963
|
+
return tv(s) === 41 && ts_next(s);
|
|
1964
|
+
case 91: /* tuple */
|
|
1965
|
+
case 123: /* object type, mapped type */
|
|
1966
|
+
case -126 /* TOK.TEMPLATE */: /* template literal type */
|
|
1967
|
+
return ts_skip_balanced(s);
|
|
1968
|
+
case -127 /* TOK.STRING */:
|
|
1969
|
+
case -128 /* TOK.NUMBER */:
|
|
1970
|
+
return ts_next(s);
|
|
1971
|
+
case 45: /* negative number literal type */
|
|
1972
|
+
return ts_next(s) && tv(s) === -128 /* TOK.NUMBER */ && ts_next(s);
|
|
1973
|
+
case -75 /* TOK.TYPEOF */:
|
|
1974
|
+
if (!ts_next(s))
|
|
1975
|
+
return false;
|
|
1976
|
+
if (tv(s) === -51 /* TOK.IMPORT */)
|
|
1977
|
+
return ts_skip_import_type(s);
|
|
1978
|
+
if (!(ts_is_type_name(tv(s)) || ts_is_keyword(tv(s))) || !ts_skip_entity_name(s))
|
|
1979
|
+
return false;
|
|
1980
|
+
if ((tv(s) === 60 || tv(s) === -106 /* TOK.SHL */) && !s.got_lf)
|
|
1981
|
+
return ts_skip_type_args(s);
|
|
1982
|
+
return true;
|
|
1983
|
+
case -51 /* TOK.IMPORT */:
|
|
1984
|
+
return ts_skip_import_type(s);
|
|
1985
|
+
}
|
|
1986
|
+
if (!ts_is_type_name(tv(s)) || !ts_skip_entity_name(s))
|
|
1987
|
+
return false;
|
|
1988
|
+
if ((tv(s) === 60 || tv(s) === -106 /* TOK.SHL */) && !s.got_lf)
|
|
1989
|
+
return ts_skip_type_args(s);
|
|
1990
|
+
return true;
|
|
1991
|
+
}
|
|
1992
|
+
/* A.B.C */
|
|
1993
|
+
function ts_skip_entity_name(s) {
|
|
1994
|
+
if (!ts_next(s))
|
|
1995
|
+
return false;
|
|
1996
|
+
while (tv(s) === 46) {
|
|
1997
|
+
if (!ts_next(s))
|
|
1998
|
+
return false;
|
|
1999
|
+
if (!token_is_ident_or_keyword(tv(s)) && tv(s) !== -87 /* TOK.PRIVATE_NAME */)
|
|
2000
|
+
return false;
|
|
2001
|
+
if (!ts_next(s))
|
|
2002
|
+
return false;
|
|
2003
|
+
}
|
|
2004
|
+
return true;
|
|
2005
|
+
}
|
|
2006
|
+
/* import("m").T<A> */
|
|
2007
|
+
function ts_skip_import_type(s) {
|
|
2008
|
+
if (!ts_next(s) || tv(s) !== 40 || !ts_skip_balanced(s))
|
|
2009
|
+
return false;
|
|
2010
|
+
while (tv(s) === 46) {
|
|
2011
|
+
if (!ts_next(s) || !token_is_ident_or_keyword(tv(s)) || !ts_next(s))
|
|
2012
|
+
return false;
|
|
2013
|
+
}
|
|
2014
|
+
if ((tv(s) === 60 || tv(s) === -106 /* TOK.SHL */) && !s.got_lf)
|
|
2015
|
+
return ts_skip_type_args(s);
|
|
2016
|
+
return true;
|
|
2017
|
+
}
|
|
2018
|
+
/* <T, U> after a type name or in an expression */
|
|
2019
|
+
function ts_skip_type_args(s) {
|
|
2020
|
+
if (!ts_eat_lt(s))
|
|
2021
|
+
return false;
|
|
2022
|
+
for (;;) {
|
|
2023
|
+
if (!ts_skip_type(s))
|
|
2024
|
+
return false;
|
|
2025
|
+
if (tv(s) !== 44)
|
|
2026
|
+
return ts_eat_gt(s);
|
|
2027
|
+
if (!ts_next(s))
|
|
2028
|
+
return false;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
/* <const T extends C = D, in out U> */
|
|
2032
|
+
function ts_skip_type_params(s) {
|
|
2033
|
+
if (!ts_eat_lt(s))
|
|
2034
|
+
return false;
|
|
2035
|
+
const A = ts_atoms(s);
|
|
2036
|
+
while (!ts_is_gt(tv(s))) {
|
|
2037
|
+
while ((tv(s) === -55 /* TOK.CONST */ || tv(s) === -73 /* TOK.IN */ || ts_word(s, A.out)) && ts_peek_is_name(s)) {
|
|
2038
|
+
if (!ts_next(s))
|
|
2039
|
+
return false;
|
|
2040
|
+
}
|
|
2041
|
+
if (!token_is_ident(tv(s)) || !ts_next(s))
|
|
2042
|
+
return false;
|
|
2043
|
+
if (tv(s) === -52 /* TOK.EXTENDS */ && !(ts_next(s) && ts_skip_type(s)))
|
|
2044
|
+
return false;
|
|
2045
|
+
if (tv(s) === 61 && !(ts_next(s) && ts_skip_type(s)))
|
|
2046
|
+
return false;
|
|
2047
|
+
if (tv(s) !== 44)
|
|
2048
|
+
break;
|
|
2049
|
+
if (!ts_next(s))
|
|
2050
|
+
return false;
|
|
2051
|
+
}
|
|
2052
|
+
return ts_eat_gt(s);
|
|
2053
|
+
}
|
|
2054
|
+
/* a return type, type predicates included: `x is T`, `asserts x`, `asserts x is T`, `this is T` */
|
|
2055
|
+
function ts_skip_return_type(s) {
|
|
2056
|
+
const A = ts_atoms(s);
|
|
2057
|
+
if (ts_word(s, A.asserts)) {
|
|
2058
|
+
const p = ts_save(s);
|
|
2059
|
+
if (ts_next(s) && !s.got_lf && (tv(s) === -125 /* TOK.IDENT */ || tv(s) === -78 /* TOK.THIS */)) {
|
|
2060
|
+
if (!ts_next(s))
|
|
2061
|
+
return false;
|
|
2062
|
+
if (ts_word(s, A.is) && !s.got_lf)
|
|
2063
|
+
return ts_next(s) && ts_skip_type(s);
|
|
2064
|
+
return true;
|
|
2065
|
+
}
|
|
2066
|
+
ts_restore(s, p);
|
|
2067
|
+
}
|
|
2068
|
+
if (tv(s) === -125 /* TOK.IDENT */ || tv(s) === -78 /* TOK.THIS */) {
|
|
2069
|
+
const p = ts_save(s);
|
|
2070
|
+
if (ts_next(s) && ts_word(s, A.is) && !s.got_lf)
|
|
2071
|
+
return ts_next(s) && ts_skip_type(s);
|
|
2072
|
+
ts_restore(s, p);
|
|
2073
|
+
}
|
|
2074
|
+
return ts_skip_type(s);
|
|
2075
|
+
}
|
|
2076
|
+
/* ': Type' (the current token is ':'), in the parser's convention: 0 or -1 */
|
|
2077
|
+
function ts_parse_annotation(s) {
|
|
2078
|
+
if (!ts_next(s) || !ts_skip_type(s))
|
|
2079
|
+
return ts_error(s, 'type expected');
|
|
2080
|
+
return 0;
|
|
2081
|
+
}
|
|
2082
|
+
/* --- expressions --- */
|
|
2083
|
+
function ts_is_binary_operator(s) {
|
|
2084
|
+
switch (tv(s)) {
|
|
2085
|
+
case 42:
|
|
2086
|
+
case 47:
|
|
2087
|
+
case 37:
|
|
2088
|
+
case -93 /* TOK.POW */:
|
|
2089
|
+
case -106 /* TOK.SHL */:
|
|
2090
|
+
case -105 /* TOK.SAR */:
|
|
2091
|
+
case -104 /* TOK.SHR */:
|
|
2092
|
+
case -102 /* TOK.LTE */:
|
|
2093
|
+
case -100 /* TOK.GTE */:
|
|
2094
|
+
case -72 /* TOK.INSTANCEOF */:
|
|
2095
|
+
case -73 /* TOK.IN */:
|
|
2096
|
+
case -99 /* TOK.EQ */:
|
|
2097
|
+
case -97 /* TOK.NEQ */:
|
|
2098
|
+
case -98 /* TOK.STRICT_EQ */:
|
|
2099
|
+
case -96 /* TOK.STRICT_NEQ */:
|
|
2100
|
+
case 38:
|
|
2101
|
+
case 94:
|
|
2102
|
+
case 124:
|
|
2103
|
+
case -95 /* TOK.LAND */:
|
|
2104
|
+
case -94 /* TOK.LOR */:
|
|
2105
|
+
case -90 /* TOK.DOUBLE_QUESTION_MARK */:
|
|
2106
|
+
return true;
|
|
2107
|
+
}
|
|
2108
|
+
return ts_word(s, JS_ATOM_as) || ts_word(s, ts_atoms(s).satisfies);
|
|
2109
|
+
}
|
|
2110
|
+
function ts_is_start_of_expression(s) {
|
|
2111
|
+
switch (tv(s)) {
|
|
2112
|
+
case -128 /* TOK.NUMBER */:
|
|
2113
|
+
case -127 /* TOK.STRING */:
|
|
2114
|
+
case -126 /* TOK.TEMPLATE */:
|
|
2115
|
+
case -125 /* TOK.IDENT */:
|
|
2116
|
+
case -87 /* TOK.PRIVATE_NAME */:
|
|
2117
|
+
case 40:
|
|
2118
|
+
case 91:
|
|
2119
|
+
case 123:
|
|
2120
|
+
case 47:
|
|
2121
|
+
case -122 /* TOK.DIV_ASSIGN */:
|
|
2122
|
+
case 43:
|
|
2123
|
+
case 45:
|
|
2124
|
+
case 33:
|
|
2125
|
+
case 126:
|
|
2126
|
+
case 60:
|
|
2127
|
+
case 64:
|
|
2128
|
+
case -107 /* TOK.INC */:
|
|
2129
|
+
case -108 /* TOK.DEC */:
|
|
2130
|
+
case -78 /* TOK.THIS */:
|
|
2131
|
+
case -50 /* TOK.SUPER */:
|
|
2132
|
+
case -85 /* TOK.NULL */:
|
|
2133
|
+
case -83 /* TOK.TRUE */:
|
|
2134
|
+
case -84 /* TOK.FALSE */:
|
|
2135
|
+
case -59 /* TOK.FUNCTION */:
|
|
2136
|
+
case -56 /* TOK.CLASS */:
|
|
2137
|
+
case -74 /* TOK.NEW */:
|
|
2138
|
+
case -75 /* TOK.TYPEOF */:
|
|
2139
|
+
case -76 /* TOK.VOID */:
|
|
2140
|
+
case -77 /* TOK.DELETE */:
|
|
2141
|
+
case -40 /* TOK.AWAIT */:
|
|
2142
|
+
case -41 /* TOK.YIELD */:
|
|
2143
|
+
case -51 /* TOK.IMPORT */:
|
|
2144
|
+
case -47 /* TOK.LET */:
|
|
2145
|
+
case -42 /* TOK.STATIC */:
|
|
2146
|
+
case -49 /* TOK.IMPLEMENTS */:
|
|
2147
|
+
case -48 /* TOK.INTERFACE */:
|
|
2148
|
+
case -46 /* TOK.PACKAGE */:
|
|
2149
|
+
case -45 /* TOK.PRIVATE */:
|
|
2150
|
+
case -44 /* TOK.PROTECTED */:
|
|
2151
|
+
case -43 /* TOK.PUBLIC */:
|
|
2152
|
+
return true;
|
|
2153
|
+
}
|
|
2154
|
+
return false;
|
|
2155
|
+
}
|
|
2156
|
+
/* TypeScript's canFollowTypeArgumentsInExpression */
|
|
2157
|
+
function ts_can_follow_type_args(s) {
|
|
2158
|
+
switch (tv(s)) {
|
|
2159
|
+
case 40:
|
|
2160
|
+
case -126 /* TOK.TEMPLATE */:
|
|
2161
|
+
return true;
|
|
2162
|
+
case 60:
|
|
2163
|
+
case 62:
|
|
2164
|
+
case 43:
|
|
2165
|
+
case 45:
|
|
2166
|
+
return false;
|
|
2167
|
+
}
|
|
2168
|
+
return s.got_lf || ts_is_binary_operator(s) || !ts_is_start_of_expression(s);
|
|
2169
|
+
}
|
|
2170
|
+
/* f<T>(x), new C<T>(), f<T>`t`, f<T>: type arguments in an expression, speculatively. As in
|
|
2171
|
+
TypeScript (reScanGreaterToken), the closing '>' must not be the start of '>=' or '>>':
|
|
2172
|
+
`a < b >= c` and `a < b >> c` are comparisons */
|
|
2173
|
+
function ts_try_expr_type_args(s) {
|
|
2174
|
+
const p = ts_save(s);
|
|
2175
|
+
if (ts_eat_lt(s)) {
|
|
2176
|
+
for (;;) {
|
|
2177
|
+
if (!ts_skip_type(s))
|
|
2178
|
+
break;
|
|
2179
|
+
if (tv(s) === 44) {
|
|
2180
|
+
if (!ts_next(s))
|
|
2181
|
+
break;
|
|
2182
|
+
continue;
|
|
2183
|
+
}
|
|
2184
|
+
if (tv(s) === 62 && ts_next(s) && ts_can_follow_type_args(s))
|
|
2185
|
+
return true;
|
|
2186
|
+
break;
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
ts_restore(s, p);
|
|
2190
|
+
return false;
|
|
2191
|
+
}
|
|
2192
|
+
/* `as T`, `as const`, `satisfies T` after an operand: 1 if one was skipped, 0 if none, -1 on error */
|
|
2193
|
+
function ts_parse_as_expr(s) {
|
|
2194
|
+
if (s.got_lf || !(ts_word(s, JS_ATOM_as) || ts_word(s, ts_atoms(s).satisfies)))
|
|
2195
|
+
return 0;
|
|
2196
|
+
if (next_token(s))
|
|
2197
|
+
return -1;
|
|
2198
|
+
if (tv(s) === -55 /* TOK.CONST */)
|
|
2199
|
+
return next_token(s) ? -1 : 1;
|
|
2200
|
+
if (!ts_skip_type(s))
|
|
2201
|
+
return ts_error(s, 'type expected');
|
|
2202
|
+
return 1;
|
|
2203
|
+
}
|
|
2204
|
+
/* skip an assignment expression approximately: stop before ',' ';' ')' ']' '}' or a ':'
|
|
2205
|
+
that does not close a '?' at depth 0 */
|
|
2206
|
+
function ts_skip_expr_tokens(s) {
|
|
2207
|
+
let pending = 0, n = 0, last_tok = 0;
|
|
2208
|
+
for (;;) {
|
|
2209
|
+
const t = tv(s);
|
|
2210
|
+
switch (t) {
|
|
2211
|
+
case 44:
|
|
2212
|
+
case 59:
|
|
2213
|
+
case 41:
|
|
2214
|
+
case 93:
|
|
2215
|
+
case 125:
|
|
2216
|
+
case -86 /* TOK.EOF */:
|
|
2217
|
+
return n > 0;
|
|
2218
|
+
case 58:
|
|
2219
|
+
if (pending === 0)
|
|
2220
|
+
return n > 0;
|
|
2221
|
+
pending--;
|
|
2222
|
+
break;
|
|
2223
|
+
case 63:
|
|
2224
|
+
pending++;
|
|
2225
|
+
break;
|
|
2226
|
+
case 40:
|
|
2227
|
+
case 91:
|
|
2228
|
+
case 123:
|
|
2229
|
+
case -126 /* TOK.TEMPLATE */:
|
|
2230
|
+
if (!ts_skip_balanced(s))
|
|
2231
|
+
return false;
|
|
2232
|
+
last_tok = t === 40 ? 41 : t === 91 ? 93 : t === 123 ? 125 : -126 /* TOK.TEMPLATE */;
|
|
2233
|
+
n++;
|
|
2234
|
+
continue;
|
|
2235
|
+
case 47:
|
|
2236
|
+
case -122 /* TOK.DIV_ASSIGN */:
|
|
2237
|
+
if (is_regexp_allowed(last_tok)) {
|
|
2238
|
+
s.buf_ptr = s.token.ptr + 1;
|
|
2239
|
+
if (js_parse_regexp(s))
|
|
2240
|
+
return false;
|
|
2241
|
+
}
|
|
2242
|
+
break;
|
|
2243
|
+
}
|
|
2244
|
+
last_tok = tv(s);
|
|
2245
|
+
n++;
|
|
2246
|
+
if (!ts_next(s))
|
|
2247
|
+
return false;
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
/* after the parameters of an arrow function candidate: ': ReturnType =>' or '=>'. In the true
|
|
2251
|
+
branch of a conditional expression, an arrow function with a return type must be followed by
|
|
2252
|
+
the conditional's ':' (TypeScript's allowReturnTypeInArrowFunction rule) */
|
|
2253
|
+
function ts_arrow_rest_ahead(s) {
|
|
2254
|
+
if (tv(s) === -92 /* TOK.ARROW */)
|
|
2255
|
+
return !s.got_lf;
|
|
2256
|
+
if (tv(s) !== 58 || !ts_next(s) || !ts_skip_return_type(s))
|
|
2257
|
+
return false;
|
|
2258
|
+
if (tv(s) !== -92 /* TOK.ARROW */ || s.got_lf)
|
|
2259
|
+
return false;
|
|
2260
|
+
if (!s.ts_cond_true)
|
|
2261
|
+
return true;
|
|
2262
|
+
if (!ts_next(s))
|
|
2263
|
+
return false;
|
|
2264
|
+
if (tv(s) === 123 ? !ts_skip_balanced(s) : !ts_skip_expr_tokens(s))
|
|
2265
|
+
return false;
|
|
2266
|
+
return tv(s) === 58;
|
|
2267
|
+
}
|
|
2268
|
+
/* '(' starts an arrow function whose parameters are followed by a return type */
|
|
2269
|
+
function ts_arrow_with_return_type_ahead(s) {
|
|
2270
|
+
const p = ts_save(s);
|
|
2271
|
+
const ok = ts_skip_balanced(s) && ts_arrow_rest_ahead(s);
|
|
2272
|
+
ts_restore(s, p);
|
|
2273
|
+
return ok;
|
|
2274
|
+
}
|
|
2275
|
+
/* '<' starts a generic arrow function: <T>(x: T) => x. In a .tsx file, TypeScript decides from the
|
|
2276
|
+
first tokens: `<T,`, `<T =` and `<T extends U` (U not '=', '>' or '/') start a generic arrow
|
|
2277
|
+
function, anything else is JSX */
|
|
2278
|
+
function ts_generic_arrow_ahead(s) {
|
|
2279
|
+
if (s.jsx)
|
|
2280
|
+
return tsx_generic_arrow_ahead(s);
|
|
2281
|
+
const p = ts_save(s);
|
|
2282
|
+
const ok = ts_skip_type_params(s) && tv(s) === 40 && ts_skip_balanced(s) && ts_arrow_rest_ahead(s);
|
|
2283
|
+
ts_restore(s, p);
|
|
2284
|
+
return ok;
|
|
2285
|
+
}
|
|
2286
|
+
function tsx_generic_arrow_ahead(s) {
|
|
2287
|
+
const p = ts_save(s);
|
|
2288
|
+
let ok = false;
|
|
2289
|
+
if (ts_next(s) && (token_is_ident(tv(s)) || tv(s) === -55 /* TOK.CONST */) && (tv(s) !== -55 /* TOK.CONST */ || ts_next(s)) && ts_next(s)) {
|
|
2290
|
+
if (tv(s) === -52 /* TOK.EXTENDS */)
|
|
2291
|
+
ok = ts_next(s) && tv(s) !== 61 && !ts_is_gt(tv(s)) && tv(s) !== 47;
|
|
2292
|
+
else
|
|
2293
|
+
ok = tv(s) === 44 || tv(s) === 61;
|
|
2294
|
+
}
|
|
2295
|
+
ts_restore(s, p);
|
|
2296
|
+
return ok;
|
|
2297
|
+
}
|
|
2298
|
+
/* '(' starts the parameter list of an arrow function */
|
|
2299
|
+
function js_arrow_ahead(s) {
|
|
2300
|
+
const tok = js_parse_skip_parens_token(s, null, true);
|
|
2301
|
+
return tok === -92 /* TOK.ARROW */ || (tok === 58 && s.ts && ts_arrow_with_return_type_ahead(s));
|
|
2302
|
+
}
|
|
2303
|
+
/* --- declarations and statements --- */
|
|
2304
|
+
/* ';' or automatic semicolon insertion, without reporting */
|
|
2305
|
+
function ts_skip_semi(s) {
|
|
2306
|
+
if (tv(s) === 59)
|
|
2307
|
+
return ts_next(s);
|
|
2308
|
+
return tv(s) === -86 /* TOK.EOF */ || tv(s) === 125 || s.got_lf;
|
|
2309
|
+
}
|
|
2310
|
+
/* interface I<T> extends A, B<C> { ... } */
|
|
2311
|
+
function ts_skip_interface(s) {
|
|
2312
|
+
if (!ts_next(s) || !token_is_ident(tv(s)) || !ts_next(s))
|
|
2313
|
+
return false;
|
|
2314
|
+
if (tv(s) === 60 && !ts_skip_type_params(s))
|
|
2315
|
+
return false;
|
|
2316
|
+
if (tv(s) === -52 /* TOK.EXTENDS */) {
|
|
2317
|
+
do {
|
|
2318
|
+
if (!ts_next(s) || !ts_skip_type(s))
|
|
2319
|
+
return false;
|
|
2320
|
+
} while (tv(s) === 44);
|
|
2321
|
+
}
|
|
2322
|
+
return tv(s) === 123 && ts_skip_balanced(s);
|
|
2323
|
+
}
|
|
2324
|
+
/* type A<T> = Type */
|
|
2325
|
+
function ts_skip_type_alias(s) {
|
|
2326
|
+
if (!ts_next(s) || !token_is_ident(tv(s)) || !ts_next(s))
|
|
2327
|
+
return false;
|
|
2328
|
+
if (tv(s) === 60 && !ts_skip_type_params(s))
|
|
2329
|
+
return false;
|
|
2330
|
+
return tv(s) === 61 && ts_next(s) && ts_skip_type(s) && ts_skip_semi(s);
|
|
2331
|
+
}
|
|
2332
|
+
/* the rest of a variable declaration list without code: names, annotations, initializers */
|
|
2333
|
+
function ts_skip_var_list(s) {
|
|
2334
|
+
for (;;) {
|
|
2335
|
+
if (tv(s) === 91 || tv(s) === 123) {
|
|
2336
|
+
if (!ts_skip_balanced(s))
|
|
2337
|
+
return false;
|
|
2338
|
+
}
|
|
2339
|
+
else if (!token_is_ident(tv(s)) || !ts_next(s)) {
|
|
2340
|
+
return false;
|
|
2341
|
+
}
|
|
2342
|
+
if (tv(s) === 33 && !ts_next(s))
|
|
2343
|
+
return false;
|
|
2344
|
+
if (tv(s) === 58 && !(ts_next(s) && ts_skip_type(s)))
|
|
2345
|
+
return false;
|
|
2346
|
+
if (tv(s) === 61 && !(ts_next(s) && ts_skip_expr_tokens(s)))
|
|
2347
|
+
return false;
|
|
2348
|
+
if (tv(s) !== 44)
|
|
2349
|
+
return ts_skip_semi(s);
|
|
2350
|
+
if (!ts_next(s))
|
|
2351
|
+
return false;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
/* function f<T>(params): R (no body: overload signature or ambient function) */
|
|
2355
|
+
function ts_skip_function_signature(s) {
|
|
2356
|
+
if (ts_word(s, JS_ATOM_async) && !ts_next(s))
|
|
2357
|
+
return false;
|
|
2358
|
+
if (tv(s) !== -59 /* TOK.FUNCTION */ || !ts_next(s))
|
|
2359
|
+
return false;
|
|
2360
|
+
if (tv(s) === 42 && !ts_next(s))
|
|
2361
|
+
return false;
|
|
2362
|
+
if ((tv(s) === -125 /* TOK.IDENT */ || ts_is_keyword(tv(s))) && tv(s) !== -52 /* TOK.EXTENDS */ && !ts_next(s))
|
|
2363
|
+
return false;
|
|
2364
|
+
if (tv(s) === 60 && !ts_skip_type_params(s))
|
|
2365
|
+
return false;
|
|
2366
|
+
if (tv(s) !== 40 || !ts_skip_balanced(s))
|
|
2367
|
+
return false;
|
|
2368
|
+
if (tv(s) === 58 && !(ts_next(s) && ts_skip_return_type(s)))
|
|
2369
|
+
return false;
|
|
2370
|
+
return true;
|
|
2371
|
+
}
|
|
2372
|
+
/* class C<T> extends B<T> implements I { ... } without code (ambient class) */
|
|
2373
|
+
function ts_skip_class_decl(s) {
|
|
2374
|
+
if (!ts_next(s))
|
|
2375
|
+
return false;
|
|
2376
|
+
while (tv(s) !== 123) {
|
|
2377
|
+
if (tv(s) === -86 /* TOK.EOF */)
|
|
2378
|
+
return false;
|
|
2379
|
+
if (tv(s) === 60) {
|
|
2380
|
+
if (!ts_skip_type_args(s))
|
|
2381
|
+
return false;
|
|
2382
|
+
}
|
|
2383
|
+
else if (tv(s) === 40 || tv(s) === 91) {
|
|
2384
|
+
if (!ts_skip_balanced(s))
|
|
2385
|
+
return false;
|
|
2386
|
+
}
|
|
2387
|
+
else if (!ts_next(s)) {
|
|
2388
|
+
return false;
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
return ts_skip_balanced(s);
|
|
2392
|
+
}
|
|
2393
|
+
/* namespace A.B { ... }, module "m" { ... }, global { ... }; `module "m";` */
|
|
2394
|
+
function ts_skip_ambient_module(s) {
|
|
2395
|
+
if (!ts_next(s))
|
|
2396
|
+
return false;
|
|
2397
|
+
if (tv(s) === -127 /* TOK.STRING */) {
|
|
2398
|
+
if (!ts_next(s))
|
|
2399
|
+
return false;
|
|
2400
|
+
}
|
|
2401
|
+
else if (token_is_ident(tv(s))) {
|
|
2402
|
+
if (!ts_next(s))
|
|
2403
|
+
return false;
|
|
2404
|
+
while (tv(s) === 46) {
|
|
2405
|
+
if (!ts_next(s) || !token_is_ident_or_keyword(tv(s)) || !ts_next(s))
|
|
2406
|
+
return false;
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
if (tv(s) === 123)
|
|
2410
|
+
return ts_skip_balanced(s);
|
|
2411
|
+
return ts_skip_semi(s);
|
|
2412
|
+
}
|
|
2413
|
+
function ts_statement_kind(s) {
|
|
2414
|
+
const A = ts_atoms(s);
|
|
2415
|
+
const t = tv(s);
|
|
2416
|
+
if (t === -54 /* TOK.ENUM */)
|
|
2417
|
+
return 6 /* TSStmt.ENUM */;
|
|
2418
|
+
if (t === -55 /* TOK.CONST */)
|
|
2419
|
+
return ts_peek(s).val === -54 /* TOK.ENUM */ ? 6 /* TSStmt.ENUM */ : 0 /* TSStmt.NONE */;
|
|
2420
|
+
if (t === -59 /* TOK.FUNCTION */)
|
|
2421
|
+
return 10 /* TSStmt.FUNCTION */;
|
|
2422
|
+
if (t === -51 /* TOK.IMPORT */) {
|
|
2423
|
+
const n = ts_peek(s);
|
|
2424
|
+
if (n.val === 40 || n.val === 46)
|
|
2425
|
+
return 0 /* TSStmt.NONE */;
|
|
2426
|
+
if (n.atom === A.type && !n.escape)
|
|
2427
|
+
return 7 /* TSStmt.IMPORT_TYPE */;
|
|
2428
|
+
if (n.val === -125 /* TOK.IDENT */) {
|
|
2429
|
+
/* import x = ... */
|
|
2430
|
+
const p = ts_save(s);
|
|
2431
|
+
const eq = ts_next(s) && ts_next(s) && tv(s) === 61;
|
|
2432
|
+
ts_restore(s, p);
|
|
2433
|
+
if (eq)
|
|
2434
|
+
return 8 /* TSStmt.IMPORT_EQUALS */;
|
|
2435
|
+
}
|
|
2436
|
+
return 0 /* TSStmt.NONE */;
|
|
2437
|
+
}
|
|
2438
|
+
if (t === -53 /* TOK.EXPORT */)
|
|
2439
|
+
return 9 /* TSStmt.EXPORT */;
|
|
2440
|
+
if (t !== -125 /* TOK.IDENT */ && !ts_is_keyword(t))
|
|
2441
|
+
return 0 /* TSStmt.NONE */;
|
|
2442
|
+
if (s.token.has_escape)
|
|
2443
|
+
return 0 /* TSStmt.NONE */;
|
|
2444
|
+
const atom = s.token.atom;
|
|
2445
|
+
if (atom === JS_ATOM_async)
|
|
2446
|
+
return ts_peek(s).val === -59 /* TOK.FUNCTION */ ? 10 /* TSStmt.FUNCTION */ : 0 /* TSStmt.NONE */;
|
|
2447
|
+
if (atom !== JS_ATOM_interface && atom !== A.type && atom !== A.declare && atom !== A.abstract &&
|
|
2448
|
+
atom !== A.namespace && atom !== A.module)
|
|
2449
|
+
return 0 /* TSStmt.NONE */;
|
|
2450
|
+
const n = ts_peek(s);
|
|
2451
|
+
if (n.lf)
|
|
2452
|
+
return 0 /* TSStmt.NONE */;
|
|
2453
|
+
const name_next = n.val === -125 /* TOK.IDENT */ || (ts_is_keyword(n.val) && n.val !== -73 /* TOK.IN */ && n.val !== -72 /* TOK.INSTANCEOF */);
|
|
2454
|
+
if (atom === JS_ATOM_interface)
|
|
2455
|
+
return name_next ? 1 /* TSStmt.INTERFACE */ : 0 /* TSStmt.NONE */;
|
|
2456
|
+
if (atom === A.type)
|
|
2457
|
+
return token_is_ident(n.val) ? 2 /* TSStmt.TYPE */ : 0 /* TSStmt.NONE */;
|
|
2458
|
+
if (atom === A.abstract)
|
|
2459
|
+
return n.val === -56 /* TOK.CLASS */ ? 4 /* TSStmt.ABSTRACT_CLASS */ : 0 /* TSStmt.NONE */;
|
|
2460
|
+
if (atom === A.namespace)
|
|
2461
|
+
return token_is_ident(n.val) ? 5 /* TSStmt.NAMESPACE */ : 0 /* TSStmt.NONE */;
|
|
2462
|
+
if (atom === A.module)
|
|
2463
|
+
return token_is_ident(n.val) || n.val === -127 /* TOK.STRING */ ? 5 /* TSStmt.NAMESPACE */ : 0 /* TSStmt.NONE */;
|
|
2464
|
+
/* declare */
|
|
2465
|
+
switch (n.val) {
|
|
2466
|
+
case -79 /* TOK.VAR */:
|
|
2467
|
+
case -47 /* TOK.LET */:
|
|
2468
|
+
case -55 /* TOK.CONST */:
|
|
2469
|
+
case -59 /* TOK.FUNCTION */:
|
|
2470
|
+
case -56 /* TOK.CLASS */:
|
|
2471
|
+
case -54 /* TOK.ENUM */:
|
|
2472
|
+
case -48 /* TOK.INTERFACE */:
|
|
2473
|
+
return 3 /* TSStmt.DECLARE */;
|
|
2474
|
+
case -125 /* TOK.IDENT */:
|
|
2475
|
+
return (n.atom === JS_ATOM_let || n.atom === A.type || n.atom === A.namespace || n.atom === A.module ||
|
|
2476
|
+
n.atom === JS_ATOM_global || n.atom === A.abstract || n.atom === JS_ATOM_interface || n.atom === JS_ATOM_async) &&
|
|
2477
|
+
!n.escape ? 3 /* TSStmt.DECLARE */ : 0 /* TSStmt.NONE */;
|
|
2478
|
+
}
|
|
2479
|
+
return 0 /* TSStmt.NONE */;
|
|
2480
|
+
}
|
|
2481
|
+
/* skip a `declare ...` statement (the current token is `declare`) */
|
|
2482
|
+
function ts_skip_declare(s) {
|
|
2483
|
+
const A = ts_atoms(s);
|
|
2484
|
+
if (!ts_next(s))
|
|
2485
|
+
return false;
|
|
2486
|
+
switch (tv(s)) {
|
|
2487
|
+
case -79 /* TOK.VAR */:
|
|
2488
|
+
case -47 /* TOK.LET */:
|
|
2489
|
+
return ts_next(s) && ts_skip_var_list(s);
|
|
2490
|
+
case -55 /* TOK.CONST */:
|
|
2491
|
+
if (ts_peek(s).val === -54 /* TOK.ENUM */)
|
|
2492
|
+
return ts_next(s) && ts_skip_enum(s);
|
|
2493
|
+
return ts_next(s) && ts_skip_var_list(s);
|
|
2494
|
+
case -59 /* TOK.FUNCTION */:
|
|
2495
|
+
if (!ts_skip_function_signature(s))
|
|
2496
|
+
return false;
|
|
2497
|
+
return tv(s) === 123 ? ts_skip_balanced(s) : ts_skip_semi(s);
|
|
2498
|
+
case -56 /* TOK.CLASS */:
|
|
2499
|
+
return ts_skip_class_decl(s);
|
|
2500
|
+
case -54 /* TOK.ENUM */:
|
|
2501
|
+
return ts_skip_enum(s);
|
|
2502
|
+
}
|
|
2503
|
+
if (ts_word(s, JS_ATOM_let))
|
|
2504
|
+
return ts_next(s) && ts_skip_var_list(s);
|
|
2505
|
+
if (ts_word(s, JS_ATOM_async)) {
|
|
2506
|
+
if (!ts_skip_function_signature(s))
|
|
2507
|
+
return false;
|
|
2508
|
+
return ts_skip_semi(s);
|
|
2509
|
+
}
|
|
2510
|
+
if (ts_word(s, A.abstract))
|
|
2511
|
+
return ts_next(s) && tv(s) === -56 /* TOK.CLASS */ && ts_skip_class_decl(s);
|
|
2512
|
+
if (ts_word(s, JS_ATOM_interface))
|
|
2513
|
+
return ts_skip_interface(s);
|
|
2514
|
+
if (ts_word(s, A.type))
|
|
2515
|
+
return ts_skip_type_alias(s);
|
|
2516
|
+
if (ts_word(s, A.namespace) || ts_word(s, A.module) || ts_word(s, JS_ATOM_global))
|
|
2517
|
+
return ts_skip_ambient_module(s);
|
|
2518
|
+
return false;
|
|
2519
|
+
}
|
|
2520
|
+
/* enum E { ... } (ambient only) */
|
|
2521
|
+
function ts_skip_enum(s) {
|
|
2522
|
+
return ts_next(s) && token_is_ident(tv(s)) && ts_next(s) && tv(s) === 123 && ts_skip_balanced(s);
|
|
2523
|
+
}
|
|
2524
|
+
/* a statement allowed in a type-only namespace body; false otherwise */
|
|
2525
|
+
function ts_skip_type_only_statement(s) {
|
|
2526
|
+
if (tv(s) === 59)
|
|
2527
|
+
return ts_next(s);
|
|
2528
|
+
if (tv(s) === -53 /* TOK.EXPORT */ && !ts_next(s))
|
|
2529
|
+
return false;
|
|
2530
|
+
switch (ts_statement_kind(s)) {
|
|
2531
|
+
case 1 /* TSStmt.INTERFACE */: return ts_skip_interface(s);
|
|
2532
|
+
case 2 /* TSStmt.TYPE */: return ts_skip_type_alias(s);
|
|
2533
|
+
case 3 /* TSStmt.DECLARE */: return ts_skip_declare(s);
|
|
2534
|
+
case 5 /* TSStmt.NAMESPACE */: return ts_skip_type_only_namespace(s);
|
|
2535
|
+
case 7 /* TSStmt.IMPORT_TYPE */: return ts_skip_import_type_decl(s);
|
|
2536
|
+
}
|
|
2537
|
+
return false;
|
|
2538
|
+
}
|
|
2539
|
+
/* namespace N { <type-only statements> }: false if the body has values */
|
|
2540
|
+
function ts_skip_type_only_namespace(s) {
|
|
2541
|
+
if (!ts_next(s))
|
|
2542
|
+
return false;
|
|
2543
|
+
if (tv(s) === -127 /* TOK.STRING */) {
|
|
2544
|
+
if (!ts_next(s))
|
|
2545
|
+
return false;
|
|
2546
|
+
}
|
|
2547
|
+
else {
|
|
2548
|
+
if (!token_is_ident(tv(s)) || !ts_next(s))
|
|
2549
|
+
return false;
|
|
2550
|
+
while (tv(s) === 46) {
|
|
2551
|
+
if (!ts_next(s) || !token_is_ident_or_keyword(tv(s)) || !ts_next(s))
|
|
2552
|
+
return false;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
if (tv(s) !== 123 || !ts_next(s))
|
|
2556
|
+
return false;
|
|
2557
|
+
while (tv(s) !== 125) {
|
|
2558
|
+
if (tv(s) === -86 /* TOK.EOF */ || !ts_skip_type_only_statement(s))
|
|
2559
|
+
return false;
|
|
2560
|
+
}
|
|
2561
|
+
return ts_next(s);
|
|
2562
|
+
}
|
|
2563
|
+
/* import type ... from "m" [with { ... }] */
|
|
2564
|
+
function ts_skip_import_type_decl(s) {
|
|
2565
|
+
const A = ts_atoms(s);
|
|
2566
|
+
if (!ts_next(s) || !ts_next(s))
|
|
2567
|
+
return false; /* 'import' 'type' */
|
|
2568
|
+
while (tv(s) !== -127 /* TOK.STRING */) {
|
|
2569
|
+
if (tv(s) === 123) {
|
|
2570
|
+
if (!ts_skip_balanced(s))
|
|
2571
|
+
return false;
|
|
2572
|
+
}
|
|
2573
|
+
else if (tv(s) === 61) {
|
|
2574
|
+
return false; /* import type x = require(...) */
|
|
2575
|
+
}
|
|
2576
|
+
else if (tv(s) === -86 /* TOK.EOF */ || tv(s) === 59 || !ts_next(s)) {
|
|
2577
|
+
return false;
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
if (!ts_next(s))
|
|
2581
|
+
return false;
|
|
2582
|
+
if ((ts_word(s, A.with_) || tv(s) === -57 /* TOK.WITH */ || ts_word(s, A.assert)) && !s.got_lf) {
|
|
2583
|
+
if (!ts_next(s) || tv(s) !== 123 || !ts_skip_balanced(s))
|
|
2584
|
+
return false;
|
|
2585
|
+
}
|
|
2586
|
+
return ts_skip_semi(s);
|
|
2587
|
+
}
|
|
2588
|
+
/* TypeScript-only statements: -1 on error, 0 if the current token does not start one (the
|
|
2589
|
+
caller parses it as JavaScript; an `abstract` before `class` has been consumed), 1 if the
|
|
2590
|
+
statement was skipped */
|
|
2591
|
+
function ts_parse_statement(s) {
|
|
2592
|
+
const A = ts_atoms(s);
|
|
2593
|
+
const start = s.token.ptr;
|
|
2594
|
+
switch (ts_statement_kind(s)) {
|
|
2595
|
+
case 0 /* TSStmt.NONE */:
|
|
2596
|
+
return 0;
|
|
2597
|
+
case 1 /* TSStmt.INTERFACE */:
|
|
2598
|
+
if (!ts_skip_interface(s))
|
|
2599
|
+
return ts_error(s, 'invalid interface declaration');
|
|
2600
|
+
return 1;
|
|
2601
|
+
case 2 /* TSStmt.TYPE */:
|
|
2602
|
+
if (!ts_skip_type_alias(s))
|
|
2603
|
+
return ts_error(s, 'invalid type alias');
|
|
2604
|
+
return 1;
|
|
2605
|
+
case 3 /* TSStmt.DECLARE */:
|
|
2606
|
+
if (!ts_skip_declare(s))
|
|
2607
|
+
return ts_error(s, 'invalid ambient declaration');
|
|
2608
|
+
return 1;
|
|
2609
|
+
case 4 /* TSStmt.ABSTRACT_CLASS */:
|
|
2610
|
+
/* `abstract` is erased; the class is parsed as JavaScript (its abstract members are erased) */
|
|
2611
|
+
return next_token(s) ? -1 : 0;
|
|
2612
|
+
case 5 /* TSStmt.NAMESPACE */: {
|
|
2613
|
+
const p = ts_save(s);
|
|
2614
|
+
if (ts_skip_type_only_namespace(s))
|
|
2615
|
+
return 1;
|
|
2616
|
+
ts_restore(s, p);
|
|
2617
|
+
return ts_unsupported(s, 'namespace declaration', start);
|
|
2618
|
+
}
|
|
2619
|
+
case 6 /* TSStmt.ENUM */:
|
|
2620
|
+
return ts_unsupported(s, 'enum', start);
|
|
2621
|
+
case 8 /* TSStmt.IMPORT_EQUALS */:
|
|
2622
|
+
return ts_unsupported(s, 'import equals declaration', start);
|
|
2623
|
+
case 7 /* TSStmt.IMPORT_TYPE */: {
|
|
2624
|
+
const p = ts_save(s);
|
|
2625
|
+
if (ts_skip_import_type_decl(s))
|
|
2626
|
+
return 1;
|
|
2627
|
+
ts_restore(s, p);
|
|
2628
|
+
/* import type x = require(...) */
|
|
2629
|
+
return ts_unsupported(s, 'import equals declaration', start);
|
|
2630
|
+
}
|
|
2631
|
+
case 10 /* TSStmt.FUNCTION */: {
|
|
2632
|
+
/* an overload signature: a declaration without a body */
|
|
2633
|
+
const p = ts_save(s);
|
|
2634
|
+
if (ts_skip_function_signature(s) && tv(s) !== 123) {
|
|
2635
|
+
if (js_parse_expect_semi(s))
|
|
2636
|
+
return -1;
|
|
2637
|
+
return 1;
|
|
2638
|
+
}
|
|
2639
|
+
ts_restore(s, p);
|
|
2640
|
+
return 0;
|
|
2641
|
+
}
|
|
2642
|
+
case 9 /* TSStmt.EXPORT */: {
|
|
2643
|
+
const n = ts_peek(s);
|
|
2644
|
+
if (n.val === 61)
|
|
2645
|
+
return ts_unsupported(s, 'export assignment', start);
|
|
2646
|
+
const p = ts_save(s);
|
|
2647
|
+
if (!ts_next(s))
|
|
2648
|
+
return -1;
|
|
2649
|
+
if (ts_word(s, JS_ATOM_as)) {
|
|
2650
|
+
/* export as namespace N; */
|
|
2651
|
+
if (!(ts_next(s) && ts_word(s, A.namespace) && ts_next(s) && token_is_ident(tv(s)) && ts_next(s)))
|
|
2652
|
+
return ts_error(s, 'invalid export declaration');
|
|
2653
|
+
return js_parse_expect_semi(s) ? -1 : 1;
|
|
2654
|
+
}
|
|
2655
|
+
if (tv(s) === -51 /* TOK.IMPORT */ && ts_peek(s).val === -125 /* TOK.IDENT */)
|
|
2656
|
+
return ts_unsupported(s, 'import equals declaration', start);
|
|
2657
|
+
if (ts_word(s, A.type)) {
|
|
2658
|
+
const n2 = ts_peek(s);
|
|
2659
|
+
if (n2.val === 123 || n2.val === 42) {
|
|
2660
|
+
/* export type { A } [from "m"]; */
|
|
2661
|
+
if (!(ts_next(s) && (tv(s) === 42 ? ts_next(s) : ts_skip_balanced(s))))
|
|
2662
|
+
return ts_error(s, 'invalid export declaration');
|
|
2663
|
+
if (ts_word(s, JS_ATOM_from) && !(ts_next(s) && tv(s) === -127 /* TOK.STRING */ && ts_next(s)))
|
|
2664
|
+
return ts_error(s, 'invalid export declaration');
|
|
2665
|
+
return js_parse_expect_semi(s) ? -1 : 1;
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
const kind = ts_statement_kind(s);
|
|
2669
|
+
switch (kind) {
|
|
2670
|
+
case 1 /* TSStmt.INTERFACE */:
|
|
2671
|
+
case 2 /* TSStmt.TYPE */:
|
|
2672
|
+
case 3 /* TSStmt.DECLARE */:
|
|
2673
|
+
case 5 /* TSStmt.NAMESPACE */:
|
|
2674
|
+
case 6 /* TSStmt.ENUM */:
|
|
2675
|
+
case 10 /* TSStmt.FUNCTION */: {
|
|
2676
|
+
const r = ts_parse_statement(s);
|
|
2677
|
+
if (r !== 0)
|
|
2678
|
+
return r;
|
|
2679
|
+
break;
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
/* an export of a value: JavaScript's error */
|
|
2683
|
+
ts_restore(s, p);
|
|
2684
|
+
return 0;
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
return 0;
|
|
2688
|
+
}
|
|
2689
|
+
/* --- classes --- */
|
|
2690
|
+
/* public/private/protected/readonly/override/declare/abstract before a class member:
|
|
2691
|
+
-1 on error, else 1 if the member is erased (declare, abstract), 0 otherwise */
|
|
2692
|
+
function ts_parse_class_modifiers(s) {
|
|
2693
|
+
const A = ts_atoms(s);
|
|
2694
|
+
let erase = 0;
|
|
2695
|
+
for (;;) {
|
|
2696
|
+
if (!(ts_word(s, JS_ATOM_public) || ts_word(s, JS_ATOM_private) || ts_word(s, JS_ATOM_protected) ||
|
|
2697
|
+
ts_word(s, A.readonly) || ts_word(s, A.override) || ts_word(s, A.declare) || ts_word(s, A.abstract)))
|
|
2698
|
+
return erase;
|
|
2699
|
+
/* TypeScript's nextTokenIsOnSameLineAndCanFollowModifier */
|
|
2700
|
+
const n = ts_peek(s);
|
|
2701
|
+
if (n.lf)
|
|
2702
|
+
return erase;
|
|
2703
|
+
switch (n.val) {
|
|
2704
|
+
case 91:
|
|
2705
|
+
case 123:
|
|
2706
|
+
case 42:
|
|
2707
|
+
case -91 /* TOK.ELLIPSIS */:
|
|
2708
|
+
case -127 /* TOK.STRING */:
|
|
2709
|
+
case -128 /* TOK.NUMBER */:
|
|
2710
|
+
case -87 /* TOK.PRIVATE_NAME */:
|
|
2711
|
+
case -125 /* TOK.IDENT */:
|
|
2712
|
+
break;
|
|
2713
|
+
default:
|
|
2714
|
+
if (!ts_is_keyword(n.val))
|
|
2715
|
+
return erase;
|
|
2716
|
+
}
|
|
2717
|
+
if (ts_word(s, A.declare) || ts_word(s, A.abstract))
|
|
2718
|
+
erase = 1;
|
|
2719
|
+
if (next_token(s))
|
|
2720
|
+
return -1;
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
/* a class member name, with its get/set/async/'*' prefix */
|
|
2724
|
+
function ts_skip_member_name(s) {
|
|
2725
|
+
if (ts_word(s, JS_ATOM_get) || ts_word(s, JS_ATOM_set) || ts_word(s, JS_ATOM_async)) {
|
|
2726
|
+
const n = ts_peek(s);
|
|
2727
|
+
if (!(n.val === 40 || n.val === 61 || n.val === 59 || n.val === 58 || n.val === 63 || n.val === 33 ||
|
|
2728
|
+
n.val === 60 || n.val === 125 || n.lf) && !ts_next(s))
|
|
2729
|
+
return false;
|
|
2730
|
+
}
|
|
2731
|
+
if (tv(s) === 42 && !ts_next(s))
|
|
2732
|
+
return false;
|
|
2733
|
+
switch (tv(s)) {
|
|
2734
|
+
case 91: return ts_skip_balanced(s);
|
|
2735
|
+
case -127 /* TOK.STRING */:
|
|
2736
|
+
case -128 /* TOK.NUMBER */:
|
|
2737
|
+
case -87 /* TOK.PRIVATE_NAME */: return ts_next(s);
|
|
2738
|
+
}
|
|
2739
|
+
return token_is_ident_or_keyword(tv(s)) && ts_next(s);
|
|
2740
|
+
}
|
|
2741
|
+
/* the member is a method without a body (overload signature) */
|
|
2742
|
+
function ts_class_member_is_signature(s) {
|
|
2743
|
+
const p = ts_save(s);
|
|
2744
|
+
let sig = false;
|
|
2745
|
+
if (ts_skip_member_name(s) && (tv(s) !== 63 || ts_next(s)) && (tv(s) === 60 || tv(s) === 40)) {
|
|
2746
|
+
sig = (tv(s) !== 60 || ts_skip_type_params(s)) && tv(s) === 40 && ts_skip_balanced(s) &&
|
|
2747
|
+
(tv(s) !== 58 || (ts_next(s) && ts_skip_return_type(s))) && tv(s) !== 123;
|
|
2748
|
+
}
|
|
2749
|
+
ts_restore(s, p);
|
|
2750
|
+
return sig;
|
|
2751
|
+
}
|
|
2752
|
+
/* [key: string]: T */
|
|
2753
|
+
function ts_is_index_signature(s) {
|
|
2754
|
+
if (tv(s) !== 91)
|
|
2755
|
+
return false;
|
|
2756
|
+
const p = ts_save(s);
|
|
2757
|
+
const ok = ts_next(s) && token_is_ident_or_keyword(tv(s)) && ts_next(s) && tv(s) === 58;
|
|
2758
|
+
ts_restore(s, p);
|
|
2759
|
+
return ok;
|
|
2760
|
+
}
|
|
2761
|
+
/* erase a class member: signature, index signature, declare field, abstract member */
|
|
2762
|
+
function ts_skip_class_member(s) {
|
|
2763
|
+
if (!ts_skip_member_name(s))
|
|
2764
|
+
return ts_error(s, 'invalid class member');
|
|
2765
|
+
if ((tv(s) === 63 || tv(s) === 33) && next_token(s))
|
|
2766
|
+
return -1;
|
|
2767
|
+
if (tv(s) === 60 && !ts_skip_type_params(s))
|
|
2768
|
+
return ts_error(s, 'invalid type parameters');
|
|
2769
|
+
if (tv(s) === 40) {
|
|
2770
|
+
if (!ts_skip_balanced(s))
|
|
2771
|
+
return ts_error(s, 'invalid parameters');
|
|
2772
|
+
if (tv(s) === 58 && ts_parse_annotation(s))
|
|
2773
|
+
return -1;
|
|
2774
|
+
if (tv(s) === 123)
|
|
2775
|
+
return ts_skip_balanced(s) ? 0 : ts_error(s, 'invalid method body');
|
|
2776
|
+
return js_parse_expect_semi(s);
|
|
2777
|
+
}
|
|
2778
|
+
if (tv(s) === 58 && ts_parse_annotation(s))
|
|
2779
|
+
return -1;
|
|
2780
|
+
if (tv(s) === 61) {
|
|
2781
|
+
if (next_token(s))
|
|
2782
|
+
return -1;
|
|
2783
|
+
if (!ts_skip_expr_tokens(s))
|
|
2784
|
+
return ts_error(s, 'invalid initializer');
|
|
2785
|
+
}
|
|
2786
|
+
return js_parse_expect_semi(s);
|
|
2787
|
+
}
|
|
2788
|
+
/* public/private/protected/readonly/override before a parameter (a parameter property) */
|
|
2789
|
+
function ts_is_param_modifier(s) {
|
|
2790
|
+
const A = ts_atoms(s);
|
|
2791
|
+
if (!(ts_word(s, JS_ATOM_public) || ts_word(s, JS_ATOM_private) || ts_word(s, JS_ATOM_protected) ||
|
|
2792
|
+
ts_word(s, A.readonly) || ts_word(s, A.override)))
|
|
2793
|
+
return false;
|
|
2794
|
+
const n = ts_peek(s);
|
|
2795
|
+
return n.val === -125 /* TOK.IDENT */ || n.val === 123 || n.val === 91 || n.val === -91 /* TOK.ELLIPSIS */ || ts_is_keyword(n.val);
|
|
2796
|
+
}
|
|
2797
|
+
/* ---------------------------------------------------------------------
|
|
2798
|
+
JSX (JS_EVAL_FLAG_JSX)
|
|
2799
|
+
|
|
2800
|
+
JSX is compiled by the parser, like the type stripping above: an
|
|
2801
|
+
element is read where a unary expression starts and emitted directly
|
|
2802
|
+
as the calls TypeScript makes for it. Modules use the automatic
|
|
2803
|
+
runtime (`jsx: "react-jsx"`): jsx, jsxs and Fragment are imported from
|
|
2804
|
+
`<importSource>/jsx-runtime`, and createElement from `<importSource>`
|
|
2805
|
+
for a key after a spread, under names no program can write (`*jsx*`,
|
|
2806
|
+
...), and each import is added to the module record only when it is
|
|
2807
|
+
used. Scripts, and files with a `@jsxRuntime classic` pragma, use the
|
|
2808
|
+
classic runtime (`jsx: "react"`): React.createElement and
|
|
2809
|
+
React.Fragment, or the `@jsx` and `@jsxFrag` pragmas.
|
|
2810
|
+
|
|
2811
|
+
Tags, attributes and text are scanned from the source by the jsx_*
|
|
2812
|
+
functions; expressions in braces go through the ordinary tokenizer
|
|
2813
|
+
and parser. Every position is a source position, so errors, stacks
|
|
2814
|
+
and the line table are those of the JSX source. jsx_skip_element
|
|
2815
|
+
skips an element without emitting anything, for the lookaheads that
|
|
2816
|
+
scan expressions token by token (arrow functions, destructuring,
|
|
2817
|
+
TypeScript). See docs/JSX.md.
|
|
2818
|
+
--------------------------------------------------------------------- */
|
|
2819
|
+
/* the named entities TypeScript decodes in JSX text and attribute strings (the HTML 4 list):
|
|
2820
|
+
name, then code point in hex */
|
|
2821
|
+
const JSX_ENTITY_TABLE = 'quot 22 amp 26 apos 27 lt 3c gt 3e nbsp a0 iexcl a1 cent a2 pound a3 curren a4 yen a5 brvbar a6 ' +
|
|
2822
|
+
'sect a7 uml a8 copy a9 ordf aa laquo ab not ac shy ad reg ae macr af deg b0 plusmn b1 sup2 b2 ' +
|
|
2823
|
+
'sup3 b3 acute b4 micro b5 para b6 middot b7 cedil b8 sup1 b9 ordm ba raquo bb frac14 bc frac12 bd ' +
|
|
2824
|
+
'frac34 be iquest bf Agrave c0 Aacute c1 Acirc c2 Atilde c3 Auml c4 Aring c5 AElig c6 Ccedil c7 ' +
|
|
2825
|
+
'Egrave c8 Eacute c9 Ecirc ca Euml cb Igrave cc Iacute cd Icirc ce Iuml cf ETH d0 Ntilde d1 ' +
|
|
2826
|
+
'Ograve d2 Oacute d3 Ocirc d4 Otilde d5 Ouml d6 times d7 Oslash d8 Ugrave d9 Uacute da Ucirc db ' +
|
|
2827
|
+
'Uuml dc Yacute dd THORN de szlig df agrave e0 aacute e1 acirc e2 atilde e3 auml e4 aring e5 ' +
|
|
2828
|
+
'aelig e6 ccedil e7 egrave e8 eacute e9 ecirc ea euml eb igrave ec iacute ed icirc ee iuml ef eth f0 ' +
|
|
2829
|
+
'ntilde f1 ograve f2 oacute f3 ocirc f4 otilde f5 ouml f6 divide f7 oslash f8 ugrave f9 uacute fa ' +
|
|
2830
|
+
'ucirc fb uuml fc yacute fd thorn fe yuml ff OElig 152 oelig 153 Scaron 160 scaron 161 Yuml 178 ' +
|
|
2831
|
+
'fnof 192 circ 2c6 tilde 2dc Alpha 391 Beta 392 Gamma 393 Delta 394 Epsilon 395 Zeta 396 Eta 397 ' +
|
|
2832
|
+
'Theta 398 Iota 399 Kappa 39a Lambda 39b Mu 39c Nu 39d Xi 39e Omicron 39f Pi 3a0 Rho 3a1 Sigma 3a3 ' +
|
|
2833
|
+
'Tau 3a4 Upsilon 3a5 Phi 3a6 Chi 3a7 Psi 3a8 Omega 3a9 alpha 3b1 beta 3b2 gamma 3b3 delta 3b4 ' +
|
|
2834
|
+
'epsilon 3b5 zeta 3b6 eta 3b7 theta 3b8 iota 3b9 kappa 3ba lambda 3bb mu 3bc nu 3bd xi 3be ' +
|
|
2835
|
+
'omicron 3bf pi 3c0 rho 3c1 sigmaf 3c2 sigma 3c3 tau 3c4 upsilon 3c5 phi 3c6 chi 3c7 psi 3c8 ' +
|
|
2836
|
+
'omega 3c9 thetasym 3d1 upsih 3d2 piv 3d6 ensp 2002 emsp 2003 thinsp 2009 zwnj 200c zwj 200d ' +
|
|
2837
|
+
'lrm 200e rlm 200f ndash 2013 mdash 2014 lsquo 2018 rsquo 2019 sbquo 201a ldquo 201c rdquo 201d ' +
|
|
2838
|
+
'bdquo 201e dagger 2020 Dagger 2021 bull 2022 hellip 2026 permil 2030 prime 2032 Prime 2033 ' +
|
|
2839
|
+
'lsaquo 2039 rsaquo 203a oline 203e frasl 2044 euro 20ac image 2111 weierp 2118 real 211c trade 2122 ' +
|
|
2840
|
+
'alefsym 2135 larr 2190 uarr 2191 rarr 2192 darr 2193 harr 2194 crarr 21b5 lArr 21d0 uArr 21d1 ' +
|
|
2841
|
+
'rArr 21d2 dArr 21d3 hArr 21d4 forall 2200 part 2202 exist 2203 empty 2205 nabla 2207 isin 2208 ' +
|
|
2842
|
+
'notin 2209 ni 220b prod 220f sum 2211 minus 2212 lowast 2217 radic 221a prop 221d infin 221e ' +
|
|
2843
|
+
'ang 2220 and 2227 or 2228 cap 2229 cup 222a int 222b there4 2234 sim 223c cong 2245 asymp 2248 ' +
|
|
2844
|
+
'ne 2260 equiv 2261 le 2264 ge 2265 sub 2282 sup 2283 nsub 2284 sube 2286 supe 2287 oplus 2295 ' +
|
|
2845
|
+
'otimes 2297 perp 22a5 sdot 22c5 lceil 2308 rceil 2309 lfloor 230a rfloor 230b lang 2329 rang 232a ' +
|
|
2846
|
+
'loz 25ca spades 2660 clubs 2663 hearts 2665 diams 2666';
|
|
2847
|
+
let jsx_entities = null;
|
|
2848
|
+
/* TypeScript's decodeEntities: named, decimal (&) and hex (&) entities; unknown ones are kept */
|
|
2849
|
+
function jsx_decode_entities(text) {
|
|
2850
|
+
if (text.indexOf('&') < 0)
|
|
2851
|
+
return text;
|
|
2852
|
+
if (jsx_entities === null) {
|
|
2853
|
+
const t = JSX_ENTITY_TABLE.split(' ');
|
|
2854
|
+
jsx_entities = new Map();
|
|
2855
|
+
for (let i = 0; i + 1 < t.length; i += 2)
|
|
2856
|
+
jsx_entities.set(t[i], parseInt(t[i + 1], 16));
|
|
2857
|
+
}
|
|
2858
|
+
const names = jsx_entities;
|
|
2859
|
+
return text.replace(/&((#((\d+)|x([\da-fA-F]+)))|(\w+));/g, (match, _all, _number, _digits, decimal, hex, word) => {
|
|
2860
|
+
const cp = decimal !== undefined ? parseInt(decimal, 10) : hex !== undefined ? parseInt(hex, 16) : names.get(word);
|
|
2861
|
+
return cp !== undefined && cp <= 0x10ffff ? String.fromCodePoint(cp) : match;
|
|
2862
|
+
});
|
|
2863
|
+
}
|
|
2864
|
+
function jsx_is_line_break(c) {
|
|
2865
|
+
return c === 10 || c === 13 || c === CP_LS || c === CP_PS;
|
|
2866
|
+
}
|
|
2867
|
+
/* TypeScript's isWhiteSpaceSingleLine */
|
|
2868
|
+
function jsx_is_space(c) {
|
|
2869
|
+
return c === 32 || c === 9 || c === 11 || c === 12 || c === 0xa0 || c === 0x85 || c === 0x1680 ||
|
|
2870
|
+
(c >= 0x2000 && c <= 0x200b) || c === 0x202f || c === 0x205f || c === 0x3000 || c === 0xfeff;
|
|
2871
|
+
}
|
|
2872
|
+
/* the string a JSX text child stands for (TypeScript's fixupWhitespaceAndDecodeEntities), or null
|
|
2873
|
+
if it produces no child: each line is trimmed, lines left empty are dropped, and the remaining
|
|
2874
|
+
lines are joined with a space. The first line keeps its leading white space and the last its
|
|
2875
|
+
trailing white space unless they hold a line break, so text on a single line is kept as is */
|
|
2876
|
+
function jsx_text_value(text) {
|
|
2877
|
+
let acc = null;
|
|
2878
|
+
let first = 0, last = -1;
|
|
2879
|
+
const add = (line) => {
|
|
2880
|
+
const decoded = jsx_decode_entities(line);
|
|
2881
|
+
acc = acc === null ? decoded : acc + ' ' + decoded;
|
|
2882
|
+
};
|
|
2883
|
+
for (let i = 0; i < text.length; i++) {
|
|
2884
|
+
const c = text.charCodeAt(i);
|
|
2885
|
+
if (jsx_is_line_break(c)) {
|
|
2886
|
+
if (first !== -1 && last !== -1)
|
|
2887
|
+
add(text.substring(first, last + 1));
|
|
2888
|
+
first = -1;
|
|
2889
|
+
}
|
|
2890
|
+
else if (!jsx_is_space(c)) {
|
|
2891
|
+
last = i;
|
|
2892
|
+
if (first === -1)
|
|
2893
|
+
first = i;
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
if (first !== -1)
|
|
2897
|
+
add(text.substring(first));
|
|
2898
|
+
return acc;
|
|
2899
|
+
}
|
|
2900
|
+
/* --- the runtime --- */
|
|
2901
|
+
/* what JSX compiles to in a file */
|
|
2902
|
+
class JSXRuntime {
|
|
2903
|
+
automatic = true;
|
|
2904
|
+
/* automatic: the import source (jsx, jsxs and Fragment come from `${source}/jsx-runtime`) */
|
|
2905
|
+
source = 'react';
|
|
2906
|
+
/* classic: the factory and fragment, as property paths */
|
|
2907
|
+
factory = ['React', 'createElement'];
|
|
2908
|
+
fragment = ['React', 'Fragment'];
|
|
2909
|
+
/* the module requests of the implicit imports, in order of first use */
|
|
2910
|
+
requests = [];
|
|
2911
|
+
}
|
|
2912
|
+
/* TypeScript's jsx pragmas: the multi-line comments before the first token are matched with
|
|
2913
|
+
TypeScript's regular expression (so one pragma per line), and each pragma takes the first word
|
|
2914
|
+
after it; @jsx and @jsxFrag take their first occurrence, @jsxImportSource and @jsxRuntime their
|
|
2915
|
+
last. An empty argument is '' */
|
|
2916
|
+
function jsx_pragmas(buf) {
|
|
2917
|
+
const pragmas = new Map();
|
|
2918
|
+
let p = 0;
|
|
2919
|
+
const skip_line = () => { while (p < buf.length && !jsx_is_line_break(buf.charCodeAt(p)))
|
|
2920
|
+
p++; };
|
|
2921
|
+
if (buf.startsWith('#!'))
|
|
2922
|
+
skip_line();
|
|
2923
|
+
for (;;) {
|
|
2924
|
+
while (p < buf.length && (jsx_is_line_break(buf.charCodeAt(p)) || lre_is_space(buf.charCodeAt(p))))
|
|
2925
|
+
p++;
|
|
2926
|
+
if (buf.startsWith('//', p)) {
|
|
2927
|
+
skip_line();
|
|
2928
|
+
}
|
|
2929
|
+
else if (buf.startsWith('/*', p)) {
|
|
2930
|
+
const end = buf.indexOf('*/', p + 2);
|
|
2931
|
+
if (end < 0)
|
|
2932
|
+
break;
|
|
2933
|
+
const text = buf.substring(p, end + 2);
|
|
2934
|
+
for (const m of text.matchAll(/@(\S+)(\s+(?:\S.*)?)?$/gm)) {
|
|
2935
|
+
const name = m[1].toLowerCase();
|
|
2936
|
+
if (name !== 'jsx' && name !== 'jsxfrag' && name !== 'jsximportsource' && name !== 'jsxruntime')
|
|
2937
|
+
continue;
|
|
2938
|
+
const arg = m[2] === undefined ? '' : m[2].trim().split(/\s+/)[0];
|
|
2939
|
+
let list = pragmas.get(name);
|
|
2940
|
+
if (list === undefined)
|
|
2941
|
+
pragmas.set(name, list = []);
|
|
2942
|
+
list.push(arg);
|
|
2943
|
+
}
|
|
2944
|
+
p = end + 2;
|
|
2945
|
+
}
|
|
2946
|
+
else {
|
|
2947
|
+
break;
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2950
|
+
return pragmas;
|
|
2951
|
+
}
|
|
2952
|
+
/* `a.b.c` as a property path, or null if it is not one (TypeScript's parseIsolatedEntityName) */
|
|
2953
|
+
function jsx_entity_path(name) {
|
|
2954
|
+
if (!name)
|
|
2955
|
+
return null;
|
|
2956
|
+
const parts = name.split('.');
|
|
2957
|
+
return parts.every(p => /^[A-Za-z_$][\w$]*$/.test(p)) ? parts : null;
|
|
2958
|
+
}
|
|
2959
|
+
/* the runtime of the file being parsed, decided at its first JSX element as TypeScript does with
|
|
2960
|
+
`jsx: "react-jsx"` for a module and `jsx: "react"` for a script: `@jsxRuntime classic` selects
|
|
2961
|
+
the classic runtime, `@jsxRuntime automatic` or `@jsxImportSource` the automatic one (a
|
|
2962
|
+
SyntaxError in a script, which cannot import) */
|
|
2963
|
+
function jsx_runtime(s) {
|
|
2964
|
+
if (s.jsx_runtime !== null)
|
|
2965
|
+
return s.jsx_runtime;
|
|
2966
|
+
const rt = new JSXRuntime();
|
|
2967
|
+
const pragmas = jsx_pragmas(s.buf);
|
|
2968
|
+
const last = (name) => pragmas.get(name)?.at(-1);
|
|
2969
|
+
const kind = last('jsxruntime');
|
|
2970
|
+
const source = last('jsximportsource');
|
|
2971
|
+
rt.automatic = kind === 'classic' ? false : s.is_module || kind === 'automatic' || source !== undefined;
|
|
2972
|
+
if (rt.automatic && !s.is_module) {
|
|
2973
|
+
js_parse_error(s, 'the automatic JSX runtime needs a module: use @jsxRuntime classic in a script');
|
|
2974
|
+
return null;
|
|
2975
|
+
}
|
|
2976
|
+
if (source)
|
|
2977
|
+
rt.source = source;
|
|
2978
|
+
rt.factory = jsx_entity_path(pragmas.get('jsx')?.[0]) ?? rt.factory;
|
|
2979
|
+
rt.fragment = jsx_entity_path(pragmas.get('jsxfrag')?.[0]) ?? rt.fragment;
|
|
2980
|
+
return s.jsx_runtime = rt;
|
|
2981
|
+
}
|
|
2982
|
+
/* the variable of an implicit import of the automatic runtime (`jsx`, `jsxs`, `Fragment` or
|
|
2983
|
+
`createElement`), added to the module record on first use */
|
|
2984
|
+
function jsx_import(s, name) {
|
|
2985
|
+
const ctx = s.ctx;
|
|
2986
|
+
const local = JS_NewAtom(ctx, `*${name}*`);
|
|
2987
|
+
let fd = s.cur_func;
|
|
2988
|
+
while (fd.parent !== null)
|
|
2989
|
+
fd = fd.parent;
|
|
2990
|
+
if (fd.closure_var.some(cv => cv.var_name === local))
|
|
2991
|
+
return local;
|
|
2992
|
+
const m = fd.module;
|
|
2993
|
+
const rt = s.jsx_runtime;
|
|
2994
|
+
const req = add_req_module_entry(m, JS_NewAtom(ctx, name === 'createElement' ? rt.source : `${rt.source}/jsx-runtime`), null);
|
|
2995
|
+
if (!rt.requests.includes(req))
|
|
2996
|
+
rt.requests.push(req);
|
|
2997
|
+
const var_idx = add_closure_var(ctx, fd, false, false, m.import_entries.length, local, true, true, 0 /* JSVarKind.NORMAL */);
|
|
2998
|
+
const mi = new JSImportEntry(var_idx, false, JS_NewAtom(ctx, name));
|
|
2999
|
+
mi.req_module_idx = req;
|
|
3000
|
+
m.import_entries.push(mi);
|
|
3001
|
+
return local;
|
|
3002
|
+
}
|
|
3003
|
+
/* TypeScript puts the implicit imports first (each import statement before the previous one), so
|
|
3004
|
+
the runtime modules are requested, and evaluated, before the file's own imports */
|
|
3005
|
+
function jsx_hoist_requests(m, requests) {
|
|
3006
|
+
const order = [...requests].reverse();
|
|
3007
|
+
for (let i = 0; i < m.req_module_entries.length; i++)
|
|
3008
|
+
if (!order.includes(i))
|
|
3009
|
+
order.push(i);
|
|
3010
|
+
const index = new Map(order.map((old, i) => [old, i]));
|
|
3011
|
+
m.req_module_entries = order.map(i => m.req_module_entries[i]);
|
|
3012
|
+
for (const mi of m.import_entries)
|
|
3013
|
+
mi.req_module_idx = index.get(mi.req_module_idx);
|
|
3014
|
+
for (const me of m.export_entries)
|
|
3015
|
+
if (me.export_type === 1 /* JSExportType.INDIRECT */)
|
|
3016
|
+
me.req_module_idx = index.get(me.req_module_idx);
|
|
3017
|
+
for (const se of m.star_export_entries)
|
|
3018
|
+
se.req_module_idx = index.get(se.req_module_idx);
|
|
3019
|
+
}
|
|
3020
|
+
/* --- scanning --- */
|
|
3021
|
+
/* skip white space, line terminators and comments in a JSX tag: the new position, or -1 after
|
|
3022
|
+
reporting an unterminated comment */
|
|
3023
|
+
function jsx_skip_space(s, p) {
|
|
3024
|
+
const buf = s.buf;
|
|
3025
|
+
while (p < s.buf_end) {
|
|
3026
|
+
const c = buf.charCodeAt(p);
|
|
3027
|
+
if (c === 47 && buf.charCodeAt(p + 1) === 42) {
|
|
3028
|
+
const end = buf.indexOf('*/', p + 2);
|
|
3029
|
+
if (end < 0)
|
|
3030
|
+
return js_parse_error_pos(s, p, 'unexpected end of comment');
|
|
3031
|
+
p = end + 2;
|
|
3032
|
+
}
|
|
3033
|
+
else if (c === 47 && buf.charCodeAt(p + 1) === 47) {
|
|
3034
|
+
p += 2;
|
|
3035
|
+
while (p < s.buf_end && !jsx_is_line_break(buf.charCodeAt(p)))
|
|
3036
|
+
p++;
|
|
3037
|
+
}
|
|
3038
|
+
else if (jsx_is_line_break(c) || lre_is_space(c)) {
|
|
3039
|
+
p++;
|
|
3040
|
+
}
|
|
3041
|
+
else {
|
|
3042
|
+
break;
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
return p;
|
|
3046
|
+
}
|
|
3047
|
+
/* the next token of a JSX tag, from s.buf_ptr: a JSX name (identifier characters and '-', in
|
|
3048
|
+
s.token.str and s.token.atom), a string (its raw text, newlines included, with the entities
|
|
3049
|
+
decoded), EOF, or a single punctuation character ('>' is never part of '>=' or '>>') */
|
|
3050
|
+
function jsx_tag_token(s) {
|
|
3051
|
+
const buf = s.buf;
|
|
3052
|
+
const p = jsx_skip_space(s, s.buf_ptr);
|
|
3053
|
+
if (p < 0)
|
|
3054
|
+
return -1;
|
|
3055
|
+
const t = s.token;
|
|
3056
|
+
t.ptr = p;
|
|
3057
|
+
t.atom = JS_ATOM_NULL;
|
|
3058
|
+
t.has_escape = false;
|
|
3059
|
+
t.is_reserved = false;
|
|
3060
|
+
if (p >= s.buf_end) {
|
|
3061
|
+
t.val = -86 /* TOK.EOF */;
|
|
3062
|
+
s.buf_ptr = p;
|
|
3063
|
+
return 0;
|
|
3064
|
+
}
|
|
3065
|
+
const c = cp_at(buf, p);
|
|
3066
|
+
if (lre_js_is_ident_first(c)) {
|
|
3067
|
+
let q = p + cp_len(c);
|
|
3068
|
+
while (q < s.buf_end) {
|
|
3069
|
+
const d = cp_at(buf, q);
|
|
3070
|
+
if (d !== 45 && !lre_js_is_ident_next(d))
|
|
3071
|
+
break;
|
|
3072
|
+
q += cp_len(d);
|
|
3073
|
+
}
|
|
3074
|
+
t.val = -125 /* TOK.IDENT */;
|
|
3075
|
+
t.str = buf.substring(p, q);
|
|
3076
|
+
t.atom = JS_NewAtom(s.ctx, t.str);
|
|
3077
|
+
s.buf_ptr = q;
|
|
3078
|
+
return 0;
|
|
3079
|
+
}
|
|
3080
|
+
if (c === 34 || c === 39) {
|
|
3081
|
+
const end = buf.indexOf(c === 34 ? '"' : "'", p + 1);
|
|
3082
|
+
if (end < 0)
|
|
3083
|
+
return js_parse_error_pos(s, p, 'unexpected end of string');
|
|
3084
|
+
t.val = -127 /* TOK.STRING */;
|
|
3085
|
+
t.str = jsx_decode_entities(buf.substring(p + 1, end));
|
|
3086
|
+
s.buf_ptr = end + 1;
|
|
3087
|
+
return 0;
|
|
3088
|
+
}
|
|
3089
|
+
if (c >= 33 && c < 127) {
|
|
3090
|
+
t.val = c;
|
|
3091
|
+
s.buf_ptr = p + 1;
|
|
3092
|
+
return 0;
|
|
3093
|
+
}
|
|
3094
|
+
return js_parse_error_pos(s, p, 'unexpected character');
|
|
3095
|
+
}
|
|
3096
|
+
/* a tag name: `div`, `a-b` and `a:b` are strings, `Foo`, `a.b.c` and `this.x` expressions */
|
|
3097
|
+
class JSXTag {
|
|
3098
|
+
text = ''; /* as written, without spaces: compared with the closing tag */
|
|
3099
|
+
ptr = 0;
|
|
3100
|
+
is_string = false;
|
|
3101
|
+
parts = [];
|
|
3102
|
+
}
|
|
3103
|
+
/* the tag name at the current token; the token after it becomes current. In TypeScript, type
|
|
3104
|
+
arguments may follow the name of an opening tag (`<List<T> items={x} />`) */
|
|
3105
|
+
function jsx_parse_tag_name(s, tag, type_args) {
|
|
3106
|
+
tag.ptr = s.token.ptr;
|
|
3107
|
+
if (tv(s) !== -125 /* TOK.IDENT */)
|
|
3108
|
+
return js_parse_error(s, 'JSX element name expected');
|
|
3109
|
+
tag.text = s.token.str;
|
|
3110
|
+
tag.parts = [s.token.atom];
|
|
3111
|
+
if (jsx_tag_token(s))
|
|
3112
|
+
return -1;
|
|
3113
|
+
if (tv(s) === 58) {
|
|
3114
|
+
/* namespaced name */
|
|
3115
|
+
if (jsx_tag_token(s))
|
|
3116
|
+
return -1;
|
|
3117
|
+
if (tv(s) !== -125 /* TOK.IDENT */)
|
|
3118
|
+
return js_parse_error(s, 'identifier expected');
|
|
3119
|
+
tag.text += ':' + s.token.str;
|
|
3120
|
+
tag.is_string = true;
|
|
3121
|
+
if (jsx_tag_token(s))
|
|
3122
|
+
return -1;
|
|
3123
|
+
}
|
|
3124
|
+
else {
|
|
3125
|
+
while (tv(s) === 46) {
|
|
3126
|
+
if (jsx_tag_token(s))
|
|
3127
|
+
return -1;
|
|
3128
|
+
if (tv(s) !== -125 /* TOK.IDENT */)
|
|
3129
|
+
return js_parse_error(s, 'identifier expected');
|
|
3130
|
+
tag.text += '.' + s.token.str;
|
|
3131
|
+
tag.parts.push(s.token.atom);
|
|
3132
|
+
if (jsx_tag_token(s))
|
|
3133
|
+
return -1;
|
|
3134
|
+
}
|
|
3135
|
+
/* TypeScript's isIntrinsicJsxName; `this` is an expression */
|
|
3136
|
+
const c = tag.text.charCodeAt(0);
|
|
3137
|
+
tag.is_string = tag.parts.length === 1 && tag.text !== 'this' && ((c >= 97 && c <= 122) || tag.text.includes('-'));
|
|
3138
|
+
}
|
|
3139
|
+
if (type_args && s.ts && tv(s) === 60) {
|
|
3140
|
+
s.buf_ptr = s.token.ptr;
|
|
3141
|
+
if (next_token(s))
|
|
3142
|
+
return -1;
|
|
3143
|
+
if (!ts_skip_type_args(s))
|
|
3144
|
+
return ts_error(s, 'invalid type arguments');
|
|
3145
|
+
/* rescan the token after the type arguments as a tag token */
|
|
3146
|
+
s.buf_ptr = s.token.ptr;
|
|
3147
|
+
if (jsx_tag_token(s))
|
|
3148
|
+
return -1;
|
|
3149
|
+
}
|
|
3150
|
+
return 0;
|
|
3151
|
+
}
|
|
3152
|
+
/* the current token is the '{' of a JSX tag: skip to just after its '}', JSX included */
|
|
3153
|
+
function jsx_skip_braces(s) {
|
|
3154
|
+
s.buf_ptr = s.token.ptr;
|
|
3155
|
+
return ts_next(s) && ts_skip_balanced(s, false);
|
|
3156
|
+
}
|
|
3157
|
+
/* the current token starts an attribute value: skip it (to just after it) */
|
|
3158
|
+
function jsx_skip_attr_value(s) {
|
|
3159
|
+
if (tv(s) === -127 /* TOK.STRING */)
|
|
3160
|
+
return true;
|
|
3161
|
+
if (tv(s) === 123)
|
|
3162
|
+
return jsx_skip_braces(s);
|
|
3163
|
+
if (tv(s) === 60)
|
|
3164
|
+
return jsx_skip_element(s);
|
|
3165
|
+
return false;
|
|
3166
|
+
}
|
|
3167
|
+
/* the current token is the '<' of a JSX element: skip the element without emitting anything, to
|
|
3168
|
+
just after its last '>'. False if it is not one (an exception may be pending) */
|
|
3169
|
+
function jsx_skip_element(s) {
|
|
3170
|
+
s.buf_ptr = s.token.ptr + 1;
|
|
3171
|
+
if (jsx_tag_token(s))
|
|
3172
|
+
return false;
|
|
3173
|
+
const tag = new JSXTag();
|
|
3174
|
+
if (tv(s) !== 62) {
|
|
3175
|
+
if (jsx_parse_tag_name(s, tag, true))
|
|
3176
|
+
return false;
|
|
3177
|
+
while (tv(s) !== 47 && tv(s) !== 62) {
|
|
3178
|
+
if (tv(s) === -125 /* TOK.IDENT */) {
|
|
3179
|
+
if (jsx_tag_token(s))
|
|
3180
|
+
return false;
|
|
3181
|
+
if (tv(s) === 58 && (jsx_tag_token(s) || tv(s) !== -125 /* TOK.IDENT */ || jsx_tag_token(s)))
|
|
3182
|
+
return false;
|
|
3183
|
+
if (tv(s) === 61 && (jsx_tag_token(s) || !jsx_skip_attr_value(s) || jsx_tag_token(s)))
|
|
3184
|
+
return false;
|
|
3185
|
+
}
|
|
3186
|
+
else if (tv(s) === 123) {
|
|
3187
|
+
if (!jsx_skip_braces(s) || jsx_tag_token(s))
|
|
3188
|
+
return false;
|
|
3189
|
+
}
|
|
3190
|
+
else {
|
|
3191
|
+
return false;
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
if (tv(s) === 47)
|
|
3195
|
+
return !jsx_tag_token(s) && tv(s) === 62;
|
|
3196
|
+
}
|
|
3197
|
+
/* children */
|
|
3198
|
+
const buf = s.buf;
|
|
3199
|
+
let p = s.buf_ptr;
|
|
3200
|
+
for (;;) {
|
|
3201
|
+
while (p < s.buf_end) {
|
|
3202
|
+
const c = buf.charCodeAt(p);
|
|
3203
|
+
if (c === 123 || c === 60)
|
|
3204
|
+
break;
|
|
3205
|
+
if (c === 62 || c === 125)
|
|
3206
|
+
return false;
|
|
3207
|
+
p++;
|
|
3208
|
+
}
|
|
3209
|
+
if (p >= s.buf_end)
|
|
3210
|
+
return false;
|
|
3211
|
+
s.buf_ptr = p;
|
|
3212
|
+
if (buf.charCodeAt(p) === 123) {
|
|
3213
|
+
if (!ts_next(s) || !ts_skip_balanced(s, false))
|
|
3214
|
+
return false;
|
|
3215
|
+
}
|
|
3216
|
+
else if (buf.charCodeAt(p + 1) === 47) {
|
|
3217
|
+
s.buf_ptr = p + 2;
|
|
3218
|
+
if (jsx_tag_token(s))
|
|
3219
|
+
return false;
|
|
3220
|
+
const close = new JSXTag();
|
|
3221
|
+
if (tv(s) !== 62 && jsx_parse_tag_name(s, close, false))
|
|
3222
|
+
return false;
|
|
3223
|
+
return tv(s) === 62 && close.text === tag.text;
|
|
3224
|
+
}
|
|
3225
|
+
else {
|
|
3226
|
+
s.token.ptr = p;
|
|
3227
|
+
if (!jsx_skip_element(s))
|
|
3228
|
+
return false;
|
|
3229
|
+
}
|
|
3230
|
+
p = s.buf_ptr;
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
/* the current token is '<' at the start of an expression: true if it starts a JSX element, which
|
|
3234
|
+
is then skipped (with the token after it current) */
|
|
3235
|
+
function jsx_try_skip(s) {
|
|
3236
|
+
const p = ts_save(s);
|
|
3237
|
+
if (jsx_skip_element(s) && ts_next(s))
|
|
3238
|
+
return true;
|
|
3239
|
+
ts_restore(s, p);
|
|
3240
|
+
return false;
|
|
3241
|
+
}
|
|
3242
|
+
/* TypeScript's hasKeyAfterPropsSpread, scanned ahead from the token after the tag name: a `key`
|
|
3243
|
+
attribute after a spread (of anything but an object literal without spreads) makes the element
|
|
3244
|
+
a createElement call, which keeps the key in the props */
|
|
3245
|
+
function jsx_key_after_spread(s) {
|
|
3246
|
+
const pos = ts_save(s);
|
|
3247
|
+
let spread = false, found = false;
|
|
3248
|
+
for (;;) {
|
|
3249
|
+
if (tv(s) === -125 /* TOK.IDENT */) {
|
|
3250
|
+
let is_key = s.token.str === 'key';
|
|
3251
|
+
if (jsx_tag_token(s))
|
|
3252
|
+
break;
|
|
3253
|
+
if (tv(s) === 58) {
|
|
3254
|
+
is_key = false;
|
|
3255
|
+
if (jsx_tag_token(s) || jsx_tag_token(s))
|
|
3256
|
+
break;
|
|
3257
|
+
}
|
|
3258
|
+
if (is_key && spread) {
|
|
3259
|
+
found = true;
|
|
1566
3260
|
break;
|
|
1567
|
-
|
|
1568
|
-
|
|
3261
|
+
}
|
|
3262
|
+
if (tv(s) === 61 && (jsx_tag_token(s) || !jsx_skip_attr_value(s) || jsx_tag_token(s)))
|
|
1569
3263
|
break;
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
3264
|
+
}
|
|
3265
|
+
else if (tv(s) === 123) {
|
|
3266
|
+
const start = s.token.ptr;
|
|
3267
|
+
if (!spread) {
|
|
3268
|
+
const literal = { ellipsis: false };
|
|
3269
|
+
s.buf_ptr = start + 1;
|
|
3270
|
+
if (!ts_next(s) || tv(s) !== -91 /* TOK.ELLIPSIS */ || !ts_next(s))
|
|
3271
|
+
break;
|
|
3272
|
+
spread = !(tv(s) === 123 && ts_skip_balanced(s, true, literal) && tv(s) === 125 && !literal.ellipsis);
|
|
3273
|
+
}
|
|
3274
|
+
s.token.ptr = start;
|
|
3275
|
+
if (!jsx_skip_braces(s) || jsx_tag_token(s))
|
|
1580
3276
|
break;
|
|
1581
3277
|
}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
3278
|
+
else {
|
|
3279
|
+
break;
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
ts_restore(s, pos);
|
|
3283
|
+
return found;
|
|
3284
|
+
}
|
|
3285
|
+
function jsx_child_start(s, ch, spread) {
|
|
3286
|
+
if (spread)
|
|
3287
|
+
ch.spread = true;
|
|
3288
|
+
if (!ch.array && (spread || ch.base + ch.n >= 65535)) {
|
|
3289
|
+
emit_op(s, 38 /* OP.array_from */);
|
|
3290
|
+
emit_u16(s, ch.base + ch.n);
|
|
3291
|
+
emit_op(s, 1 /* OP.push_i32 */);
|
|
3292
|
+
emit_u32(s, ch.base + ch.n);
|
|
3293
|
+
ch.array = true;
|
|
3294
|
+
}
|
|
3295
|
+
}
|
|
3296
|
+
function jsx_child_end(s, ch, spread) {
|
|
3297
|
+
if (ch.array) {
|
|
3298
|
+
if (spread) {
|
|
3299
|
+
emit_op(s, 83 /* OP.append */);
|
|
1585
3300
|
}
|
|
1586
3301
|
else {
|
|
1587
|
-
|
|
3302
|
+
emit_op(s, 82 /* OP.define_array_el */);
|
|
3303
|
+
emit_op(s, 145 /* OP.inc */);
|
|
1588
3304
|
}
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
3305
|
+
}
|
|
3306
|
+
ch.n++;
|
|
3307
|
+
}
|
|
3308
|
+
/* emit a property path (the classic factory or fragment); with `method`, keep the object of the
|
|
3309
|
+
last property for a method call. True if it is one */
|
|
3310
|
+
function jsx_emit_path(s, path, method) {
|
|
3311
|
+
emit_ident_ref(s, JS_NewAtom(s.ctx, path[0]));
|
|
3312
|
+
for (let i = 1; i < path.length; i++) {
|
|
3313
|
+
emit_op(s, method && i === path.length - 1 ? 67 /* OP.get_field2 */ : 66 /* OP.get_field */);
|
|
3314
|
+
emit_atom(s, JS_NewAtom(s.ctx, path[i]));
|
|
3315
|
+
}
|
|
3316
|
+
return method && path.length > 1;
|
|
3317
|
+
}
|
|
3318
|
+
/* emit the type of an element: a string, or the value of the tag expression */
|
|
3319
|
+
function jsx_emit_tag(s, tag) {
|
|
3320
|
+
if (tag.is_string)
|
|
3321
|
+
return emit_push_const(s, tag.text, true);
|
|
3322
|
+
emit_source_pos(s, tag.ptr);
|
|
3323
|
+
if (tag.parts[0] === JS_ATOM_this) {
|
|
3324
|
+
emit_op(s, 186 /* OP.scope_get_var */);
|
|
3325
|
+
emit_atom(s, JS_ATOM_this);
|
|
3326
|
+
emit_u16(s, 0);
|
|
3327
|
+
}
|
|
3328
|
+
else {
|
|
3329
|
+
emit_ident_ref(s, tag.parts[0]);
|
|
3330
|
+
}
|
|
3331
|
+
for (let i = 1; i < tag.parts.length; i++) {
|
|
3332
|
+
emit_op(s, 66 /* OP.get_field */);
|
|
3333
|
+
emit_atom(s, tag.parts[i]);
|
|
3334
|
+
}
|
|
3335
|
+
return 0;
|
|
3336
|
+
}
|
|
3337
|
+
/* the current token starts an attribute value: emit it (s.buf_ptr ends just after it) */
|
|
3338
|
+
function jsx_parse_attr_value(s) {
|
|
3339
|
+
if (tv(s) === -127 /* TOK.STRING */)
|
|
3340
|
+
return emit_push_const(s, s.token.str, true);
|
|
3341
|
+
if (tv(s) === 60)
|
|
3342
|
+
return jsx_parse_element(s);
|
|
3343
|
+
if (tv(s) !== 123)
|
|
3344
|
+
return js_parse_error(s, "'{' or JSX element expected");
|
|
3345
|
+
if (next_token(s))
|
|
3346
|
+
return -1;
|
|
3347
|
+
if (tv(s) === 125)
|
|
3348
|
+
return js_parse_error(s, 'JSX attributes must only be assigned a non-empty expression');
|
|
3349
|
+
if (js_parse_expr(s))
|
|
3350
|
+
return -1;
|
|
3351
|
+
if (tv(s) !== 125)
|
|
3352
|
+
return js_parse_error(s, "expecting '}'");
|
|
3353
|
+
return 0;
|
|
3354
|
+
}
|
|
3355
|
+
/* the children of an element, up to and including its closing tag */
|
|
3356
|
+
function jsx_parse_children(s, ch, tag, start) {
|
|
3357
|
+
const buf = s.buf;
|
|
3358
|
+
let p = s.buf_ptr;
|
|
3359
|
+
for (;;) {
|
|
3360
|
+
/* text */
|
|
3361
|
+
let q = p;
|
|
3362
|
+
while (q < s.buf_end) {
|
|
3363
|
+
const c = buf.charCodeAt(q);
|
|
3364
|
+
if (c === 123 || c === 60)
|
|
3365
|
+
break;
|
|
3366
|
+
if (c === 62)
|
|
3367
|
+
return js_parse_error_pos(s, q, "Unexpected token. Did you mean `{'>'}` or `>`?");
|
|
3368
|
+
if (c === 125)
|
|
3369
|
+
return js_parse_error_pos(s, q, "Unexpected token. Did you mean `{'}'}` or `}`?");
|
|
3370
|
+
q++;
|
|
3371
|
+
}
|
|
3372
|
+
if (q > p) {
|
|
3373
|
+
const text = jsx_text_value(buf.substring(p, q));
|
|
3374
|
+
if (text !== null) {
|
|
3375
|
+
jsx_child_start(s, ch, false);
|
|
3376
|
+
if (emit_push_const(s, text, true))
|
|
3377
|
+
return -1;
|
|
3378
|
+
jsx_child_end(s, ch, false);
|
|
3379
|
+
}
|
|
1594
3380
|
}
|
|
1595
|
-
if (
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
3381
|
+
if (q >= s.buf_end) {
|
|
3382
|
+
return js_parse_error_pos(s, start, tag ? `JSX element '${tag.text}' has no corresponding closing tag`
|
|
3383
|
+
: 'JSX fragment has no corresponding closing tag');
|
|
3384
|
+
}
|
|
3385
|
+
if (buf.charCodeAt(q) === 123) {
|
|
3386
|
+
/* {expression}, {...spread}, or only comments */
|
|
3387
|
+
const r = jsx_skip_space(s, q + 1);
|
|
3388
|
+
if (r < 0)
|
|
3389
|
+
return -1;
|
|
3390
|
+
if (buf.charCodeAt(r) === 125) {
|
|
3391
|
+
p = r + 1;
|
|
3392
|
+
continue;
|
|
3393
|
+
}
|
|
3394
|
+
s.buf_ptr = q + 1;
|
|
3395
|
+
if (next_token(s))
|
|
3396
|
+
return -1;
|
|
3397
|
+
const spread = tv(s) === -91 /* TOK.ELLIPSIS */;
|
|
3398
|
+
if (spread && next_token(s))
|
|
3399
|
+
return -1;
|
|
3400
|
+
jsx_child_start(s, ch, spread);
|
|
3401
|
+
if (js_parse_expr(s))
|
|
3402
|
+
return -1;
|
|
3403
|
+
if (tv(s) !== 125)
|
|
3404
|
+
return js_parse_error(s, "expecting '}'");
|
|
3405
|
+
jsx_child_end(s, ch, spread);
|
|
3406
|
+
}
|
|
3407
|
+
else if (buf.charCodeAt(q + 1) === 47) {
|
|
3408
|
+
/* the closing tag */
|
|
3409
|
+
s.buf_ptr = q + 2;
|
|
3410
|
+
if (jsx_tag_token(s))
|
|
3411
|
+
return -1;
|
|
3412
|
+
const close = new JSXTag();
|
|
3413
|
+
close.ptr = s.token.ptr;
|
|
3414
|
+
if (tv(s) !== 62 && jsx_parse_tag_name(s, close, false))
|
|
3415
|
+
return -1;
|
|
3416
|
+
if (tv(s) !== 62)
|
|
3417
|
+
return js_parse_error(s, "expecting '>'");
|
|
3418
|
+
const name = tag ? tag.text : '';
|
|
3419
|
+
if (close.text !== name) {
|
|
3420
|
+
const found = close.text ? `</${close.text}>` : '</>';
|
|
3421
|
+
return js_parse_error_pos(s, close.ptr, tag ? `expected corresponding JSX closing tag for <${name}>, found ${found}`
|
|
3422
|
+
: `expected corresponding closing tag for JSX fragment, found ${found}`);
|
|
3423
|
+
}
|
|
3424
|
+
return 0;
|
|
3425
|
+
}
|
|
3426
|
+
else {
|
|
3427
|
+
s.token.ptr = q;
|
|
3428
|
+
s.token.val = 60;
|
|
3429
|
+
jsx_child_start(s, ch, false);
|
|
3430
|
+
if (jsx_parse_element(s))
|
|
3431
|
+
return -1;
|
|
3432
|
+
jsx_child_end(s, ch, false);
|
|
1602
3433
|
}
|
|
3434
|
+
p = s.buf_ptr;
|
|
1603
3435
|
}
|
|
1604
|
-
if (pbits)
|
|
1605
|
-
pbits.bits = bits;
|
|
1606
|
-
/* restore the parser state */
|
|
1607
|
-
Object.assign(s.token, pos.token);
|
|
1608
|
-
s.buf_ptr = saved_ptr;
|
|
1609
|
-
s.got_lf = saved_got_lf;
|
|
1610
|
-
return tok;
|
|
1611
3436
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
3437
|
+
/* the current token is the '<' of a JSX element or fragment: emit its value, as TypeScript
|
|
3438
|
+
compiles it. On return s.buf_ptr is just after the element's last '>' (the current token is
|
|
3439
|
+
not meaningful). In the jsx/jsxs form the key is evaluated after the other props and the
|
|
3440
|
+
children, as the third argument: its value is skipped and parsed again at the end */
|
|
3441
|
+
function jsx_parse_element(s) {
|
|
3442
|
+
const rt = jsx_runtime(s);
|
|
3443
|
+
if (rt === null)
|
|
3444
|
+
return -1;
|
|
3445
|
+
const fd = s.cur_func;
|
|
3446
|
+
const start = s.token.ptr;
|
|
3447
|
+
s.buf_ptr = start + 1;
|
|
3448
|
+
if (jsx_tag_token(s))
|
|
3449
|
+
return -1;
|
|
3450
|
+
let tag = null;
|
|
3451
|
+
if (tv(s) !== 62) {
|
|
3452
|
+
tag = new JSXTag();
|
|
3453
|
+
if (jsx_parse_tag_name(s, tag, true))
|
|
3454
|
+
return -1;
|
|
3455
|
+
}
|
|
3456
|
+
const form = !rt.automatic ? 2 /* JSXForm.CLASSIC */ : tag && jsx_key_after_spread(s) ? 1 /* JSXForm.CREATE_ELEMENT */ : 0 /* JSXForm.JSX */;
|
|
3457
|
+
/* the function: `*jsx*` is patched to `*jsxs*` once the children are known */
|
|
3458
|
+
let method = false;
|
|
3459
|
+
const callee_pos = fd.byte_code.size;
|
|
3460
|
+
if (form === 2 /* JSXForm.CLASSIC */)
|
|
3461
|
+
method = jsx_emit_path(s, rt.factory, true);
|
|
3462
|
+
else
|
|
3463
|
+
emit_ident_ref(s, form === 0 /* JSXForm.JSX */ ? JS_ATOM_NULL : jsx_import(s, 'createElement'));
|
|
3464
|
+
/* the type */
|
|
3465
|
+
if (tag !== null) {
|
|
3466
|
+
if (jsx_emit_tag(s, tag))
|
|
3467
|
+
return -1;
|
|
3468
|
+
}
|
|
3469
|
+
else if (form === 2 /* JSXForm.CLASSIC */) {
|
|
3470
|
+
jsx_emit_path(s, rt.fragment, false);
|
|
3471
|
+
}
|
|
3472
|
+
else {
|
|
3473
|
+
emit_ident_ref(s, jsx_import(s, 'Fragment'));
|
|
3474
|
+
}
|
|
3475
|
+
/* the props: null without attributes, except in the jsx form */
|
|
3476
|
+
let key_ptr = -2; /* jsx form: -1 for `key` without a value, else the position of its value */
|
|
3477
|
+
if (form !== 0 /* JSXForm.JSX */ && (tv(s) === 47 || tv(s) === 62)) {
|
|
3478
|
+
emit_op(s, 7 /* OP.null */);
|
|
3479
|
+
}
|
|
3480
|
+
else {
|
|
3481
|
+
emit_op(s, 11 /* OP.object */);
|
|
3482
|
+
while (tv(s) !== 47 && tv(s) !== 62) {
|
|
3483
|
+
if (tv(s) === 123) {
|
|
3484
|
+
/* {...props} */
|
|
3485
|
+
if (next_token(s))
|
|
3486
|
+
return -1;
|
|
3487
|
+
if (tv(s) !== -91 /* TOK.ELLIPSIS */)
|
|
3488
|
+
return js_parse_error(s, "expecting '...'");
|
|
3489
|
+
if (next_token(s) || js_parse_expr(s))
|
|
3490
|
+
return -1;
|
|
3491
|
+
if (tv(s) !== 125)
|
|
3492
|
+
return js_parse_error(s, "expecting '}'");
|
|
3493
|
+
emit_op(s, 7 /* OP.null */); /* dummy excludeList */
|
|
3494
|
+
emit_op(s, 84 /* OP.copy_data_properties */);
|
|
3495
|
+
emit_u8(s, 2 | (1 << 2) | (0 << 5));
|
|
3496
|
+
emit_op(s, 14 /* OP.drop */); /* pop excludeList */
|
|
3497
|
+
emit_op(s, 14 /* OP.drop */); /* pop src object */
|
|
3498
|
+
}
|
|
3499
|
+
else if (tv(s) === -125 /* TOK.IDENT */) {
|
|
3500
|
+
let name = s.token.atom;
|
|
3501
|
+
const is_key = s.token.str === 'key';
|
|
3502
|
+
if (jsx_tag_token(s))
|
|
3503
|
+
return -1;
|
|
3504
|
+
if (tv(s) === 58) {
|
|
3505
|
+
/* namespaced attribute: a:b */
|
|
3506
|
+
const ns = JS_AtomGetStr(s.ctx, name);
|
|
3507
|
+
if (jsx_tag_token(s))
|
|
3508
|
+
return -1;
|
|
3509
|
+
if (tv(s) !== -125 /* TOK.IDENT */)
|
|
3510
|
+
return js_parse_error(s, 'identifier expected');
|
|
3511
|
+
name = JS_NewAtom(s.ctx, ns + ':' + s.token.str);
|
|
3512
|
+
if (jsx_tag_token(s))
|
|
3513
|
+
return -1;
|
|
3514
|
+
}
|
|
3515
|
+
else if (is_key && form === 0 /* JSXForm.JSX */ && key_ptr === -2) {
|
|
3516
|
+
/* TypeScript passes the first `key` as the third argument */
|
|
3517
|
+
if (tv(s) !== 61) {
|
|
3518
|
+
key_ptr = -1;
|
|
3519
|
+
continue;
|
|
3520
|
+
}
|
|
3521
|
+
if (jsx_tag_token(s))
|
|
3522
|
+
return -1;
|
|
3523
|
+
key_ptr = s.token.ptr;
|
|
3524
|
+
if (!jsx_skip_attr_value(s))
|
|
3525
|
+
return ts_error(s, "'{' or JSX element expected");
|
|
3526
|
+
if (jsx_tag_token(s))
|
|
3527
|
+
return -1;
|
|
3528
|
+
continue;
|
|
3529
|
+
}
|
|
3530
|
+
if (tv(s) === 61) {
|
|
3531
|
+
if (jsx_tag_token(s) || jsx_parse_attr_value(s))
|
|
3532
|
+
return -1;
|
|
3533
|
+
set_object_name(s, name);
|
|
3534
|
+
}
|
|
3535
|
+
else {
|
|
3536
|
+
/* boolean shorthand */
|
|
3537
|
+
emit_op(s, 10 /* OP.push_true */);
|
|
3538
|
+
emit_op(s, 77 /* OP.define_field */);
|
|
3539
|
+
emit_atom(s, name);
|
|
3540
|
+
continue;
|
|
3541
|
+
}
|
|
3542
|
+
emit_op(s, 77 /* OP.define_field */);
|
|
3543
|
+
emit_atom(s, name);
|
|
3544
|
+
}
|
|
3545
|
+
else {
|
|
3546
|
+
return js_parse_error(s, tv(s) === -86 /* TOK.EOF */ ? 'unexpected end of input in a JSX tag' : 'unexpected token in a JSX tag');
|
|
3547
|
+
}
|
|
3548
|
+
if (jsx_tag_token(s))
|
|
3549
|
+
return -1;
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
/* the children */
|
|
3553
|
+
const ch = { n: 0, spread: false, array: false, base: form === 0 /* JSXForm.JSX */ ? 0 : 2 };
|
|
3554
|
+
if (tv(s) === 47) {
|
|
3555
|
+
if (jsx_tag_token(s))
|
|
3556
|
+
return -1;
|
|
3557
|
+
if (tv(s) !== 62)
|
|
3558
|
+
return js_parse_error(s, "expecting '>'");
|
|
3559
|
+
}
|
|
3560
|
+
else if (jsx_parse_children(s, ch, tag, start)) {
|
|
3561
|
+
return -1;
|
|
3562
|
+
}
|
|
3563
|
+
/* the call */
|
|
3564
|
+
if (form === 0 /* JSXForm.JSX */) {
|
|
3565
|
+
const children = JS_NewAtom(s.ctx, 'children');
|
|
3566
|
+
if (ch.array) {
|
|
3567
|
+
emit_op(s, 14 /* OP.drop */); /* the index */
|
|
3568
|
+
}
|
|
3569
|
+
else if (ch.n > 1) {
|
|
3570
|
+
emit_op(s, 38 /* OP.array_from */);
|
|
3571
|
+
emit_u16(s, ch.n);
|
|
3572
|
+
}
|
|
3573
|
+
else if (ch.n === 1) {
|
|
3574
|
+
set_object_name(s, children);
|
|
3575
|
+
}
|
|
3576
|
+
if (ch.n > 0) {
|
|
3577
|
+
emit_op(s, 77 /* OP.define_field */);
|
|
3578
|
+
emit_atom(s, children);
|
|
3579
|
+
}
|
|
3580
|
+
put_u32(fd.byte_code.buf, callee_pos + 1, jsx_import(s, ch.n > 1 || ch.spread ? 'jsxs' : 'jsx'));
|
|
3581
|
+
let argc = 2;
|
|
3582
|
+
if (key_ptr !== -2) {
|
|
3583
|
+
if (key_ptr === -1) {
|
|
3584
|
+
emit_op(s, 10 /* OP.push_true */);
|
|
3585
|
+
}
|
|
3586
|
+
else {
|
|
3587
|
+
const end = s.buf_ptr;
|
|
3588
|
+
s.buf_ptr = key_ptr;
|
|
3589
|
+
if (jsx_tag_token(s) || jsx_parse_attr_value(s))
|
|
3590
|
+
return -1;
|
|
3591
|
+
s.buf_ptr = end;
|
|
3592
|
+
}
|
|
3593
|
+
argc = 3;
|
|
3594
|
+
}
|
|
3595
|
+
emit_source_pos(s, start);
|
|
3596
|
+
emit_op(s, 34 /* OP.call */);
|
|
3597
|
+
emit_u16(s, argc);
|
|
3598
|
+
}
|
|
3599
|
+
else if (ch.array) {
|
|
3600
|
+
emit_op(s, 14 /* OP.drop */); /* the index */
|
|
3601
|
+
emit_source_pos(s, start);
|
|
3602
|
+
if (method) {
|
|
3603
|
+
emit_op(s, 24 /* OP.perm3 */); /* obj func array -> func obj array */
|
|
3604
|
+
}
|
|
3605
|
+
else {
|
|
3606
|
+
emit_op(s, 6 /* OP.undefined */); /* func array -> func undefined array */
|
|
3607
|
+
emit_op(s, 27 /* OP.swap */);
|
|
3608
|
+
}
|
|
3609
|
+
emit_op(s, 39 /* OP.apply */);
|
|
3610
|
+
emit_u16(s, 0);
|
|
3611
|
+
}
|
|
3612
|
+
else {
|
|
3613
|
+
emit_source_pos(s, start);
|
|
3614
|
+
emit_op(s, method ? 36 /* OP.call_method */ : 34 /* OP.call */);
|
|
3615
|
+
emit_u16(s, 2 + ch.n);
|
|
3616
|
+
}
|
|
3617
|
+
return 0;
|
|
3618
|
+
}
|
|
1615
3619
|
/* ---------------------------------------------------------------------
|
|
1616
3620
|
Bytecode emission helpers
|
|
1617
3621
|
--------------------------------------------------------------------- */
|
|
@@ -2414,7 +4418,7 @@ function js_parse_property_name(s, out, allow_method, allow_var, allow_private)
|
|
|
2414
4418
|
if (next_token(s))
|
|
2415
4419
|
return -1;
|
|
2416
4420
|
if (tv(s) === 58 || tv(s) === 44 || tv(s) === 125 || tv(s) === 40 || tv(s) === 61 ||
|
|
2417
|
-
(tv(s) === 59 && allow_private)) {
|
|
4421
|
+
(tv(s) === 59 && allow_private) || (s.ts && (tv(s) === 60 || tv(s) === 63 || tv(s) === 33))) {
|
|
2418
4422
|
is_non_reserved_ident = true;
|
|
2419
4423
|
ident_found = true;
|
|
2420
4424
|
}
|
|
@@ -2431,7 +4435,8 @@ function js_parse_property_name(s, out, allow_method, allow_var, allow_private)
|
|
|
2431
4435
|
name = s.token.atom;
|
|
2432
4436
|
if (next_token(s))
|
|
2433
4437
|
return -1;
|
|
2434
|
-
if (tv(s) === 58 || tv(s) === 44 || tv(s) === 125 || tv(s) === 40 || tv(s) === 61
|
|
4438
|
+
if (tv(s) === 58 || tv(s) === 44 || tv(s) === 125 || tv(s) === 40 || tv(s) === 61 ||
|
|
4439
|
+
(s.ts && (tv(s) === 60 || tv(s) === 63 || tv(s) === 33))) {
|
|
2435
4440
|
is_non_reserved_ident = true;
|
|
2436
4441
|
ident_found = true;
|
|
2437
4442
|
}
|
|
@@ -2486,6 +4491,11 @@ function js_parse_property_name(s, out, allow_method, allow_var, allow_private)
|
|
|
2486
4491
|
return -1;
|
|
2487
4492
|
}
|
|
2488
4493
|
}
|
|
4494
|
+
if (s.ts && allow_method && tv(s) === 60) {
|
|
4495
|
+
/* method type parameters: m<T>(x: T) {} */
|
|
4496
|
+
if (!ts_skip_type_params(s))
|
|
4497
|
+
return ts_error(s, 'invalid type parameters');
|
|
4498
|
+
}
|
|
2489
4499
|
if (ident_found) {
|
|
2490
4500
|
if (is_non_reserved_ident && prop_type === PROP_TYPE_IDENT && allow_var) {
|
|
2491
4501
|
if (!(tv(s) === 58 || (tv(s) === 40 && allow_method)))
|
|
@@ -3107,6 +5117,8 @@ function js_parse_destructuring_element(s, tok, is_arg, hasval, has_ellipsis, al
|
|
|
3107
5117
|
if (tok) {
|
|
3108
5118
|
if (js_define_var(s, var_name, tok))
|
|
3109
5119
|
return -1;
|
|
5120
|
+
if (export_flag && add_local_export(s, var_name))
|
|
5121
|
+
return -1;
|
|
3110
5122
|
scope = fd.scope_level; /* XXX: check */
|
|
3111
5123
|
}
|
|
3112
5124
|
if (tv(s) === 61 /* = */) { /* handle optional default value */
|
|
@@ -3189,6 +5201,8 @@ function js_parse_destructuring_element(s, tok, is_arg, hasval, has_ellipsis, al
|
|
|
3189
5201
|
return -1;
|
|
3190
5202
|
if (js_define_var(s, var_name, tok))
|
|
3191
5203
|
return -1;
|
|
5204
|
+
if (export_flag && add_local_export(s, var_name))
|
|
5205
|
+
return -1;
|
|
3192
5206
|
if (need_var_reference(s, tok)) {
|
|
3193
5207
|
/* Must make a reference for proper `with` semantics */
|
|
3194
5208
|
emit_op(s, 186 /* OP.scope_get_var */);
|
|
@@ -3254,6 +5268,13 @@ function js_parse_destructuring_element(s, tok, is_arg, hasval, has_ellipsis, al
|
|
|
3254
5268
|
else {
|
|
3255
5269
|
return js_parse_error(s, 'invalid assignment syntax');
|
|
3256
5270
|
}
|
|
5271
|
+
if (s.ts && (tv(s) === 63 || tv(s) === 58)) {
|
|
5272
|
+
/* {a, b}?: T */
|
|
5273
|
+
if (tv(s) === 63 && next_token(s))
|
|
5274
|
+
return -1;
|
|
5275
|
+
if (tv(s) === 58 && ts_parse_annotation(s))
|
|
5276
|
+
return -1;
|
|
5277
|
+
}
|
|
3257
5278
|
if (tv(s) === 61 && allow_initializer) {
|
|
3258
5279
|
label_done = emit_goto(s, 109 /* OP.goto */, -1);
|
|
3259
5280
|
if (next_token(s))
|
|
@@ -3502,6 +5523,21 @@ function js_parse_postfix_expr(s, parse_flags) {
|
|
|
3502
5523
|
return js_parse_error(s, "invalid use of 'import()'");
|
|
3503
5524
|
if (js_parse_assign_expr(s))
|
|
3504
5525
|
return -1;
|
|
5526
|
+
/* optional options argument, and trailing comma */
|
|
5527
|
+
let has_options = false;
|
|
5528
|
+
if (tv(s) === 44) {
|
|
5529
|
+
if (next_token(s))
|
|
5530
|
+
return -1;
|
|
5531
|
+
if (tv(s) !== 41) {
|
|
5532
|
+
if (js_parse_assign_expr(s))
|
|
5533
|
+
return -1;
|
|
5534
|
+
has_options = true;
|
|
5535
|
+
if (tv(s) === 44 && next_token(s))
|
|
5536
|
+
return -1;
|
|
5537
|
+
}
|
|
5538
|
+
}
|
|
5539
|
+
if (!has_options)
|
|
5540
|
+
emit_op(s, 6 /* OP.undefined */);
|
|
3505
5541
|
if (js_parse_expect(s, 41))
|
|
3506
5542
|
return -1;
|
|
3507
5543
|
emit_op(s, 54 /* OP.import */);
|
|
@@ -3521,6 +5557,9 @@ function js_parse_postfix_expr(s, parse_flags) {
|
|
|
3521
5557
|
if (next_token(s))
|
|
3522
5558
|
return -1;
|
|
3523
5559
|
has_optional_chain = true;
|
|
5560
|
+
/* a?.<T>(x) */
|
|
5561
|
+
if (s.ts && (tv(s) === 60 || tv(s) === -106 /* TOK.SHL */) && !ts_try_expr_type_args(s) && JS_HasException(s.ctx))
|
|
5562
|
+
return -1;
|
|
3524
5563
|
if (tv(s) === 40 && accept_lparen)
|
|
3525
5564
|
action = 'call';
|
|
3526
5565
|
else if (tv(s) === 91)
|
|
@@ -3549,6 +5588,19 @@ function js_parse_postfix_expr(s, parse_flags) {
|
|
|
3549
5588
|
action = 'array';
|
|
3550
5589
|
}
|
|
3551
5590
|
else {
|
|
5591
|
+
if (s.ts) {
|
|
5592
|
+
/* non-null assertion x! (not after a line break) */
|
|
5593
|
+
if (tv(s) === 33 && !s.got_lf) {
|
|
5594
|
+
if (next_token(s))
|
|
5595
|
+
return -1;
|
|
5596
|
+
continue;
|
|
5597
|
+
}
|
|
5598
|
+
/* type arguments: f<T>(x), new C<T>(), f<T>`t`, f<T> */
|
|
5599
|
+
if ((tv(s) === 60 || tv(s) === -106 /* TOK.SHL */) && ts_try_expr_type_args(s))
|
|
5600
|
+
continue;
|
|
5601
|
+
if (JS_HasException(s.ctx))
|
|
5602
|
+
return -1;
|
|
5603
|
+
}
|
|
3552
5604
|
break;
|
|
3553
5605
|
}
|
|
3554
5606
|
if (action === 'call') {
|
|
@@ -4069,6 +6121,26 @@ function js_parse_unary(s, parse_flags) {
|
|
|
4069
6121
|
parse_flags = 0;
|
|
4070
6122
|
break;
|
|
4071
6123
|
default:
|
|
6124
|
+
if (s.jsx && tv(s) === 60) {
|
|
6125
|
+
/* a JSX element (in TypeScript, `<T>expr` is JSX too) */
|
|
6126
|
+
if (jsx_parse_element(s) || next_token(s))
|
|
6127
|
+
return -1;
|
|
6128
|
+
/* TypeScript reads a '<' after an element as a second element: <a/><b/> */
|
|
6129
|
+
if (tv(s) === 60)
|
|
6130
|
+
return js_parse_error(s, 'JSX expressions must have one parent element');
|
|
6131
|
+
break;
|
|
6132
|
+
}
|
|
6133
|
+
if (s.ts && tv(s) === 60) {
|
|
6134
|
+
/* type assertion <T>expr */
|
|
6135
|
+
if (next_token(s))
|
|
6136
|
+
return -1;
|
|
6137
|
+
if (!ts_skip_type(s) || !ts_eat_gt(s))
|
|
6138
|
+
return ts_error(s, 'invalid type assertion');
|
|
6139
|
+
if (js_parse_unary(s, PF_POW_FORBIDDEN))
|
|
6140
|
+
return -1;
|
|
6141
|
+
parse_flags = 0;
|
|
6142
|
+
break;
|
|
6143
|
+
}
|
|
4072
6144
|
if (js_parse_postfix_expr(s, PF_POSTFIX_CALL))
|
|
4073
6145
|
return -1;
|
|
4074
6146
|
if (!s.got_lf && (tv(s) === -108 /* TOK.DEC */ || tv(s) === -107 /* TOK.INC */)) {
|
|
@@ -4193,7 +6265,14 @@ function js_parse_expr_binary(s, level, parse_flags) {
|
|
|
4193
6265
|
else
|
|
4194
6266
|
return 0;
|
|
4195
6267
|
break;
|
|
4196
|
-
default:
|
|
6268
|
+
default: {
|
|
6269
|
+
if (!s.ts)
|
|
6270
|
+
return 0;
|
|
6271
|
+
const r = ts_parse_as_expr(s);
|
|
6272
|
+
if (r <= 0)
|
|
6273
|
+
return r;
|
|
6274
|
+
continue;
|
|
6275
|
+
}
|
|
4197
6276
|
}
|
|
4198
6277
|
break;
|
|
4199
6278
|
case 5:
|
|
@@ -4307,8 +6386,19 @@ function js_parse_cond_expr(s, parse_flags) {
|
|
|
4307
6386
|
if (next_token(s))
|
|
4308
6387
|
return -1;
|
|
4309
6388
|
const label1 = emit_goto(s, 107 /* OP.if_false */, -1);
|
|
4310
|
-
if (
|
|
6389
|
+
if (s.ts) {
|
|
6390
|
+
/* TypeScript: an arrow function with a return type in the true branch must be
|
|
6391
|
+
followed by the ':' of the conditional */
|
|
6392
|
+
const saved = s.ts_cond_true;
|
|
6393
|
+
s.ts_cond_true = true;
|
|
6394
|
+
const r = js_parse_assign_expr2(s, PF_IN_ACCEPTED);
|
|
6395
|
+
s.ts_cond_true = saved;
|
|
6396
|
+
if (r)
|
|
6397
|
+
return -1;
|
|
6398
|
+
}
|
|
6399
|
+
else if (js_parse_assign_expr(s)) {
|
|
4311
6400
|
return -1;
|
|
6401
|
+
}
|
|
4312
6402
|
if (js_parse_expect(s, 58))
|
|
4313
6403
|
return -1;
|
|
4314
6404
|
const label2 = emit_goto(s, 109 /* OP.goto */, -1);
|
|
@@ -4441,7 +6531,10 @@ function js_parse_assign_expr2(s, parse_flags) {
|
|
|
4441
6531
|
}
|
|
4442
6532
|
return 0;
|
|
4443
6533
|
}
|
|
4444
|
-
else if (tv(s) === 40 &&
|
|
6534
|
+
else if (tv(s) === 40 && js_arrow_ahead(s)) {
|
|
6535
|
+
return js_parse_function_decl(s, 3 /* JSParseFunctionEnum.ARROW */, 0 /* JSFunctionKind.NORMAL */, JS_ATOM_NULL, s.token.ptr);
|
|
6536
|
+
}
|
|
6537
|
+
else if (s.ts && tv(s) === 60 && ts_generic_arrow_ahead(s)) {
|
|
4445
6538
|
return js_parse_function_decl(s, 3 /* JSParseFunctionEnum.ARROW */, 0 /* JSFunctionKind.NORMAL */, JS_ATOM_NULL, s.token.ptr);
|
|
4446
6539
|
}
|
|
4447
6540
|
else if (token_is_pseudo_keyword(s, JS_ATOM_async)) {
|
|
@@ -4452,7 +6545,7 @@ function js_parse_assign_expr2(s, parse_flags) {
|
|
|
4452
6545
|
const pos = js_parse_get_pos(s);
|
|
4453
6546
|
if (next_token(s))
|
|
4454
6547
|
return -1;
|
|
4455
|
-
if ((tv(s) === 40 &&
|
|
6548
|
+
if ((tv(s) === 40 && js_arrow_ahead(s)) || (s.ts && tv(s) === 60 && ts_generic_arrow_ahead(s)) ||
|
|
4456
6549
|
(tv(s) === -125 /* TOK.IDENT */ && !s.token.is_reserved && peek_token(s, true) === -92 /* TOK.ARROW */)) {
|
|
4457
6550
|
return js_parse_function_decl(s, 3 /* JSParseFunctionEnum.ARROW */, 2 /* JSFunctionKind.ASYNC */, JS_ATOM_NULL, source_ptr);
|
|
4458
6551
|
}
|
|
@@ -4705,8 +6798,17 @@ function js_parse_var(s, parse_flags, tok, export_flag) {
|
|
|
4705
6798
|
return js_parse_error(s, "'let' is not a valid lexical identifier");
|
|
4706
6799
|
if (next_token(s))
|
|
4707
6800
|
return -1;
|
|
6801
|
+
if (s.ts && (tv(s) === 33 || tv(s) === 58)) {
|
|
6802
|
+
/* let x!: T */
|
|
6803
|
+
if (tv(s) === 33 && next_token(s))
|
|
6804
|
+
return -1;
|
|
6805
|
+
if (tv(s) === 58 && ts_parse_annotation(s))
|
|
6806
|
+
return -1;
|
|
6807
|
+
}
|
|
4708
6808
|
if (js_define_var(s, name, tok))
|
|
4709
6809
|
return -1;
|
|
6810
|
+
if (export_flag && add_local_export(s, name))
|
|
6811
|
+
return -1;
|
|
4710
6812
|
if (tv(s) === 61 /* = */) {
|
|
4711
6813
|
if (next_token(s))
|
|
4712
6814
|
return -1;
|
|
@@ -4746,7 +6848,9 @@ function js_parse_var(s, parse_flags, tok, export_flag) {
|
|
|
4746
6848
|
}
|
|
4747
6849
|
else {
|
|
4748
6850
|
const bits = { bits: 0 };
|
|
4749
|
-
|
|
6851
|
+
let next_tok;
|
|
6852
|
+
if ((tv(s) === 91 || tv(s) === 123) &&
|
|
6853
|
+
((next_tok = js_parse_skip_parens_token(s, bits, false)) === 61 || (next_tok === 58 && s.ts))) {
|
|
4750
6854
|
emit_op(s, 6 /* OP.undefined */);
|
|
4751
6855
|
if (js_parse_destructuring_element(s, tok, 0, true, bits.bits & SKIP_HAS_ELLIPSIS, true, export_flag) < 0)
|
|
4752
6856
|
return -1;
|
|
@@ -5040,6 +7144,14 @@ function js_parse_statement_or_decl(s, decl_mask) {
|
|
|
5040
7144
|
return 0;
|
|
5041
7145
|
}
|
|
5042
7146
|
}
|
|
7147
|
+
if (s.ts) {
|
|
7148
|
+
/* TypeScript-only statements are skipped; `abstract class` continues as a class */
|
|
7149
|
+
const r = ts_parse_statement(s);
|
|
7150
|
+
if (r < 0)
|
|
7151
|
+
return -1;
|
|
7152
|
+
if (r > 0)
|
|
7153
|
+
return 0;
|
|
7154
|
+
}
|
|
5043
7155
|
let tok = tv(s);
|
|
5044
7156
|
switch (tok) {
|
|
5045
7157
|
case 123: /* { */
|
|
@@ -5440,7 +7552,11 @@ function js_parse_statement_or_decl(s, decl_mask) {
|
|
|
5440
7552
|
}
|
|
5441
7553
|
else {
|
|
5442
7554
|
const name = s.token.atom;
|
|
5443
|
-
if (next_token(s)
|
|
7555
|
+
if (next_token(s))
|
|
7556
|
+
return -1;
|
|
7557
|
+
if (s.ts && tv(s) === 58 && ts_parse_annotation(s))
|
|
7558
|
+
return -1;
|
|
7559
|
+
if (js_define_var(s, name, -61 /* TOK.CATCH */) < 0)
|
|
5444
7560
|
return -1;
|
|
5445
7561
|
/* store the exception value in the catch variable */
|
|
5446
7562
|
emit_op(s, 187 /* OP.scope_put_var */);
|
|
@@ -5624,10 +7740,22 @@ function js_parse_expr_statement(s) {
|
|
|
5624
7740
|
return 0;
|
|
5625
7741
|
}
|
|
5626
7742
|
function js_parse_assign_expr(s) {
|
|
7743
|
+
if (s.ts_cond_true) {
|
|
7744
|
+
s.ts_cond_true = false;
|
|
7745
|
+
const r = js_parse_assign_expr2(s, PF_IN_ACCEPTED);
|
|
7746
|
+
s.ts_cond_true = true;
|
|
7747
|
+
return r;
|
|
7748
|
+
}
|
|
5627
7749
|
return js_parse_assign_expr2(s, PF_IN_ACCEPTED);
|
|
5628
7750
|
}
|
|
5629
7751
|
/* allowed parse_flags: PF_IN_ACCEPTED */
|
|
5630
7752
|
function js_parse_expr2(s, parse_flags) {
|
|
7753
|
+
if (s.ts_cond_true) {
|
|
7754
|
+
s.ts_cond_true = false;
|
|
7755
|
+
const r = js_parse_expr2(s, parse_flags);
|
|
7756
|
+
s.ts_cond_true = true;
|
|
7757
|
+
return r;
|
|
7758
|
+
}
|
|
5631
7759
|
let comma = false;
|
|
5632
7760
|
for (;;) {
|
|
5633
7761
|
if (js_parse_assign_expr2(s, parse_flags))
|
|
@@ -5799,6 +7927,10 @@ function js_parse_class(s, is_class_expr, export_flag) {
|
|
|
5799
7927
|
else
|
|
5800
7928
|
class_var_name = class_name;
|
|
5801
7929
|
}
|
|
7930
|
+
if (s.ts && tv(s) === 60 && !ts_skip_type_params(s)) {
|
|
7931
|
+
ts_error(s, 'invalid type parameters');
|
|
7932
|
+
return fail();
|
|
7933
|
+
}
|
|
5802
7934
|
push_scope(s);
|
|
5803
7935
|
if (tv(s) === -52 /* TOK.EXTENDS */) {
|
|
5804
7936
|
class_flags = JS_DEFINE_CLASS_HAS_HERITAGE;
|
|
@@ -5806,10 +7938,24 @@ function js_parse_class(s, is_class_expr, export_flag) {
|
|
|
5806
7938
|
return fail();
|
|
5807
7939
|
if (js_parse_left_hand_side_expr(s))
|
|
5808
7940
|
return fail();
|
|
7941
|
+
/* class C extends B<T> */
|
|
7942
|
+
if (s.ts && (tv(s) === 60 || tv(s) === -106 /* TOK.SHL */) && !ts_skip_type_args(s)) {
|
|
7943
|
+
ts_error(s, 'invalid type arguments');
|
|
7944
|
+
return fail();
|
|
7945
|
+
}
|
|
5809
7946
|
}
|
|
5810
7947
|
else {
|
|
5811
7948
|
emit_op(s, 6 /* OP.undefined */);
|
|
5812
7949
|
}
|
|
7950
|
+
if (s.ts && ts_word(s, JS_ATOM_implements)) {
|
|
7951
|
+
/* implements I, J<T> */
|
|
7952
|
+
do {
|
|
7953
|
+
if (!ts_next(s) || !ts_skip_type(s)) {
|
|
7954
|
+
ts_error(s, 'type expected');
|
|
7955
|
+
return fail();
|
|
7956
|
+
}
|
|
7957
|
+
} while (tv(s) === 44);
|
|
7958
|
+
}
|
|
5813
7959
|
/* add a 'const' definition for the class name */
|
|
5814
7960
|
if (class_name !== JS_ATOM_NULL) {
|
|
5815
7961
|
if (define_var(s, fd, class_name, 2 /* JSVarDefEnum.CONST */) < 0)
|
|
@@ -5841,17 +7987,21 @@ function js_parse_class(s, is_class_expr, export_flag) {
|
|
|
5841
7987
|
return fail();
|
|
5842
7988
|
continue;
|
|
5843
7989
|
}
|
|
7990
|
+
/* TypeScript modifiers; declare and abstract members are erased */
|
|
7991
|
+
let ts_erase = 0;
|
|
7992
|
+
if (s.ts && (ts_erase = ts_parse_class_modifiers(s)) < 0)
|
|
7993
|
+
return fail();
|
|
5844
7994
|
let is_static = false;
|
|
5845
7995
|
if (tv(s) === -42 /* TOK.STATIC */) {
|
|
5846
7996
|
const next = peek_token(s, true);
|
|
5847
|
-
if (!(next === 59 || next === 125 || next === 40 || next === 61))
|
|
7997
|
+
if (!(next === 59 || next === 125 || next === 40 || next === 61 || (s.ts && (next === 58 || next === 63 || next === 33 || next === 60))))
|
|
5848
7998
|
is_static = true;
|
|
5849
7999
|
}
|
|
5850
8000
|
let prop_type = -1;
|
|
5851
8001
|
if (is_static) {
|
|
5852
8002
|
if (next_token(s))
|
|
5853
8003
|
return fail();
|
|
5854
|
-
if (tv(s) === 123) {
|
|
8004
|
+
if (tv(s) === 123 && !ts_erase) {
|
|
5855
8005
|
const cf = class_fields[1];
|
|
5856
8006
|
if (!cf.fields_init_fd) {
|
|
5857
8007
|
if (emit_class_init_start(s, cf))
|
|
@@ -5880,6 +8030,13 @@ function js_parse_class(s, is_class_expr, export_flag) {
|
|
|
5880
8030
|
s.cur_func = s.cur_func.parent;
|
|
5881
8031
|
continue;
|
|
5882
8032
|
}
|
|
8033
|
+
if (s.ts) {
|
|
8034
|
+
const r = ts_parse_class_modifiers(s);
|
|
8035
|
+
if (r < 0)
|
|
8036
|
+
return fail();
|
|
8037
|
+
if (r > 0)
|
|
8038
|
+
ts_erase = 1;
|
|
8039
|
+
}
|
|
5883
8040
|
/* allow "static" field name */
|
|
5884
8041
|
if (tv(s) === 59 || tv(s) === 61) {
|
|
5885
8042
|
is_static = false;
|
|
@@ -5887,6 +8044,12 @@ function js_parse_class(s, is_class_expr, export_flag) {
|
|
|
5887
8044
|
prop_type = PROP_TYPE_IDENT;
|
|
5888
8045
|
}
|
|
5889
8046
|
}
|
|
8047
|
+
if (s.ts && prop_type < 0 && (ts_erase || ts_is_index_signature(s) || ts_class_member_is_signature(s))) {
|
|
8048
|
+
/* erased: declare field, abstract member, index signature, overload signature */
|
|
8049
|
+
if (ts_skip_class_member(s))
|
|
8050
|
+
return fail();
|
|
8051
|
+
continue;
|
|
8052
|
+
}
|
|
5890
8053
|
if (is_static)
|
|
5891
8054
|
emit_op(s, 27 /* OP.swap */);
|
|
5892
8055
|
const start_ptr = s.token.ptr;
|
|
@@ -5897,6 +8060,13 @@ function js_parse_class(s, is_class_expr, export_flag) {
|
|
|
5897
8060
|
return fail();
|
|
5898
8061
|
name = out.name;
|
|
5899
8062
|
}
|
|
8063
|
+
if (s.ts) {
|
|
8064
|
+
/* x?: T, x!: T, m?() {} */
|
|
8065
|
+
if ((tv(s) === 63 || tv(s) === 33) && next_token(s))
|
|
8066
|
+
return fail();
|
|
8067
|
+
if (tv(s) === 58 && (prop_type & ~PROP_TYPE_PRIVATE) === PROP_TYPE_IDENT && ts_parse_annotation(s))
|
|
8068
|
+
return fail();
|
|
8069
|
+
}
|
|
5900
8070
|
const is_private = prop_type & PROP_TYPE_PRIVATE;
|
|
5901
8071
|
prop_type &= ~PROP_TYPE_PRIVATE;
|
|
5902
8072
|
if ((name === JS_ATOM_constructor && !is_static && prop_type !== PROP_TYPE_IDENT) ||
|
|
@@ -6453,6 +8623,13 @@ function js_parse_function_decl2(s, func_type, func_kind, func_name, ptr, export
|
|
|
6453
8623
|
if (func_type === 8 /* JSParseFunctionEnum.CLASS_CONSTRUCTOR */) {
|
|
6454
8624
|
emit_class_field_init(s);
|
|
6455
8625
|
}
|
|
8626
|
+
if (s.ts && tv(s) === 60) {
|
|
8627
|
+
/* function f<T>(...), m<T>(...), <T>(...) => ... */
|
|
8628
|
+
if (!ts_skip_type_params(s)) {
|
|
8629
|
+
ts_error(s, 'invalid type parameters');
|
|
8630
|
+
return fail();
|
|
8631
|
+
}
|
|
8632
|
+
}
|
|
6456
8633
|
/* parse arguments */
|
|
6457
8634
|
fd.has_simple_parameter_list = true;
|
|
6458
8635
|
fd.has_parameter_expressions = false;
|
|
@@ -6487,6 +8664,22 @@ function js_parse_function_decl2(s, func_type, func_kind, func_name, ptr, export
|
|
|
6487
8664
|
}
|
|
6488
8665
|
while (tv(s) !== 41) {
|
|
6489
8666
|
let rest = false;
|
|
8667
|
+
if (s.ts) {
|
|
8668
|
+
if (tv(s) === -78 /* TOK.THIS */ && ts_peek(s).val === 58) {
|
|
8669
|
+
/* this parameter: f(this: T, ...) */
|
|
8670
|
+
if (next_token(s) || ts_parse_annotation(s))
|
|
8671
|
+
return fail();
|
|
8672
|
+
if (tv(s) === 41)
|
|
8673
|
+
break;
|
|
8674
|
+
if (js_parse_expect(s, 44))
|
|
8675
|
+
return fail();
|
|
8676
|
+
continue;
|
|
8677
|
+
}
|
|
8678
|
+
if (ts_is_param_modifier(s)) {
|
|
8679
|
+
ts_unsupported(s, 'parameter property', s.token.ptr);
|
|
8680
|
+
return fail();
|
|
8681
|
+
}
|
|
8682
|
+
}
|
|
6490
8683
|
if (tv(s) === -91 /* TOK.ELLIPSIS */) {
|
|
6491
8684
|
if (func_type === 5 /* JSParseFunctionEnum.SETTER */) {
|
|
6492
8685
|
js_parse_error(s, 'invalid number of arguments for getter or setter');
|
|
@@ -6539,6 +8732,13 @@ function js_parse_function_decl2(s, func_type, func_kind, func_name, ptr, export
|
|
|
6539
8732
|
return fail();
|
|
6540
8733
|
if (next_token(s))
|
|
6541
8734
|
return fail();
|
|
8735
|
+
if (s.ts && (tv(s) === 63 || tv(s) === 58)) {
|
|
8736
|
+
/* x?: T */
|
|
8737
|
+
if (tv(s) === 63 && next_token(s))
|
|
8738
|
+
return fail();
|
|
8739
|
+
if (tv(s) === 58 && ts_parse_annotation(s))
|
|
8740
|
+
return fail();
|
|
8741
|
+
}
|
|
6542
8742
|
if (rest) {
|
|
6543
8743
|
emit_op(s, 13 /* OP.rest */);
|
|
6544
8744
|
emit_u16(s, idx);
|
|
@@ -6639,6 +8839,13 @@ function js_parse_function_decl2(s, func_type, func_kind, func_name, ptr, export
|
|
|
6639
8839
|
}
|
|
6640
8840
|
if (next_token(s))
|
|
6641
8841
|
return fail();
|
|
8842
|
+
if (s.ts && tv(s) === 58) {
|
|
8843
|
+
/* return type */
|
|
8844
|
+
if (!ts_next(s) || !ts_skip_return_type(s)) {
|
|
8845
|
+
ts_error(s, 'type expected');
|
|
8846
|
+
return fail();
|
|
8847
|
+
}
|
|
8848
|
+
}
|
|
6642
8849
|
/* generator function: yield after the parameters are evaluated */
|
|
6643
8850
|
if (func_kind === 1 /* JSFunctionKind.GENERATOR */ || func_kind === 3 /* JSFunctionKind.ASYNC_GENERATOR */)
|
|
6644
8851
|
emit_op(s, 137 /* OP.initial_yield */);
|
|
@@ -6795,16 +9002,572 @@ function js_parse_function_decl2(s, func_type, func_kind, func_name, ptr, export
|
|
|
6795
9002
|
function js_parse_function_decl(s, func_type, func_kind, func_name, ptr) {
|
|
6796
9003
|
return js_parse_function_decl2(s, func_type, func_kind, func_name, ptr, 0 /* JSParseExportEnum.NONE */, null);
|
|
6797
9004
|
}
|
|
9005
|
+
/* ---------------------------------------------------------------------
|
|
9006
|
+
Modules: import and export declarations (quickjs.c js_parse_import,
|
|
9007
|
+
js_parse_export and their helpers)
|
|
9008
|
+
--------------------------------------------------------------------- */
|
|
9009
|
+
/* a canonical key for import attributes, so that equal requests share an entry */
|
|
9010
|
+
function attributes_key(attrs) {
|
|
9011
|
+
if (attrs === null)
|
|
9012
|
+
return '';
|
|
9013
|
+
const keys = Object.keys(attrs).sort();
|
|
9014
|
+
return JSON.stringify(keys.map(k => [k, attrs[k]]));
|
|
9015
|
+
}
|
|
9016
|
+
function add_req_module_entry(m, module_name, attributes) {
|
|
9017
|
+
/* no need to add the module request if it is already present */
|
|
9018
|
+
const key = attributes_key(attributes);
|
|
9019
|
+
for (let i = 0; i < m.req_module_entries.length; i++) {
|
|
9020
|
+
const rme = m.req_module_entries[i];
|
|
9021
|
+
if (rme.module_name === module_name && attributes_key(rme.attributes) === key)
|
|
9022
|
+
return i;
|
|
9023
|
+
}
|
|
9024
|
+
m.req_module_entries.push(new JSReqModuleEntry(module_name, attributes));
|
|
9025
|
+
return m.req_module_entries.length - 1;
|
|
9026
|
+
}
|
|
9027
|
+
function find_export_entry(m, export_name) {
|
|
9028
|
+
for (const me of m.export_entries)
|
|
9029
|
+
if (me.export_name === export_name)
|
|
9030
|
+
return me;
|
|
9031
|
+
return null;
|
|
9032
|
+
}
|
|
9033
|
+
function add_export_entry(s, m, local_name, export_name, export_type) {
|
|
9034
|
+
if (find_export_entry(m, export_name)) {
|
|
9035
|
+
js_parse_error(s, `duplicate exported name '${JS_AtomGetStr(s.ctx, export_name)}'`);
|
|
9036
|
+
return null;
|
|
9037
|
+
}
|
|
9038
|
+
const me = new JSExportEntry(local_name, export_name, export_type);
|
|
9039
|
+
m.export_entries.push(me);
|
|
9040
|
+
return me;
|
|
9041
|
+
}
|
|
9042
|
+
function add_star_export_entry(m, req_module_idx) {
|
|
9043
|
+
m.star_export_entries.push(new JSStarExportEntry(req_module_idx));
|
|
9044
|
+
}
|
|
9045
|
+
/* export entries of a declaration being parsed (`export let`, `export function`, ...) */
|
|
9046
|
+
function add_local_export(s, name) {
|
|
9047
|
+
const m = s.cur_func.module;
|
|
9048
|
+
if (!m)
|
|
9049
|
+
return js_parse_error(s, 'export outside of a module');
|
|
9050
|
+
return add_export_entry(s, m, name, name, 0 /* JSExportType.LOCAL */) ? 0 : -1;
|
|
9051
|
+
}
|
|
9052
|
+
function add_import(s, m, local_name, import_name, is_star) {
|
|
9053
|
+
const fd = s.cur_func;
|
|
9054
|
+
if (local_name === JS_ATOM_arguments || local_name === JS_ATOM_eval)
|
|
9055
|
+
return js_parse_error(s, 'invalid import binding');
|
|
9056
|
+
for (const cv of fd.closure_var) {
|
|
9057
|
+
if (cv.var_name === local_name)
|
|
9058
|
+
return js_parse_error(s, 'duplicate import binding');
|
|
9059
|
+
}
|
|
9060
|
+
/* a namespace import gets its own variable, set when the module is linked */
|
|
9061
|
+
const is_local = is_star;
|
|
9062
|
+
const var_idx = add_closure_var(s.ctx, fd, is_local, false, m.import_entries.length, local_name, true, true, 0 /* JSVarKind.NORMAL */);
|
|
9063
|
+
if (var_idx < 0)
|
|
9064
|
+
return -1;
|
|
9065
|
+
m.import_entries.push(new JSImportEntry(var_idx, is_star, import_name));
|
|
9066
|
+
return 0;
|
|
9067
|
+
}
|
|
9068
|
+
/* a string used as a module export name must be well formed (no lone surrogates) */
|
|
9069
|
+
function is_well_formed_string(str) {
|
|
9070
|
+
for (let i = 0; i < str.length; i++) {
|
|
9071
|
+
const c = str.charCodeAt(i);
|
|
9072
|
+
if (c >= 0xd800 && c <= 0xdbff) {
|
|
9073
|
+
const d = str.charCodeAt(i + 1);
|
|
9074
|
+
if (!(d >= 0xdc00 && d <= 0xdfff))
|
|
9075
|
+
return false;
|
|
9076
|
+
i++;
|
|
9077
|
+
}
|
|
9078
|
+
else if (c >= 0xdc00 && c <= 0xdfff) {
|
|
9079
|
+
return false;
|
|
9080
|
+
}
|
|
9081
|
+
}
|
|
9082
|
+
return true;
|
|
9083
|
+
}
|
|
9084
|
+
/* ModuleExportName: an IdentifierName or a string. Returns the atom (JS_ATOM_NULL on error);
|
|
9085
|
+
out.kind: 0 identifier, 1 reserved word, 2 string */
|
|
9086
|
+
function js_parse_module_export_name(s, out) {
|
|
9087
|
+
let atom;
|
|
9088
|
+
if (tv(s) === -127 /* TOK.STRING */) {
|
|
9089
|
+
if (!is_well_formed_string(s.token.str)) {
|
|
9090
|
+
js_parse_error(s, 'invalid module export name');
|
|
9091
|
+
return JS_ATOM_NULL;
|
|
9092
|
+
}
|
|
9093
|
+
atom = JS_NewAtom(s.ctx, s.token.str);
|
|
9094
|
+
out.kind = 2;
|
|
9095
|
+
}
|
|
9096
|
+
else if (token_is_ident_or_keyword(tv(s)) || token_is_ident(tv(s))) {
|
|
9097
|
+
atom = s.token.atom;
|
|
9098
|
+
out.kind = token_is_ident(tv(s)) && !s.token.is_reserved ? 0 : 1;
|
|
9099
|
+
}
|
|
9100
|
+
else {
|
|
9101
|
+
js_parse_error(s, 'identifier expected');
|
|
9102
|
+
return JS_ATOM_NULL;
|
|
9103
|
+
}
|
|
9104
|
+
if (next_token(s))
|
|
9105
|
+
return JS_ATOM_NULL;
|
|
9106
|
+
return atom;
|
|
9107
|
+
}
|
|
9108
|
+
/* the binding identifier of an import (after `as`, or a shorthand name) */
|
|
9109
|
+
function js_parse_import_binding(s) {
|
|
9110
|
+
if (!token_is_ident(tv(s))) {
|
|
9111
|
+
js_parse_error(s, 'identifier expected');
|
|
9112
|
+
return JS_ATOM_NULL;
|
|
9113
|
+
}
|
|
9114
|
+
if (s.token.is_reserved) {
|
|
9115
|
+
js_parse_error_reserved_identifier(s);
|
|
9116
|
+
return JS_ATOM_NULL;
|
|
9117
|
+
}
|
|
9118
|
+
const atom = s.token.atom;
|
|
9119
|
+
if (next_token(s))
|
|
9120
|
+
return JS_ATOM_NULL;
|
|
9121
|
+
return atom;
|
|
9122
|
+
}
|
|
9123
|
+
/* `with { type: "json" }` after a module specifier: the attributes, or null. Returns -1 on error */
|
|
9124
|
+
function js_parse_with_clause(s, out) {
|
|
9125
|
+
out.attributes = null;
|
|
9126
|
+
if (tv(s) !== -57 /* TOK.WITH */)
|
|
9127
|
+
return 0;
|
|
9128
|
+
if (next_token(s))
|
|
9129
|
+
return -1;
|
|
9130
|
+
if (js_parse_expect(s, 123))
|
|
9131
|
+
return -1;
|
|
9132
|
+
const attrs = Object.create(null);
|
|
9133
|
+
while (tv(s) !== 125) {
|
|
9134
|
+
let key;
|
|
9135
|
+
if (tv(s) === -127 /* TOK.STRING */)
|
|
9136
|
+
key = s.token.str;
|
|
9137
|
+
else if (token_is_ident_or_keyword(tv(s)) || token_is_ident(tv(s)))
|
|
9138
|
+
key = JS_AtomGetStr(s.ctx, s.token.atom);
|
|
9139
|
+
else
|
|
9140
|
+
return js_parse_error(s, 'identifier or string expected');
|
|
9141
|
+
if (Object.prototype.hasOwnProperty.call(attrs, key))
|
|
9142
|
+
return js_parse_error(s, `duplicate import attribute '${key}'`);
|
|
9143
|
+
if (next_token(s))
|
|
9144
|
+
return -1;
|
|
9145
|
+
if (js_parse_expect(s, 58))
|
|
9146
|
+
return -1;
|
|
9147
|
+
if (tv(s) !== -127 /* TOK.STRING */)
|
|
9148
|
+
return js_parse_error(s, 'string expected');
|
|
9149
|
+
attrs[key] = s.token.str;
|
|
9150
|
+
if (next_token(s))
|
|
9151
|
+
return -1;
|
|
9152
|
+
if (tv(s) !== 44)
|
|
9153
|
+
break;
|
|
9154
|
+
if (next_token(s))
|
|
9155
|
+
return -1;
|
|
9156
|
+
}
|
|
9157
|
+
if (js_parse_expect(s, 125))
|
|
9158
|
+
return -1;
|
|
9159
|
+
out.attributes = attrs;
|
|
9160
|
+
return 0;
|
|
9161
|
+
}
|
|
9162
|
+
/* `from "specifier" [with { ... }]`: the request index, or -1 */
|
|
9163
|
+
function js_parse_from_clause(s, m) {
|
|
9164
|
+
if (!token_is_pseudo_keyword(s, JS_ATOM_from))
|
|
9165
|
+
return js_parse_error(s, 'from clause expected');
|
|
9166
|
+
if (next_token(s))
|
|
9167
|
+
return -1;
|
|
9168
|
+
return js_parse_module_specifier(s, m);
|
|
9169
|
+
}
|
|
9170
|
+
function js_parse_module_specifier(s, m) {
|
|
9171
|
+
if (tv(s) !== -127 /* TOK.STRING */)
|
|
9172
|
+
return js_parse_error(s, 'string expected');
|
|
9173
|
+
const module_name = JS_NewAtom(s.ctx, s.token.str);
|
|
9174
|
+
if (next_token(s))
|
|
9175
|
+
return -1;
|
|
9176
|
+
const w = { attributes: null };
|
|
9177
|
+
if (js_parse_with_clause(s, w))
|
|
9178
|
+
return -1;
|
|
9179
|
+
return add_req_module_entry(m, module_name, w.attributes);
|
|
9180
|
+
}
|
|
9181
|
+
/* a TypeScript `type` modifier on an import or export specifier (`{ type A }`): true if the
|
|
9182
|
+
specifier is type only and was skipped. TypeScript's rules:
|
|
9183
|
+
{ type } name `type` { type as } type-only `as`
|
|
9184
|
+
{ type as as } `type` aliased `as` { type as as as } type-only `as` aliased `as` */
|
|
9185
|
+
function ts_skip_type_specifier(s) {
|
|
9186
|
+
if (!s.ts || !token_is_pseudo_keyword(s, ts_atoms(s).type))
|
|
9187
|
+
return false;
|
|
9188
|
+
const p = ts_save(s);
|
|
9189
|
+
const ok = () => { return true; };
|
|
9190
|
+
if (!ts_next(s)) {
|
|
9191
|
+
ts_restore(s, p);
|
|
9192
|
+
return false;
|
|
9193
|
+
}
|
|
9194
|
+
const end = () => tv(s) === 44 || tv(s) === 125;
|
|
9195
|
+
if (end()) {
|
|
9196
|
+
ts_restore(s, p);
|
|
9197
|
+
return false;
|
|
9198
|
+
} /* { type } */
|
|
9199
|
+
if (token_is_pseudo_keyword(s, JS_ATOM_as)) {
|
|
9200
|
+
if (!ts_next(s)) {
|
|
9201
|
+
ts_restore(s, p);
|
|
9202
|
+
return false;
|
|
9203
|
+
}
|
|
9204
|
+
if (end())
|
|
9205
|
+
return ok(); /* { type as }: type-only import of `as` */
|
|
9206
|
+
if (token_is_pseudo_keyword(s, JS_ATOM_as)) {
|
|
9207
|
+
if (!ts_next(s)) {
|
|
9208
|
+
ts_restore(s, p);
|
|
9209
|
+
return false;
|
|
9210
|
+
}
|
|
9211
|
+
if (end()) {
|
|
9212
|
+
ts_restore(s, p);
|
|
9213
|
+
return false;
|
|
9214
|
+
} /* { type as as }: `type` aliased `as` */
|
|
9215
|
+
/* { type as as x }: type-only `as` aliased `x` */
|
|
9216
|
+
if (!ts_next(s)) {
|
|
9217
|
+
ts_restore(s, p);
|
|
9218
|
+
return false;
|
|
9219
|
+
}
|
|
9220
|
+
return ok();
|
|
9221
|
+
}
|
|
9222
|
+
/* { type as x }: `type` aliased `x` */
|
|
9223
|
+
ts_restore(s, p);
|
|
9224
|
+
return false;
|
|
9225
|
+
}
|
|
9226
|
+
/* { type A [as B] } */
|
|
9227
|
+
if (!ts_next(s)) {
|
|
9228
|
+
ts_restore(s, p);
|
|
9229
|
+
return false;
|
|
9230
|
+
}
|
|
9231
|
+
if (token_is_pseudo_keyword(s, JS_ATOM_as)) {
|
|
9232
|
+
if (!ts_next(s) || !ts_next(s)) {
|
|
9233
|
+
ts_restore(s, p);
|
|
9234
|
+
return false;
|
|
9235
|
+
}
|
|
9236
|
+
}
|
|
9237
|
+
return ok();
|
|
9238
|
+
}
|
|
9239
|
+
function js_parse_import(s) {
|
|
9240
|
+
const m = s.cur_func.module;
|
|
9241
|
+
if (next_token(s))
|
|
9242
|
+
return -1;
|
|
9243
|
+
const first_import = m.import_entries.length;
|
|
9244
|
+
let idx;
|
|
9245
|
+
if (tv(s) === -127 /* TOK.STRING */) {
|
|
9246
|
+
/* import "m" */
|
|
9247
|
+
idx = js_parse_module_specifier(s, m);
|
|
9248
|
+
if (idx < 0)
|
|
9249
|
+
return -1;
|
|
9250
|
+
}
|
|
9251
|
+
else {
|
|
9252
|
+
let need_from = true;
|
|
9253
|
+
if (token_is_ident(tv(s))) {
|
|
9254
|
+
/* default import */
|
|
9255
|
+
const local_name = js_parse_import_binding(s);
|
|
9256
|
+
if (local_name === JS_ATOM_NULL)
|
|
9257
|
+
return -1;
|
|
9258
|
+
if (add_import(s, m, local_name, JS_ATOM_default, false))
|
|
9259
|
+
return -1;
|
|
9260
|
+
if (tv(s) !== 44)
|
|
9261
|
+
need_from = false;
|
|
9262
|
+
else if (next_token(s))
|
|
9263
|
+
return -1;
|
|
9264
|
+
}
|
|
9265
|
+
if (need_from || tv(s) === 42 || tv(s) === 123) {
|
|
9266
|
+
if (tv(s) === 42) {
|
|
9267
|
+
/* namespace import */
|
|
9268
|
+
if (next_token(s))
|
|
9269
|
+
return -1;
|
|
9270
|
+
if (!token_is_pseudo_keyword(s, JS_ATOM_as))
|
|
9271
|
+
return js_parse_error(s, "expecting 'as'");
|
|
9272
|
+
if (next_token(s))
|
|
9273
|
+
return -1;
|
|
9274
|
+
const local_name = js_parse_import_binding(s);
|
|
9275
|
+
if (local_name === JS_ATOM_NULL)
|
|
9276
|
+
return -1;
|
|
9277
|
+
if (add_import(s, m, local_name, JS_ATOM__star_, true))
|
|
9278
|
+
return -1;
|
|
9279
|
+
}
|
|
9280
|
+
else if (tv(s) === 123) {
|
|
9281
|
+
if (next_token(s))
|
|
9282
|
+
return -1;
|
|
9283
|
+
while (tv(s) !== 125) {
|
|
9284
|
+
if (ts_skip_type_specifier(s)) {
|
|
9285
|
+
if (tv(s) !== 44)
|
|
9286
|
+
break;
|
|
9287
|
+
if (next_token(s))
|
|
9288
|
+
return -1;
|
|
9289
|
+
continue;
|
|
9290
|
+
}
|
|
9291
|
+
const k = { kind: 0 };
|
|
9292
|
+
const start = s.token.ptr;
|
|
9293
|
+
const import_name = js_parse_module_export_name(s, k);
|
|
9294
|
+
if (import_name === JS_ATOM_NULL)
|
|
9295
|
+
return -1;
|
|
9296
|
+
let local_name;
|
|
9297
|
+
if (token_is_pseudo_keyword(s, JS_ATOM_as)) {
|
|
9298
|
+
if (next_token(s))
|
|
9299
|
+
return -1;
|
|
9300
|
+
local_name = js_parse_import_binding(s);
|
|
9301
|
+
if (local_name === JS_ATOM_NULL)
|
|
9302
|
+
return -1;
|
|
9303
|
+
}
|
|
9304
|
+
else {
|
|
9305
|
+
if (k.kind !== 0)
|
|
9306
|
+
return js_parse_error_pos(s, start, k.kind === 2 ? "expecting 'as'" : 'identifier expected');
|
|
9307
|
+
local_name = import_name;
|
|
9308
|
+
}
|
|
9309
|
+
if (add_import(s, m, local_name, import_name, false))
|
|
9310
|
+
return -1;
|
|
9311
|
+
if (tv(s) !== 44)
|
|
9312
|
+
break;
|
|
9313
|
+
if (next_token(s))
|
|
9314
|
+
return -1;
|
|
9315
|
+
}
|
|
9316
|
+
if (js_parse_expect(s, 125))
|
|
9317
|
+
return -1;
|
|
9318
|
+
}
|
|
9319
|
+
else {
|
|
9320
|
+
return js_parse_error(s, 'identifier expected');
|
|
9321
|
+
}
|
|
9322
|
+
}
|
|
9323
|
+
idx = js_parse_from_clause(s, m);
|
|
9324
|
+
if (idx < 0)
|
|
9325
|
+
return -1;
|
|
9326
|
+
}
|
|
9327
|
+
for (let i = first_import; i < m.import_entries.length; i++)
|
|
9328
|
+
m.import_entries[i].req_module_idx = idx;
|
|
9329
|
+
return js_parse_expect_semi(s);
|
|
9330
|
+
}
|
|
9331
|
+
/* the name of the declaration after `function` / `async function` / `class`, if any */
|
|
9332
|
+
function export_decl_name(s) {
|
|
9333
|
+
const p = ts_save(s);
|
|
9334
|
+
let name = JS_ATOM_NULL;
|
|
9335
|
+
if (token_is_pseudo_keyword(s, JS_ATOM_async) && !ts_next(s)) {
|
|
9336
|
+
ts_restore(s, p);
|
|
9337
|
+
return name;
|
|
9338
|
+
}
|
|
9339
|
+
if (tv(s) === -59 /* TOK.FUNCTION */ || tv(s) === -56 /* TOK.CLASS */) {
|
|
9340
|
+
if (ts_next(s) && (tv(s) !== 42 || ts_next(s)) && (token_is_ident(tv(s)) && !s.token.is_reserved))
|
|
9341
|
+
name = s.token.atom;
|
|
9342
|
+
}
|
|
9343
|
+
ts_restore(s, p);
|
|
9344
|
+
return name;
|
|
9345
|
+
}
|
|
9346
|
+
/* skip a TypeScript `abstract` before `class`: -1 on error */
|
|
9347
|
+
function ts_skip_abstract(s) {
|
|
9348
|
+
if (s.ts && token_is_pseudo_keyword(s, ts_atoms(s).abstract) && peek_token(s, true) === -56 /* TOK.CLASS */)
|
|
9349
|
+
return next_token(s);
|
|
9350
|
+
return 0;
|
|
9351
|
+
}
|
|
9352
|
+
function js_parse_export(s) {
|
|
9353
|
+
const fd = s.cur_func;
|
|
9354
|
+
const m = fd.module;
|
|
9355
|
+
if (next_token(s))
|
|
9356
|
+
return -1;
|
|
9357
|
+
/* TypeScript: `export abstract class` is a class */
|
|
9358
|
+
if (ts_skip_abstract(s))
|
|
9359
|
+
return -1;
|
|
9360
|
+
const tok = tv(s);
|
|
9361
|
+
const is_async_function = token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, true) === -59 /* TOK.FUNCTION */;
|
|
9362
|
+
if (tok === -56 /* TOK.CLASS */) {
|
|
9363
|
+
const name = export_decl_name(s);
|
|
9364
|
+
if (js_parse_class(s, false, 1 /* JSParseExportEnum.NAMED */))
|
|
9365
|
+
return -1;
|
|
9366
|
+
return add_local_export(s, name);
|
|
9367
|
+
}
|
|
9368
|
+
if (tok === -59 /* TOK.FUNCTION */ || is_async_function) {
|
|
9369
|
+
const name = export_decl_name(s);
|
|
9370
|
+
if (js_parse_function_decl2(s, 0 /* JSParseFunctionEnum.STATEMENT */, 0 /* JSFunctionKind.NORMAL */, JS_ATOM_NULL, s.token.ptr, 1 /* JSParseExportEnum.NAMED */, null))
|
|
9371
|
+
return -1;
|
|
9372
|
+
return add_local_export(s, name);
|
|
9373
|
+
}
|
|
9374
|
+
switch (tok) {
|
|
9375
|
+
case 123: { /* { */
|
|
9376
|
+
const first_export = m.export_entries.length;
|
|
9377
|
+
let invalid_local = -1; /* position of a local name that is not an identifier reference */
|
|
9378
|
+
if (next_token(s))
|
|
9379
|
+
return -1;
|
|
9380
|
+
while (tv(s) !== 125) {
|
|
9381
|
+
if (ts_skip_type_specifier(s)) {
|
|
9382
|
+
if (tv(s) !== 44)
|
|
9383
|
+
break;
|
|
9384
|
+
if (next_token(s))
|
|
9385
|
+
return -1;
|
|
9386
|
+
continue;
|
|
9387
|
+
}
|
|
9388
|
+
const k = { kind: 0 };
|
|
9389
|
+
const start = s.token.ptr;
|
|
9390
|
+
const local_name = js_parse_module_export_name(s, k);
|
|
9391
|
+
if (local_name === JS_ATOM_NULL)
|
|
9392
|
+
return -1;
|
|
9393
|
+
if (k.kind !== 0 && invalid_local < 0)
|
|
9394
|
+
invalid_local = start;
|
|
9395
|
+
let export_name = local_name;
|
|
9396
|
+
if (token_is_pseudo_keyword(s, JS_ATOM_as)) {
|
|
9397
|
+
if (next_token(s))
|
|
9398
|
+
return -1;
|
|
9399
|
+
export_name = js_parse_module_export_name(s, { kind: 0 });
|
|
9400
|
+
if (export_name === JS_ATOM_NULL)
|
|
9401
|
+
return -1;
|
|
9402
|
+
}
|
|
9403
|
+
if (!add_export_entry(s, m, local_name, export_name, 0 /* JSExportType.LOCAL */))
|
|
9404
|
+
return -1;
|
|
9405
|
+
if (tv(s) !== 44)
|
|
9406
|
+
break;
|
|
9407
|
+
if (next_token(s))
|
|
9408
|
+
return -1;
|
|
9409
|
+
}
|
|
9410
|
+
if (js_parse_expect(s, 125))
|
|
9411
|
+
return -1;
|
|
9412
|
+
if (token_is_pseudo_keyword(s, JS_ATOM_from)) {
|
|
9413
|
+
const idx = js_parse_from_clause(s, m);
|
|
9414
|
+
if (idx < 0)
|
|
9415
|
+
return -1;
|
|
9416
|
+
for (let i = first_export; i < m.export_entries.length; i++) {
|
|
9417
|
+
const me = m.export_entries[i];
|
|
9418
|
+
me.export_type = 1 /* JSExportType.INDIRECT */;
|
|
9419
|
+
me.req_module_idx = idx;
|
|
9420
|
+
}
|
|
9421
|
+
}
|
|
9422
|
+
else if (invalid_local >= 0) {
|
|
9423
|
+
return js_parse_error_pos(s, invalid_local, 'identifier expected');
|
|
9424
|
+
}
|
|
9425
|
+
break;
|
|
9426
|
+
}
|
|
9427
|
+
case 42: { /* * */
|
|
9428
|
+
if (next_token(s))
|
|
9429
|
+
return -1;
|
|
9430
|
+
if (token_is_pseudo_keyword(s, JS_ATOM_as)) {
|
|
9431
|
+
/* export * as ns from "m" */
|
|
9432
|
+
if (next_token(s))
|
|
9433
|
+
return -1;
|
|
9434
|
+
const export_name = js_parse_module_export_name(s, { kind: 0 });
|
|
9435
|
+
if (export_name === JS_ATOM_NULL)
|
|
9436
|
+
return -1;
|
|
9437
|
+
const idx = js_parse_from_clause(s, m);
|
|
9438
|
+
if (idx < 0)
|
|
9439
|
+
return -1;
|
|
9440
|
+
const me = add_export_entry(s, m, JS_ATOM__star_, export_name, 1 /* JSExportType.INDIRECT */);
|
|
9441
|
+
if (!me)
|
|
9442
|
+
return -1;
|
|
9443
|
+
me.req_module_idx = idx;
|
|
9444
|
+
}
|
|
9445
|
+
else {
|
|
9446
|
+
const idx = js_parse_from_clause(s, m);
|
|
9447
|
+
if (idx < 0)
|
|
9448
|
+
return -1;
|
|
9449
|
+
add_star_export_entry(m, idx);
|
|
9450
|
+
}
|
|
9451
|
+
break;
|
|
9452
|
+
}
|
|
9453
|
+
case -64 /* TOK.DEFAULT */: {
|
|
9454
|
+
if (next_token(s))
|
|
9455
|
+
return -1;
|
|
9456
|
+
if (ts_skip_abstract(s))
|
|
9457
|
+
return -1;
|
|
9458
|
+
if (tv(s) === -56 /* TOK.CLASS */) {
|
|
9459
|
+
let name = export_decl_name(s);
|
|
9460
|
+
if (js_parse_class(s, false, 2 /* JSParseExportEnum.DEFAULT */))
|
|
9461
|
+
return -1;
|
|
9462
|
+
if (name === JS_ATOM_NULL)
|
|
9463
|
+
name = JS_ATOM__default_;
|
|
9464
|
+
return add_export_entry(s, m, name, JS_ATOM_default, 0 /* JSExportType.LOCAL */) ? 0 : -1;
|
|
9465
|
+
}
|
|
9466
|
+
if (tv(s) === -59 /* TOK.FUNCTION */ || (token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, true) === -59 /* TOK.FUNCTION */)) {
|
|
9467
|
+
let name = export_decl_name(s);
|
|
9468
|
+
if (js_parse_function_decl2(s, 0 /* JSParseFunctionEnum.STATEMENT */, 0 /* JSFunctionKind.NORMAL */, JS_ATOM_NULL, s.token.ptr, 2 /* JSParseExportEnum.DEFAULT */, null))
|
|
9469
|
+
return -1;
|
|
9470
|
+
if (name === JS_ATOM_NULL)
|
|
9471
|
+
name = JS_ATOM__default_;
|
|
9472
|
+
return add_export_entry(s, m, name, JS_ATOM_default, 0 /* JSExportType.LOCAL */) ? 0 : -1;
|
|
9473
|
+
}
|
|
9474
|
+
if (js_parse_assign_expr(s))
|
|
9475
|
+
return -1;
|
|
9476
|
+
/* set the name of anonymous functions */
|
|
9477
|
+
set_object_name(s, JS_ATOM_default);
|
|
9478
|
+
/* store the value in the _default_ variable and export it */
|
|
9479
|
+
const local_name = JS_ATOM__default_;
|
|
9480
|
+
if (define_var(s, fd, local_name, 1 /* JSVarDefEnum.LET */) < 0)
|
|
9481
|
+
return -1;
|
|
9482
|
+
emit_op(s, 191 /* OP.scope_put_var_init */);
|
|
9483
|
+
emit_atom(s, local_name);
|
|
9484
|
+
emit_u16(s, 0);
|
|
9485
|
+
if (!add_export_entry(s, m, local_name, JS_ATOM_default, 0 /* JSExportType.LOCAL */))
|
|
9486
|
+
return -1;
|
|
9487
|
+
break;
|
|
9488
|
+
}
|
|
9489
|
+
case -79 /* TOK.VAR */:
|
|
9490
|
+
case -47 /* TOK.LET */:
|
|
9491
|
+
case -55 /* TOK.CONST */:
|
|
9492
|
+
if (next_token(s))
|
|
9493
|
+
return -1;
|
|
9494
|
+
if (js_parse_var(s, PF_IN_ACCEPTED, tok, true))
|
|
9495
|
+
return -1;
|
|
9496
|
+
break;
|
|
9497
|
+
default:
|
|
9498
|
+
return js_parse_error(s, 'invalid export syntax');
|
|
9499
|
+
}
|
|
9500
|
+
return js_parse_expect_semi(s);
|
|
9501
|
+
}
|
|
9502
|
+
/* Add the module global variables as closure variables of the module function, turn the
|
|
9503
|
+
exports of imported bindings into indirect exports, and resolve the local exports
|
|
9504
|
+
(quickjs.c add_module_variables) */
|
|
9505
|
+
function add_module_variables(ctx, fd) {
|
|
9506
|
+
const m = fd.module;
|
|
9507
|
+
/* the imported variables were added as closure variables in js_parse_import(); add the
|
|
9508
|
+
module global variables */
|
|
9509
|
+
for (let i = 0; i < fd.global_vars.length; i++) {
|
|
9510
|
+
const hf = fd.global_vars[i];
|
|
9511
|
+
for (const cv of fd.closure_var) {
|
|
9512
|
+
if (cv.var_name === hf.var_name) {
|
|
9513
|
+
JS_ThrowSyntaxError(ctx, `invalid redefinition of imported binding '${JS_AtomGetStr(ctx, hf.var_name)}'`);
|
|
9514
|
+
return -1;
|
|
9515
|
+
}
|
|
9516
|
+
}
|
|
9517
|
+
}
|
|
9518
|
+
for (let i = 0; i < fd.global_vars.length; i++) {
|
|
9519
|
+
const hf = fd.global_vars[i];
|
|
9520
|
+
if (add_closure_var(ctx, fd, true, false, i, hf.var_name, hf.is_const, hf.is_lexical, 0 /* JSVarKind.NORMAL */) < 0)
|
|
9521
|
+
return -1;
|
|
9522
|
+
}
|
|
9523
|
+
/* an export of an imported binding is an indirect export (ParseModule) */
|
|
9524
|
+
for (const me of m.export_entries) {
|
|
9525
|
+
if (me.export_type !== 0 /* JSExportType.LOCAL */)
|
|
9526
|
+
continue;
|
|
9527
|
+
const mi = m.import_entries.find(e => fd.closure_var[e.var_idx].var_name === me.local_name);
|
|
9528
|
+
if (mi && !mi.is_star) {
|
|
9529
|
+
me.export_type = 1 /* JSExportType.INDIRECT */;
|
|
9530
|
+
me.req_module_idx = mi.req_module_idx;
|
|
9531
|
+
me.local_name = mi.import_name;
|
|
9532
|
+
}
|
|
9533
|
+
}
|
|
9534
|
+
/* resolve the variable names of the local exports */
|
|
9535
|
+
for (const me of m.export_entries) {
|
|
9536
|
+
if (me.export_type !== 0 /* JSExportType.LOCAL */)
|
|
9537
|
+
continue;
|
|
9538
|
+
const idx = fd.closure_var.findIndex(cv => cv.var_name === me.local_name);
|
|
9539
|
+
if (idx < 0) {
|
|
9540
|
+
JS_ThrowSyntaxError(ctx, `exported variable '${JS_AtomGetStr(ctx, me.local_name)}' does not exist`);
|
|
9541
|
+
return -1;
|
|
9542
|
+
}
|
|
9543
|
+
me.var_idx = idx;
|
|
9544
|
+
}
|
|
9545
|
+
return 0;
|
|
9546
|
+
}
|
|
6798
9547
|
function js_parse_source_element(s) {
|
|
9548
|
+
if (s.ts && (tv(s) === -59 /* TOK.FUNCTION */ || token_is_pseudo_keyword(s, JS_ATOM_async))) {
|
|
9549
|
+
/* overload signature */
|
|
9550
|
+
const r = ts_parse_statement(s);
|
|
9551
|
+
if (r < 0)
|
|
9552
|
+
return -1;
|
|
9553
|
+
if (r > 0)
|
|
9554
|
+
return 0;
|
|
9555
|
+
}
|
|
6799
9556
|
if (tv(s) === -59 /* TOK.FUNCTION */ || (token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, true) === -59 /* TOK.FUNCTION */)) {
|
|
6800
9557
|
if (js_parse_function_decl(s, 0 /* JSParseFunctionEnum.STATEMENT */, 0 /* JSFunctionKind.NORMAL */, JS_ATOM_NULL, s.token.ptr))
|
|
6801
9558
|
return -1;
|
|
6802
9559
|
}
|
|
6803
|
-
else if (tv(s) === -53 /* TOK.EXPORT */ && s
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
9560
|
+
else if ((tv(s) === -53 /* TOK.EXPORT */ || (tv(s) === -51 /* TOK.IMPORT */ && peek_token(s, false) !== 40 && peek_token(s, false) !== 46)) &&
|
|
9561
|
+
s.cur_func.module) {
|
|
9562
|
+
if (s.ts) {
|
|
9563
|
+
/* type-only imports and exports, and the rejected forms */
|
|
9564
|
+
const r = ts_parse_statement(s);
|
|
9565
|
+
if (r < 0)
|
|
9566
|
+
return -1;
|
|
9567
|
+
if (r > 0)
|
|
9568
|
+
return 0;
|
|
9569
|
+
}
|
|
9570
|
+
return tv(s) === -53 /* TOK.EXPORT */ ? js_parse_export(s) : js_parse_import(s);
|
|
6808
9571
|
}
|
|
6809
9572
|
else {
|
|
6810
9573
|
if (js_parse_statement_or_decl(s, DECL_MASK_ALL))
|
|
@@ -7916,6 +10679,17 @@ function instantiate_hoisted_definitions(ctx, s, bc) {
|
|
|
7916
10679
|
bc.put_u16(i);
|
|
7917
10680
|
}
|
|
7918
10681
|
}
|
|
10682
|
+
/* the module global variables must be initialized before evaluating the module so that
|
|
10683
|
+
the exported functions are visible if there are cyclic module references */
|
|
10684
|
+
let label_next = -1;
|
|
10685
|
+
if (s.module) {
|
|
10686
|
+
label_next = new_label_fd(s);
|
|
10687
|
+
/* if 'this' is true, initialize the global variables and return */
|
|
10688
|
+
bc.putc(8 /* OP.push_this */);
|
|
10689
|
+
bc.putc(107 /* OP.if_false */);
|
|
10690
|
+
bc.put_u32(label_next);
|
|
10691
|
+
update_label(s, label_next, 1);
|
|
10692
|
+
}
|
|
7919
10693
|
/* add the global variables (only happens if s->is_global_var is true) */
|
|
7920
10694
|
for (let i = 0; i < s.global_vars.length; i++) {
|
|
7921
10695
|
const hf = s.global_vars[i];
|
|
@@ -7993,6 +10767,12 @@ function instantiate_hoisted_definitions(ctx, s, bc) {
|
|
|
7993
10767
|
}
|
|
7994
10768
|
}
|
|
7995
10769
|
}
|
|
10770
|
+
if (s.module) {
|
|
10771
|
+
bc.putc(41 /* OP.return_undef */);
|
|
10772
|
+
bc.putc(184 /* OP.label */);
|
|
10773
|
+
bc.put_u32(label_next);
|
|
10774
|
+
s.label_slots[label_next].pos2 = bc.size;
|
|
10775
|
+
}
|
|
7996
10776
|
s.global_vars = [];
|
|
7997
10777
|
}
|
|
7998
10778
|
function skip_dead_code(s, bc_buf, bc_len, pos, linep) {
|
|
@@ -9607,6 +12387,10 @@ export function js_create_function(ctx, fd, ps) {
|
|
|
9607
12387
|
lookup is done. */
|
|
9608
12388
|
if (fd.has_eval_call)
|
|
9609
12389
|
add_eval_variables(ctx, fd);
|
|
12390
|
+
if (fd.module) {
|
|
12391
|
+
if (add_module_variables(ctx, fd))
|
|
12392
|
+
return null;
|
|
12393
|
+
}
|
|
9610
12394
|
/* first create all the child functions */
|
|
9611
12395
|
for (const fd1 of fd.child_list) {
|
|
9612
12396
|
const cpool_idx = fd1.parent_cpool_idx;
|
|
@@ -9684,9 +12468,12 @@ export function __JS_EvalInternal(ctx, this_obj, input, filename, flags, scope_i
|
|
|
9684
12468
|
else {
|
|
9685
12469
|
if (flags & JS_EVAL_FLAG_STRICT)
|
|
9686
12470
|
js_mode |= JS_MODE_STRICT;
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
12471
|
+
}
|
|
12472
|
+
let m = null;
|
|
12473
|
+
if (eval_type === JS_EVAL_TYPE_MODULE) {
|
|
12474
|
+
m = new JSModuleDef(JS_NewAtom(ctx, filename));
|
|
12475
|
+
m.realm = ctx;
|
|
12476
|
+
js_mode |= JS_MODE_STRICT;
|
|
9690
12477
|
}
|
|
9691
12478
|
const fd = js_new_function_def(ctx, null, true, false, filename, s.buf_start);
|
|
9692
12479
|
s.cur_func = fd;
|
|
@@ -9710,20 +12497,33 @@ export function __JS_EvalInternal(ctx, this_obj, input, filename, flags, scope_i
|
|
|
9710
12497
|
if (add_closure_variables(ctx, fd, b, scope_idx))
|
|
9711
12498
|
return JS_EXCEPTION;
|
|
9712
12499
|
}
|
|
9713
|
-
|
|
12500
|
+
fd.module = m;
|
|
12501
|
+
if (m !== null || (flags & JS_EVAL_FLAG_ASYNC)) {
|
|
9714
12502
|
fd.in_function_body = true;
|
|
9715
12503
|
fd.func_kind = 2 /* JSFunctionKind.ASYNC */;
|
|
9716
12504
|
}
|
|
9717
|
-
s.is_module =
|
|
12505
|
+
s.is_module = (m !== null);
|
|
9718
12506
|
s.allow_html_comments = !s.is_module;
|
|
12507
|
+
s.ts = (flags & JS_EVAL_FLAG_STRIP_TYPES) !== 0;
|
|
12508
|
+
s.jsx = (flags & JS_EVAL_FLAG_JSX) !== 0;
|
|
9719
12509
|
push_scope(s); /* body scope */
|
|
9720
12510
|
fd.body_scope = fd.scope_level;
|
|
9721
12511
|
if (js_parse_program(s))
|
|
9722
12512
|
return JS_EXCEPTION;
|
|
12513
|
+
if (m !== null)
|
|
12514
|
+
m.has_tla = fd.has_await;
|
|
12515
|
+
if (m !== null && s.jsx_runtime !== null && s.jsx_runtime.requests.length)
|
|
12516
|
+
jsx_hoist_requests(m, s.jsx_runtime.requests);
|
|
9723
12517
|
/* create the function object and all the enclosed functions */
|
|
9724
12518
|
const fb = js_create_function(ctx, fd, s);
|
|
9725
12519
|
if (!fb)
|
|
9726
12520
|
return JS_EXCEPTION;
|
|
12521
|
+
if (m !== null) {
|
|
12522
|
+
/* the module record stands for the compiled module (JS_TAG_MODULE in C) */
|
|
12523
|
+
if (hooks.js_module_compiled === null)
|
|
12524
|
+
return JS_ThrowSyntaxError(ctx, 'modules are not supported in this build');
|
|
12525
|
+
return hooks.js_module_compiled(ctx, m, fb, flags);
|
|
12526
|
+
}
|
|
9727
12527
|
if (flags & JS_EVAL_FLAG_COMPILE_ONLY) {
|
|
9728
12528
|
return hooks.js_closure(ctx, fb, var_refs, sf);
|
|
9729
12529
|
}
|