diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2023-11-05 17:16:09 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2023-11-05 17:16:09 +0800 |
| commit | d1d9f00b1bd660842addf5e6b1d1b64c852a9eea (patch) | |
| tree | 60fb37ae73a1109d95301de5ec9b61b5726a4b61 /node_modules/acorn-import-assertions | |
| parent | 7c85166c4cbdd862fc4252007d2df5befcbc2a58 (diff) | |
added hover prefixer
Diffstat (limited to 'node_modules/acorn-import-assertions')
| -rw-r--r-- | node_modules/acorn-import-assertions/README.md | 15 | ||||
| -rw-r--r-- | node_modules/acorn-import-assertions/lib/index.js | 235 | ||||
| -rw-r--r-- | node_modules/acorn-import-assertions/lib/index.mjs | 242 | ||||
| -rw-r--r-- | node_modules/acorn-import-assertions/package.json | 49 | ||||
| -rw-r--r-- | node_modules/acorn-import-assertions/src/index.js | 242 |
5 files changed, 783 insertions, 0 deletions
diff --git a/node_modules/acorn-import-assertions/README.md b/node_modules/acorn-import-assertions/README.md new file mode 100644 index 00000000..4b9b3adf --- /dev/null +++ b/node_modules/acorn-import-assertions/README.md @@ -0,0 +1,15 @@ +# Support for import assertions in acorn + +## Usage + +This module provides a plugin that can be used to extend the Acorn Parser class: + +```js +const {Parser} = require('acorn'); +const {importAssertions} = require('acorn-import-assertions'); +Parser.extend(importAssertions).parse('...'); +``` + +## License + +This plugin is released under an MIT License. diff --git a/node_modules/acorn-import-assertions/lib/index.js b/node_modules/acorn-import-assertions/lib/index.js new file mode 100644 index 00000000..18a187ec --- /dev/null +++ b/node_modules/acorn-import-assertions/lib/index.js @@ -0,0 +1,235 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.importAssertions = importAssertions; +var _acorn = _interopRequireWildcard(require("acorn")); +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); } +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; } +const leftCurlyBrace = "{".charCodeAt(0); +const space = " ".charCodeAt(0); +const keyword = "assert"; +const FUNC_STATEMENT = 1, + FUNC_HANGING_STATEMENT = 2, + FUNC_NULLABLE_ID = 4; +function importAssertions(Parser) { + // Use supplied version acorn version if present, to avoid + // reference mismatches due to different acorn versions. This + // allows this plugin to be used with Rollup which supplies + // its own internal version of acorn and thereby sidesteps + // the package manager. + const acorn = Parser.acorn || _acorn; + const { + tokTypes: tt, + TokenType + } = acorn; + return class extends Parser { + constructor(...args) { + super(...args); + this.assertToken = new TokenType(keyword); + } + _codeAt(i) { + return this.input.charCodeAt(i); + } + _eat(t) { + if (this.type !== t) { + this.unexpected(); + } + this.next(); + } + readToken(code) { + let i = 0; + for (; i < keyword.length; i++) { + if (this._codeAt(this.pos + i) !== keyword.charCodeAt(i)) { + return super.readToken(code); + } + } + + // ensure that the keyword is at the correct location + // ie `assert{...` or `assert {...` + for (;; i++) { + if (this._codeAt(this.pos + i) === leftCurlyBrace) { + // Found '{' + break; + } else if (this._codeAt(this.pos + i) === space) { + // white space is allowed between `assert` and `{`, so continue. + continue; + } else { + return super.readToken(code); + } + } + + // If we're inside a dynamic import expression we'll parse + // the `assert` keyword as a standard object property name + // ie `import(""./foo.json", { assert: { type: "json" } })` + if (this.type.label === "{") { + return super.readToken(code); + } + this.pos += keyword.length; + return this.finishToken(this.assertToken); + } + parseDynamicImport(node) { + this.next(); // skip `(` + + // Parse node.source. + node.source = this.parseMaybeAssign(); + if (this.eat(tt.comma)) { + const obj = this.parseObj(false); + node.arguments = [obj]; + } + this._eat(tt.parenR); + return this.finishNode(node, "ImportExpression"); + } + + // ported from acorn/src/statement.js pp.parseExport + parseExport(node, exports) { + this.next(); + // export * from '...' + if (this.eat(tt.star)) { + if (this.options.ecmaVersion >= 11) { + if (this.eatContextual("as")) { + node.exported = this.parseIdent(true); + this.checkExport(exports, node.exported.name, this.lastTokStart); + } else { + node.exported = null; + } + } + this.expectContextual("from"); + if (this.type !== tt.string) { + this.unexpected(); + } + node.source = this.parseExprAtom(); + if (this.type === this.assertToken || this.type === tt._with) { + this.next(); + const assertions = this.parseImportAssertions(); + if (assertions) { + node.assertions = assertions; + } + } + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration"); + } + if (this.eat(tt._default)) { + // export default ... + this.checkExport(exports, "default", this.lastTokStart); + var isAsync; + if (this.type === tt._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { + this.next(); + } + node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync); + } else if (this.type === tt._class) { + var cNode = this.startNode(); + node.declaration = this.parseClass(cNode, "nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); + } + return this.finishNode(node, "ExportDefaultDeclaration"); + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseStatement(null); + if (node.declaration.type === "VariableDeclaration") { + this.checkVariableExport(exports, node.declaration.declarations); + } else { + this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); + } + node.specifiers = []; + node.source = null; + } else { + // export { x, y as z } [from '...'] + node.declaration = null; + node.specifiers = this.parseExportSpecifiers(exports); + if (this.eatContextual("from")) { + if (this.type !== tt.string) { + this.unexpected(); + } + node.source = this.parseExprAtom(); + if (this.type === this.assertToken || this.type === tt._with) { + this.next(); + const assertions = this.parseImportAssertions(); + if (assertions) { + node.assertions = assertions; + } + } + } else { + for (var i = 0, list = node.specifiers; i < list.length; i += 1) { + // check for keywords used as local names + var spec = list[i]; + this.checkUnreserved(spec.local); + // check if export is defined + this.checkLocalExport(spec.local); + } + node.source = null; + } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration"); + } + parseImport(node) { + this.next(); + // import '...' + if (this.type === tt.string) { + node.specifiers = []; + node.source = this.parseExprAtom(); + } else { + node.specifiers = this.parseImportSpecifiers(); + this.expectContextual("from"); + node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected(); + } + if (this.type === this.assertToken || this.type == tt._with) { + this.next(); + const assertions = this.parseImportAssertions(); + if (assertions) { + node.assertions = assertions; + } + } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration"); + } + parseImportAssertions() { + this._eat(tt.braceL); + const attrs = this.parseAssertEntries(); + this._eat(tt.braceR); + return attrs; + } + parseAssertEntries() { + const attrs = []; + const attrNames = new Set(); + do { + if (this.type === tt.braceR) { + break; + } + const node = this.startNode(); + + // parse AssertionKey : IdentifierName, StringLiteral + let assertionKeyNode; + if (this.type === tt.string) { + assertionKeyNode = this.parseLiteral(this.value); + } else { + assertionKeyNode = this.parseIdent(true); + } + this.next(); + node.key = assertionKeyNode; + + // check if we already have an entry for an attribute + // if a duplicate entry is found, throw an error + // for now this logic will come into play only when someone declares `type` twice + if (attrNames.has(node.key.name)) { + this.raise(this.pos, "Duplicated key in assertions"); + } + attrNames.add(node.key.name); + if (this.type !== tt.string) { + this.raise(this.pos, "Only string is supported as an assertion value"); + } + node.value = this.parseLiteral(this.value); + attrs.push(this.finishNode(node, "ImportAttribute")); + } while (this.eat(tt.comma)); + return attrs; + } + }; +}
\ No newline at end of file diff --git a/node_modules/acorn-import-assertions/lib/index.mjs b/node_modules/acorn-import-assertions/lib/index.mjs new file mode 100644 index 00000000..6e1d37db --- /dev/null +++ b/node_modules/acorn-import-assertions/lib/index.mjs @@ -0,0 +1,242 @@ +import * as _acorn from "acorn"; + +const leftCurlyBrace = "{".charCodeAt(0); +const space = " ".charCodeAt(0); + +const keyword = "assert"; +const FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4 + +export function importAssertions(Parser) { + // Use supplied version acorn version if present, to avoid + // reference mismatches due to different acorn versions. This + // allows this plugin to be used with Rollup which supplies + // its own internal version of acorn and thereby sidesteps + // the package manager. + const acorn = Parser.acorn || _acorn; + const { tokTypes: tt, TokenType } = acorn; + + return class extends Parser { + constructor(...args) { + super(...args); + this.assertToken = new TokenType(keyword); + } + + _codeAt(i) { + return this.input.charCodeAt(i); + } + + _eat(t) { + if (this.type !== t) { + this.unexpected(); + } + this.next(); + } + + readToken(code) { + let i = 0; + for (; i < keyword.length; i++) { + if (this._codeAt(this.pos + i) !== keyword.charCodeAt(i)) { + return super.readToken(code); + } + } + + // ensure that the keyword is at the correct location + // ie `assert{...` or `assert {...` + for (;; i++) { + if (this._codeAt(this.pos + i) === leftCurlyBrace) { + // Found '{' + break; + } else if (this._codeAt(this.pos + i) === space) { + // white space is allowed between `assert` and `{`, so continue. + continue; + } else { + return super.readToken(code); + } + } + + // If we're inside a dynamic import expression we'll parse + // the `assert` keyword as a standard object property name + // ie `import(""./foo.json", { assert: { type: "json" } })` + if (this.type.label === "{") { + return super.readToken(code); + } + + this.pos += keyword.length; + return this.finishToken(this.assertToken); + } + + parseDynamicImport(node) { + this.next(); // skip `(` + + // Parse node.source. + node.source = this.parseMaybeAssign(); + + if (this.eat(tt.comma)) { + const obj = this.parseObj(false); + node.arguments = [obj]; + } + this._eat(tt.parenR); + return this.finishNode(node, "ImportExpression"); + } + + // ported from acorn/src/statement.js pp.parseExport + parseExport(node, exports) { + this.next(); + // export * from '...' + if (this.eat(tt.star)) { + if (this.options.ecmaVersion >= 11) { + if (this.eatContextual("as")) { + node.exported = this.parseIdent(true); + this.checkExport(exports, node.exported.name, this.lastTokStart); + } else { + node.exported = null; + } + } + this.expectContextual("from"); + if (this.type !== tt.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + + if (this.type === this.assertToken || this.type === tt._with) { + this.next(); + const assertions = this.parseImportAssertions(); + if (assertions) { + node.assertions = assertions; + } + } + + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(tt._default)) { // export default ... + this.checkExport(exports, "default", this.lastTokStart); + var isAsync; + if (this.type === tt._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync); + } else if (this.type === tt._class) { + var cNode = this.startNode(); + node.declaration = this.parseClass(cNode, "nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); + } + return this.finishNode(node, "ExportDefaultDeclaration") + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseStatement(null); + if (node.declaration.type === "VariableDeclaration") + { this.checkVariableExport(exports, node.declaration.declarations); } + else + { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } + node.specifiers = []; + node.source = null; + } else { // export { x, y as z } [from '...'] + node.declaration = null; + node.specifiers = this.parseExportSpecifiers(exports); + if (this.eatContextual("from")) { + if (this.type !== tt.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + + if (this.type === this.assertToken || this.type === tt._with) { + this.next(); + const assertions = this.parseImportAssertions(); + if (assertions) { + node.assertions = assertions; + } + } + } else { + for (var i = 0, list = node.specifiers; i < list.length; i += 1) { + // check for keywords used as local names + var spec = list[i]; + + this.checkUnreserved(spec.local); + // check if export is defined + this.checkLocalExport(spec.local); + } + + node.source = null; + } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration") + } + + parseImport(node) { + this.next(); + // import '...' + if (this.type === tt.string) { + node.specifiers = []; + node.source = this.parseExprAtom(); + } else { + node.specifiers = this.parseImportSpecifiers(); + this.expectContextual("from"); + node.source = + this.type === tt.string ? this.parseExprAtom() : this.unexpected(); + } + + if (this.type === this.assertToken || this.type == tt._with) { + this.next(); + const assertions = this.parseImportAssertions(); + if (assertions) { + node.assertions = assertions; + } + } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration"); + } + + parseImportAssertions() { + this._eat(tt.braceL); + const attrs = this.parseAssertEntries(); + this._eat(tt.braceR); + return attrs; + } + + parseAssertEntries() { + const attrs = []; + const attrNames = new Set(); + + do { + if (this.type === tt.braceR) { + break; + } + + const node = this.startNode(); + + // parse AssertionKey : IdentifierName, StringLiteral + let assertionKeyNode; + if (this.type === tt.string) { + assertionKeyNode = this.parseLiteral(this.value); + } else { + assertionKeyNode = this.parseIdent(true); + } + this.next(); + node.key = assertionKeyNode; + + // check if we already have an entry for an attribute + // if a duplicate entry is found, throw an error + // for now this logic will come into play only when someone declares `type` twice + if (attrNames.has(node.key.name)) { + this.raise(this.pos, "Duplicated key in assertions"); + } + attrNames.add(node.key.name); + + if (this.type !== tt.string) { + this.raise( + this.pos, + "Only string is supported as an assertion value" + ); + } + + node.value = this.parseLiteral(this.value); + + attrs.push(this.finishNode(node, "ImportAttribute")); + } while (this.eat(tt.comma)); + + return attrs; + } + }; +} diff --git a/node_modules/acorn-import-assertions/package.json b/node_modules/acorn-import-assertions/package.json new file mode 100644 index 00000000..7a9ae8b3 --- /dev/null +++ b/node_modules/acorn-import-assertions/package.json @@ -0,0 +1,49 @@ +{ + "name": "acorn-import-assertions", + "version": "1.9.0", + "description": "Support for import assertions in acorn", + "main": "lib/index.js", + "module": "src/index.js", + "exports": { + ".": { + "import": "./lib/index.mjs", + "require": "./lib/index.js" + }, + "./package.json": "./package.json", + "./": "./" + }, + "scripts": { + "build": "babel ./src --out-dir ./lib && node post-build.js", + "prepublishOnly": "npm run build", + "test": "mocha ./test/index.js", + "test:test262": "node run_test262.js", + "watch": "babel ./src --out-dir ./lib --watch" + }, + "author": "Sven Sauleau <sven@sauleau.com>", + "license": "MIT", + "devDependencies": { + "@babel/cli": "^7.14.8", + "@babel/core": "^7.15.0", + "@babel/preset-env": "^7.15.0", + "@babel/register": "^7.15.3", + "acorn": "^8.4.1", + "chai": "^4.3.4", + "mocha": "^9.1.0", + "test262": "tc39/test262#47ab262658cd97ae35c9a537808cac18fa4ab567", + "test262-parser-runner": "^0.5.0" + }, + "peerDependencies": { + "acorn": "^8" + }, + "repository": { + "type": "git", + "url": "https://github.com/xtuc/acorn-import-assertions" + }, + "browserslist": [ + "maintained node versions" + ], + "files": [ + "lib", + "src" + ] +} diff --git a/node_modules/acorn-import-assertions/src/index.js b/node_modules/acorn-import-assertions/src/index.js new file mode 100644 index 00000000..6e1d37db --- /dev/null +++ b/node_modules/acorn-import-assertions/src/index.js @@ -0,0 +1,242 @@ +import * as _acorn from "acorn"; + +const leftCurlyBrace = "{".charCodeAt(0); +const space = " ".charCodeAt(0); + +const keyword = "assert"; +const FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4 + +export function importAssertions(Parser) { + // Use supplied version acorn version if present, to avoid + // reference mismatches due to different acorn versions. This + // allows this plugin to be used with Rollup which supplies + // its own internal version of acorn and thereby sidesteps + // the package manager. + const acorn = Parser.acorn || _acorn; + const { tokTypes: tt, TokenType } = acorn; + + return class extends Parser { + constructor(...args) { + super(...args); + this.assertToken = new TokenType(keyword); + } + + _codeAt(i) { + return this.input.charCodeAt(i); + } + + _eat(t) { + if (this.type !== t) { + this.unexpected(); + } + this.next(); + } + + readToken(code) { + let i = 0; + for (; i < keyword.length; i++) { + if (this._codeAt(this.pos + i) !== keyword.charCodeAt(i)) { + return super.readToken(code); + } + } + + // ensure that the keyword is at the correct location + // ie `assert{...` or `assert {...` + for (;; i++) { + if (this._codeAt(this.pos + i) === leftCurlyBrace) { + // Found '{' + break; + } else if (this._codeAt(this.pos + i) === space) { + // white space is allowed between `assert` and `{`, so continue. + continue; + } else { + return super.readToken(code); + } + } + + // If we're inside a dynamic import expression we'll parse + // the `assert` keyword as a standard object property name + // ie `import(""./foo.json", { assert: { type: "json" } })` + if (this.type.label === "{") { + return super.readToken(code); + } + + this.pos += keyword.length; + return this.finishToken(this.assertToken); + } + + parseDynamicImport(node) { + this.next(); // skip `(` + + // Parse node.source. + node.source = this.parseMaybeAssign(); + + if (this.eat(tt.comma)) { + const obj = this.parseObj(false); + node.arguments = [obj]; + } + this._eat(tt.parenR); + return this.finishNode(node, "ImportExpression"); + } + + // ported from acorn/src/statement.js pp.parseExport + parseExport(node, exports) { + this.next(); + // export * from '...' + if (this.eat(tt.star)) { + if (this.options.ecmaVersion >= 11) { + if (this.eatContextual("as")) { + node.exported = this.parseIdent(true); + this.checkExport(exports, node.exported.name, this.lastTokStart); + } else { + node.exported = null; + } + } + this.expectContextual("from"); + if (this.type !== tt.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + + if (this.type === this.assertToken || this.type === tt._with) { + this.next(); + const assertions = this.parseImportAssertions(); + if (assertions) { + node.assertions = assertions; + } + } + + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(tt._default)) { // export default ... + this.checkExport(exports, "default", this.lastTokStart); + var isAsync; + if (this.type === tt._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync); + } else if (this.type === tt._class) { + var cNode = this.startNode(); + node.declaration = this.parseClass(cNode, "nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); + } + return this.finishNode(node, "ExportDefaultDeclaration") + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseStatement(null); + if (node.declaration.type === "VariableDeclaration") + { this.checkVariableExport(exports, node.declaration.declarations); } + else + { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } + node.specifiers = []; + node.source = null; + } else { // export { x, y as z } [from '...'] + node.declaration = null; + node.specifiers = this.parseExportSpecifiers(exports); + if (this.eatContextual("from")) { + if (this.type !== tt.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + + if (this.type === this.assertToken || this.type === tt._with) { + this.next(); + const assertions = this.parseImportAssertions(); + if (assertions) { + node.assertions = assertions; + } + } + } else { + for (var i = 0, list = node.specifiers; i < list.length; i += 1) { + // check for keywords used as local names + var spec = list[i]; + + this.checkUnreserved(spec.local); + // check if export is defined + this.checkLocalExport(spec.local); + } + + node.source = null; + } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration") + } + + parseImport(node) { + this.next(); + // import '...' + if (this.type === tt.string) { + node.specifiers = []; + node.source = this.parseExprAtom(); + } else { + node.specifiers = this.parseImportSpecifiers(); + this.expectContextual("from"); + node.source = + this.type === tt.string ? this.parseExprAtom() : this.unexpected(); + } + + if (this.type === this.assertToken || this.type == tt._with) { + this.next(); + const assertions = this.parseImportAssertions(); + if (assertions) { + node.assertions = assertions; + } + } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration"); + } + + parseImportAssertions() { + this._eat(tt.braceL); + const attrs = this.parseAssertEntries(); + this._eat(tt.braceR); + return attrs; + } + + parseAssertEntries() { + const attrs = []; + const attrNames = new Set(); + + do { + if (this.type === tt.braceR) { + break; + } + + const node = this.startNode(); + + // parse AssertionKey : IdentifierName, StringLiteral + let assertionKeyNode; + if (this.type === tt.string) { + assertionKeyNode = this.parseLiteral(this.value); + } else { + assertionKeyNode = this.parseIdent(true); + } + this.next(); + node.key = assertionKeyNode; + + // check if we already have an entry for an attribute + // if a duplicate entry is found, throw an error + // for now this logic will come into play only when someone declares `type` twice + if (attrNames.has(node.key.name)) { + this.raise(this.pos, "Duplicated key in assertions"); + } + attrNames.add(node.key.name); + + if (this.type !== tt.string) { + this.raise( + this.pos, + "Only string is supported as an assertion value" + ); + } + + node.value = this.parseLiteral(this.value); + + attrs.push(this.finishNode(node, "ImportAttribute")); + } while (this.eat(tt.comma)); + + return attrs; + } + }; +} |
