index.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.importAssertions = importAssertions;
  6. var _acorn = _interopRequireWildcard(require("acorn"));
  7. function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
  8. function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  9. const leftCurlyBrace = "{".charCodeAt(0);
  10. const space = " ".charCodeAt(0);
  11. const keyword = "assert";
  12. const FUNC_STATEMENT = 1,
  13. FUNC_HANGING_STATEMENT = 2,
  14. FUNC_NULLABLE_ID = 4;
  15. function importAssertions(Parser) {
  16. // Use supplied version acorn version if present, to avoid
  17. // reference mismatches due to different acorn versions. This
  18. // allows this plugin to be used with Rollup which supplies
  19. // its own internal version of acorn and thereby sidesteps
  20. // the package manager.
  21. const acorn = Parser.acorn || _acorn;
  22. const {
  23. tokTypes: tt,
  24. TokenType
  25. } = acorn;
  26. return class extends Parser {
  27. constructor(...args) {
  28. super(...args);
  29. this.assertToken = new TokenType(keyword);
  30. }
  31. _codeAt(i) {
  32. return this.input.charCodeAt(i);
  33. }
  34. _eat(t) {
  35. if (this.type !== t) {
  36. this.unexpected();
  37. }
  38. this.next();
  39. }
  40. readToken(code) {
  41. let i = 0;
  42. for (; i < keyword.length; i++) {
  43. if (this._codeAt(this.pos + i) !== keyword.charCodeAt(i)) {
  44. return super.readToken(code);
  45. }
  46. }
  47. // ensure that the keyword is at the correct location
  48. // ie `assert{...` or `assert {...`
  49. for (;; i++) {
  50. if (this._codeAt(this.pos + i) === leftCurlyBrace) {
  51. // Found '{'
  52. break;
  53. } else if (this._codeAt(this.pos + i) === space) {
  54. // white space is allowed between `assert` and `{`, so continue.
  55. continue;
  56. } else {
  57. return super.readToken(code);
  58. }
  59. }
  60. // If we're inside a dynamic import expression we'll parse
  61. // the `assert` keyword as a standard object property name
  62. // ie `import(""./foo.json", { assert: { type: "json" } })`
  63. if (this.type.label === "{") {
  64. return super.readToken(code);
  65. }
  66. this.pos += keyword.length;
  67. return this.finishToken(this.assertToken);
  68. }
  69. parseDynamicImport(node) {
  70. this.next(); // skip `(`
  71. // Parse node.source.
  72. node.source = this.parseMaybeAssign();
  73. if (this.eat(tt.comma)) {
  74. const obj = this.parseObj(false);
  75. node.arguments = [obj];
  76. }
  77. this._eat(tt.parenR);
  78. return this.finishNode(node, "ImportExpression");
  79. }
  80. // ported from acorn/src/statement.js pp.parseExport
  81. parseExport(node, exports) {
  82. this.next();
  83. // export * from '...'
  84. if (this.eat(tt.star)) {
  85. if (this.options.ecmaVersion >= 11) {
  86. if (this.eatContextual("as")) {
  87. node.exported = this.parseIdent(true);
  88. this.checkExport(exports, node.exported.name, this.lastTokStart);
  89. } else {
  90. node.exported = null;
  91. }
  92. }
  93. this.expectContextual("from");
  94. if (this.type !== tt.string) {
  95. this.unexpected();
  96. }
  97. node.source = this.parseExprAtom();
  98. if (this.type === this.assertToken || this.type === tt._with) {
  99. this.next();
  100. const assertions = this.parseImportAssertions();
  101. if (assertions) {
  102. node.assertions = assertions;
  103. }
  104. }
  105. this.semicolon();
  106. return this.finishNode(node, "ExportAllDeclaration");
  107. }
  108. if (this.eat(tt._default)) {
  109. // export default ...
  110. this.checkExport(exports, "default", this.lastTokStart);
  111. var isAsync;
  112. if (this.type === tt._function || (isAsync = this.isAsyncFunction())) {
  113. var fNode = this.startNode();
  114. this.next();
  115. if (isAsync) {
  116. this.next();
  117. }
  118. node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync);
  119. } else if (this.type === tt._class) {
  120. var cNode = this.startNode();
  121. node.declaration = this.parseClass(cNode, "nullableID");
  122. } else {
  123. node.declaration = this.parseMaybeAssign();
  124. this.semicolon();
  125. }
  126. return this.finishNode(node, "ExportDefaultDeclaration");
  127. }
  128. // export var|const|let|function|class ...
  129. if (this.shouldParseExportStatement()) {
  130. node.declaration = this.parseStatement(null);
  131. if (node.declaration.type === "VariableDeclaration") {
  132. this.checkVariableExport(exports, node.declaration.declarations);
  133. } else {
  134. this.checkExport(exports, node.declaration.id.name, node.declaration.id.start);
  135. }
  136. node.specifiers = [];
  137. node.source = null;
  138. } else {
  139. // export { x, y as z } [from '...']
  140. node.declaration = null;
  141. node.specifiers = this.parseExportSpecifiers(exports);
  142. if (this.eatContextual("from")) {
  143. if (this.type !== tt.string) {
  144. this.unexpected();
  145. }
  146. node.source = this.parseExprAtom();
  147. if (this.type === this.assertToken || this.type === tt._with) {
  148. this.next();
  149. const assertions = this.parseImportAssertions();
  150. if (assertions) {
  151. node.assertions = assertions;
  152. }
  153. }
  154. } else {
  155. for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
  156. // check for keywords used as local names
  157. var spec = list[i];
  158. this.checkUnreserved(spec.local);
  159. // check if export is defined
  160. this.checkLocalExport(spec.local);
  161. }
  162. node.source = null;
  163. }
  164. this.semicolon();
  165. }
  166. return this.finishNode(node, "ExportNamedDeclaration");
  167. }
  168. parseImport(node) {
  169. this.next();
  170. // import '...'
  171. if (this.type === tt.string) {
  172. node.specifiers = [];
  173. node.source = this.parseExprAtom();
  174. } else {
  175. node.specifiers = this.parseImportSpecifiers();
  176. this.expectContextual("from");
  177. node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
  178. }
  179. if (this.type === this.assertToken || this.type == tt._with) {
  180. this.next();
  181. const assertions = this.parseImportAssertions();
  182. if (assertions) {
  183. node.assertions = assertions;
  184. }
  185. }
  186. this.semicolon();
  187. return this.finishNode(node, "ImportDeclaration");
  188. }
  189. parseImportAssertions() {
  190. this._eat(tt.braceL);
  191. const attrs = this.parseAssertEntries();
  192. this._eat(tt.braceR);
  193. return attrs;
  194. }
  195. parseAssertEntries() {
  196. const attrs = [];
  197. const attrNames = new Set();
  198. do {
  199. if (this.type === tt.braceR) {
  200. break;
  201. }
  202. const node = this.startNode();
  203. // parse AssertionKey : IdentifierName, StringLiteral
  204. let assertionKeyNode;
  205. if (this.type === tt.string) {
  206. assertionKeyNode = this.parseLiteral(this.value);
  207. } else {
  208. assertionKeyNode = this.parseIdent(true);
  209. }
  210. this.next();
  211. node.key = assertionKeyNode;
  212. // check if we already have an entry for an attribute
  213. // if a duplicate entry is found, throw an error
  214. // for now this logic will come into play only when someone declares `type` twice
  215. if (attrNames.has(node.key.name)) {
  216. this.raise(this.pos, "Duplicated key in assertions");
  217. }
  218. attrNames.add(node.key.name);
  219. if (this.type !== tt.string) {
  220. this.raise(this.pos, "Only string is supported as an assertion value");
  221. }
  222. node.value = this.parseLiteral(this.value);
  223. attrs.push(this.finishNode(node, "ImportAttribute"));
  224. } while (this.eat(tt.comma));
  225. return attrs;
  226. }
  227. };
  228. }