support class literals (#4658)
This commit is contained in:
188
lib/parse.js
188
lib/parse.js
@@ -44,10 +44,10 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var KEYWORDS = "break case catch const continue debugger default delete do else finally for function if in instanceof let new return switch throw try typeof var void while with";
|
||||
var KEYWORDS = "break case catch class const continue debugger default delete do else extends finally for function if in instanceof let new return switch throw try typeof var void while with";
|
||||
var KEYWORDS_ATOM = "false null true";
|
||||
var RESERVED_WORDS = [
|
||||
"abstract async await boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield",
|
||||
"abstract async await boolean byte char double enum export final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield",
|
||||
KEYWORDS_ATOM,
|
||||
KEYWORDS,
|
||||
].join(" ");
|
||||
@@ -886,6 +886,10 @@ function parse($TEXT, options) {
|
||||
next();
|
||||
return break_cont(AST_Break);
|
||||
|
||||
case "class":
|
||||
next();
|
||||
return class_(AST_DefClass);
|
||||
|
||||
case "const":
|
||||
next();
|
||||
var node = const_();
|
||||
@@ -1047,6 +1051,128 @@ function parse($TEXT, options) {
|
||||
return stat;
|
||||
}
|
||||
|
||||
function class_(ctor) {
|
||||
var was_async = S.in_async;
|
||||
var was_gen = S.in_generator;
|
||||
S.input.push_directives_stack();
|
||||
S.input.add_directive("use strict");
|
||||
var name;
|
||||
if (ctor === AST_DefClass) {
|
||||
name = as_symbol(AST_SymbolDefClass);
|
||||
} else {
|
||||
name = as_symbol(AST_SymbolClass, true);
|
||||
}
|
||||
var parent = null;
|
||||
if (is("keyword", "extends")) {
|
||||
next();
|
||||
handle_regexp();
|
||||
parent = expr_atom(true);
|
||||
}
|
||||
expect("{");
|
||||
var props = [];
|
||||
while (!is("punc", "}")) {
|
||||
if (is("punc", ";")) {
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
var start = S.token;
|
||||
var fixed = is("name", "static");
|
||||
if (fixed) next();
|
||||
var async = is("name", "async") && peek();
|
||||
if (async) {
|
||||
if (async.type == "punc" && /^[(=;}]$/.test(async.value) || has_newline_before(async)) {
|
||||
async = false;
|
||||
} else {
|
||||
async = next();
|
||||
}
|
||||
}
|
||||
if (is("operator", "*")) {
|
||||
next();
|
||||
var internal = is("name") && /^#/.test(S.token.value);
|
||||
var key = as_property_key();
|
||||
var gen_start = S.token;
|
||||
var gen = function_(async ? AST_AsyncGeneratorFunction : AST_GeneratorFunction);
|
||||
gen.start = gen_start;
|
||||
gen.end = prev();
|
||||
props.push(new AST_ClassMethod({
|
||||
start: start,
|
||||
static: fixed,
|
||||
private: internal,
|
||||
key: key,
|
||||
value: gen,
|
||||
end: prev(),
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
var internal = is("name") && /^#/.test(S.token.value);
|
||||
var key = as_property_key();
|
||||
if (is("punc", "(")) {
|
||||
var func_start = S.token;
|
||||
var func = function_(async ? AST_AsyncFunction : AST_Function);
|
||||
func.start = func_start;
|
||||
func.end = prev();
|
||||
props.push(new AST_ClassMethod({
|
||||
start: start,
|
||||
static: fixed,
|
||||
private: internal,
|
||||
key: key,
|
||||
value: func,
|
||||
end: prev(),
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
if (async) unexpected(async);
|
||||
var value = null;
|
||||
if (is("operator", "=")) {
|
||||
next();
|
||||
S.in_async = false;
|
||||
S.in_generator = false;
|
||||
value = maybe_assign();
|
||||
S.in_generator = was_gen;
|
||||
S.in_async = was_async;
|
||||
} else if (!(is("punc", ";") || is("punc", "}"))) {
|
||||
var type = null;
|
||||
switch (key) {
|
||||
case "get":
|
||||
type = AST_ClassGetter;
|
||||
break;
|
||||
case "set":
|
||||
type = AST_ClassSetter;
|
||||
break;
|
||||
}
|
||||
if (type) {
|
||||
props.push(new type({
|
||||
start: start,
|
||||
static: fixed,
|
||||
private: is("name") && /^#/.test(S.token.value),
|
||||
key: as_property_key(),
|
||||
value: create_accessor(),
|
||||
end: prev(),
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
semicolon();
|
||||
props.push(new AST_ClassField({
|
||||
start: start,
|
||||
static: fixed,
|
||||
private: internal,
|
||||
key: key,
|
||||
value: value,
|
||||
end: prev(),
|
||||
}));
|
||||
}
|
||||
next();
|
||||
S.input.pop_directives_stack();
|
||||
S.in_generator = was_gen;
|
||||
S.in_async = was_async;
|
||||
return new ctor({
|
||||
extends: parent,
|
||||
name: name,
|
||||
properties: props,
|
||||
});
|
||||
}
|
||||
|
||||
function for_() {
|
||||
var await = is("name", "await") && next();
|
||||
expect("(");
|
||||
@@ -1365,13 +1491,12 @@ function parse($TEXT, options) {
|
||||
return new AST_ExportDeclaration({ body: export_decl() });
|
||||
}
|
||||
|
||||
function maybe_named(def, exp) {
|
||||
var node = function_(exp);
|
||||
if (node.name) {
|
||||
node = new def(node);
|
||||
node.name = new AST_SymbolDefun(node.name);
|
||||
function maybe_named(def, expr) {
|
||||
if (expr.name) {
|
||||
expr = new def(expr);
|
||||
expr.name = new (def === AST_DefClass ? AST_SymbolDefClass : AST_SymbolDefun)(expr.name);
|
||||
}
|
||||
return node;
|
||||
return expr;
|
||||
}
|
||||
|
||||
function export_default_decl() {
|
||||
@@ -1380,14 +1505,17 @@ function parse($TEXT, options) {
|
||||
if (!is_token(peek(), "keyword", "function")) return;
|
||||
next();
|
||||
next();
|
||||
if (!is("operator", "*")) return maybe_named(AST_AsyncDefun, AST_AsyncFunction);
|
||||
if (!is("operator", "*")) return maybe_named(AST_AsyncDefun, function_(AST_AsyncFunction));
|
||||
next();
|
||||
return maybe_named(AST_AsyncGeneratorDefun, AST_AsyncGeneratorFunction);
|
||||
return maybe_named(AST_AsyncGeneratorDefun, function_(AST_AsyncGeneratorFunction));
|
||||
case "class":
|
||||
next();
|
||||
return maybe_named(AST_DefClass, class_(AST_ClassExpression));
|
||||
case "function":
|
||||
next();
|
||||
if (!is("operator", "*")) return maybe_named(AST_Defun, AST_Function);
|
||||
if (!is("operator", "*")) return maybe_named(AST_Defun, function_(AST_Function));
|
||||
next();
|
||||
return maybe_named(AST_GeneratorDefun, AST_GeneratorFunction);
|
||||
return maybe_named(AST_GeneratorDefun, function_(AST_GeneratorFunction));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1399,6 +1527,9 @@ function parse($TEXT, options) {
|
||||
if (!is("operator", "*")) return function_(AST_AsyncDefun);
|
||||
next();
|
||||
return function_(AST_AsyncGeneratorDefun);
|
||||
case "class":
|
||||
next();
|
||||
return class_(AST_DefClass);
|
||||
case "const":
|
||||
next();
|
||||
var node = const_();
|
||||
@@ -1706,7 +1837,14 @@ function parse($TEXT, options) {
|
||||
}
|
||||
unexpected();
|
||||
}
|
||||
if (is("keyword", "function")) {
|
||||
if (is("keyword")) switch (start.value) {
|
||||
case "class":
|
||||
next();
|
||||
var clazz = class_(AST_ClassExpression);
|
||||
clazz.start = start;
|
||||
clazz.end = prev();
|
||||
return subscripts(clazz, allow_calls);
|
||||
case "function":
|
||||
next();
|
||||
var func;
|
||||
if (is("operator", "*")) {
|
||||
@@ -1813,7 +1951,7 @@ function parse($TEXT, options) {
|
||||
var gen = function_(AST_GeneratorFunction);
|
||||
gen.start = gen_start;
|
||||
gen.end = prev();
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
a.push(new AST_ObjectMethod({
|
||||
start: start,
|
||||
key: key,
|
||||
value: gen,
|
||||
@@ -1862,7 +2000,7 @@ function parse($TEXT, options) {
|
||||
var func = function_(AST_Function);
|
||||
func.start = func_start;
|
||||
func.end = prev();
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
a.push(new AST_ObjectMethod({
|
||||
start: start,
|
||||
key: key,
|
||||
value: func,
|
||||
@@ -1888,7 +2026,7 @@ function parse($TEXT, options) {
|
||||
var func = function_(is_gen ? AST_AsyncGeneratorFunction : AST_AsyncFunction);
|
||||
func.start = func_start;
|
||||
func.end = prev();
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
a.push(new AST_ObjectMethod({
|
||||
start: start,
|
||||
key: key,
|
||||
value: func,
|
||||
@@ -1948,9 +2086,21 @@ function parse($TEXT, options) {
|
||||
|
||||
function _make_symbol(type, token) {
|
||||
var name = token.value;
|
||||
if (name === "await" && S.in_async) unexpected(token);
|
||||
if (name === "yield" && S.in_generator) unexpected(token);
|
||||
return new (name === "this" ? AST_This : type)({
|
||||
switch (name) {
|
||||
case "await":
|
||||
if (S.in_async) unexpected(token);
|
||||
break;
|
||||
case "super":
|
||||
type = AST_Super;
|
||||
break;
|
||||
case "this":
|
||||
type = AST_This;
|
||||
break;
|
||||
case "yield":
|
||||
if (S.in_generator) unexpected(token);
|
||||
break;
|
||||
}
|
||||
return new type({
|
||||
name: "" + name,
|
||||
start: token,
|
||||
end: token,
|
||||
|
||||
Reference in New Issue
Block a user