support string namespace in import & export (#5570)
This commit is contained in:
52
lib/ast.js
52
lib/ast.js
@@ -1366,34 +1366,29 @@ var AST_ExportDefault = DEFNODE("ExportDefault", "body", {
|
|||||||
},
|
},
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
var AST_ExportForeign = DEFNODE("ExportForeign", "aliases keys path quote", {
|
var AST_ExportForeign = DEFNODE("ExportForeign", "aliases keys path", {
|
||||||
$documentation: "An `export ... from '...'` statement",
|
$documentation: "An `export ... from '...'` statement",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
aliases: "[string*] array of aliases to export",
|
aliases: "[AST_String*] array of aliases to export",
|
||||||
keys: "[string*] array of keys to import",
|
keys: "[AST_String*] array of keys to import",
|
||||||
path: "[string] the path to import module",
|
path: "[AST_String] the path to import module",
|
||||||
quote: "[string?] the original quote character",
|
|
||||||
},
|
},
|
||||||
_equals: function(node) {
|
_equals: function(node) {
|
||||||
return this.path == node.path
|
return this.path.equals(node.path)
|
||||||
&& list_equals(this.aliases, node.aliases)
|
&& all_equals(this.aliases, node.aliases)
|
||||||
&& list_equals(this.keys, node.keys);
|
&& all_equals(this.keys, node.keys);
|
||||||
},
|
},
|
||||||
_validate: function() {
|
_validate: function() {
|
||||||
if (this.aliases.length != this.keys.length) {
|
if (this.aliases.length != this.keys.length) {
|
||||||
throw new Error("aliases:key length mismatch: " + this.aliases.length + " != " + this.keys.length);
|
throw new Error("aliases:key length mismatch: " + this.aliases.length + " != " + this.keys.length);
|
||||||
}
|
}
|
||||||
this.aliases.forEach(function(name) {
|
this.aliases.forEach(function(name) {
|
||||||
if (typeof name != "string") throw new Error("aliases must contain string");
|
if (!(name instanceof AST_String)) throw new Error("aliases must contain AST_String");
|
||||||
});
|
});
|
||||||
this.keys.forEach(function(name) {
|
this.keys.forEach(function(name) {
|
||||||
if (typeof name != "string") throw new Error("keys must contain string");
|
if (!(name instanceof AST_String)) throw new Error("keys must contain AST_String");
|
||||||
});
|
});
|
||||||
if (typeof this.path != "string") throw new Error("path must be string");
|
if (!(this.path instanceof AST_String)) throw new Error("path must be AST_String");
|
||||||
if (this.quote != null) {
|
|
||||||
if (typeof this.quote != "string") throw new Error("quote must be string");
|
|
||||||
if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
@@ -1420,17 +1415,16 @@ var AST_ExportReferences = DEFNODE("ExportReferences", "properties", {
|
|||||||
},
|
},
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
var AST_Import = DEFNODE("Import", "all default path properties quote", {
|
var AST_Import = DEFNODE("Import", "all default path properties", {
|
||||||
$documentation: "An `import` statement",
|
$documentation: "An `import` statement",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
all: "[AST_SymbolImport?] the imported namespace, or null if not specified",
|
all: "[AST_SymbolImport?] the imported namespace, or null if not specified",
|
||||||
default: "[AST_SymbolImport?] the alias for default `export`, or null if not specified",
|
default: "[AST_SymbolImport?] the alias for default `export`, or null if not specified",
|
||||||
path: "[string] the path to import module",
|
path: "[AST_String] the path to import module",
|
||||||
properties: "[(AST_SymbolImport*)?] array of aliases, or null if not specified",
|
properties: "[(AST_SymbolImport*)?] array of aliases, or null if not specified",
|
||||||
quote: "[string?] the original quote character",
|
|
||||||
},
|
},
|
||||||
_equals: function(node) {
|
_equals: function(node) {
|
||||||
return this.path == node.path
|
return this.path.equals(node.path)
|
||||||
&& prop_equals(this.all, node.all)
|
&& prop_equals(this.all, node.all)
|
||||||
&& prop_equals(this.default, node.default)
|
&& prop_equals(this.default, node.default)
|
||||||
&& !this.properties == !node.properties
|
&& !this.properties == !node.properties
|
||||||
@@ -1453,16 +1447,12 @@ var AST_Import = DEFNODE("Import", "all default path properties quote", {
|
|||||||
}
|
}
|
||||||
if (this.default != null) {
|
if (this.default != null) {
|
||||||
if (!(this.default instanceof AST_SymbolImport)) throw new Error("default must be AST_SymbolImport");
|
if (!(this.default instanceof AST_SymbolImport)) throw new Error("default must be AST_SymbolImport");
|
||||||
if (this.default.key !== "") throw new Error("invalid default key: " + this.default.key);
|
if (this.default.key.value !== "") throw new Error("invalid default key: " + this.default.key.value);
|
||||||
}
|
}
|
||||||
if (typeof this.path != "string") throw new Error("path must be string");
|
if (!(this.path instanceof AST_String)) throw new Error("path must be AST_String");
|
||||||
if (this.properties != null) this.properties.forEach(function(node) {
|
if (this.properties != null) this.properties.forEach(function(node) {
|
||||||
if (!(node instanceof AST_SymbolImport)) throw new Error("properties must contain AST_SymbolImport");
|
if (!(node instanceof AST_SymbolImport)) throw new Error("properties must contain AST_SymbolImport");
|
||||||
});
|
});
|
||||||
if (this.quote != null) {
|
|
||||||
if (typeof this.quote != "string") throw new Error("quote must be string");
|
|
||||||
if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
@@ -2005,14 +1995,14 @@ var AST_SymbolConst = DEFNODE("SymbolConst", null, {
|
|||||||
var AST_SymbolImport = DEFNODE("SymbolImport", "key", {
|
var AST_SymbolImport = DEFNODE("SymbolImport", "key", {
|
||||||
$documentation: "Symbol defined by an `import` statement",
|
$documentation: "Symbol defined by an `import` statement",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
key: "[string] the original `export` name",
|
key: "[AST_String] the original `export` name",
|
||||||
},
|
},
|
||||||
_equals: function(node) {
|
_equals: function(node) {
|
||||||
return this.name == node.name
|
return this.name == node.name
|
||||||
&& this.key == node.key;
|
&& this.key.equals(node.key);
|
||||||
},
|
},
|
||||||
_validate: function() {
|
_validate: function() {
|
||||||
if (typeof this.key != "string") throw new Error("key must be string");
|
if (!(this.key instanceof AST_String)) throw new Error("key must be AST_String");
|
||||||
},
|
},
|
||||||
}, AST_SymbolConst);
|
}, AST_SymbolConst);
|
||||||
|
|
||||||
@@ -2066,14 +2056,14 @@ var AST_SymbolRef = DEFNODE("SymbolRef", "fixed in_arg redef", {
|
|||||||
var AST_SymbolExport = DEFNODE("SymbolExport", "alias", {
|
var AST_SymbolExport = DEFNODE("SymbolExport", "alias", {
|
||||||
$documentation: "Reference in an `export` statement",
|
$documentation: "Reference in an `export` statement",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
alias: "[string] the `export` alias",
|
alias: "[AST_String] the `export` alias",
|
||||||
},
|
},
|
||||||
_equals: function(node) {
|
_equals: function(node) {
|
||||||
return this.name == node.name
|
return this.name == node.name
|
||||||
&& this.alias == node.alias;
|
&& this.alias.equals(node.alias);
|
||||||
},
|
},
|
||||||
_validate: function() {
|
_validate: function() {
|
||||||
if (typeof this.alias != "string") throw new Error("alias must be string");
|
if (!(this.alias instanceof AST_String)) throw new Error("alias must be AST_String");
|
||||||
},
|
},
|
||||||
}, AST_SymbolRef);
|
}, AST_SymbolRef);
|
||||||
|
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
function export_symbol(sym) {
|
function export_symbol(sym) {
|
||||||
if (!(sym instanceof AST_SymbolDeclaration)) return;
|
if (!(sym instanceof AST_SymbolDeclaration)) return;
|
||||||
var node = make_node(AST_SymbolExport, sym, sym);
|
var node = make_node(AST_SymbolExport, sym, sym);
|
||||||
node.alias = node.name;
|
node.alias = make_node(AST_String, node, { value: node.name });
|
||||||
props.push(node);
|
props.push(node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -316,13 +316,22 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
ExportAllDeclaration: function(M) {
|
ExportAllDeclaration: function(M) {
|
||||||
var alias = M.exported ? read_name(M.exported) : "*";
|
var start = my_start_token(M);
|
||||||
|
var end = my_end_token(M);
|
||||||
return new AST_ExportForeign({
|
return new AST_ExportForeign({
|
||||||
start: my_start_token(M),
|
start: start,
|
||||||
end: my_end_token(M),
|
end: end,
|
||||||
aliases: [ alias ],
|
aliases: [ M.exported ? from_moz_alias(M.exported) : new AST_String({
|
||||||
keys: [ "*" ],
|
start: start,
|
||||||
path: M.source.value,
|
value: "*",
|
||||||
|
end: end,
|
||||||
|
}) ],
|
||||||
|
keys: [ new AST_String({
|
||||||
|
start: start,
|
||||||
|
value: "*",
|
||||||
|
end: end,
|
||||||
|
}) ],
|
||||||
|
path: from_moz(M.source),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
ExportDefaultDeclaration: function(M) {
|
ExportDefaultDeclaration: function(M) {
|
||||||
@@ -359,15 +368,15 @@
|
|||||||
if (M.source) {
|
if (M.source) {
|
||||||
var aliases = [], keys = [];
|
var aliases = [], keys = [];
|
||||||
M.specifiers.forEach(function(prop) {
|
M.specifiers.forEach(function(prop) {
|
||||||
aliases.push(read_name(prop.exported));
|
aliases.push(from_moz_alias(prop.exported));
|
||||||
keys.push(read_name(prop.local));
|
keys.push(from_moz_alias(prop.local));
|
||||||
});
|
});
|
||||||
return new AST_ExportForeign({
|
return new AST_ExportForeign({
|
||||||
start: my_start_token(M),
|
start: my_start_token(M),
|
||||||
end: my_end_token(M),
|
end: my_end_token(M),
|
||||||
aliases: aliases,
|
aliases: aliases,
|
||||||
keys: keys,
|
keys: keys,
|
||||||
path: M.source.value,
|
path: from_moz(M.source),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return new AST_ExportReferences({
|
return new AST_ExportReferences({
|
||||||
@@ -375,38 +384,48 @@
|
|||||||
end: my_end_token(M),
|
end: my_end_token(M),
|
||||||
properties: M.specifiers.map(function(prop) {
|
properties: M.specifiers.map(function(prop) {
|
||||||
var sym = new AST_SymbolExport(from_moz(prop.local));
|
var sym = new AST_SymbolExport(from_moz(prop.local));
|
||||||
sym.alias = read_name(prop.exported);
|
sym.alias = from_moz_alias(prop.exported);
|
||||||
return sym;
|
return sym;
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
ImportDeclaration: function(M) {
|
ImportDeclaration: function(M) {
|
||||||
|
var start = my_start_token(M);
|
||||||
|
var end = my_end_token(M);
|
||||||
var all = null, def = null, props = null;
|
var all = null, def = null, props = null;
|
||||||
M.specifiers.forEach(function(prop) {
|
M.specifiers.forEach(function(prop) {
|
||||||
var sym = new AST_SymbolImport(from_moz(prop.local));
|
var sym = new AST_SymbolImport(from_moz(prop.local));
|
||||||
switch (prop.type) {
|
switch (prop.type) {
|
||||||
case "ImportDefaultSpecifier":
|
case "ImportDefaultSpecifier":
|
||||||
def = sym;
|
def = sym;
|
||||||
def.key = "";
|
def.key = new AST_String({
|
||||||
|
start: start,
|
||||||
|
value: "",
|
||||||
|
end: end,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "ImportNamespaceSpecifier":
|
case "ImportNamespaceSpecifier":
|
||||||
all = sym;
|
all = sym;
|
||||||
all.key = "*";
|
all.key = new AST_String({
|
||||||
|
start: start,
|
||||||
|
value: "*",
|
||||||
|
end: end,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sym.key = prop.imported.name || syn.name;
|
sym.key = from_moz_alias(prop.imported);
|
||||||
if (!props) props = [];
|
if (!props) props = [];
|
||||||
props.push(sym);
|
props.push(sym);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return new AST_Import({
|
return new AST_Import({
|
||||||
start: my_start_token(M),
|
start: start,
|
||||||
end: my_end_token(M),
|
end: end,
|
||||||
all: all,
|
all: all,
|
||||||
default: def,
|
default: def,
|
||||||
properties: props,
|
properties: props,
|
||||||
path: M.source.value,
|
path: from_moz(M.source),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
ImportExpression: function(M) {
|
ImportExpression: function(M) {
|
||||||
@@ -797,38 +816,26 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
def_to_moz(AST_ExportForeign, function To_Moz_ExportAllDeclaration_ExportNamedDeclaration(M) {
|
def_to_moz(AST_ExportForeign, function To_Moz_ExportAllDeclaration_ExportNamedDeclaration(M) {
|
||||||
if (M.keys[0] == "*") return {
|
if (M.keys[0].value == "*") return {
|
||||||
type: "ExportAllDeclaration",
|
type: "ExportAllDeclaration",
|
||||||
exported: M.aliases[0] == "*" ? null : {
|
exported: M.aliases[0].value == "*" ? null : to_moz_alias(M.aliases[0]),
|
||||||
type: "Identifier",
|
source: to_moz(M.path),
|
||||||
name: M.aliases[0],
|
|
||||||
},
|
|
||||||
source: {
|
|
||||||
type: "Literal",
|
|
||||||
value: M.path,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
var specifiers = [];
|
var specifiers = [];
|
||||||
for (var i = 0; i < M.aliases.length; i++) {
|
for (var i = 0; i < M.aliases.length; i++) {
|
||||||
specifiers.push({
|
specifiers.push(set_moz_loc({
|
||||||
|
start: M.keys[i].start,
|
||||||
|
end: M.aliases[i].end,
|
||||||
|
}, {
|
||||||
type: "ExportSpecifier",
|
type: "ExportSpecifier",
|
||||||
exported: {
|
local: to_moz_alias(M.keys[i]),
|
||||||
type: "Identifier",
|
exported: to_moz_alias(M.aliases[i]),
|
||||||
name: M.aliases[i],
|
}));
|
||||||
},
|
|
||||||
local: {
|
|
||||||
type: "Identifier",
|
|
||||||
name: M.keys[i],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: "ExportNamedDeclaration",
|
type: "ExportNamedDeclaration",
|
||||||
specifiers: specifiers,
|
specifiers: specifiers,
|
||||||
source: {
|
source: to_moz(M.path),
|
||||||
type: "Literal",
|
|
||||||
value: M.path,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -836,44 +843,41 @@
|
|||||||
return {
|
return {
|
||||||
type: "ExportNamedDeclaration",
|
type: "ExportNamedDeclaration",
|
||||||
specifiers: M.properties.map(function(prop) {
|
specifiers: M.properties.map(function(prop) {
|
||||||
return {
|
return set_moz_loc({
|
||||||
|
start: prop.start,
|
||||||
|
end: prop.alias.end,
|
||||||
|
}, {
|
||||||
type: "ExportSpecifier",
|
type: "ExportSpecifier",
|
||||||
local: to_moz(prop),
|
local: to_moz(prop),
|
||||||
exported: {
|
exported: to_moz_alias(prop.alias),
|
||||||
type: "Identifier",
|
});
|
||||||
name: prop.alias,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
def_to_moz(AST_Import, function To_Moz_ImportDeclaration(M) {
|
def_to_moz(AST_Import, function To_Moz_ImportDeclaration(M) {
|
||||||
var specifiers = M.properties ? M.properties.map(function(prop) {
|
var specifiers = M.properties ? M.properties.map(function(prop) {
|
||||||
return {
|
return set_moz_loc({
|
||||||
|
start: prop.key.start,
|
||||||
|
end: prop.end,
|
||||||
|
}, {
|
||||||
type: "ImportSpecifier",
|
type: "ImportSpecifier",
|
||||||
local: to_moz(prop),
|
local: to_moz(prop),
|
||||||
imported: {
|
imported: to_moz_alias(prop.key),
|
||||||
type: "Identifier",
|
});
|
||||||
name: prop.key,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}) : [];
|
}) : [];
|
||||||
if (M.all) specifiers.unshift({
|
if (M.all) specifiers.unshift(set_moz_loc(M.all, {
|
||||||
type: "ImportNamespaceSpecifier",
|
type: "ImportNamespaceSpecifier",
|
||||||
local: to_moz(M.all),
|
local: to_moz(M.all),
|
||||||
});
|
}));
|
||||||
if (M.default) specifiers.unshift({
|
if (M.default) specifiers.unshift(set_moz_loc(M.default, {
|
||||||
type: "ImportDefaultSpecifier",
|
type: "ImportDefaultSpecifier",
|
||||||
local: to_moz(M.default),
|
local: to_moz(M.default),
|
||||||
});
|
}));
|
||||||
return {
|
return {
|
||||||
type: "ImportDeclaration",
|
type: "ImportDeclaration",
|
||||||
specifiers: specifiers,
|
specifiers: specifiers,
|
||||||
source: {
|
source: to_moz(M.path),
|
||||||
type: "Literal",
|
|
||||||
value: M.path,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1220,6 +1224,14 @@
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function from_moz_alias(moz) {
|
||||||
|
return new AST_String({
|
||||||
|
start: my_start_token(moz),
|
||||||
|
value: read_name(moz),
|
||||||
|
end: my_end_token(moz),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
AST_Node.from_mozilla_ast = function(node) {
|
AST_Node.from_mozilla_ast = function(node) {
|
||||||
var save_stack = FROM_MOZ_STACK;
|
var save_stack = FROM_MOZ_STACK;
|
||||||
FROM_MOZ_STACK = [];
|
FROM_MOZ_STACK = [];
|
||||||
@@ -1271,6 +1283,13 @@
|
|||||||
return node != null ? node.to_mozilla_ast() : null;
|
return node != null ? node.to_mozilla_ast() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function to_moz_alias(alias) {
|
||||||
|
return is_identifier_string(alias.value) ? set_moz_loc(alias, {
|
||||||
|
type: "Identifier",
|
||||||
|
name: alias.value,
|
||||||
|
}) : to_moz(alias);
|
||||||
|
}
|
||||||
|
|
||||||
function to_moz_block(node) {
|
function to_moz_block(node) {
|
||||||
return {
|
return {
|
||||||
type: "BlockStatement",
|
type: "BlockStatement",
|
||||||
|
|||||||
@@ -1061,6 +1061,14 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
|
function print_alias(alias, output) {
|
||||||
|
var value = alias.value;
|
||||||
|
if (value == "*" || is_identifier_string(value)) {
|
||||||
|
output.print_name(value);
|
||||||
|
} else {
|
||||||
|
output.print_string(value, alias.quote);
|
||||||
|
}
|
||||||
|
}
|
||||||
DEFPRINT(AST_ExportForeign, function(output) {
|
DEFPRINT(AST_ExportForeign, function(output) {
|
||||||
var self = this;
|
var self = this;
|
||||||
output.print("export");
|
output.print("export");
|
||||||
@@ -1068,7 +1076,7 @@ function OutputStream(options) {
|
|||||||
var len = self.keys.length;
|
var len = self.keys.length;
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
print_braced_empty(self, output);
|
print_braced_empty(self, output);
|
||||||
} else if (self.keys[0] == "*") {
|
} else if (self.keys[0].value == "*") {
|
||||||
print_entry(0);
|
print_entry(0);
|
||||||
} else output.with_block(function() {
|
} else output.with_block(function() {
|
||||||
output.indent();
|
output.indent();
|
||||||
@@ -1084,18 +1092,18 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
output.print("from");
|
output.print("from");
|
||||||
output.space();
|
output.space();
|
||||||
output.print_string(self.path, self.quote);
|
self.path.print(output);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
|
|
||||||
function print_entry(index) {
|
function print_entry(index) {
|
||||||
var alias = self.aliases[index];
|
var alias = self.aliases[index];
|
||||||
var key = self.keys[index];
|
var key = self.keys[index];
|
||||||
output.print_name(key);
|
print_alias(key, output);
|
||||||
if (alias != key) {
|
if (alias.value != key.value) {
|
||||||
output.space();
|
output.space();
|
||||||
output.print("as");
|
output.print("as");
|
||||||
output.space();
|
output.space();
|
||||||
output.print_name(alias);
|
print_alias(alias, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1124,7 +1132,7 @@ function OutputStream(options) {
|
|||||||
output.print("from");
|
output.print("from");
|
||||||
output.space();
|
output.space();
|
||||||
}
|
}
|
||||||
output.print_string(self.path, self.quote);
|
self.path.print(output);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1734,19 +1742,19 @@ function OutputStream(options) {
|
|||||||
var name = get_symbol_name(self);
|
var name = get_symbol_name(self);
|
||||||
output.print_name(name);
|
output.print_name(name);
|
||||||
var alias = self.alias;
|
var alias = self.alias;
|
||||||
if (alias != name) {
|
if (alias.value != name) {
|
||||||
output.space();
|
output.space();
|
||||||
output.print("as");
|
output.print("as");
|
||||||
output.space();
|
output.space();
|
||||||
output.print_name(alias);
|
print_alias(alias, output);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_SymbolImport, function(output) {
|
DEFPRINT(AST_SymbolImport, function(output) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var name = get_symbol_name(self);
|
var name = get_symbol_name(self);
|
||||||
var key = self.key;
|
var key = self.key;
|
||||||
if (key && key != name) {
|
if (key.value && key.value != name) {
|
||||||
output.print_name(key);
|
print_alias(key, output);
|
||||||
output.space();
|
output.space();
|
||||||
output.print("as");
|
output.print("as");
|
||||||
output.space();
|
output.space();
|
||||||
|
|||||||
85
lib/parse.js
85
lib/parse.js
@@ -1442,28 +1442,41 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function is_alias() {
|
function is_alias() {
|
||||||
return is("name") || is_identifier_string(S.token.value);
|
return is("name") || is("string") || is_identifier_string(S.token.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_string(token) {
|
||||||
|
return new AST_String({
|
||||||
|
start: token,
|
||||||
|
quote: token.quote,
|
||||||
|
value: token.value,
|
||||||
|
end: token,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function as_path() {
|
||||||
|
var path = S.token;
|
||||||
|
expect_token("string");
|
||||||
|
semicolon();
|
||||||
|
return make_string(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
function export_() {
|
function export_() {
|
||||||
if (is("operator", "*")) {
|
if (is("operator", "*")) {
|
||||||
|
var key = S.token;
|
||||||
|
var alias = key;
|
||||||
next();
|
next();
|
||||||
var alias = "*";
|
|
||||||
if (is("name", "as")) {
|
if (is("name", "as")) {
|
||||||
next();
|
next();
|
||||||
if (!is_alias()) expect_token("name");
|
if (!is_alias()) expect_token("name");
|
||||||
alias = S.token.value;
|
alias = S.token;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
expect_token("name", "from");
|
expect_token("name", "from");
|
||||||
var path = S.token;
|
|
||||||
expect_token("string");
|
|
||||||
semicolon();
|
|
||||||
return new AST_ExportForeign({
|
return new AST_ExportForeign({
|
||||||
aliases: [ alias ],
|
aliases: [ make_string(alias) ],
|
||||||
keys: [ "*" ],
|
keys: [ make_string(key) ],
|
||||||
path: path.value,
|
path: as_path(),
|
||||||
quote: path.quote,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (is("punc", "{")) {
|
if (is("punc", "{")) {
|
||||||
@@ -1477,26 +1490,20 @@ function parse($TEXT, options) {
|
|||||||
if (is("name", "as")) {
|
if (is("name", "as")) {
|
||||||
next();
|
next();
|
||||||
if (!is_alias()) expect_token("name");
|
if (!is_alias()) expect_token("name");
|
||||||
aliases.push(S.token.value);
|
aliases.push(S.token);
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
aliases.push(key.value);
|
aliases.push(key);
|
||||||
}
|
}
|
||||||
if (!is("punc", "}")) expect(",");
|
if (!is("punc", "}")) expect(",");
|
||||||
}
|
}
|
||||||
expect("}");
|
expect("}");
|
||||||
if (is("name", "from")) {
|
if (is("name", "from")) {
|
||||||
next();
|
next();
|
||||||
var path = S.token;
|
|
||||||
expect_token("string");
|
|
||||||
semicolon();
|
|
||||||
return new AST_ExportForeign({
|
return new AST_ExportForeign({
|
||||||
aliases: aliases,
|
aliases: aliases.map(make_string),
|
||||||
keys: keys.map(function(token) {
|
keys: keys.map(make_string),
|
||||||
return token.value;
|
path: as_path(),
|
||||||
}),
|
|
||||||
path: path.value,
|
|
||||||
quote: path.quote,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
semicolon();
|
semicolon();
|
||||||
@@ -1504,7 +1511,7 @@ function parse($TEXT, options) {
|
|||||||
properties: keys.map(function(token, index) {
|
properties: keys.map(function(token, index) {
|
||||||
if (!is_token(token, "name")) token_error(token, "Name expected");
|
if (!is_token(token, "name")) token_error(token, "Name expected");
|
||||||
var sym = _make_symbol(AST_SymbolExport, token);
|
var sym = _make_symbol(AST_SymbolExport, token);
|
||||||
sym.alias = aliases[index];
|
sym.alias = make_string(aliases[index]);
|
||||||
return sym;
|
return sym;
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -1594,26 +1601,42 @@ function parse($TEXT, options) {
|
|||||||
var all = null;
|
var all = null;
|
||||||
var def = as_symbol(AST_SymbolImport, true);
|
var def = as_symbol(AST_SymbolImport, true);
|
||||||
var props = null;
|
var props = null;
|
||||||
if (def ? (def.key = "", is("punc", ",") && next()) : !is("string")) {
|
var cont;
|
||||||
|
if (def) {
|
||||||
|
def.key = new AST_String({
|
||||||
|
start: def.start,
|
||||||
|
value: "",
|
||||||
|
end: def.end,
|
||||||
|
});
|
||||||
|
if (cont = is("punc", ",")) next();
|
||||||
|
} else {
|
||||||
|
cont = !is("string");
|
||||||
|
}
|
||||||
|
if (cont) {
|
||||||
if (is("operator", "*")) {
|
if (is("operator", "*")) {
|
||||||
|
var key = S.token;
|
||||||
next();
|
next();
|
||||||
expect_token("name", "as");
|
expect_token("name", "as");
|
||||||
all = as_symbol(AST_SymbolImport);
|
all = as_symbol(AST_SymbolImport);
|
||||||
all.key = "*";
|
all.key = make_string(key);
|
||||||
} else {
|
} else {
|
||||||
expect("{");
|
expect("{");
|
||||||
props = [];
|
props = [];
|
||||||
while (is_alias()) {
|
while (is_alias()) {
|
||||||
var alias;
|
var alias;
|
||||||
if (is_token(peek(), "name", "as")) {
|
if (is_token(peek(), "name", "as")) {
|
||||||
var key = S.token.value;
|
var key = S.token;
|
||||||
next();
|
next();
|
||||||
next();
|
next();
|
||||||
alias = as_symbol(AST_SymbolImport);
|
alias = as_symbol(AST_SymbolImport);
|
||||||
alias.key = key;
|
alias.key = make_string(key);
|
||||||
} else {
|
} else {
|
||||||
alias = as_symbol(AST_SymbolImport);
|
alias = as_symbol(AST_SymbolImport);
|
||||||
alias.key = alias.name;
|
alias.key = new AST_String({
|
||||||
|
start: alias.start,
|
||||||
|
value: alias.name,
|
||||||
|
end: alias.end,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
props.push(alias);
|
props.push(alias);
|
||||||
if (!is("punc", "}")) expect(",");
|
if (!is("punc", "}")) expect(",");
|
||||||
@@ -1622,15 +1645,11 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (all || def || props) expect_token("name", "from");
|
if (all || def || props) expect_token("name", "from");
|
||||||
var path = S.token;
|
|
||||||
expect_token("string");
|
|
||||||
semicolon();
|
|
||||||
return new AST_Import({
|
return new AST_Import({
|
||||||
all: all,
|
all: all,
|
||||||
default: def,
|
default: def,
|
||||||
path: path.value,
|
path: as_path(),
|
||||||
properties: props,
|
properties: props,
|
||||||
quote: path.quote,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1808,7 +1827,7 @@ function parse($TEXT, options) {
|
|||||||
ret = new AST_BigInt({ value: value });
|
ret = new AST_BigInt({ value: value });
|
||||||
break;
|
break;
|
||||||
case "string":
|
case "string":
|
||||||
ret = new AST_String({ value : value, quote : tok.quote });
|
ret = new AST_String({ value: value, quote: tok.quote });
|
||||||
break;
|
break;
|
||||||
case "regexp":
|
case "regexp":
|
||||||
ret = new AST_RegExp({ value: value });
|
ret = new AST_RegExp({ value: value });
|
||||||
|
|||||||
@@ -109,6 +109,17 @@ foreign: {
|
|||||||
expect_exact: 'export*from"foo";export{}from"bar";export*as a from"baz";export{default}from"moo";export{b,c as case,default as delete,d}from"moz";'
|
expect_exact: 'export*from"foo";export{}from"bar";export*as a from"baz";export{default}from"moo";export{b,c as case,default as delete,d}from"moz";'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
non_identifiers: {
|
||||||
|
beautify = {
|
||||||
|
quote_style: 3,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
export * as "42" from 'foo';
|
||||||
|
export { '42', "delete" as 'foo' } from "bar";
|
||||||
|
}
|
||||||
|
expect_exact: "export*as\"42\"from'foo';export{'42',delete as foo}from\"bar\";"
|
||||||
|
}
|
||||||
|
|
||||||
same_quotes: {
|
same_quotes: {
|
||||||
beautify = {
|
beautify = {
|
||||||
beautify: true,
|
beautify: true,
|
||||||
|
|||||||
@@ -40,6 +40,17 @@ default_keys: {
|
|||||||
expect_exact: 'import foo,{bar}from"baz";'
|
expect_exact: 'import foo,{bar}from"baz";'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
non_identifiers: {
|
||||||
|
beautify = {
|
||||||
|
quote_style: 3,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
import { '42' as foo } from "bar";
|
||||||
|
import { "foo" as bar } from 'baz';
|
||||||
|
}
|
||||||
|
expect_exact: "import{'42'as foo}from\"bar\";import{foo as bar}from'baz';"
|
||||||
|
}
|
||||||
|
|
||||||
dynamic: {
|
dynamic: {
|
||||||
input: {
|
input: {
|
||||||
(async a => await import(a))("foo").then(bar);
|
(async a => await import(a))("foo").then(bar);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
var acorn = require("acorn");
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var UglifyJS = require("../node");
|
var UglifyJS = require("../node");
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ describe("export", function() {
|
|||||||
"export { * };",
|
"export { * };",
|
||||||
"export { * as A };",
|
"export { * as A };",
|
||||||
"export { 42 as A };",
|
"export { 42 as A };",
|
||||||
|
"export { 'A' as B };",
|
||||||
"export { A as B-C };",
|
"export { A as B-C };",
|
||||||
"export { default as A };",
|
"export { default as A };",
|
||||||
].forEach(function(code) {
|
].forEach(function(code) {
|
||||||
@@ -51,8 +53,11 @@ describe("export", function() {
|
|||||||
it("Should reject invalid `export ... from ...` statement syntax", function() {
|
it("Should reject invalid `export ... from ...` statement syntax", function() {
|
||||||
[
|
[
|
||||||
"export from 'path';",
|
"export from 'path';",
|
||||||
|
"export A from 'path';",
|
||||||
"export * from `path`;",
|
"export * from `path`;",
|
||||||
|
"export 'A' from 'path';",
|
||||||
"export A as B from 'path';",
|
"export A as B from 'path';",
|
||||||
|
"export 'A' as B from 'path';",
|
||||||
"export default from 'path';",
|
"export default from 'path';",
|
||||||
"export { A }, B from 'path';",
|
"export { A }, B from 'path';",
|
||||||
"export * as A, B from 'path';",
|
"export * as A, B from 'path';",
|
||||||
@@ -128,4 +133,49 @@ describe("export", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should interoperate with ESTree correctly", function() {
|
||||||
|
[
|
||||||
|
"export var A = 42;",
|
||||||
|
"export default (class A {});",
|
||||||
|
"var A; export { A as '42' };",
|
||||||
|
"export { '42' } from 'path';",
|
||||||
|
"export * as '42' from 'path';",
|
||||||
|
].forEach(function(code) {
|
||||||
|
var ast = UglifyJS.parse(code);
|
||||||
|
try {
|
||||||
|
var spidermonkey = ast.to_mozilla_ast();
|
||||||
|
} catch (ex) {
|
||||||
|
assert.fail("[to_mozilla_ast] " + ex.stack);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var ast2 = UglifyJS.AST_Node.from_mozilla_ast(spidermonkey);
|
||||||
|
} catch (ex) {
|
||||||
|
assert.fail("[from_mozilla_ast] " + ex.stack);
|
||||||
|
}
|
||||||
|
assert.strictEqual(ast2.print_to_string(), ast.print_to_string(), [
|
||||||
|
"spidermonkey:",
|
||||||
|
ast.print_to_string(),
|
||||||
|
ast2.print_to_string(),
|
||||||
|
].join("\n"));
|
||||||
|
try {
|
||||||
|
var acorn_est = acorn.parse(code, {
|
||||||
|
ecmaVersion: "latest",
|
||||||
|
locations: true,
|
||||||
|
sourceType: "module",
|
||||||
|
});
|
||||||
|
} catch (ex) {
|
||||||
|
assert.fail("[acorn.parse] " + ex.stack);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var ast3 = UglifyJS.AST_Node.from_mozilla_ast(acorn_est);
|
||||||
|
} catch (ex) {
|
||||||
|
assert.fail("[from_acorn] " + ex.stack);
|
||||||
|
}
|
||||||
|
assert.strictEqual(ast3.print_to_string(), ast.print_to_string(), [
|
||||||
|
"acorn:",
|
||||||
|
ast.print_to_string(),
|
||||||
|
ast3.print_to_string(),
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
var acorn = require("acorn");
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var UglifyJS = require("../node");
|
var UglifyJS = require("../node");
|
||||||
|
|
||||||
@@ -12,14 +13,21 @@ describe("import", function() {
|
|||||||
"import from 'path';",
|
"import from 'path';",
|
||||||
"if (0) import 'path';",
|
"if (0) import 'path';",
|
||||||
"import * from 'path';",
|
"import * from 'path';",
|
||||||
|
"import 'A' from 'path';",
|
||||||
|
"import A-B from 'path';",
|
||||||
"import A as B from 'path';",
|
"import A as B from 'path';",
|
||||||
"import { A }, B from 'path';",
|
"import { A }, B from 'path';",
|
||||||
|
"import * as 'A' from 'path';",
|
||||||
|
"import * as A-B from 'path';",
|
||||||
"import * as A, B from 'path';",
|
"import * as A, B from 'path';",
|
||||||
"import * as A, {} from 'path';",
|
"import * as A, {} from 'path';",
|
||||||
"import { * as A } from 'path';",
|
"import { * as A } from 'path';",
|
||||||
|
"import { * as 'A' } from 'path';",
|
||||||
|
"import { * as A-B } from 'path';",
|
||||||
"function f() { import 'path'; }",
|
"function f() { import 'path'; }",
|
||||||
"import { 42 as A } from 'path';",
|
"import { 42 as A } from 'path';",
|
||||||
"import { A-B as C } from 'path';",
|
"import { A-B as C } from 'path';",
|
||||||
|
"import { 'A' as 'B' } from 'path';",
|
||||||
].forEach(function(code) {
|
].forEach(function(code) {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
UglifyJS.parse(code);
|
UglifyJS.parse(code);
|
||||||
@@ -53,4 +61,49 @@ describe("import", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should interoperate with ESTree correctly", function() {
|
||||||
|
[
|
||||||
|
"import A from 'path';",
|
||||||
|
"import * as A from 'path';",
|
||||||
|
"import A, * as B from 'path';",
|
||||||
|
"import { '42' as A, B } from 'path';",
|
||||||
|
"import A, { '42' as B } from 'path';",
|
||||||
|
].forEach(function(code) {
|
||||||
|
var ast = UglifyJS.parse(code);
|
||||||
|
try {
|
||||||
|
var spidermonkey = ast.to_mozilla_ast();
|
||||||
|
} catch (ex) {
|
||||||
|
assert.fail("[to_mozilla_ast] " + ex.stack);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var ast2 = UglifyJS.AST_Node.from_mozilla_ast(spidermonkey);
|
||||||
|
} catch (ex) {
|
||||||
|
assert.fail("[from_mozilla_ast] " + ex.stack);
|
||||||
|
}
|
||||||
|
assert.strictEqual(ast2.print_to_string(), ast.print_to_string(), [
|
||||||
|
"spidermonkey:",
|
||||||
|
ast.print_to_string(),
|
||||||
|
ast2.print_to_string(),
|
||||||
|
].join("\n"));
|
||||||
|
try {
|
||||||
|
var acorn_est = acorn.parse(code, {
|
||||||
|
ecmaVersion: "latest",
|
||||||
|
locations: true,
|
||||||
|
sourceType: "module",
|
||||||
|
});
|
||||||
|
} catch (ex) {
|
||||||
|
assert.fail("[acorn.parse] " + ex.stack);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var ast3 = UglifyJS.AST_Node.from_mozilla_ast(acorn_est);
|
||||||
|
} catch (ex) {
|
||||||
|
assert.fail("[from_acorn] " + ex.stack);
|
||||||
|
}
|
||||||
|
assert.strictEqual(ast3.print_to_string(), ast.print_to_string(), [
|
||||||
|
"acorn:",
|
||||||
|
ast.print_to_string(),
|
||||||
|
ast3.print_to_string(),
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user