vite-plugin-top-level-await
Version:
Transform code to support top-level await in normal browsers for Vite.
75 lines (74 loc) • 2.74 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.CodePattern = void 0;
exports.findHighestPattern = findHighestPattern;
const Visitor_1 = require("@swc/core/Visitor");
// Throw an exception when found top-level await to exit earlier from AST traversal
class FoundTopLevelAwaitError extends Error {
}
class FindPatternsVisitor extends Visitor_1.Visitor {
// Hook class/function visiting functions so we can know the current level
constructor() {
super();
// Set the flag when a dynamic import is found
this.foundDynamicImport = false;
// Tell if one await is in top-level or not
this.currentLevel = 0;
const visitor = this;
function hook(methodName) {
const originalFunction = visitor[methodName];
visitor[methodName] = function () {
/* istanbul ignore next */
// A optimize: if we have already found dynamic imports, don't go deeper
if (visitor.foundDynamicImport)
return arguments[0];
visitor.currentLevel++;
const result = originalFunction.apply(this, arguments);
visitor.currentLevel--;
return result;
};
}
hook("visitClass");
hook("visitArrowFunctionExpression");
hook("visitFunction");
hook("visitMethodProperty");
}
visitAwaitExpression(expr) {
if (this.currentLevel === 0)
throw new FoundTopLevelAwaitError();
return super.visitAwaitExpression(expr);
}
visitForOfStatement(stmt) {
if (stmt.await && this.currentLevel === 0) {
throw new FoundTopLevelAwaitError();
}
return super.visitForOfStatement(stmt);
}
visitCallExpression(expr) {
if (expr.callee.type === "Import")
this.foundDynamicImport = true;
return super.visitCallExpression(expr);
}
}
var CodePattern;
(function (CodePattern) {
CodePattern["TopLevelAwait"] = "TopLevelAwait";
CodePattern["DynamicImport"] = "DynamicImport";
})(CodePattern || (exports.CodePattern = CodePattern = {}));
// Return the "highest" pattern found in the code
// i.e. if we found top-level await, we don't care if there're any dynamic imports then
function findHighestPattern(ast) {
try {
const visitor = new FindPatternsVisitor();
visitor.visitModule(ast);
if (visitor.foundDynamicImport)
return CodePattern.DynamicImport;
}
catch (e) {
if (e instanceof FoundTopLevelAwaitError)
return CodePattern.TopLevelAwait;
/* istanbul ignore next */
throw e;
}
return null;
}
;