terser 5.16.0 → 5.16.2

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.
@@ -205,9 +205,10 @@ export function trim_unreachable_code(compressor, stat, target) {
205
205
 
206
206
  /** Tighten a bunch of statements together, and perform statement-level optimization. */
207
207
  export function tighten_body(statements, compressor) {
208
- var in_loop, in_try;
209
- var scope = compressor.find_parent(AST_Scope).get_defun_scope();
210
- find_loop_scope_try();
208
+ const nearest_scope = compressor.find_scope();
209
+ const defun_scope = nearest_scope.get_defun_scope();
210
+ const { in_loop, in_try } = find_loop_scope_try();
211
+
211
212
  var CHANGED, max_iter = 10;
212
213
  do {
213
214
  CHANGED = false;
@@ -231,19 +232,20 @@ export function tighten_body(statements, compressor) {
231
232
  } while (CHANGED && max_iter-- > 0);
232
233
 
233
234
  function find_loop_scope_try() {
234
- var node = compressor.self(), level = 0;
235
+ var node = compressor.self(), level = 0, in_loop = false, in_try = false;
235
236
  do {
236
237
  if (node instanceof AST_Catch || node instanceof AST_Finally) {
237
238
  level++;
238
239
  } else if (node instanceof AST_IterationStatement) {
239
240
  in_loop = true;
240
241
  } else if (node instanceof AST_Scope) {
241
- scope = node;
242
242
  break;
243
243
  } else if (node instanceof AST_Try) {
244
244
  in_try = true;
245
245
  }
246
246
  } while (node = compressor.parent(level++));
247
+
248
+ return { in_loop, in_try };
247
249
  }
248
250
 
249
251
  // Search from right to left for assignment-like expressions:
@@ -255,7 +257,7 @@ export function tighten_body(statements, compressor) {
255
257
  // Will not attempt to collapse assignments into or past code blocks
256
258
  // which are not sequentially executed, e.g. loops and conditionals.
257
259
  function collapse(statements, compressor) {
258
- if (scope.pinned())
260
+ if (nearest_scope.pinned() || defun_scope.pinned())
259
261
  return statements;
260
262
  var args;
261
263
  var candidates = [];
@@ -319,10 +321,11 @@ export function tighten_body(statements, compressor) {
319
321
  stop_if_hit = parent;
320
322
  }
321
323
  // Replace variable with assignment when found
322
- if (can_replace
324
+ if (
325
+ can_replace
323
326
  && !(node instanceof AST_SymbolDeclaration)
324
327
  && lhs.equivalent_to(node)
325
- && !shadows(node.scope, lvalues)
328
+ && !shadows(scanner.find_scope() || nearest_scope, lvalues)
326
329
  ) {
327
330
  if (stop_if_hit) {
328
331
  abort = true;
@@ -527,9 +530,9 @@ export function tighten_body(statements, compressor) {
527
530
  return true;
528
531
  if (node instanceof AST_SymbolRef && (fn.variables.has(node.name) || redefined_within_scope(node.definition(), fn))) {
529
532
  var s = node.definition().scope;
530
- if (s !== scope)
533
+ if (s !== defun_scope)
531
534
  while (s = s.parent_scope) {
532
- if (s === scope)
535
+ if (s === defun_scope)
533
536
  return true;
534
537
  }
535
538
  return found = true;
@@ -851,7 +854,7 @@ export function tighten_body(statements, compressor) {
851
854
  while (lhs instanceof AST_PropAccess)
852
855
  lhs = lhs.expression;
853
856
  return lhs instanceof AST_SymbolRef
854
- && lhs.definition().scope === scope
857
+ && lhs.definition().scope.get_defun_scope() === defun_scope
855
858
  && !(in_loop
856
859
  && (lvalues.has(lhs.name)
857
860
  || candidate instanceof AST_Unary
@@ -886,15 +889,11 @@ export function tighten_body(statements, compressor) {
886
889
  var def = sym.definition();
887
890
  if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun)
888
891
  return false;
889
- if (def.scope.get_defun_scope() !== scope)
892
+ if (def.scope.get_defun_scope() !== defun_scope)
890
893
  return true;
891
- return !def.references.every((ref) => {
892
- var s = ref.scope.get_defun_scope();
893
- // "block" scope within AST_Catch
894
- if (s.TYPE == "Scope")
895
- s = s.parent_scope;
896
- return s === scope;
897
- });
894
+ return def.references.some((ref) =>
895
+ ref.scope.get_defun_scope() !== defun_scope
896
+ );
898
897
  }
899
898
 
900
899
  function side_effects_external(node, lhs) {
@@ -910,18 +909,20 @@ export function tighten_body(statements, compressor) {
910
909
  if (node instanceof AST_Sub)
911
910
  return side_effects_external(node.expression, true);
912
911
  if (node instanceof AST_SymbolRef)
913
- return node.definition().scope !== scope;
912
+ return node.definition().scope.get_defun_scope() !== defun_scope;
914
913
  }
915
914
  return false;
916
915
  }
917
916
 
918
- function shadows(newScope, lvalues) {
919
- for (const {def} of lvalues.values()) {
920
- let current = newScope;
921
- while (current && current !== def.scope) {
922
- let nested_def = current.variables.get(def.name);
923
- if (nested_def && nested_def !== def) return true;
924
- current = current.parent_scope;
917
+ /**
918
+ * Will any of the pulled-in lvalues shadow a variable in newScope or parents?
919
+ * similar to scope_encloses_variables_in_this_scope */
920
+ function shadows(my_scope, lvalues) {
921
+ for (const { def } of lvalues.values()) {
922
+ const looked_up = my_scope.find_variable(def.name);
923
+ if (looked_up) {
924
+ if (looked_up === def) continue;
925
+ return true;
925
926
  }
926
927
  }
927
928
  return false;
@@ -1343,7 +1344,7 @@ export function tighten_body(statements, compressor) {
1343
1344
  break;
1344
1345
  if (def.name.name != sym.name)
1345
1346
  break;
1346
- if (!node.right.is_constant_expression(scope))
1347
+ if (!node.right.is_constant_expression(nearest_scope))
1347
1348
  break;
1348
1349
  var prop = node.left.property;
1349
1350
  if (prop instanceof AST_Node) {
@@ -1403,14 +1404,21 @@ export function tighten_body(statements, compressor) {
1403
1404
  CHANGED = true;
1404
1405
  stat.init = exprs.length ? make_sequence(stat.init, exprs) : null;
1405
1406
  statements[++j] = stat;
1406
- } else if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) {
1407
+ } else if (
1408
+ prev instanceof AST_Var
1409
+ && (!stat.init || stat.init.TYPE == prev.TYPE)
1410
+ ) {
1407
1411
  if (stat.init) {
1408
1412
  prev.definitions = prev.definitions.concat(stat.init.definitions);
1409
1413
  }
1410
1414
  stat.init = prev;
1411
1415
  statements[j] = stat;
1412
1416
  CHANGED = true;
1413
- } else if (defs && stat.init && defs.TYPE == stat.init.TYPE && declarations_only(stat.init)) {
1417
+ } else if (
1418
+ defs instanceof AST_Var
1419
+ && stat.init instanceof AST_Var
1420
+ && declarations_only(stat.init)
1421
+ ) {
1414
1422
  defs.definitions = defs.definitions.concat(stat.init.definitions);
1415
1423
  stat.init = null;
1416
1424
  statements[++j] = stat;
package/lib/minify.js CHANGED
@@ -19,12 +19,15 @@ import {
19
19
  reserve_quoted_keys,
20
20
  } from "./propmangle.js";
21
21
 
22
- var to_ascii = typeof atob == "undefined" ? function(b64) {
23
- return Buffer.from(b64, "base64").toString();
24
- } : atob;
25
- var to_base64 = typeof btoa == "undefined" ? function(str) {
26
- return Buffer.from(str).toString("base64");
27
- } : btoa;
22
+ // to/from base64 functions
23
+ // Prefer built-in Buffer, if available, then use hack
24
+ // https://developer.mozilla.org/en-US/docs/Glossary/Base64#The_Unicode_Problem
25
+ var to_ascii = typeof Buffer !== "undefined"
26
+ ? (b64) => Buffer.from(b64, "base64").toString()
27
+ : (b64) => decodeURIComponent(escape(atob(b64)));
28
+ var to_base64 = typeof Buffer !== "undefined"
29
+ ? (str) => Buffer.from(str).toString("base64")
30
+ : (str) => btoa(unescape(encodeURIComponent(str)));
28
31
 
29
32
  function read_source_map(code) {
30
33
  var match = /(?:^|[^.])\/\/# sourceMappingURL=data:application\/json(;[\w=-]*)?;base64,([+/0-9A-Za-z]*=*)\s*$/.exec(code);
@@ -529,24 +529,11 @@ import { is_basic_identifier_string } from "./parse.js";
529
529
  var imported_name = null;
530
530
  var imported_names = null;
531
531
  M.specifiers.forEach(function (specifier) {
532
- if (specifier.type === "ImportSpecifier") {
532
+ if (specifier.type === "ImportSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
533
533
  if (!imported_names) { imported_names = []; }
534
- imported_names.push(new AST_NameMapping({
535
- start: my_start_token(specifier),
536
- end: my_end_token(specifier),
537
- foreign_name: from_moz(specifier.imported),
538
- name: from_moz(specifier.local)
539
- }));
534
+ imported_names.push(from_moz(specifier));
540
535
  } else if (specifier.type === "ImportDefaultSpecifier") {
541
- imported_name = from_moz(specifier.local);
542
- } else if (specifier.type === "ImportNamespaceSpecifier") {
543
- if (!imported_names) { imported_names = []; }
544
- imported_names.push(new AST_NameMapping({
545
- start: my_start_token(specifier),
546
- end: my_end_token(specifier),
547
- foreign_name: new AST_SymbolImportForeign({ name: "*" }),
548
- name: from_moz(specifier.local)
549
- }));
536
+ imported_name = from_moz(specifier);
550
537
  }
551
538
  });
552
539
  return new AST_Import({
@@ -559,14 +546,39 @@ import { is_basic_identifier_string } from "./parse.js";
559
546
  });
560
547
  },
561
548
 
549
+ ImportSpecifier: function(M) {
550
+ return new AST_NameMapping({
551
+ start: my_start_token(M),
552
+ end: my_end_token(M),
553
+ foreign_name: from_moz(M.imported),
554
+ name: from_moz(M.local)
555
+ });
556
+ },
557
+
558
+ ImportDefaultSpecifier: function(M) {
559
+ return from_moz(M.local);
560
+ },
561
+
562
+ ImportNamespaceSpecifier: function(M) {
563
+ return new AST_NameMapping({
564
+ start: my_start_token(M),
565
+ end: my_end_token(M),
566
+ foreign_name: new AST_SymbolImportForeign({ name: "*" }),
567
+ name: from_moz(M.local)
568
+ });
569
+ },
570
+
562
571
  ExportAllDeclaration: function(M) {
572
+ var foreign_name = M.exported == null ?
573
+ new AST_SymbolExportForeign({ name: "*" }) :
574
+ from_moz(M.exported);
563
575
  return new AST_Export({
564
576
  start: my_start_token(M),
565
577
  end: my_end_token(M),
566
578
  exported_names: [
567
579
  new AST_NameMapping({
568
580
  name: new AST_SymbolExportForeign({ name: "*" }),
569
- foreign_name: new AST_SymbolExportForeign({ name: "*" })
581
+ foreign_name: foreign_name
570
582
  })
571
583
  ],
572
584
  module_name: from_moz(M.source),
@@ -580,10 +592,7 @@ import { is_basic_identifier_string } from "./parse.js";
580
592
  end: my_end_token(M),
581
593
  exported_definition: from_moz(M.declaration),
582
594
  exported_names: M.specifiers && M.specifiers.length ? M.specifiers.map(function (specifier) {
583
- return new AST_NameMapping({
584
- foreign_name: from_moz(specifier.exported),
585
- name: from_moz(specifier.local)
586
- });
595
+ return from_moz(specifier);
587
596
  }) : null,
588
597
  module_name: from_moz(M.source),
589
598
  assert_clause: assert_clause_from_moz(M.assertions)
@@ -599,6 +608,13 @@ import { is_basic_identifier_string } from "./parse.js";
599
608
  });
600
609
  },
601
610
 
611
+ ExportSpecifier: function(M) {
612
+ return new AST_NameMapping({
613
+ foreign_name: from_moz(M.exported),
614
+ name: from_moz(M.local)
615
+ });
616
+ },
617
+
602
618
  Literal: function(M) {
603
619
  var val = M.value, args = {
604
620
  start : my_start_token(M),
@@ -624,6 +640,22 @@ import { is_basic_identifier_string } from "./parse.js";
624
640
  if (val === null) return new AST_Null(args);
625
641
  switch (typeof val) {
626
642
  case "string":
643
+ args.quote = "\"";
644
+ var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
645
+ if (p.type == "ImportSpecifier") {
646
+ args.name = val;
647
+ return new AST_SymbolImportForeign(args);
648
+ } else if (p.type == "ExportSpecifier") {
649
+ args.name = val;
650
+ if (M == p.exported) {
651
+ return new AST_SymbolExportForeign(args);
652
+ } else {
653
+ return new AST_SymbolExport(args);
654
+ }
655
+ } else if (p.type == "ExportAllDeclaration" && M == p.exported) {
656
+ args.name = val;
657
+ return new AST_SymbolExportForeign(args);
658
+ }
627
659
  args.value = val;
628
660
  return new AST_String(args);
629
661
  case "number":
@@ -1328,10 +1360,17 @@ import { is_basic_identifier_string } from "./parse.js";
1328
1360
 
1329
1361
  def_to_moz(AST_Export, function To_Moz_ExportDeclaration(M) {
1330
1362
  if (M.exported_names) {
1331
- if (M.exported_names[0].name.name === "*") {
1363
+ var first_exported = M.exported_names[0];
1364
+ var first_exported_name = first_exported.name;
1365
+ if (first_exported_name.name === "*" && !first_exported_name.quote) {
1366
+ var foreign_name = first_exported.foreign_name;
1367
+ var exported = foreign_name.name === "*" && !foreign_name.quote
1368
+ ? null
1369
+ : to_moz(foreign_name);
1332
1370
  return {
1333
1371
  type: "ExportAllDeclaration",
1334
1372
  source: to_moz(M.module_name),
1373
+ exported: exported,
1335
1374
  assertions: assert_clause_to_moz(M.assert_clause)
1336
1375
  };
1337
1376
  }
@@ -1363,19 +1402,22 @@ import { is_basic_identifier_string } from "./parse.js";
1363
1402
  local: to_moz(M.imported_name)
1364
1403
  });
1365
1404
  }
1366
- if (M.imported_names && M.imported_names[0].foreign_name.name === "*") {
1367
- specifiers.push({
1368
- type: "ImportNamespaceSpecifier",
1369
- local: to_moz(M.imported_names[0].name)
1370
- });
1371
- } else if (M.imported_names) {
1372
- M.imported_names.forEach(function(name_mapping) {
1405
+ if (M.imported_names) {
1406
+ var first_imported_foreign_name = M.imported_names[0].foreign_name;
1407
+ if (first_imported_foreign_name.name === "*" && !first_imported_foreign_name.quote) {
1373
1408
  specifiers.push({
1374
- type: "ImportSpecifier",
1375
- local: to_moz(name_mapping.name),
1376
- imported: to_moz(name_mapping.foreign_name)
1409
+ type: "ImportNamespaceSpecifier",
1410
+ local: to_moz(M.imported_names[0].name)
1377
1411
  });
1378
- });
1412
+ } else {
1413
+ M.imported_names.forEach(function(name_mapping) {
1414
+ specifiers.push({
1415
+ type: "ImportSpecifier",
1416
+ local: to_moz(name_mapping.name),
1417
+ imported: to_moz(name_mapping.foreign_name)
1418
+ });
1419
+ });
1420
+ }
1379
1421
  }
1380
1422
  return {
1381
1423
  type: "ImportDeclaration",
@@ -1639,7 +1681,14 @@ import { is_basic_identifier_string } from "./parse.js";
1639
1681
  });
1640
1682
 
1641
1683
  def_to_moz(AST_Symbol, function To_Moz_Identifier(M, parent) {
1642
- if (M instanceof AST_SymbolMethod && parent.quote) {
1684
+ if (
1685
+ (M instanceof AST_SymbolMethod && parent.quote) ||
1686
+ ((
1687
+ M instanceof AST_SymbolImportForeign ||
1688
+ M instanceof AST_SymbolExportForeign ||
1689
+ M instanceof AST_SymbolExport
1690
+ ) && M.quote)
1691
+ ) {
1643
1692
  return {
1644
1693
  type: "Literal",
1645
1694
  value: M.name
package/lib/output.js CHANGED
@@ -1225,7 +1225,7 @@ function OutputStream(options) {
1225
1225
  }
1226
1226
 
1227
1227
  AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
1228
- force_statement(this.body, output);
1228
+ print_maybe_braced_body(this.body, output);
1229
1229
  });
1230
1230
 
1231
1231
  DEFPRINT(AST_Statement, function(self, output) {
@@ -1554,7 +1554,7 @@ function OutputStream(options) {
1554
1554
  b = b.body;
1555
1555
  } else break;
1556
1556
  }
1557
- force_statement(self.body, output);
1557
+ print_maybe_braced_body(self.body, output);
1558
1558
  }
1559
1559
  DEFPRINT(AST_If, function(self, output) {
1560
1560
  output.print("if");
@@ -1571,7 +1571,7 @@ function OutputStream(options) {
1571
1571
  if (self.alternative instanceof AST_If)
1572
1572
  self.alternative.print(output);
1573
1573
  else
1574
- force_statement(self.alternative, output);
1574
+ print_maybe_braced_body(self.alternative, output);
1575
1575
  } else {
1576
1576
  self._do_print_body(output);
1577
1577
  }
@@ -1681,7 +1681,9 @@ function OutputStream(options) {
1681
1681
  output.space();
1682
1682
  }
1683
1683
  if (self.imported_names) {
1684
- if (self.imported_names.length === 1 && self.imported_names[0].foreign_name.name === "*") {
1684
+ if (self.imported_names.length === 1 &&
1685
+ self.imported_names[0].foreign_name.name === "*" &&
1686
+ !self.imported_names[0].foreign_name.quote) {
1685
1687
  self.imported_names[0].print(output);
1686
1688
  } else {
1687
1689
  output.print("{");
@@ -1715,14 +1717,31 @@ function OutputStream(options) {
1715
1717
  DEFPRINT(AST_NameMapping, function(self, output) {
1716
1718
  var is_import = output.parent() instanceof AST_Import;
1717
1719
  var definition = self.name.definition();
1720
+ var foreign_name = self.foreign_name;
1718
1721
  var names_are_different =
1719
1722
  (definition && definition.mangled_name || self.name.name) !==
1720
- self.foreign_name.name;
1723
+ foreign_name.name;
1724
+ if (!names_are_different &&
1725
+ foreign_name.name === "*" &&
1726
+ foreign_name.quote != self.name.quote) {
1727
+ // export * as "*"
1728
+ names_are_different = true;
1729
+ }
1730
+ var foreign_name_is_name = foreign_name.quote == null;
1721
1731
  if (names_are_different) {
1722
1732
  if (is_import) {
1723
- output.print(self.foreign_name.name);
1733
+ if (foreign_name_is_name) {
1734
+ output.print(foreign_name.name);
1735
+ } else {
1736
+ output.print_string(foreign_name.name, foreign_name.quote);
1737
+ }
1724
1738
  } else {
1725
- self.name.print(output);
1739
+ if (self.name.quote == null) {
1740
+ self.name.print(output);
1741
+ } else {
1742
+ output.print_string(self.name.name, self.name.quote);
1743
+ }
1744
+
1726
1745
  }
1727
1746
  output.space();
1728
1747
  output.print("as");
@@ -1730,10 +1749,18 @@ function OutputStream(options) {
1730
1749
  if (is_import) {
1731
1750
  self.name.print(output);
1732
1751
  } else {
1733
- output.print(self.foreign_name.name);
1752
+ if (foreign_name_is_name) {
1753
+ output.print(foreign_name.name);
1754
+ } else {
1755
+ output.print_string(foreign_name.name, foreign_name.quote);
1756
+ }
1734
1757
  }
1735
1758
  } else {
1736
- self.name.print(output);
1759
+ if (self.name.quote == null) {
1760
+ self.name.print(output);
1761
+ } else {
1762
+ output.print_string(self.name.name, self.name.quote);
1763
+ }
1737
1764
  }
1738
1765
  });
1739
1766
 
@@ -1745,8 +1772,10 @@ function OutputStream(options) {
1745
1772
  output.space();
1746
1773
  }
1747
1774
  if (self.exported_names) {
1748
- if (self.exported_names.length === 1 && self.exported_names[0].name.name === "*") {
1749
- self.exported_names[0].print(output);
1775
+ if (self.exported_names.length === 1 &&
1776
+ self.exported_names[0].name.name === "*" &&
1777
+ !self.exported_names[0].name.quote) {
1778
+ self.exported_names[0].print(output);
1750
1779
  } else {
1751
1780
  output.print("{");
1752
1781
  self.exported_names.forEach(function(name_export, i) {
@@ -2266,12 +2295,15 @@ function OutputStream(options) {
2266
2295
  }
2267
2296
  });
2268
2297
 
2269
- function force_statement(stat, output) {
2298
+ /** if, for, while, may or may not have braces surrounding its body */
2299
+ function print_maybe_braced_body(stat, output) {
2270
2300
  if (output.option("braces")) {
2271
2301
  make_block(stat, output);
2272
2302
  } else {
2273
2303
  if (!stat || stat instanceof AST_EmptyStatement)
2274
2304
  output.force_semicolon();
2305
+ else if (stat instanceof AST_Let || stat instanceof AST_Const || stat instanceof AST_Class)
2306
+ make_block(stat, output);
2275
2307
  else
2276
2308
  stat.print(output);
2277
2309
  }
package/lib/parse.js CHANGED
@@ -2089,14 +2089,20 @@ function parse($TEXT, options) {
2089
2089
  });
2090
2090
  }
2091
2091
 
2092
+ /**
2093
+ * var
2094
+ * vardef1 = 2,
2095
+ * vardef2 = 3;
2096
+ */
2092
2097
  function vardefs(no_in, kind) {
2093
- var a = [];
2098
+ var var_defs = [];
2094
2099
  var def;
2095
2100
  for (;;) {
2096
2101
  var sym_type =
2097
2102
  kind === "var" ? AST_SymbolVar :
2098
2103
  kind === "const" ? AST_SymbolConst :
2099
2104
  kind === "let" ? AST_SymbolLet : null;
2105
+ // var { a } = b
2100
2106
  if (is("punc", "{") || is("punc", "[")) {
2101
2107
  def = new AST_VarDef({
2102
2108
  start: S.token,
@@ -2116,12 +2122,12 @@ function parse($TEXT, options) {
2116
2122
  });
2117
2123
  if (def.name.name == "import") croak("Unexpected token: import");
2118
2124
  }
2119
- a.push(def);
2125
+ var_defs.push(def);
2120
2126
  if (!is("punc", ","))
2121
2127
  break;
2122
2128
  next();
2123
2129
  }
2124
- return a;
2130
+ return var_defs;
2125
2131
  }
2126
2132
 
2127
2133
  var var_ = function(no_in) {
@@ -2548,6 +2554,7 @@ function parse($TEXT, options) {
2548
2554
 
2549
2555
  expect("{");
2550
2556
  // mark in class feild,
2557
+ const save_in_class = S.in_class;
2551
2558
  S.in_class = true;
2552
2559
  while (is("punc", ";")) { next(); } // Leading semicolons are okay in class bodies.
2553
2560
  while (!is("punc", "}")) {
@@ -2558,7 +2565,7 @@ function parse($TEXT, options) {
2558
2565
  while (is("punc", ";")) { next(); }
2559
2566
  }
2560
2567
  // mark in class feild,
2561
- S.in_class = false;
2568
+ S.in_class = save_in_class;
2562
2569
 
2563
2570
  S.input.pop_directives_stack();
2564
2571
 
@@ -2787,9 +2794,10 @@ function parse($TEXT, options) {
2787
2794
  }
2788
2795
 
2789
2796
  function map_name(is_import) {
2790
- function make_symbol(type) {
2797
+ function make_symbol(type, quote) {
2791
2798
  return new type({
2792
2799
  name: as_property_name(),
2800
+ quote: quote || undefined,
2793
2801
  start: prev(),
2794
2802
  end: prev()
2795
2803
  });
@@ -2802,16 +2810,16 @@ function parse($TEXT, options) {
2802
2810
  var name;
2803
2811
 
2804
2812
  if (is_import) {
2805
- foreign_name = make_symbol(foreign_type);
2813
+ foreign_name = make_symbol(foreign_type, start.quote);
2806
2814
  } else {
2807
- name = make_symbol(type);
2815
+ name = make_symbol(type, start.quote);
2808
2816
  }
2809
2817
  if (is("name", "as")) {
2810
2818
  next(); // The "as" word
2811
2819
  if (is_import) {
2812
2820
  name = make_symbol(type);
2813
2821
  } else {
2814
- foreign_name = make_symbol(foreign_type);
2822
+ foreign_name = make_symbol(foreign_type, S.token.quote);
2815
2823
  }
2816
2824
  } else if (is_import) {
2817
2825
  name = new type(foreign_name);
@@ -2827,20 +2835,26 @@ function parse($TEXT, options) {
2827
2835
  });
2828
2836
  }
2829
2837
 
2830
- function map_nameAsterisk(is_import, name) {
2838
+ function map_nameAsterisk(is_import, import_or_export_foreign_name) {
2831
2839
  var foreign_type = is_import ? AST_SymbolImportForeign : AST_SymbolExportForeign;
2832
2840
  var type = is_import ? AST_SymbolImport : AST_SymbolExport;
2833
2841
  var start = S.token;
2834
- var foreign_name;
2842
+ var name, foreign_name;
2835
2843
  var end = prev();
2836
2844
 
2845
+ if (is_import) {
2846
+ name = import_or_export_foreign_name;
2847
+ } else {
2848
+ foreign_name = import_or_export_foreign_name;
2849
+ }
2850
+
2837
2851
  name = name || new type({
2838
2852
  start: start,
2839
2853
  name: "*",
2840
2854
  end: end,
2841
2855
  });
2842
2856
 
2843
- foreign_name = new foreign_type({
2857
+ foreign_name = foreign_name || new foreign_type({
2844
2858
  start: start,
2845
2859
  name: "*",
2846
2860
  end: end,
@@ -2869,9 +2883,9 @@ function parse($TEXT, options) {
2869
2883
  } else if (is("operator", "*")) {
2870
2884
  var name;
2871
2885
  next();
2872
- if (is_import && is("name", "as")) {
2886
+ if (is("name", "as")) {
2873
2887
  next(); // The "as" word
2874
- name = as_symbol(is_import ? AST_SymbolImport : AST_SymbolExportForeign);
2888
+ name = is_import ? as_symbol(AST_SymbolImport) : as_symbol_or_string(AST_SymbolExportForeign);
2875
2889
  }
2876
2890
  names = [map_nameAsterisk(is_import, name)];
2877
2891
  }
@@ -3036,6 +3050,27 @@ function parse($TEXT, options) {
3036
3050
  return sym;
3037
3051
  }
3038
3052
 
3053
+ function as_symbol_or_string(type) {
3054
+ if (!is("name")) {
3055
+ if (!is("string")) {
3056
+ croak("Name or string expected");
3057
+ }
3058
+ var tok = S.token;
3059
+ var ret = new type({
3060
+ start : tok,
3061
+ end : tok,
3062
+ name : tok.value,
3063
+ quote : tok.quote
3064
+ });
3065
+ next();
3066
+ return ret;
3067
+ }
3068
+ var sym = _make_symbol(type);
3069
+ _verify_symbol(sym);
3070
+ next();
3071
+ return sym;
3072
+ }
3073
+
3039
3074
  // Annotate AST_Call, AST_Lambda or AST_New with the special comments
3040
3075
  function annotate(node) {
3041
3076
  var start = node.start;