| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- /**
- * @param {{ defer?: boolean, source?: boolean }} options
- * @param {typeof import("acorn").Parser} Parser
- * @param {typeof import("acorn").tokTypes} acorn
- */
- exports.plugin = function acornImportPhase(options, Parser, tt) {
- return class extends Parser {
- parseImport(node) {
- this._phase = null;
- const result = super.parseImport(node);
- if (this._phase) {
- node.phase = this._phase;
- }
- return result;
- }
- parseImportSpecifiers() {
- let phase =
- options.defer !== false && this.isContextual("defer")
- ? "defer"
- : options.source !== false && this.isContextual("source")
- ? "source"
- : null;
- if (!phase) return super.parseImportSpecifiers();
- const phaseId = this.parseIdent();
- if (this.isContextual("from") || this.type === tt.comma) {
- const defaultSpecifier = this.startNodeAt(phaseId.start, phaseId.loc && phaseId.loc.start);
- defaultSpecifier.local = phaseId;
- this.checkLValSimple(phaseId, /* BIND_LEXICAL */ 2);
- const nodes = [this.finishNode(defaultSpecifier, "ImportDefaultSpecifier")];
- if (this.eat(tt.comma)) {
- if (this.type !== tt.star && this.type !== tt.braceL) {
- this.unexpected();
- }
- nodes.push(...super.parseImportSpecifiers());
- }
- return nodes;
- }
- this._phase = phase;
- if (phase === "defer") {
- if (this.type !== tt.star) {
- this.raiseRecoverable(
- phaseId.start,
- "'import defer' can only be used with namespace imports ('import defer * as identifierName from ...')."
- );
- }
- } else if (phase === "source") {
- if (this.type !== tt.name) {
- this.raiseRecoverable(
- phaseId.start,
- "'import source' can only be used with direct identifier specifier imports."
- );
- }
- }
- const specifiers = super.parseImportSpecifiers();
- if (phase === "source" && specifiers.some(s => s.type !== "ImportDefaultSpecifier")) {
- this.raiseRecoverable(
- phaseId.start,
- `'import source' can only be used with direct identifier specifier imports ('import source identifierName from ...').`
- );
- }
- return specifiers;
- }
- parseExprImport(forNew) {
- const node = super.parseExprImport(forNew);
- if (node.type === "MetaProperty" && (node.property.name === "defer" || node.property.name === "source")) {
- if (this.type === tt.parenL) {
- const dynImport = this.parseDynamicImport(this.startNodeAt(node.start, node.loc && node.loc.start));
- dynImport.phase = node.property.name;
- return dynImport;
- } else {
- this.raiseRecoverable(
- node.start,
- `'import.${node.property.name}' can only be used in a dynamic import.`
- );
- }
- }
- return node;
- }
- parseImportMeta(node) {
- this.next();
- var containsEsc = this.containsEsc;
- node.property = this.parseIdent(true);
- const { name } = node.property;
- if (name !== "meta" && name !== "defer" && name !== "source") {
- this.raiseRecoverable(
- node.property.start,
- "The only valid meta property for import is 'import.meta'"
- );
- }
- if (containsEsc) {
- this.raiseRecoverable(
- node.start,
- `'import.${name}' must not contain escaped characters`
- );
- }
- if (
- name === "meta" &&
- this.options.sourceType !== "module" &&
- !this.options.allowImportExportEverywhere
- ) {
- this.raiseRecoverable(
- node.start,
- "Cannot use 'import.meta' outside a module"
- );
- }
- return this.finishNode(node, "MetaProperty");
- }
- };
- };
|