usingnamespace @import("imports.zig"); // Dear reader, // There are some things you should know about this file to make it easier for humans to read // "P" is the internal parts of the parser // "p.e" allocates a new Expr // "p.b" allocates a new Binding // "p.s" allocates a new Stmt // We do it this way so if we want to refactor how these are allocated in the future, we only have to modify one function to change it everywhere // Everything in JavaScript is either an Expression, a Binding, or a Statement. // Expression: foo(1) // Statement: let a = 1; // Binding: 1 // While the names for Expr, Binding, and Stmt are directly copied from esbuild, those were likely inspired by Go's parser. // which is another example of a very fast parser. const TemplatePartTuple = std.meta.Tuple(&[_]type{ []E.TemplatePart, logger.Loc }); const ScopeOrderList = std.ArrayListUnmanaged(?ScopeOrder); pub fn ExpressionTransposer( comptime Kontext: type, visitor: fn (ptr: *Kontext, arg: Expr, state: anytype) Expr, ) type { return struct { pub const Context = Kontext; pub const This = @This(); context: *Context, pub fn init(c: *Context) This { return This{ .context = c, }; } pub fn maybeTransposeIf(self: *This, arg: Expr, state: anytype) Expr { switch (arg.data) { .e_if => |ex| { ex.yes = self.maybeTransposeIf(ex.yes, state); ex.no = self.maybeTransposeIf(ex.no, state); return arg; }, else => { return visitor(self.context, arg, state); }, } } }; } pub fn locAfterOp(e: E.Binary) logger.Loc { if (e.left.loc.start < e.right.loc.start) { return e.right.loc; } else { // handle the case when we have transposed the operands return e.left.loc; } } const ExportsStringName = "exports"; pub const ImportScanner = struct { stmts: []Stmt = &([_]Stmt{}), kept_import_equals: bool = false, removed_import_equals: bool = false, pub fn scan(comptime P: type, p: P, stmts: []Stmt, comptime convert_exports: bool) !ImportScanner { var scanner = ImportScanner{}; var stmts_end: usize = 0; for (stmts) |_stmt, _stmt_i| { // zls needs the hint, it seems. var stmt: Stmt = _stmt; switch (stmt.data) { .s_import => |st| { var record: *ImportRecord = &p.import_records.items[st.import_record_index]; // The official TypeScript compiler always removes unused imported // symbols. However, we deliberately deviate from the official // TypeScript compiler's behavior doing this in a specific scenario: // we are not bundling, symbol renaming is off, and the tsconfig.json // "importsNotUsedAsValues" setting is present and is not set to // "remove". // // This exists to support the use case of compiling partial modules for // compile-to-JavaScript languages such as Svelte. These languages try // to reference imports in ways that are impossible for esbuild to know // about when esbuild is only given a partial module to compile. Here // is an example of some Svelte code that might use esbuild to convert // TypeScript to JavaScript: // // //
//

Hello {name}!

// //
// // Tools that use esbuild to compile TypeScript code inside a Svelte // file like this only give esbuild the contents of the