Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
9c7adda552 WIP: SourceProvider refactoring - BunSourceProvider implementation
Refactored ResolvedSource and ZigSourceProvider to eliminate complexity and reduce memory usage.

## Changes:
- Created new types: TranspiledSource, SpecialModule, ModuleResult (Zig)
- Implemented BunSourceProvider to replace ZigSourceProvider (C++)
- Migrated all call sites from Zig::SourceProvider::create() to Bun__createSourceProvider()
- Deleted ZigSourceProvider.{h,cpp}
- Moved helper functions to BunSourceProvider

## Status:
 Compiles successfully
 Basic functionality works (console.log, bun:ffi)
⚠️  node:path and other node compat modules hang - needs investigation

## Known Issues:
- require('node:path') hangs (infinite loop or blocking)
- Need to complete ModuleResult integration in builtin module handling
- May need to adjust Zig/C++ bridge for builtin modules with source code

Target: Reduce code by 392 lines, clarify ownership model
2025-10-25 07:29:04 +00:00
19 changed files with 1114 additions and 836 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1519,11 +1519,11 @@ pub fn fetchWithoutOnLoadPlugins(
referrer: String,
log: *logger.Log,
comptime flags: FetchFlags,
) anyerror!ResolvedSource {
) anyerror!ModuleResult {
bun.assert(VirtualMachine.isLoaded());
if (try ModuleLoader.fetchBuiltinModule(jsc_vm, _specifier)) |builtin| {
return builtin;
if (try ModuleLoader.fetchBuiltinModule(jsc_vm, _specifier)) |module_result| {
return module_result;
}
const specifier_clone = _specifier.toUTF8(bun.default_allocator);
@@ -1863,7 +1863,7 @@ pub fn drainMicrotasks(this: *VirtualMachine) void {
this.eventLoop().drainMicrotasks() catch {}; // TODO: properly propagate exception upwards
}
pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, referrer: bun.String, log: *logger.Log, ret: *ErrorableResolvedSource, err: anyerror) void {
pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, referrer: bun.String, log: *logger.Log, ret: *ErrorableModuleResult, err: anyerror) void {
switch (log.msgs.items.len) {
0 => {
const msg: logger.Msg = brk: {
@@ -1882,14 +1882,14 @@ pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, refer
};
};
{
ret.* = ErrorableResolvedSource.err(err, (bun.api.BuildMessage.create(globalThis, globalThis.allocator(), msg) catch |e| globalThis.takeException(e)));
ret.* = ErrorableModuleResult.err(err, (bun.api.BuildMessage.create(globalThis, globalThis.allocator(), msg) catch |e| globalThis.takeException(e)));
}
return;
},
1 => {
const msg = log.msgs.items[0];
ret.* = ErrorableResolvedSource.err(err, switch (msg.metadata) {
ret.* = ErrorableModuleResult.err(err, switch (msg.metadata) {
.build => (bun.api.BuildMessage.create(globalThis, globalThis.allocator(), msg) catch |e| globalThis.takeException(e)),
.resolve => (bun.api.ResolveMessage.create(
globalThis,
@@ -1919,7 +1919,7 @@ pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, refer
};
}
ret.* = ErrorableResolvedSource.err(
ret.* = ErrorableModuleResult.err(
err,
globalThis.createAggregateError(
errors,
@@ -2797,9 +2797,12 @@ pub fn remapZigException(
var log = logger.Log.init(bun.default_allocator);
defer log.deinit();
var original_source = fetchWithoutOnLoadPlugins(this, this.global, top.source_url, bun.String.empty, &log, .print_source) catch return;
var module_result = fetchWithoutOnLoadPlugins(this, this.global, top.source_url, bun.String.empty, &log, .print_source) catch return;
must_reset_parser_arena_later.* = true;
break :code original_source.source_code.toUTF8(bun.default_allocator);
break :code switch (module_result.tag) {
.transpiled => module_result.value.transpiled.source_code.toUTF8(bun.default_allocator),
else => return, // For builtin/special modules, we can't show source
};
};
if (enable_source_code_preview and code.len == 0) {
@@ -3729,6 +3732,7 @@ const DNSResolver = bun.api.dns.Resolver;
const jsc = bun.jsc;
const ConsoleObject = jsc.ConsoleObject;
const ErrorableModuleResult = jsc.ErrorableModuleResult;
const ErrorableResolvedSource = jsc.ErrorableResolvedSource;
const ErrorableString = jsc.ErrorableString;
const EventLoop = jsc.EventLoop;
@@ -3737,6 +3741,7 @@ const JSGlobalObject = jsc.JSGlobalObject;
const JSInternalPromise = jsc.JSInternalPromise;
const JSModuleLoader = jsc.JSModuleLoader;
const JSValue = jsc.JSValue;
const ModuleResult = jsc.ModuleResult;
const Node = jsc.Node;
const ResolvedSource = jsc.ResolvedSource;
const SavedSourceMap = jsc.SavedSourceMap;

View File

@@ -0,0 +1,313 @@
#include "root.h"
#include "helpers.h"
#include "BunSourceProvider.h"
#include <JavaScriptCore/BytecodeCacheError.h>
#include "ZigGlobalObject.h"
#include "wtf/Assertions.h"
#include <JavaScriptCore/Completion.h>
#include <wtf/Scope.h>
#include <wtf/text/StringHash.h>
#include <sys/stat.h>
#include <JavaScriptCore/SourceCodeKey.h>
#include <mimalloc.h>
#include <JavaScriptCore/CodeCache.h>
namespace Zig {
using Base = JSC::SourceProvider;
using BytecodeCacheGenerator = JSC::BytecodeCacheGenerator;
using UnlinkedFunctionExecutable = JSC::UnlinkedFunctionExecutable;
using CachedBytecode = JSC::CachedBytecode;
using UnlinkedFunctionCodeBlock = JSC::UnlinkedFunctionCodeBlock;
using SourceCode = JSC::SourceCode;
using CodeSpecializationKind = JSC::CodeSpecializationKind;
using SourceOrigin = JSC::SourceOrigin;
using String = WTF::String;
using SourceProviderSourceType = JSC::SourceProviderSourceType;
extern "C" bool BunTest__shouldGenerateCodeCoverage(BunString sourceURL);
extern "C" void Bun__addSourceProviderSourceMap(void* bun_vm, JSC::SourceProvider* opaque_source_provider, BunString* specifier);
extern "C" void Bun__removeSourceProviderSourceMap(void* bun_vm, JSC::SourceProvider* opaque_source_provider, BunString* specifier);
extern "C" void ByteRangeMapping__generate(BunString sourceURL, BunString code, int sourceID);
// Forward declaration - implementation is at the end of the file
JSC::SourceOrigin toSourceOrigin(const WTF::String& sourceURL, bool isBuiltin);
Ref<BunSourceProvider> BunSourceProvider::create(
Zig::GlobalObject* globalObject,
Ref<WTF::StringImpl>&& source,
const SourceOrigin& origin,
WTF::String&& sourceURL,
RefPtr<JSC::CachedBytecode>&& bytecode,
JSC::SourceProviderSourceType sourceType)
{
return adoptRef(*new BunSourceProvider(
globalObject,
WTFMove(source),
origin,
WTFMove(sourceURL),
WTFMove(bytecode),
sourceType));
}
BunSourceProvider::BunSourceProvider(
Zig::GlobalObject* globalObject,
Ref<WTF::StringImpl>&& source,
const SourceOrigin& origin,
WTF::String&& sourceURL,
RefPtr<JSC::CachedBytecode>&& bytecode,
JSC::SourceProviderSourceType sourceType)
: Base(origin, WTFMove(sourceURL), String(), JSC::SourceTaintedOrigin::Untainted, TextPosition(), sourceType)
, m_source(WTFMove(source))
, m_cachedBytecode(WTFMove(bytecode))
, m_globalObject(globalObject)
{
}
StringView BunSourceProvider::source() const
{
return StringView(m_source.get());
}
BunSourceProvider::~BunSourceProvider()
{
// Sourcemap cleanup is handled separately via Bun__removeSourceProviderSourceMap
// called from the caller when needed
}
unsigned BunSourceProvider::hash() const
{
if (m_hash) {
return m_hash;
}
return m_source->hash();
}
// Helper function for converting source URLs to SourceOrigin (used by Bun__createSourceProvider and JSCommonJSModule.cpp)
JSC::SourceOrigin toSourceOrigin(const WTF::String& sourceURL, bool isBuiltin)
{
using namespace WTF::StringLiterals;
ASSERT_WITH_MESSAGE(!sourceURL.startsWith("file://"_s), "specifier should not already be a file URL");
if (isBuiltin) {
if (sourceURL.startsWith("node:"_s)) {
return JSC::SourceOrigin(WTF::URL(WTF::makeString("builtin://node/"_s, sourceURL.substring(5))));
} else if (sourceURL.startsWith("bun:"_s)) {
return JSC::SourceOrigin(WTF::URL(WTF::makeString("builtin://bun/"_s, sourceURL.substring(4))));
} else {
return JSC::SourceOrigin(WTF::URL(WTF::makeString("builtin://"_s, sourceURL)));
}
}
return JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(sourceURL));
}
}; // namespace Zig
// C bridge function to create a BunSourceProvider from TranspiledSource
extern "C" JSC::SourceProvider* Bun__createSourceProvider(
Zig::GlobalObject* globalObject,
const TranspiledSource* source,
bool isBuiltin)
{
using namespace Zig;
auto sourceString = source->source_code.toWTFString(BunString::ZeroCopy);
auto sourceURL = source->source_url.toWTFString(BunString::ZeroCopy);
bool isCommonJS = source->flags.is_commonjs;
auto sourceType = isCommonJS ?
JSC::SourceProviderSourceType::Program :
JSC::SourceProviderSourceType::Module;
// Handle bytecode if present
RefPtr<JSC::CachedBytecode> bytecode;
if (source->bytecode_cache) {
const auto destructorPtr = [](const void* ptr) {
mi_free(const_cast<void*>(ptr));
};
const auto destructorNoOp = [](const void* ptr) {
// no-op, for bun build --compile.
};
// For already_bundled bytecode, we don't free it (it's embedded)
const auto destructor = source->flags.is_already_bundled ? destructorNoOp : destructorPtr;
bytecode = JSC::CachedBytecode::create(
std::span<uint8_t>(source->bytecode_cache, source->bytecode_cache_len),
destructor,
{}
);
}
bool isCodeCoverageEnabled = !!globalObject->vm().controlFlowProfiler();
bool shouldGenerateCodeCoverage = isCodeCoverageEnabled && !isBuiltin &&
BunTest__shouldGenerateCodeCoverage(source->source_url);
auto provider = BunSourceProvider::create(
globalObject->isThreadLocalDefaultGlobalObject ? globalObject : nullptr,
sourceString.isNull() ? *WTF::StringImpl::empty() : *sourceString.impl(),
toSourceOrigin(sourceURL, isBuiltin),
WTFMove(sourceURL),
WTFMove(bytecode),
sourceType
);
// Generate code coverage mapping if needed
if (shouldGenerateCodeCoverage) {
ByteRangeMapping__generate(
Bun::toString(provider->sourceURL()),
Bun::toString(provider->source().toStringWithoutCopying()),
provider->asID()
);
}
// Register sourcemap if needed
if (source->flags.is_already_bundled) {
BunString sourceUrlBun = source->source_url;
Bun__addSourceProviderSourceMap(
globalObject->bunVM(),
provider.ptr(),
&sourceUrlBun
);
}
// Transfer ownership to caller
return &provider.leakRef();
}
// =============================================================================
// Exported extern "C" utility functions (formerly in ZigSourceProvider.cpp)
// =============================================================================
extern "C" {
// Decrement reference count for cached bytecode
void CachedBytecode__deref(JSC::CachedBytecode* cachedBytecode)
{
cachedBytecode->deref();
}
// Get source code slice from a SourceProvider
BunString ZigSourceProvider__getSourceSlice(JSC::SourceProvider* provider)
{
return Bun::toStringView(provider->source());
}
} // extern "C"
// Shared VM for bytecode caching - thread-local to avoid conflicts
static JSC::VM& getVMForBytecodeCache()
{
static thread_local JSC::VM* vmForBytecodeCache = nullptr;
if (!vmForBytecodeCache) {
const auto heapSize = JSC::HeapType::Small;
auto vmPtr = JSC::VM::tryCreate(heapSize);
vmPtr->refSuppressingSaferCPPChecking();
vmForBytecodeCache = vmPtr.get();
vmPtr->heap.acquireAccess();
}
return *vmForBytecodeCache;
}
extern "C" {
// Generate cached bytecode for ES modules
bool generateCachedModuleByteCodeFromSourceCode(
BunString* sourceProviderURL,
const Latin1Character* inputSourceCode,
size_t inputSourceCodeSize,
const uint8_t** outputByteCode,
size_t* outputByteCodeSize,
JSC::CachedBytecode** cachedBytecodePtr)
{
std::span<const Latin1Character> sourceCodeSpan(inputSourceCode, inputSourceCodeSize);
JSC::SourceCode sourceCode = JSC::makeSource(
WTF::String(sourceCodeSpan),
Zig::toSourceOrigin(sourceProviderURL->toWTFString(), false),
JSC::SourceTaintedOrigin::Untainted
);
JSC::VM& vm = getVMForBytecodeCache();
JSC::JSLockHolder locker(vm);
JSC::LexicallyScopedFeatures lexicallyScopedFeatures = JSC::StrictModeLexicallyScopedFeature;
JSC::JSParserScriptMode scriptMode = JSC::JSParserScriptMode::Module;
JSC::EvalContextType evalContextType = JSC::EvalContextType::None;
JSC::ParserError parserError;
JSC::UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = JSC::recursivelyGenerateUnlinkedCodeBlockForModuleProgram(
vm, sourceCode, lexicallyScopedFeatures, scriptMode, {}, parserError, evalContextType
);
if (parserError.isValid())
return false;
if (!unlinkedCodeBlock)
return false;
auto key = JSC::sourceCodeKeyForSerializedModule(vm, sourceCode);
RefPtr<JSC::CachedBytecode> cachedBytecode = JSC::encodeCodeBlock(vm, key, unlinkedCodeBlock);
if (!cachedBytecode)
return false;
cachedBytecode->ref();
*cachedBytecodePtr = cachedBytecode.get();
*outputByteCode = cachedBytecode->span().data();
*outputByteCodeSize = cachedBytecode->span().size();
return true;
}
// Generate cached bytecode for CommonJS programs
bool generateCachedCommonJSProgramByteCodeFromSourceCode(
BunString* sourceProviderURL,
const Latin1Character* inputSourceCode,
size_t inputSourceCodeSize,
const uint8_t** outputByteCode,
size_t* outputByteCodeSize,
JSC::CachedBytecode** cachedBytecodePtr)
{
std::span<const Latin1Character> sourceCodeSpan(inputSourceCode, inputSourceCodeSize);
JSC::SourceCode sourceCode = JSC::makeSource(
WTF::String(sourceCodeSpan),
Zig::toSourceOrigin(sourceProviderURL->toWTFString(), false),
JSC::SourceTaintedOrigin::Untainted
);
JSC::VM& vm = getVMForBytecodeCache();
JSC::JSLockHolder locker(vm);
JSC::LexicallyScopedFeatures lexicallyScopedFeatures = JSC::NoLexicallyScopedFeatures;
JSC::JSParserScriptMode scriptMode = JSC::JSParserScriptMode::Classic;
JSC::EvalContextType evalContextType = JSC::EvalContextType::None;
JSC::ParserError parserError;
JSC::UnlinkedProgramCodeBlock* unlinkedCodeBlock = JSC::recursivelyGenerateUnlinkedCodeBlockForProgram(
vm, sourceCode, lexicallyScopedFeatures, scriptMode, {}, parserError, evalContextType
);
if (parserError.isValid())
return false;
if (!unlinkedCodeBlock)
return false;
auto key = JSC::sourceCodeKeyForSerializedProgram(vm, sourceCode);
RefPtr<JSC::CachedBytecode> cachedBytecode = JSC::encodeCodeBlock(vm, key, unlinkedCodeBlock);
if (!cachedBytecode)
return false;
cachedBytecode->ref();
*cachedBytecodePtr = cachedBytecode.get();
*outputByteCode = cachedBytecode->span().data();
*outputByteCodeSize = cachedBytecode->span().size();
return true;
}
} // extern "C"

View File

@@ -0,0 +1,69 @@
#include "headers.h"
#include "root.h"
#pragma once
namespace JSC {
class Structure;
class Identifier;
class SourceCodeKey;
class SourceProvider;
} // namespace JSC
#include <JavaScriptCore/CachedBytecode.h>
#include <JavaScriptCore/JSGlobalObject.h>
#include <JavaScriptCore/JSTypeInfo.h>
#include <JavaScriptCore/SourceProvider.h>
#include <JavaScriptCore/Structure.h>
namespace Zig {
class GlobalObject;
class BunSourceProvider final : public JSC::SourceProvider {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED(BunSourceProvider);
using Base = JSC::SourceProvider;
using BytecodeCacheGenerator = JSC::BytecodeCacheGenerator;
using UnlinkedFunctionExecutable = JSC::UnlinkedFunctionExecutable;
using CachedBytecode = JSC::CachedBytecode;
using UnlinkedFunctionCodeBlock = JSC::UnlinkedFunctionCodeBlock;
using SourceCode = JSC::SourceCode;
using CodeSpecializationKind = JSC::CodeSpecializationKind;
using SourceOrigin = JSC::SourceOrigin;
public:
static Ref<BunSourceProvider> create(
Zig::GlobalObject* globalObject,
Ref<WTF::StringImpl>&& source,
const SourceOrigin& origin,
WTF::String&& sourceURL,
RefPtr<JSC::CachedBytecode>&& bytecode,
JSC::SourceProviderSourceType sourceType);
~BunSourceProvider() final;
unsigned hash() const final;
StringView source() const final;
RefPtr<JSC::CachedBytecode> cachedBytecode() const final
{
return m_cachedBytecode.copyRef();
};
private:
BunSourceProvider(
Zig::GlobalObject* globalObject,
Ref<WTF::StringImpl>&& source,
const SourceOrigin& origin,
WTF::String&& sourceURL,
RefPtr<JSC::CachedBytecode>&& bytecode,
JSC::SourceProviderSourceType sourceType);
// Simplified members (vs ZigSourceProvider)
Ref<WTF::StringImpl> m_source;
RefPtr<JSC::CachedBytecode> m_cachedBytecode;
Zig::GlobalObject* m_globalObject; // For sourcemap cleanup only
unsigned m_hash = 0;
};
} // namespace Zig

View File

@@ -1,5 +1,4 @@
#include "root.h"
#include "ZigSourceProvider.h"
#include <JavaScriptCore/ControlFlowProfiler.h>
using namespace JSC;

View File

@@ -260,7 +260,7 @@ JSC::EncodedJSValue builtinLoader(JSC::JSGlobalObject* globalObject, JSC::CallFr
BunString specifierBunString = Bun::toString(specifierWtfString);
BunString empty = BunStringEmpty;
JSC::VM& vm = globalObject->vm();
ErrorableResolvedSource res;
ErrorableModuleResult res;
res.success = false;
memset(&res.result, 0, sizeof res.result);

View File

@@ -66,7 +66,6 @@
#include <JavaScriptCore/JSMapInlines.h>
#include <JavaScriptCore/GetterSetter.h>
#include "ZigSourceProvider.h"
#include <JavaScriptCore/FunctionPrototype.h>
#include "JSCommonJSModule.h"
#include <JavaScriptCore/JSModuleNamespaceObject.h>
@@ -82,6 +81,14 @@
#include "ErrorCode.h"
extern "C" bool Bun__isBunMain(JSC::JSGlobalObject* global, const BunString*);
extern "C" JSC::SourceProvider* Bun__createSourceProvider(
Zig::GlobalObject* globalObject,
const TranspiledSource* source,
bool isBuiltin);
namespace Zig {
JSC::SourceOrigin toSourceOrigin(const WTF::String& sourceURL, bool isBuiltin);
}
namespace Bun {
using namespace JSC;
@@ -1311,7 +1318,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireNativeModule, (JSGlobalObject * lexica
JSValue specifierValue = callframe->argument(0);
WTF::String specifier = specifierValue.toWTFString(globalObject);
RETURN_IF_EXCEPTION(throwScope, {});
ErrorableResolvedSource res;
ErrorableModuleResult res;
res.success = false;
memset(&res.result, 0, sizeof res.result);
BunString specifierStr = Bun::toString(specifier);
@@ -1360,12 +1367,21 @@ void JSCommonJSModule::evaluate(
}
}
auto sourceProvider = Zig::SourceProvider::create(jsCast<Zig::GlobalObject*>(globalObject), source, JSC::SourceProviderSourceType::Program, isBuiltIn);
// Convert ResolvedSource to TranspiledSource for Bun__createSourceProvider
TranspiledSource transpiledSource;
transpiledSource.source_code = source.source_code;
transpiledSource.source_url = source.source_url;
transpiledSource.bytecode_cache = source.bytecode_cache;
transpiledSource.bytecode_cache_len = source.bytecode_cache_size;
transpiledSource.flags.is_commonjs = source.isCommonJSModule;
transpiledSource.flags.is_already_bundled = source.already_bundled;
auto* sourceProvider = Bun__createSourceProvider(globalObject, &transpiledSource, isBuiltIn);
this->ignoreESModuleAnnotation = source.tag == ResolvedSourceTagPackageJSONTypeModule;
if (this->hasEvaluated)
return;
this->sourceCode = JSC::SourceCode(WTFMove(sourceProvider));
this->sourceCode = JSC::SourceCode(adoptRef(*sourceProvider));
evaluateCommonJSModuleOnce(vm, globalObject, this, this->m_dirname.get(), this->m_filename.get());
}
@@ -1461,12 +1477,21 @@ std::optional<JSC::SourceCode> createCommonJSModule(
source.source_code = Bun::toStringRef(concat);
}
auto sourceProvider = Zig::SourceProvider::create(jsCast<Zig::GlobalObject*>(globalObject), source, JSC::SourceProviderSourceType::Program, isBuiltIn);
// Convert ResolvedSource to TranspiledSource for Bun__createSourceProvider
TranspiledSource transpiledSource;
transpiledSource.source_code = source.source_code;
transpiledSource.source_url = source.source_url;
transpiledSource.bytecode_cache = source.bytecode_cache;
transpiledSource.bytecode_cache_len = source.bytecode_cache_size;
transpiledSource.flags.is_commonjs = source.isCommonJSModule;
transpiledSource.flags.is_already_bundled = source.already_bundled;
auto* sourceProvider = Bun__createSourceProvider(globalObject, &transpiledSource, isBuiltIn);
sourceOrigin = sourceProvider->sourceOrigin();
moduleObject = JSCommonJSModule::create(
vm,
globalObject->CommonJSModuleObjectStructure(),
requireMapKey, filename, dirname, WTFMove(JSC::SourceCode(WTFMove(sourceProvider))));
requireMapKey, filename, dirname, WTFMove(JSC::SourceCode(adoptRef(*sourceProvider))));
moduleObject->putDirect(vm,
WebCore::clientData(vm)->builtinNames().exportsPublicName(),
@@ -1527,6 +1552,118 @@ std::optional<JSC::SourceCode> createCommonJSModule(
sourceURL));
}
// New overload for TranspiledSource
std::optional<JSC::SourceCode> createCommonJSModule(
Zig::GlobalObject* globalObject,
JSString* requireMapKey,
const TranspiledSource& source,
bool isBuiltIn)
{
auto& vm = JSC::getVM(globalObject);
auto scope = DECLARE_THROW_SCOPE(vm);
JSCommonJSModule* moduleObject = nullptr;
WTF::String sourceURL = source.source_url.toWTFString();
JSValue entry = globalObject->requireMap()->get(globalObject, requireMapKey);
RETURN_IF_EXCEPTION(scope, {});
SourceOrigin sourceOrigin;
if (entry) {
moduleObject = jsDynamicCast<JSCommonJSModule*>(entry);
}
if (!moduleObject) {
size_t index = sourceURL.reverseFind(PLATFORM_SEP, sourceURL.length());
JSString* dirname;
JSString* filename = requireMapKey;
if (index != WTF::notFound) {
dirname = JSC::jsSubstring(globalObject, requireMapKey, 0, index);
RETURN_IF_EXCEPTION(scope, {});
} else {
dirname = jsEmptyString(vm);
}
auto requireMap = globalObject->requireMap();
if (requireMap->size() == 0) {
requireMapKey = JSC::jsString(vm, WTF::String("."_s));
}
// Handle module wrapper if needed
auto sourceString = source.source_code.toWTFString(BunString::ZeroCopy);
if (globalObject->hasOverriddenModuleWrapper) [[unlikely]] {
sourceString = makeString(
globalObject->m_moduleWrapperStart,
sourceString,
globalObject->m_moduleWrapperEnd);
}
// Create source provider using Bun__createSourceProvider
auto* provider = Bun__createSourceProvider(globalObject, &source, isBuiltIn);
sourceOrigin = provider->sourceOrigin();
moduleObject = JSCommonJSModule::create(
vm,
globalObject->CommonJSModuleObjectStructure(),
requireMapKey, filename, dirname, WTFMove(JSC::SourceCode(adoptRef(*provider))));
moduleObject->putDirect(vm,
WebCore::clientData(vm)->builtinNames().exportsPublicName(),
JSC::constructEmptyObject(globalObject, globalObject->objectPrototype()), 0);
requireMap->set(globalObject, filename, moduleObject);
RETURN_IF_EXCEPTION(scope, {});
} else {
sourceOrigin = Zig::toSourceOrigin(sourceURL, isBuiltIn);
}
moduleObject->ignoreESModuleAnnotation = false; // TranspiledSource doesn't have package.json type flag
return JSC::SourceCode(
JSC::SyntheticSourceProvider::create(
[](JSC::JSGlobalObject* lexicalGlobalObject,
const JSC::Identifier& moduleKey,
Vector<JSC::Identifier, 4>& exportNames,
JSC::MarkedArgumentBuffer& exportValues) -> void {
auto* globalObject = jsCast<Zig::GlobalObject*>(lexicalGlobalObject);
auto& vm = JSC::getVM(globalObject);
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue keyValue = identifierToJSValue(vm, moduleKey);
JSValue entry = globalObject->requireMap()->get(globalObject, keyValue);
RETURN_IF_EXCEPTION(scope, {});
if (entry) {
if (auto* moduleObject = jsDynamicCast<JSCommonJSModule*>(entry)) {
if (!moduleObject->hasEvaluated) {
evaluateCommonJSModuleOnce(
vm,
globalObject,
moduleObject,
moduleObject->m_dirname.get(),
moduleObject->m_filename.get());
if (auto exception = scope.exception()) {
scope.clearException();
// On error, remove the module from the require map
// so that it can be re-evaluated on the next require.
globalObject->requireMap()->remove(globalObject, moduleObject->filename());
RETURN_IF_EXCEPTION(scope, {});
scope.throwException(globalObject, exception);
return;
}
}
moduleObject->toSyntheticSource(globalObject, moduleKey, exportNames, exportValues);
RETURN_IF_EXCEPTION(scope, {});
}
} else {
// require map was cleared of the entry
}
},
sourceOrigin,
sourceURL));
}
JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* lexicalGlobalObject, const WTF::String& pathString)
{
ASSERT(!pathString.startsWith("file://"_s));

View File

@@ -177,6 +177,21 @@ inline std::optional<JSC::SourceCode> createCommonJSModule(
return createCommonJSModule(globalObject, specifierValue, source, false);
}
// New overload for TranspiledSource
std::optional<JSC::SourceCode> createCommonJSModule(
Zig::GlobalObject* globalObject,
JSC::JSString* specifierValue,
const TranspiledSource& source,
bool isBuiltIn);
inline std::optional<JSC::SourceCode> createCommonJSModule(
Zig::GlobalObject* globalObject,
JSC::JSString* specifierValue,
const TranspiledSource& source)
{
return createCommonJSModule(globalObject, specifierValue, source, false);
}
class RequireResolveFunctionPrototype final : public JSC::JSNonFinalObject {
public:
using Base = JSC::JSNonFinalObject;

View File

@@ -11,8 +11,6 @@
#include <JavaScriptCore/JSInternalPromise.h>
#include <JavaScriptCore/JSInternalFieldObjectImpl.h>
#include "ZigSourceProvider.h"
#include <JavaScriptCore/JSSourceCode.h>
#include <JavaScriptCore/JSString.h>
#include <JavaScriptCore/ObjectConstructor.h>

View File

@@ -93,7 +93,7 @@ public:
JSValue fetchESMSourceCodeSync(
Zig::GlobalObject* globalObject,
JSString* spceifierJS,
ErrorableResolvedSource* res,
ErrorableModuleResult* res,
BunString* specifier,
BunString* referrer,
BunString* typeAttribute);
@@ -101,7 +101,7 @@ JSValue fetchESMSourceCodeSync(
JSValue fetchESMSourceCodeAsync(
Zig::GlobalObject* globalObject,
JSString* spceifierJS,
ErrorableResolvedSource* res,
ErrorableModuleResult* res,
BunString* specifier,
BunString* referrer,
BunString* typeAttribute);
@@ -123,7 +123,7 @@ JSValue fetchCommonJSModuleNonBuiltin(
JSC::JSValue specifierValue,
BunString* referrer,
BunString* typeAttribute,
ErrorableResolvedSource* res,
ErrorableModuleResult* res,
JSCommonJSModule* target,
String specifierWtfString,
BunLoaderType forceLoaderType,
@@ -136,6 +136,6 @@ JSValue resolveAndFetchBuiltinModule(
JSValue fetchBuiltinModuleWithoutResolution(
Zig::GlobalObject* globalObject,
BunString* specifier,
ErrorableResolvedSource* res);
ErrorableModuleResult* res);
} // namespace Bun

View File

@@ -0,0 +1,19 @@
/// Tagged union return type from transpiler
pub const ModuleResult = extern struct {
tag: Tag,
value: extern union {
transpiled: TranspiledSource,
special: SpecialModule,
builtin_id: u32,
},
pub const Tag = enum(u8) {
transpiled,
special,
builtin,
};
};
const bun = @import("bun");
const TranspiledSource = @import("./TranspiledSource.zig").TranspiledSource;
const SpecialModule = @import("./SpecialModule.zig").SpecialModule;

View File

@@ -0,0 +1,18 @@
/// For special cases that need JSValue handling
pub const SpecialModule = extern struct {
tag: Tag,
jsvalue: JSValue,
pub const Tag = enum(u8) {
/// Return exports object directly
exports_object,
/// Return default export only
export_default_object,
/// Call custom require.extensions handler
custom_extension,
};
};
const bun = @import("bun");
const jsc = bun.jsc;
const JSValue = jsc.JSValue;

View File

@@ -0,0 +1,25 @@
/// Minimal POD struct for transpiled source code
/// Can be safely created on worker threads
pub const TranspiledSource = extern struct {
/// Transpiled source code (Latin1 or UTF16)
/// Ownership transfers to C++ on return
source_code: bun.String,
/// Module specifier for debugging/sourcemaps
source_url: bun.String,
/// Optional bytecode cache (for bun build --compile)
bytecode_cache: ?[*]u8 = null,
bytecode_cache_len: usize = 0,
/// Packed flags
flags: Flags = .{},
pub const Flags = packed struct(u32) {
is_commonjs: bool = false,
is_already_bundled: bool = false,
_padding: u30 = 0,
};
};
const bun = @import("bun");

View File

@@ -153,7 +153,6 @@
#include "webcrypto/JSCryptoKey.h"
#include "webcrypto/JSSubtleCrypto.h"
#include "ZigGeneratedClasses.h"
#include "ZigSourceProvider.h"
#include "UtilInspect.h"
#include "Base64Helpers.h"
#include "wtf/text/OrdinalNumber.h"
@@ -577,7 +576,7 @@ JSC_DEFINE_HOST_FUNCTION(functionFulfillModuleSync,
}
auto specifier = Bun::toString(moduleKey);
ErrorableResolvedSource res;
ErrorableModuleResult res;
res.success = false;
// zero-initialize entire result union. zeroed BunString has BunStringTag::Dead, and zeroed
// EncodedJSValues are empty, which our code should be handling
@@ -3309,7 +3308,7 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalOb
auto source = Bun::toString(sourceString);
auto typeAttribute = Bun::toString(typeAttributeString);
ErrorableResolvedSource res;
ErrorableModuleResult res;
res.success = false;
// zero-initialize entire result union. zeroed BunString has BunStringTag::Dead, and zeroed
// EncodedJSValues are empty, which our code should be handling

View File

@@ -1,368 +0,0 @@
#include "root.h"
#include "helpers.h"
#include "ZigSourceProvider.h"
#include <JavaScriptCore/BytecodeCacheError.h>
#include "ZigGlobalObject.h"
#include "wtf/Assertions.h"
#include <JavaScriptCore/Completion.h>
#include <wtf/Scope.h>
#include <wtf/text/StringHash.h>
#include <sys/stat.h>
#include <JavaScriptCore/SourceCodeKey.h>
#include <mimalloc.h>
#include <JavaScriptCore/CodeCache.h>
namespace Zig {
using Base = JSC::SourceProvider;
using BytecodeCacheGenerator = JSC::BytecodeCacheGenerator;
using UnlinkedFunctionExecutable = JSC::UnlinkedFunctionExecutable;
using CachedBytecode = JSC::CachedBytecode;
using UnlinkedFunctionCodeBlock = JSC::UnlinkedFunctionCodeBlock;
using SourceCode = JSC::SourceCode;
using CodeSpecializationKind = JSC::CodeSpecializationKind;
using SourceOrigin = JSC::SourceOrigin;
using String = WTF::String;
using SourceProviderSourceType = JSC::SourceProviderSourceType;
SourceOrigin toSourceOrigin(const String& sourceURL, bool isBuiltin)
{
ASSERT_WITH_MESSAGE(!sourceURL.startsWith("file://"_s), "specifier should not already be a file URL");
if (isBuiltin) {
if (sourceURL.startsWith("node:"_s)) {
return SourceOrigin(WTF::URL(makeString("builtin://node/"_s, sourceURL.substring(5))));
} else if (sourceURL.startsWith("bun:"_s)) {
return SourceOrigin(WTF::URL(makeString("builtin://bun/"_s, sourceURL.substring(4))));
} else {
return SourceOrigin(WTF::URL(makeString("builtin://"_s, sourceURL)));
}
}
return SourceOrigin(WTF::URL::fileURLWithFileSystemPath(sourceURL));
}
extern "C" int ByteRangeMapping__getSourceID(void* mappings, BunString sourceURL);
extern "C" void* ByteRangeMapping__find(BunString sourceURL);
void* sourceMappingForSourceURL(const WTF::String& sourceURL)
{
return ByteRangeMapping__find(Bun::toString(sourceURL));
}
extern "C" void ByteRangeMapping__generate(BunString sourceURL, BunString code, int sourceID);
JSC::SourceID sourceIDForSourceURL(const WTF::String& sourceURL)
{
void* mappings = ByteRangeMapping__find(Bun::toString(sourceURL));
if (!mappings) {
return 0;
}
return ByteRangeMapping__getSourceID(mappings, Bun::toString(sourceURL));
}
extern "C" bool BunTest__shouldGenerateCodeCoverage(BunString sourceURL);
extern "C" void Bun__addSourceProviderSourceMap(void* bun_vm, SourceProvider* opaque_source_provider, BunString* specifier);
extern "C" void Bun__removeSourceProviderSourceMap(void* bun_vm, SourceProvider* opaque_source_provider, BunString* specifier);
Ref<SourceProvider> SourceProvider::create(
Zig::GlobalObject* globalObject,
ResolvedSource& resolvedSource,
JSC::SourceProviderSourceType sourceType,
bool isBuiltin)
{
auto string = resolvedSource.source_code.toWTFString(BunString::ZeroCopy);
auto sourceURLString = resolvedSource.source_url.toWTFString(BunString::ZeroCopy);
bool isCodeCoverageEnabled = !!globalObject->vm().controlFlowProfiler();
bool shouldGenerateCodeCoverage = isCodeCoverageEnabled && !isBuiltin && BunTest__shouldGenerateCodeCoverage(resolvedSource.source_url);
if (resolvedSource.needsDeref && !isBuiltin) {
resolvedSource.needsDeref = false;
resolvedSource.source_code.deref();
// Do not deref either source_url or specifier
// Specifier's lifetime is the JSValue, mostly
// source_url is owned by the string above
// https://github.com/oven-sh/bun/issues/9521
}
const auto getProvider = [&]() -> Ref<SourceProvider> {
if (resolvedSource.bytecode_cache != nullptr) {
const auto destructorPtr = [](const void* ptr) {
mi_free(const_cast<void*>(ptr));
};
const auto destructorNoOp = [](const void* ptr) {
// no-op, for bun build --compile.
};
const auto destructor = resolvedSource.needsDeref ? destructorPtr : destructorNoOp;
Ref<JSC::CachedBytecode> bytecode = JSC::CachedBytecode::create(std::span<uint8_t>(resolvedSource.bytecode_cache, resolvedSource.bytecode_cache_size), destructor, {});
auto provider = adoptRef(*new SourceProvider(
globalObject->isThreadLocalDefaultGlobalObject ? globalObject : nullptr,
resolvedSource,
string.isNull() ? *StringImpl::empty() : *string.impl(),
JSC::SourceTaintedOrigin::Untainted,
toSourceOrigin(sourceURLString, isBuiltin),
sourceURLString.impl(), TextPosition(),
sourceType));
provider->m_cachedBytecode = WTFMove(bytecode);
return provider;
}
return adoptRef(*new SourceProvider(
globalObject->isThreadLocalDefaultGlobalObject ? globalObject : nullptr,
resolvedSource,
string.isNull() ? *StringImpl::empty() : *string.impl(),
JSC::SourceTaintedOrigin::Untainted,
toSourceOrigin(sourceURLString, isBuiltin),
sourceURLString.impl(), TextPosition(),
sourceType));
};
auto provider = getProvider();
if (shouldGenerateCodeCoverage) {
ByteRangeMapping__generate(Bun::toString(provider->sourceURL()), Bun::toString(provider->source().toStringWithoutCopying()), provider->asID());
}
if (resolvedSource.already_bundled) {
Bun__addSourceProviderSourceMap(globalObject->bunVM(), provider.ptr(), &resolvedSource.source_url);
}
return provider;
}
StringView SourceProvider::source() const
{
return StringView(m_source.get());
}
SourceProvider::~SourceProvider()
{
if (m_resolvedSource.already_bundled) {
BunString str = Bun::toString(sourceURL());
Bun__removeSourceProviderSourceMap(m_globalObject->bunVM(), this, &str);
}
}
extern "C" void CachedBytecode__deref(JSC::CachedBytecode* cachedBytecode)
{
cachedBytecode->deref();
}
static JSC::VM& getVMForBytecodeCache()
{
static thread_local JSC::VM* vmForBytecodeCache = nullptr;
if (!vmForBytecodeCache) {
const auto heapSize = JSC::HeapType::Small;
auto vmPtr = JSC::VM::tryCreate(heapSize);
vmPtr->refSuppressingSaferCPPChecking();
vmForBytecodeCache = vmPtr.get();
vmPtr->heap.acquireAccess();
}
return *vmForBytecodeCache;
}
extern "C" bool generateCachedModuleByteCodeFromSourceCode(BunString* sourceProviderURL, const Latin1Character* inputSourceCode, size_t inputSourceCodeSize, const uint8_t** outputByteCode, size_t* outputByteCodeSize, JSC::CachedBytecode** cachedBytecodePtr)
{
std::span<const Latin1Character> sourceCodeSpan(inputSourceCode, inputSourceCodeSize);
JSC::SourceCode sourceCode = JSC::makeSource(WTF::String(sourceCodeSpan), toSourceOrigin(sourceProviderURL->toWTFString(), false), JSC::SourceTaintedOrigin::Untainted);
JSC::VM& vm = getVMForBytecodeCache();
JSC::JSLockHolder locker(vm);
LexicallyScopedFeatures lexicallyScopedFeatures = StrictModeLexicallyScopedFeature;
JSParserScriptMode scriptMode = JSParserScriptMode::Module;
EvalContextType evalContextType = EvalContextType::None;
ParserError parserError;
UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = JSC::recursivelyGenerateUnlinkedCodeBlockForModuleProgram(vm, sourceCode, lexicallyScopedFeatures, scriptMode, {}, parserError, evalContextType);
if (parserError.isValid())
return false;
if (!unlinkedCodeBlock)
return false;
auto key = JSC::sourceCodeKeyForSerializedModule(vm, sourceCode);
RefPtr<JSC::CachedBytecode> cachedBytecode = JSC::encodeCodeBlock(vm, key, unlinkedCodeBlock);
if (!cachedBytecode)
return false;
cachedBytecode->ref();
*cachedBytecodePtr = cachedBytecode.get();
*outputByteCode = cachedBytecode->span().data();
*outputByteCodeSize = cachedBytecode->span().size();
return true;
}
extern "C" bool generateCachedCommonJSProgramByteCodeFromSourceCode(BunString* sourceProviderURL, const Latin1Character* inputSourceCode, size_t inputSourceCodeSize, const uint8_t** outputByteCode, size_t* outputByteCodeSize, JSC::CachedBytecode** cachedBytecodePtr)
{
std::span<const Latin1Character> sourceCodeSpan(inputSourceCode, inputSourceCodeSize);
JSC::SourceCode sourceCode = JSC::makeSource(WTF::String(sourceCodeSpan), toSourceOrigin(sourceProviderURL->toWTFString(), false), JSC::SourceTaintedOrigin::Untainted);
JSC::VM& vm = getVMForBytecodeCache();
JSC::JSLockHolder locker(vm);
LexicallyScopedFeatures lexicallyScopedFeatures = NoLexicallyScopedFeatures;
JSParserScriptMode scriptMode = JSParserScriptMode::Classic;
EvalContextType evalContextType = EvalContextType::None;
ParserError parserError;
UnlinkedProgramCodeBlock* unlinkedCodeBlock = JSC::recursivelyGenerateUnlinkedCodeBlockForProgram(vm, sourceCode, lexicallyScopedFeatures, scriptMode, {}, parserError, evalContextType);
if (parserError.isValid())
return false;
if (!unlinkedCodeBlock)
return false;
auto key = JSC::sourceCodeKeyForSerializedProgram(vm, sourceCode);
RefPtr<JSC::CachedBytecode> cachedBytecode = JSC::encodeCodeBlock(vm, key, unlinkedCodeBlock);
if (!cachedBytecode)
return false;
cachedBytecode->ref();
*cachedBytecodePtr = cachedBytecode.get();
*outputByteCode = cachedBytecode->span().data();
*outputByteCodeSize = cachedBytecode->span().size();
return true;
}
unsigned SourceProvider::hash() const
{
if (m_hash) {
return m_hash;
}
return m_source->hash();
}
void SourceProvider::freeSourceCode()
{
}
void SourceProvider::updateCache(const UnlinkedFunctionExecutable* executable, const SourceCode&,
CodeSpecializationKind kind,
const UnlinkedFunctionCodeBlock* codeBlock)
{
// if (!m_resolvedSource.bytecodecache_fd || !m_cachedBytecode)
return;
JSC::BytecodeCacheError error;
RefPtr<JSC::CachedBytecode> cachedBytecode = JSC::encodeFunctionCodeBlock(executable->vm(), codeBlock, error);
if (cachedBytecode && !error.isValid())
m_cachedBytecode->addFunctionUpdate(executable, kind, *cachedBytecode);
}
void SourceProvider::cacheBytecode(const BytecodeCacheGenerator& generator)
{
// if (!m_resolvedSource.bytecodecache_fd)
return;
if (!m_cachedBytecode)
m_cachedBytecode = JSC::CachedBytecode::create();
auto update = generator();
if (update)
m_cachedBytecode->addGlobalUpdate(*update);
}
void SourceProvider::commitCachedBytecode()
{
// if (!m_resolvedSource.bytecodecache_fd || !m_cachedBytecode || !m_cachedBytecode->hasUpdates())
return;
// auto clearBytecode = WTF::makeScopeExit([&] { m_cachedBytecode = nullptr; });
// const auto fd = m_resolvedSource.bytecodecache_fd;
// auto fileSize = FileSystem::fileSize(fd);
// if (!fileSize)
// return;
// size_t cacheFileSize;
// if (!WTF::convertSafely(*fileSize, cacheFileSize) || cacheFileSize != m_cachedBytecode->size()) {
// // The bytecode cache has already been updated
// return;
// }
// if (!FileSystem::truncateFile(fd, m_cachedBytecode->sizeForUpdate()))
// return;
// m_cachedBytecode->commitUpdates([&](off_t offset, const void* data, size_t size) {
// long long result = FileSystem::seekFile(fd, offset, FileSystem::FileSeekOrigin::Beginning);
// ASSERT_UNUSED(result, result != -1);
// size_t bytesWritten = static_cast<size_t>(FileSystem::writeToFile(fd, data, size));
// ASSERT_UNUSED(bytesWritten, bytesWritten == size);
// });
}
bool SourceProvider::isBytecodeCacheEnabled() const
{
// return m_resolvedSource.bytecodecache_fd > 0;
return false;
}
void SourceProvider::readOrGenerateByteCodeCache(JSC::VM& vm, const JSC::SourceCode& sourceCode)
{
// auto status = this->readCache(vm, sourceCode);
// switch (status) {
// case -1: {
// m_resolvedSource.bytecodecache_fd = 0;
// break;
// }
// case 0: {
// JSC::BytecodeCacheError err;
// m_cachedBytecode = JSC::generateModuleBytecode(vm, sourceCode, m_resolvedSource.bytecodecache_fd, err);
// if (err.isValid()) {
// m_resolvedSource.bytecodecache_fd = 0;
// m_cachedBytecode = JSC::CachedBytecode::create();
// }
// }
// // TODO: read the bytecode into a JSC::SourceCode object here
// case 1: {
// }
// }
}
int SourceProvider::readCache(JSC::VM& vm, const JSC::SourceCode& sourceCode)
{
return -1;
// if (m_resolvedSource.bytecodecache_fd == 0)
// return -1;
// if (!FileSystem::isHandleValid(m_resolvedSource.bytecodecache_fd))
// return -1;
// const auto fd = m_resolvedSource.bytecodecache_fd;
// bool success;
// FileSystem::MappedFileData mappedFile(fd, FileSystem::MappedFileMode::Shared, success);
// if (!success)
// return -1;
// const uint8_t* fileData = reinterpret_cast<const uint8_t*>(mappedFile.data());
// unsigned fileTotalSize = mappedFile.size();
// if (fileTotalSize == 0)
// return 0;
// Ref<JSC::CachedBytecode> cachedBytecode = JSC::CachedBytecode::create(WTFMove(mappedFile));
// // auto key = JSC::sourceCodeKeyForSerializedModule(vm, sourceCode);
// // if (isCachedBytecodeStillValid(vm, cachedBytecode.copyRef(), key,
// // JSC::SourceCodeType::ModuleType)) {
// m_cachedBytecode = WTFMove(cachedBytecode);
// return 1;
// } else {
// FileSystem::truncateFile(fd, 0);
// return 0;
// }
}
extern "C" BunString ZigSourceProvider__getSourceSlice(SourceProvider* provider)
{
return Bun::toStringView(provider->source());
}
}; // namespace Zig

View File

@@ -1,80 +0,0 @@
#include "headers.h"
#include "root.h"
#pragma once
namespace JSC {
class Structure;
class Identifier;
class SourceCodeKey;
class SourceProvider;
} // namespace JSC
#include <JavaScriptCore/CachedBytecode.h>
#include <JavaScriptCore/JSGlobalObject.h>
#include <JavaScriptCore/JSTypeInfo.h>
#include <JavaScriptCore/SourceProvider.h>
#include <JavaScriptCore/Structure.h>
namespace Zig {
class GlobalObject;
void forEachSourceProvider(WTF::Function<void(JSC::SourceID)>);
JSC::SourceID sourceIDForSourceURL(const WTF::String& sourceURL);
void* sourceMappingForSourceURL(const WTF::String& sourceURL);
JSC::SourceOrigin toSourceOrigin(const String& sourceURL, bool isBuiltin);
class SourceProvider final : public JSC::SourceProvider {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED(SourceProvider);
using Base = JSC::SourceProvider;
using BytecodeCacheGenerator = JSC::BytecodeCacheGenerator;
using UnlinkedFunctionExecutable = JSC::UnlinkedFunctionExecutable;
using CachedBytecode = JSC::CachedBytecode;
using UnlinkedFunctionCodeBlock = JSC::UnlinkedFunctionCodeBlock;
using SourceCode = JSC::SourceCode;
using CodeSpecializationKind = JSC::CodeSpecializationKind;
using SourceOrigin = JSC::SourceOrigin;
public:
static Ref<SourceProvider> create(
Zig::GlobalObject*,
ResolvedSource& resolvedSource,
JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::Module,
bool isBuiltIn = false);
~SourceProvider();
unsigned hash() const override;
StringView source() const override;
RefPtr<JSC::CachedBytecode> cachedBytecode() const final
{
return m_cachedBytecode.copyRef();
};
void updateCache(const UnlinkedFunctionExecutable* executable, const SourceCode&, CodeSpecializationKind kind, const UnlinkedFunctionCodeBlock* codeBlock);
void cacheBytecode(const BytecodeCacheGenerator& generator);
void commitCachedBytecode();
bool isBytecodeCacheEnabled() const;
void readOrGenerateByteCodeCache(JSC::VM& vm, const JSC::SourceCode& sourceCode);
ResolvedSource m_resolvedSource;
int readCache(JSC::VM& vm, const JSC::SourceCode& sourceCode);
void freeSourceCode();
private:
SourceProvider(Zig::GlobalObject* globalObject, ResolvedSource resolvedSource, Ref<WTF::StringImpl>&& sourceImpl,
JSC::SourceTaintedOrigin taintedness,
const SourceOrigin& sourceOrigin, WTF::String&& sourceURL,
const TextPosition& startPosition, JSC::SourceProviderSourceType sourceType)
: Base(sourceOrigin, WTFMove(sourceURL), String(), taintedness, startPosition, sourceType)
, m_globalObject(globalObject)
, m_source(sourceImpl)
{
m_resolvedSource = resolvedSource;
}
Zig::GlobalObject* m_globalObject;
RefPtr<JSC::CachedBytecode> m_cachedBytecode;
Ref<WTF::StringImpl> m_source;
unsigned m_hash = 0;
};
} // namespace Zig

View File

@@ -129,6 +129,67 @@ typedef struct ErrorableResolvedSource {
bool success;
} ErrorableResolvedSource;
// New module result types for Phase 2 refactoring
typedef struct TranspiledSourceFlags {
bool is_commonjs;
bool is_already_bundled;
uint32_t _padding : 30;
} TranspiledSourceFlags;
typedef struct TranspiledSource {
BunString source_code;
BunString source_url;
uint8_t* bytecode_cache;
size_t bytecode_cache_len;
TranspiledSourceFlags flags;
} TranspiledSource;
#ifdef __cplusplus
enum class SpecialModuleTag : uint8_t {
exports_object = 0,
export_default_object = 1,
custom_extension = 2,
};
#else
typedef uint8_t SpecialModuleTag;
#endif
typedef struct SpecialModule {
SpecialModuleTag tag;
JSC::EncodedJSValue jsvalue;
} SpecialModule;
#ifdef __cplusplus
enum class ModuleResultTag : uint8_t {
transpiled = 0,
special = 1,
builtin = 2,
};
#else
typedef uint8_t ModuleResultTag;
#endif
typedef union ModuleResultValue {
TranspiledSource transpiled;
SpecialModule special;
uint32_t builtin_id;
} ModuleResultValue;
typedef struct ModuleResult {
ModuleResultTag tag;
ModuleResultValue value;
} ModuleResult;
typedef union ErrorableModuleResultResult {
ModuleResult value;
ZigErrorType err;
} ErrorableModuleResultResult;
typedef struct ErrorableModuleResult {
ErrorableModuleResultResult result;
bool success;
} ErrorableModuleResult;
typedef struct SystemError {
int errno_;
BunString code;
@@ -354,7 +415,7 @@ extern "C" bool Bun__transpileVirtualModule(
const BunString* referrer,
ZigString* sourceCode,
BunLoaderType loader,
ErrorableResolvedSource* result);
ErrorableModuleResult* result);
extern "C" JSC::EncodedJSValue Bun__runVirtualModule(
JSC::JSGlobalObject* global,
@@ -366,7 +427,7 @@ extern "C" JSC::JSInternalPromise* Bun__transpileFile(
BunString* specifier,
BunString* referrer,
const BunString* typeAttribute,
ErrorableResolvedSource* result,
ErrorableModuleResult* result,
bool allowPromise,
bool isCommonJSRequire,
BunLoaderType forceLoaderType);
@@ -376,11 +437,11 @@ extern "C" bool Bun__fetchBuiltinModule(
JSC::JSGlobalObject* global,
const BunString* specifier,
const BunString* referrer,
ErrorableResolvedSource* result);
ErrorableModuleResult* result);
extern "C" bool Bun__resolveAndFetchBuiltinModule(
void* bunVM,
const BunString* specifier,
ErrorableResolvedSource* result);
ErrorableModuleResult* result);
// Used in process.version
extern "C" const char* Bun__version;

View File

@@ -90,6 +90,7 @@ pub const RegularExpression = @import("./bindings/RegularExpression.zig").Regula
// JavaScript-related
pub const Errorable = @import("./bindings/Errorable.zig").Errorable;
pub const ResolvedSource = @import("./bindings/ResolvedSource.zig").ResolvedSource;
pub const ModuleResult = @import("./bindings/ModuleResult.zig").ModuleResult;
pub const ErrorCode = @import("./bindings/ErrorCode.zig").ErrorCode;
pub const JSErrorCode = @import("./bindings/JSErrorCode.zig").JSErrorCode;
pub const ZigErrorType = @import("./bindings/ZigErrorType.zig").ZigErrorType;
@@ -103,6 +104,7 @@ pub const JSRuntimeType = @import("./bindings/JSRuntimeType.zig").JSRuntimeType;
pub const ZigStackFrameCode = @import("./bindings/ZigStackFrameCode.zig").ZigStackFrameCode;
pub const ErrorableResolvedSource = Errorable(ResolvedSource);
pub const ErrorableModuleResult = Errorable(ModuleResult);
pub const ErrorableZigString = Errorable(ZigString);
pub const ErrorableJSValue = Errorable(JSValue);
pub const ErrorableString = Errorable(bun.String);

View File

@@ -44,7 +44,6 @@
#endif
#include "JSDOMConvertBase.h"
#include "ZigSourceProvider.h"
#include "mimalloc.h"
#include <JavaScriptCore/ControlFlowProfiler.h>
@@ -62,6 +61,22 @@ using namespace JSC;
using namespace WTF;
using namespace WebCore;
// Extern declarations for code coverage support functions from Zig
extern "C" void* ByteRangeMapping__find(BunString sourceURL);
extern "C" JSC::SourceID ByteRangeMapping__getSourceID(void* mappings, BunString sourceURL);
namespace Zig {
// Helper function to find source ID for a given source URL (used for code coverage)
inline JSC::SourceID sourceIDForSourceURL(const WTF::String& sourceURL)
{
void* mappings = ByteRangeMapping__find(Bun::toString(sourceURL));
if (!mappings) {
return 0;
}
return ByteRangeMapping__getSourceID(mappings, Bun::toString(sourceURL));
}
} // namespace Zig
JSC_DECLARE_HOST_FUNCTION(functionStartRemoteDebugger);
JSC_DEFINE_HOST_FUNCTION(functionStartRemoteDebugger,
(JSGlobalObject * globalObject,