From 4ee546a24e94372db2a975266560059bd166a46f Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 10 Dec 2024 18:51:38 -0800 Subject: [PATCH] wip --- cmake/tools/SetupWebKit.cmake | 2 + src/analyze_transpiled_module.zig | 20 ++ src/bake/BakeGlobalObject.cpp | 2 +- src/bake/BakeSourceProvider.cpp | 2 +- .../bindings/BunAnalyzeTranspiledModule.cpp | 293 ++++++++++++++++++ src/bun.js/bindings/ModuleLoader.cpp | 4 +- src/bun.js/bindings/ZigSourceProvider.h | 2 +- src/bun.js/bindings/bindings.cpp | 2 +- src/bun.js/bindings/bindings.zig | 4 + src/bun.js/bindings/napi.cpp | 2 +- src/js_printer.zig | 50 +++ 11 files changed, 376 insertions(+), 7 deletions(-) create mode 100644 src/analyze_transpiled_module.zig create mode 100644 src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index e7cb26be5e..bb980737b4 100644 --- a/cmake/tools/SetupWebKit.cmake +++ b/cmake/tools/SetupWebKit.cmake @@ -28,6 +28,8 @@ if(WEBKIT_LOCAL) ${WEBKIT_PATH} ${WEBKIT_PATH}/JavaScriptCore/Headers/JavaScriptCore ${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders + ${WEBKIT_PATH}/JavaScriptCore/DerivedSources/inspector + ${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders/JavaScriptCore ${WEBKIT_PATH}/bmalloc/Headers ${WEBKIT_PATH}/WTF/Headers ) diff --git a/src/analyze_transpiled_module.zig b/src/analyze_transpiled_module.zig new file mode 100644 index 0000000000..3e59761793 --- /dev/null +++ b/src/analyze_transpiled_module.zig @@ -0,0 +1,20 @@ +const std = @import("std"); +const bun = @import("bun.zig"); + +export fn zig_log_u8(m1: [*:0]const u8, m2_ptr: [*]const u8, m2_len: usize) void { + std.log.err("{s}{s}", .{ std.mem.span(m1), m2_ptr[0..m2_len] }); +} +export fn zig_log_cstr(m1: [*:0]const u8, m2: [*:0]const u8) void { + std.log.err("{s}{s}", .{ std.mem.span(m1), std.mem.span(m2) }); +} +export fn zig_log_ushort(m1: [*:0]const u8, value: c_ushort) void { + std.log.err("{s}{d}", .{ std.mem.span(m1), value }); +} + +// export fn Bun__analyzeTranspiledModule(globalObject: *bun.JSC.JSGlobalObject, moduleKey: *anyopaque, sourceCode: *anyopaque) *bun.JSC.JSModuleRecord { +// // const record = bun.JSC.JSModuleRecord.create(globalObject, globalObject.vm(), globalObject.moduleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables, features); +// _ = globalObject; +// _ = moduleKey; +// _ = sourceCode; +// @panic("TODO analyzeTranspiledModule"); +// } diff --git a/src/bake/BakeGlobalObject.cpp b/src/bake/BakeGlobalObject.cpp index 4bd4a4647e..5c1ccac907 100644 --- a/src/bake/BakeGlobalObject.cpp +++ b/src/bake/BakeGlobalObject.cpp @@ -115,7 +115,7 @@ JSC::JSInternalPromise* bakeModuleLoaderFetch(JSC::JSGlobalObject* globalObject, origin, WTFMove(moduleKey), WTF::TextPosition(), - JSC::SourceProviderSourceType::Module)); + JSC::SourceProviderSourceType::BunTranspiledModule)); return resolvedInternalPromise(globalObject, JSC::JSSourceCode::create(vm, WTFMove(sourceCode))); } return rejectedInternalPromise(globalObject, createTypeError(globalObject, makeString("Bundle does not have \""_s, moduleKey, "\". This is a bug in Bun's bundler."_s))); diff --git a/src/bake/BakeSourceProvider.cpp b/src/bake/BakeSourceProvider.cpp index 2a51ffa0aa..0a0970b4e4 100644 --- a/src/bake/BakeSourceProvider.cpp +++ b/src/bake/BakeSourceProvider.cpp @@ -122,7 +122,7 @@ extern "C" JSC::EncodedJSValue BakeRegisterProductionChunk(JSC::JSGlobalObject* origin, WTFMove(string), WTF::TextPosition(), - JSC::SourceProviderSourceType::Module + JSC::SourceProviderSourceType::BunTranspiledModule )); global->moduleLoader()->provideFetch(global, key, sourceCode); diff --git a/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp b/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp new file mode 100644 index 0000000000..c09f695eb5 --- /dev/null +++ b/src/bun.js/bindings/BunAnalyzeTranspiledModule.cpp @@ -0,0 +1,293 @@ +#include "root.h" + +#include "JavaScriptCore/JSInternalPromise.h" +#include "JavaScriptCore/JSModuleRecord.h" +// #include "JavaScriptCore/BuiltinNames.h" +// #include "JavaScriptCore/CatchScope.h" +#include "JavaScriptCore/GlobalObjectMethodTable.h" +// #include "JavaScriptCore/JSCInlines.h" +// #include "JavaScriptCore/JSInternalPromise.h" +// #include "JavaScriptCore/JSMap.h" +// #include "JavaScriptCore/JSModuleNamespaceObject.h" +#include "JavaScriptCore/JSModuleRecord.h" +// #include "JavaScriptCore/JSScriptFetchParameters.h" +// #include "JavaScriptCore/JSSourceCode.h" +// #include "JavaScriptCore/JSWebAssembly.h" +#include "JavaScriptCore/Nodes.h" +// #include "JavaScriptCore/ObjectConstructor.h" +#include "JavaScriptCore/Parser.h" +#include "JavaScriptCore/ParserError.h" +#include "JavaScriptCore/SyntheticModuleRecord.h" +// #include "JavaScriptCore/VMTrapsInlines.h" +#include +// #include "JavaScriptCore/IdentifierInlines.h" +#include "JavaScriptCore/JSGlobalObject.h" +#include "JavaScriptCore/JSModuleRecord.h" +#include "JavaScriptCore/ModuleScopeData.h" +#include "JavaScriptCore/ExceptionScope.h" +// #include "JavaScriptCore/StrongInlines.h" + +// ref: JSModuleLoader.cpp +// ref: ModuleAnalyzer2.cpp +// ref: JSModuleRecord.cpp +// ref: NodesAnalyzeModule.cpp, search ::analyzeModule + +#include "JavaScriptCore/ErrorType.h" + +namespace JSC { + +class JSModuleRecord; +class SourceCode; +class ScriptFetchParameters; + +class ModuleAnalyzer { + WTF_MAKE_NONCOPYABLE(ModuleAnalyzer); + WTF_FORBID_HEAP_ALLOCATION; + +public: + ModuleAnalyzer(JSGlobalObject*, const Identifier& moduleKey, const SourceCode&, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables, CodeFeatures); + + Expected> analyze(ModuleProgramNode&); + + VM& vm() { return m_vm; } + + JSModuleRecord* moduleRecord() { return m_moduleRecord; } + + void appendRequestedModule(const Identifier&, RefPtr&&); + + void fail(std::tuple&& errorMessage) { m_errorMessage = errorMessage; } + +private: + void exportVariable(ModuleProgramNode&, const RefPtr&, const VariableEnvironmentEntry&); + + VM& m_vm; + JSModuleRecord* m_moduleRecord; + IdentifierSet m_requestedModules; + std::tuple m_errorMessage; +}; + +} // namespace JSC + +namespace JSC { + +ModuleAnalyzer::ModuleAnalyzer(JSGlobalObject* globalObject, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables, CodeFeatures features) + : m_vm(globalObject->vm()) + , m_moduleRecord(JSModuleRecord::create(globalObject, m_vm, globalObject->moduleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables, features)) +{ +} + +void ModuleAnalyzer::appendRequestedModule(const Identifier& specifier, RefPtr&& attributes) +{ + auto result = m_requestedModules.add(specifier.impl()); + if (result.isNewEntry) + moduleRecord()->appendRequestedModule(specifier, WTFMove(attributes)); +} + +void ModuleAnalyzer::exportVariable(ModuleProgramNode& moduleProgramNode, const RefPtr& localName, const VariableEnvironmentEntry& variable) +{ + // In the parser, we already marked the variables as Exported and Imported. + // By leveraging this information, we collect the information that is needed + // to construct the module environment. + // + // I E + // * = exported module local variable + // * = imported binding + // = non-exported module local variable + // * * = indirect exported binding + // + // One exception is namespace binding (like import * as ns from "mod"). + // This is annotated as an imported, but the actual binding is locate in the + // current module. + + if (!variable.isExported()) + return; + + // Exported module local variable. + if (!variable.isImported()) { + for (auto& exportName : moduleProgramNode.moduleScopeData().exportedBindings().get(localName.get())) + moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createLocal(Identifier::fromUid(m_vm, exportName.get()), Identifier::fromUid(m_vm, localName.get()))); + return; + } + + if (variable.isImportedNamespace()) { + // Exported namespace binding. + // import * as namespace from "mod" + // export { namespace } + // + // Sec 15.2.1.16.1 step 11-a-ii-2-b https://tc39.github.io/ecma262/#sec-parsemodule + // Namespace export is handled as local export since a namespace object binding itself is implemented as a local binding. + for (auto& exportName : moduleProgramNode.moduleScopeData().exportedBindings().get(localName.get())) + moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createLocal(Identifier::fromUid(m_vm, exportName.get()), Identifier::fromUid(m_vm, localName.get()))); + return; + } + + // Indirectly exported binding. + // import a from "mod" + // export { a } + std::optional optionalImportEntry = moduleRecord()->tryGetImportEntry(localName.get()); + ASSERT(optionalImportEntry); + const JSModuleRecord::ImportEntry& importEntry = *optionalImportEntry; + for (auto& exportName : moduleProgramNode.moduleScopeData().exportedBindings().get(localName.get())) + moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createIndirect(Identifier::fromUid(m_vm, exportName.get()), importEntry.importName, importEntry.moduleRequest)); +} + +Expected> ModuleAnalyzer::analyze(ModuleProgramNode& moduleProgramNode) +{ + // Traverse the module AST and collect + // * Import entries + // * Export entries that have FromClause (e.g. export { a } from "mod") + // * Export entries that have star (e.g. export * from "mod") + // * Aliased export names (e.g. export { a as b }) + if (!moduleProgramNode.analyzeModule(*this)) + return makeUnexpected(WTFMove(m_errorMessage)); + + // Based on the collected information, categorize export entries into 3 types. + // 1. Local export entries + // This references the local variable in the current module. + // This variable should be allocated in the current module environment as a heap variable. + // + // const variable = 20 + // export { variable } + // + // 2. Namespace export entries + // This references the namespace object imported by some import entries. + // This variable itself should be allocated in the current module environment as a heap variable. + // But when the other modules attempt to resolve this export name in this module, this module + // should tell the link to the original module. + // + // import * as namespace from "mod" + // export { namespace as mod } + // + // 3. Indirect export entries + // This references the imported binding name from the other module. + // This module environment itself should hold the pointer to (1) the original module and + // (2) the binding in the original module. The variable itself is allocated in the original + // module. This indirect binding is resolved when the CodeBlock resolves the references. + // + // import mod from "mod" + // export { mod } + // + // export { a } from "mod" + // + // And separeted from the above 3 types, we also collect the star export entries. + // + // 4. Star export entries + // This exports all the names from the specified external module as the current module's name. + // + // export * from "mod" + for (const auto& pair : m_moduleRecord->declaredVariables()) + exportVariable(moduleProgramNode, pair.key, pair.value); + + for (const auto& pair : m_moduleRecord->lexicalVariables()) + exportVariable(moduleProgramNode, pair.key, pair.value); + + if (UNLIKELY(Options::dumpModuleRecord())) + m_moduleRecord->dump(); + + return m_moduleRecord; +} + +} // namespace JSC + +namespace JSC { + +extern "C" void zig_log_u8(const char* m1, const unsigned char* m2, size_t m2_size); +extern "C" void zig_log_cstr(const char* m1, const char* m2); +extern "C" void zig_log_ushort(const char* m1, unsigned short value); + +extern "C" __attribute__((weak)) EncodedJSValue Bun__analyzeTranspiledModule(JSGlobalObject* globalObject, const Identifier& moduleKey, const SourceCode& sourceCode, JSInternalPromise* promise) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto rejectWithError = [&](JSValue error) { + promise->reject(globalObject, error); + return promise; + }; + + ParserError error; + std::unique_ptr moduleProgramNode = parseRootNode( + vm, sourceCode, ImplementationVisibility::Public, JSParserBuiltinMode::NotBuiltin, + StrictModeLexicallyScopedFeature, JSParserScriptMode::Module, SourceParseMode::ModuleAnalyzeMode, error); + if (error.isValid()) + RELEASE_AND_RETURN(scope, JSValue::encode(rejectWithError(error.toErrorObject(globalObject, sourceCode)))); + ASSERT(moduleProgramNode); + + ModuleAnalyzer ModuleAnalyzer(globalObject, moduleKey, sourceCode, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables(), moduleProgramNode->features()); + RETURN_IF_EXCEPTION(scope, JSValue::encode(promise->rejectWithCaughtException(globalObject, scope))); + + auto result = ModuleAnalyzer.analyze(*moduleProgramNode); + zig_log_cstr(" ---code---\n\n", sourceCode.toUTF8().data()); + zig_log_cstr(" ------", ""); + zig_log_cstr(" BunAnalyzeTranspiledModule:", ""); + if (!result) { + auto [errorType, message] = WTFMove(result.error()); + zig_log_cstr(" -> Error:", message.ascii().data()); + RELEASE_AND_RETURN(scope, JSValue::encode(rejectWithError(createError(globalObject, errorType, message)))); + } + + JSModuleRecord* moduleRecord = result.value(); + + // VariableEnvironment declaredVariables = VariableEnvironment(); + // VariableEnvironment lexicalVariables = VariableEnvironment(); + // CodeFeatures features = 0; + if (true) { + zig_log_cstr(" -> Success.", ""); + zig_log_cstr(" varDeclarations:", ""); + { + auto iter = moduleRecord->m_declaredVariables.begin(); + auto end = moduleRecord->m_declaredVariables.end(); + while (iter != end) { + auto& pair = *iter; + + zig_log_u8(" - ", pair.key->span8().data(), pair.key->span8().size()); + + ++iter; + } + } + zig_log_cstr(" lexicalVariables:", ""); + { + auto iter = moduleRecord->m_lexicalVariables.begin(); + auto end = moduleRecord->m_lexicalVariables.end(); + while (iter != end) { + auto& pair = *iter; + + zig_log_u8(" - ", pair.key->span8().data(), pair.key->span8().size()); + + ++iter; + } + } + // zig_log + zig_log_ushort(" features: ", moduleRecord->m_features); + + moduleRecord->dump(); + zig_log_cstr(" -> done", ""); + + // declaredVariables.add(); + // features |= ImportMetaFeature; + } + + // it looks like the only usage of moduleRecord->m_lexicalVariables and others is in modulerecord and + // JSModuleRecord::instantiateDeclarations for declaredVariables + // SymbolTableEntry entry = symbolTable->get(variable.key.get()); + // VarOffset offset = entry.varOffset(); + // if (!offset.isStack()) { + // bool putResult = false; + // symbolTablePutTouchWatchpointSet(moduleEnvironment, globalObject, Identifier::fromUid(vm, variable.key.get()), jsUndefined(), /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult); + // RETURN_IF_EXCEPTION(scope, void()); + // } + + // m_sourceCode is easy, we have it already + // m_declaredVariables is: + // m_lexicalVariables is: + // m_moduleProgramExecutable is managed by JSModuleRecord + // m_features is: + // const CodeFeatures ImportMetaFeature = 1 << 12; + // (that is the only used CodeFeature) + + scope.release(); + promise->fulfillWithNonPromise(globalObject, result.value()); + return JSValue::encode(promise); +} + +} diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index bb0653d1e8..8af4d6662c 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -745,7 +745,7 @@ static JSValue fetchESMSourceCode( auto tag = res->result.value.tag; switch (tag) { case SyntheticModuleType::ESM: { - auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true); + auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::BunTranspiledModule, true); return rejectOrResolve(JSSourceCode::create(vm, JSC::SourceCode(provider))); } @@ -764,7 +764,7 @@ static JSValue fetchESMSourceCode( auto source = JSC::SourceCode(JSC::SyntheticSourceProvider::create(generateInternalModuleSourceCode(globalObject, static_cast(tag & mask)), JSC::SourceOrigin(URL(makeString("builtins://"_s, moduleKey))), moduleKey)); return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source))); } else { - auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true); + auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::BunTranspiledModule, true); return rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider))); } } diff --git a/src/bun.js/bindings/ZigSourceProvider.h b/src/bun.js/bindings/ZigSourceProvider.h index eddb638665..53a8e1ea99 100644 --- a/src/bun.js/bindings/ZigSourceProvider.h +++ b/src/bun.js/bindings/ZigSourceProvider.h @@ -39,7 +39,7 @@ public: static Ref create( Zig::GlobalObject*, ResolvedSource& resolvedSource, - JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::Module, + JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::BunTranspiledModule, bool isBuiltIn = false); ~SourceProvider(); unsigned hash() const override; diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 7305ad8930..6472cf3fb5 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -2582,7 +2582,7 @@ JSC__JSValue JSC__JSModuleLoader__evaluate(JSC__JSGlobalObject* globalObject, co JSC::SourceCode sourceCode = JSC::makeSource( src, JSC::SourceOrigin { origin }, JSC::SourceTaintedOrigin::Untainted, origin.fileSystemPath(), - WTF::TextPosition(), JSC::SourceProviderSourceType::Module); + WTF::TextPosition(), JSC::SourceProviderSourceType::BunTranspiledModule); globalObject->moduleLoader()->provideFetch(globalObject, jsString(vm, origin.fileSystemPath()), WTFMove(sourceCode)); auto* promise = JSC::importModule(globalObject, JSC::Identifier::fromString(vm, origin.fileSystemPath()), JSValue(jsString(vm, referrer.fileSystemPath())), JSValue(), JSValue()); diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 173add2802..3236da80f2 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -7154,3 +7154,7 @@ pub const DeferredError = struct { return err; } }; + +comptime { + _ = @import("../../analyze_transpiled_module.zig"); +} diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 0c8bdec56d..984bddabcd 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -110,7 +110,7 @@ JSC::SourceCode generateSourceCode(WTF::String keyString, JSC::VM& vm, JSC::JSOb sourceCodeBuilder.append(";\n"_s); } globalObject->putDirect(vm, ident, object, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum); - return JSC::makeSource(sourceCodeBuilder.toString(), JSC::SourceOrigin(), JSC::SourceTaintedOrigin::Untainted, keyString, WTF::TextPosition(), JSC::SourceProviderSourceType::Module); + return JSC::makeSource(sourceCodeBuilder.toString(), JSC::SourceOrigin(), JSC::SourceTaintedOrigin::Untainted, keyString, WTF::TextPosition(), JSC::SourceProviderSourceType::BunTranspiledModule); } } diff --git a/src/js_printer.zig b/src/js_printer.zig index 2963b96e65..0fd4aeec60 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -691,6 +691,7 @@ fn NewPrinter( prev_reg_exp_end: i32 = -1, call_target: ?Expr.Data = null, writer: Writer, + contains_import_meta: bool = false, has_printed_bundled_import_statement: bool = false, imported_module_ids: std.ArrayList(u32), @@ -1003,6 +1004,7 @@ fn NewPrinter( printInternalBunImport(p, import, @TypeOf("globalThis.Bun.jest(__filename)"), "globalThis.Bun.jest(__filename)"); }, else => { + p.contains_import_meta = true; printInternalBunImport(p, import, @TypeOf("globalThis.Bun.jest(import.meta.path)"), "globalThis.Bun.jest(import.meta.path)"); }, } @@ -1685,12 +1687,14 @@ fn NewPrinter( if (module_type == .cjs) { p.print("Promise.resolve(globalThis.Bun.jest(__filename))"); } else { + p.contains_import_meta = true; p.print("Promise.resolve(globalThis.Bun.jest(import.meta.path))"); } } else if (record.kind == .require) { if (module_type == .cjs) { p.print("globalThis.Bun.jest(__filename)"); } else { + p.contains_import_meta = true; p.print("globalThis.Bun.jest(import.meta.path)"); } } @@ -1837,6 +1841,7 @@ fn NewPrinter( } if (module_type == .esm and is_bun_platform) { + p.contains_import_meta = true; p.print("import.meta.require"); } else if (p.options.require_ref) |ref| { p.printSymbol(ref); @@ -2065,6 +2070,7 @@ fn NewPrinter( p.print(".importMeta()"); } else if (!p.options.import_meta_ref.isValid()) { // Most of the time, leave it in there + p.contains_import_meta = true; p.print("import.meta"); } else { // Note: The bundler will not hit this code path. The bundler will replace @@ -2089,6 +2095,7 @@ fn NewPrinter( p.printSpaceBeforeIdentifier(); p.addSourceMapping(expr.loc); } + p.contains_import_meta = true; p.print("import.meta.main"); } else { bun.assert(p.options.module_type != .internal_bake_dev); @@ -2278,6 +2285,7 @@ fn NewPrinter( p.addSourceMapping(expr.loc); if (p.options.module_type == .esm and is_bun_platform) { + p.contains_import_meta = true; p.print("import.meta.require.main"); } else if (p.options.require_ref) |require_ref| { p.printSymbol(require_ref); @@ -2291,6 +2299,7 @@ fn NewPrinter( p.addSourceMapping(expr.loc); if (p.options.module_type == .esm and is_bun_platform) { + p.contains_import_meta = true; p.print("import.meta.require"); } else if (p.options.require_ref) |require_ref| { p.printSymbol(require_ref); @@ -2303,6 +2312,7 @@ fn NewPrinter( p.addSourceMapping(expr.loc); if (p.options.module_type == .esm and is_bun_platform) { + p.contains_import_meta = true; p.print("import.meta.require.resolve"); } else if (p.options.require_ref) |require_ref| { p.printSymbol(require_ref); @@ -2332,6 +2342,7 @@ fn NewPrinter( p.printSpaceBeforeIdentifier(); if (p.options.module_type == .esm and is_bun_platform) { + p.contains_import_meta = true; p.print("import.meta.require.resolve"); } else if (p.options.require_ref) |require_ref| { p.printSymbol(require_ref); @@ -4324,6 +4335,7 @@ fn NewPrinter( p.printSymbol(s.namespace_ref); p.@"print = "(); + p.contains_import_meta = true; p.print("import.meta.require("); p.printImportRecordPath(record); p.print(")"); @@ -5842,6 +5854,44 @@ pub fn printAst( } } + std.log.err("\n\n\n\n\n\n \x1b[97mPrinting AST:\x1b(B\x1b[m", .{}); + std.log.err(" Import Records:", .{}); + for (tree.import_records.slice()) |record| { + std.log.err(" - {s}", .{record.path.text}); + } + std.log.err(" Export Records:", .{}); + for (tree.parts.slice()) |part| { + for (part.stmts) |stmt| { + switch (stmt.data) { + .s_export_clause, + .s_export_default, + .s_export_equals, + .s_export_from, + .s_export_star, + .s_lazy_export, + => { + std.log.err(" - {s}", .{@tagName(stmt.data)}); + }, + .s_local => |local| { + if (local.is_export) { + std.log.err(" - {s} (is_export)", .{@tagName(stmt.data)}); + } + }, + else => {}, + } + } + } + std.log.err(" Uses import.meta: {}", .{printer.contains_import_meta}); + + // - varDeclarations: + // + // - lexicalVariables: + // + + // if(comptime true) { + // tree + // } + try printer.writer.done(); return @as(usize, @intCast(@max(printer.writer.written, 0)));