little bit of errors, little bit of bytecode caching. neither finished

Former-commit-id: c774c395136d58330aa7cad7e9fa434bcef7d5c6
This commit is contained in:
Jarred Sumner
2021-07-30 00:50:29 -07:00
parent ba743d776a
commit 7245f90b2d
27 changed files with 1662 additions and 820 deletions

View File

@@ -20,7 +20,7 @@ pub fn importRoute(
arguments: []const js.JSValueRef,
exception: js.ExceptionRef,
) js.JSObjectRef {
return JavaScript.VirtualMachine.vm.require(
return JavaScript.VirtualMachine.instance.require(
ctx,
std.fs.path.dirname(this.route.file_path).?,
this.route.file_path,

View File

@@ -1,40 +1,42 @@
#include "ZigGlobalObject.h"
#include "helpers.h"
#include "ZigConsoleClient.h"
#include <JavaScriptCore/CallFrameInlines.h>
#include <JavaScriptCore/CatchScope.h>
#include <JavaScriptCore/ClassInfo.h>
#include <JavaScriptCore/Completion.h>
#include <JavaScriptCore/Error.h>
#include <JavaScriptCore/Exception.h>
#include <JavaScriptCore/Identifier.h>
#include <JavaScriptCore/InitializeThreading.h>
#include <JavaScriptCore/JSCast.h>
#include <JavaScriptCore/JSContextInternal.h>
#include <JavaScriptCore/JSInternalPromise.h>
#include <JavaScriptCore/JSModuleLoader.h>
#include <JavaScriptCore/JSNativeStdFunction.h>
#include <JavaScriptCore/JSPromise.h>
#include <JavaScriptCore/JSSourceCode.h>
#include <JavaScriptCore/JSString.h>
#include <JavaScriptCore/JSValueInternal.h>
#include <JavaScriptCore/JSVirtualMachineInternal.h>
#include <JavaScriptCore/ObjectConstructor.h>
#include <JavaScriptCore/SourceOrigin.h>
#include <JavaScriptCore/Identifier.h>
#include <wtf/URL.h>
#include <JavaScriptCore/ClassInfo.h>
#include <JavaScriptCore/JSString.h>
#include <JavaScriptCore/VM.h>
#include <JavaScriptCore/WasmFaultSignalHandler.h>
#include <JavaScriptCore/JSCast.h>
#include <JavaScriptCore/InitializeThreading.h>
#include "ZigConsoleClient.h"
#include <wtf/URL.h>
#include <JavaScriptCore/JSLock.h>
#include <wtf/StdLibExtras.h>
#include <iostream>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <JavaScriptCore/JSClassRef.h>
#include <JavaScriptCore/JSCallbackObject.h>
#include <JavaScriptCore/JSClassRef.h>
#include "ZigSourceProvider.h"
using JSGlobalObject = JSC::JSGlobalObject;
using Exception = JSC::Exception;
@@ -48,193 +50,199 @@ using JSObject = JSC::JSObject;
using JSNonFinalObject = JSC::JSNonFinalObject;
namespace JSCastingHelpers = JSC::JSCastingHelpers;
extern "C" JSC__JSGlobalObject *Zig__GlobalObject__create(JSClassRef *globalObjectClass, int count,
void *console_client) {
std::set_terminate([]() { Zig__GlobalObject__onCrash(); });
JSC::initialize();
extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(JSClassRef* globalObjectClass, int count, void* console_client) {
std::set_terminate([](){ Zig__GlobalObject__onCrash(); });
JSC::initialize();
JSC::VM& vm = JSC::VM::create(JSC::LargeHeap).leakRef();
JSC::VM &vm = JSC::VM::create(JSC::LargeHeap).leakRef();
#if ENABLE(WEBASSEMBLY)
JSC::Wasm::enableFastMemory();
#endif
#if ENABLE(WEBASSEMBLY)
JSC::Wasm::enableFastMemory();
#endif
JSC::JSLockHolder locker(vm);
Zig::GlobalObject *globalObject = Zig::GlobalObject::create(vm, Zig::GlobalObject::createStructure(vm, JSC::jsNull()));
globalObject->setConsole(globalObject);
JSC::JSLockHolder locker(vm);
Zig::GlobalObject *globalObject =
Zig::GlobalObject::create(vm, Zig::GlobalObject::createStructure(vm, JSC::jsNull()));
globalObject->setConsole(globalObject);
if (count > 0) {
globalObject->installAPIGlobals(globalObjectClass, count);
}
if (count > 0) { globalObject->installAPIGlobals(globalObjectClass, count); }
JSC::gcProtect(globalObject);
vm.ref();
return globalObject;
JSC::gcProtect(globalObject);
vm.ref();
return globalObject;
}
namespace Zig {
const JSC::ClassInfo GlobalObject::s_info = { "GlobalObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
const JSC::ClassInfo GlobalObject::s_info = {"GlobalObject", &Base::s_info, nullptr, nullptr,
CREATE_METHOD_TABLE(GlobalObject)};
const JSC::GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = {
&supportsRichSourceInfo,
&shouldInterruptScript,
&javaScriptRuntimeFlags,
nullptr, // queueTaskToEventLoop
nullptr, // &shouldInterruptScriptBeforeTimeout,
&moduleLoaderImportModule, // moduleLoaderImportModule
&moduleLoaderResolve, // moduleLoaderResolve
&moduleLoaderFetch, // moduleLoaderFetch
&moduleLoaderCreateImportMetaProperties, // moduleLoaderCreateImportMetaProperties
&moduleLoaderEvaluate, // moduleLoaderEvaluate
&promiseRejectionTracker, // promiseRejectionTracker
&reportUncaughtExceptionAtEventLoop,
&currentScriptExecutionOwner,
&scriptExecutionStatus,
nullptr, // defaultLanguage
nullptr, // compileStreaming
nullptr, // instantiateStreaming
&supportsRichSourceInfo,
&shouldInterruptScript,
&javaScriptRuntimeFlags,
nullptr, // queueTaskToEventLoop
nullptr, // &shouldInterruptScriptBeforeTimeout,
&moduleLoaderImportModule, // moduleLoaderImportModule
&moduleLoaderResolve, // moduleLoaderResolve
&moduleLoaderFetch, // moduleLoaderFetch
&moduleLoaderCreateImportMetaProperties, // moduleLoaderCreateImportMetaProperties
&moduleLoaderEvaluate, // moduleLoaderEvaluate
&promiseRejectionTracker, // promiseRejectionTracker
&reportUncaughtExceptionAtEventLoop,
&currentScriptExecutionOwner,
&scriptExecutionStatus,
nullptr, // defaultLanguage
nullptr, // compileStreaming
nullptr, // instantiateStreaming
};
void GlobalObject::reportUncaughtExceptionAtEventLoop(JSGlobalObject* globalObject, Exception* exception) {
Zig__GlobalObject__reportUncaughtException(globalObject, exception);
void GlobalObject::reportUncaughtExceptionAtEventLoop(JSGlobalObject *globalObject,
Exception *exception) {
Zig__GlobalObject__reportUncaughtException(globalObject, exception);
}
void GlobalObject::promiseRejectionTracker(JSGlobalObject* obj, JSC::JSPromise* prom, JSC::JSPromiseRejectionOperation reject) {
Zig__GlobalObject__promiseRejectionTracker(obj, prom, reject == JSC::JSPromiseRejectionOperation::Reject ? 0 : 1);
void GlobalObject::promiseRejectionTracker(JSGlobalObject *obj, JSC::JSPromise *prom,
JSC::JSPromiseRejectionOperation reject) {
Zig__GlobalObject__promiseRejectionTracker(
obj, prom, reject == JSC::JSPromiseRejectionOperation::Reject ? 0 : 1);
}
static Zig::ConsoleClient* m_console;
static Zig::ConsoleClient *m_console;
void GlobalObject::setConsole(void* console) {
m_console = new Zig::ConsoleClient(console);
this->setConsoleClient(makeWeakPtr(m_console));
void GlobalObject::setConsole(void *console) {
m_console = new Zig::ConsoleClient(console);
this->setConsoleClient(makeWeakPtr(m_console));
}
void GlobalObject::installAPIGlobals(JSClassRef* globals, int count) {
WTF::Vector<GlobalPropertyInfo> extraStaticGlobals;
extraStaticGlobals.reserveCapacity((size_t)count);
void GlobalObject::installAPIGlobals(JSClassRef *globals, int count) {
WTF::Vector<GlobalPropertyInfo> extraStaticGlobals;
extraStaticGlobals.reserveCapacity((size_t)count);
for (int i = 0; i < count; i++) {
auto jsClass = globals[i];
for (int i = 0; i < count; i++) {
auto jsClass = globals[i];
JSC::JSCallbackObject<JSNonFinalObject>* object = JSC::JSCallbackObject<JSNonFinalObject>::create(this, this->callbackObjectStructure(), jsClass, nullptr);
if (JSObject* prototype = jsClass->prototype(this))
object->setPrototypeDirect(vm(), prototype);
JSC::JSCallbackObject<JSNonFinalObject> *object =
JSC::JSCallbackObject<JSNonFinalObject>::create(this, this->callbackObjectStructure(),
jsClass, nullptr);
if (JSObject *prototype = jsClass->prototype(this)) object->setPrototypeDirect(vm(), prototype);
extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo{ JSC::Identifier::fromString(vm(), jsClass->className()), JSC::JSValue(object), JSC::PropertyAttribute::DontDelete | 0 });
}
this->addStaticGlobals(extraStaticGlobals.data(), count);
extraStaticGlobals.releaseBuffer();
extraStaticGlobals.uncheckedAppend(
GlobalPropertyInfo{JSC::Identifier::fromString(vm(), jsClass->className()),
JSC::JSValue(object), JSC::PropertyAttribute::DontDelete | 0});
}
this->addStaticGlobals(extraStaticGlobals.data(), count);
extraStaticGlobals.releaseBuffer();
}
JSC::Identifier GlobalObject::moduleLoaderResolve(
JSGlobalObject* globalObject,
JSModuleLoader* loader,
JSValue key,
JSValue referrer,
JSValue origin
) {
auto res = Zig__GlobalObject__resolve(
globalObject,
toZigString(key, globalObject),
referrer.isString() ? toZigString(referrer, globalObject) : ZigStringEmpty
);
JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject *globalObject,
JSModuleLoader *loader, JSValue key,
JSValue referrer, JSValue origin) {
auto res = Zig__GlobalObject__resolve(globalObject, toZigString(key, globalObject),
referrer.isString() ? toZigString(referrer, globalObject)
: ZigStringEmpty);
if (res.success) {
return toIdentifier(res.result.value, globalObject);
} else {
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
throwException(scope, res.result.err.message, globalObject);
return globalObject->vm().propertyNames->emptyIdentifier;
}
if (res.success) {
return toIdentifier(res.result.value, globalObject);
} else {
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
throwException(scope, res.result.err.message, globalObject);
return globalObject->vm().propertyNames->emptyIdentifier;
}
}
JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin& sourceOrigin)
{
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSC::JSInternalPromise *GlobalObject::moduleLoaderImportModule(JSGlobalObject *globalObject,
JSModuleLoader *,
JSString *moduleNameValue,
JSValue parameters,
const SourceOrigin &sourceOrigin) {
JSC::VM &vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
auto* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
auto *promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
auto sourceURL = sourceOrigin.url();
auto resolved = Zig__GlobalObject__resolve(globalObject, toZigString(moduleNameValue, globalObject), sourceURL.isEmpty() ? ZigStringCwd : toZigString(sourceURL.fileSystemPath()));
if (!resolved.success) {
throwException(scope, resolved.result.err.message, globalObject);
return promise->rejectWithCaughtException(globalObject, scope);
}
auto sourceURL = sourceOrigin.url();
auto resolved = Zig__GlobalObject__resolve(
globalObject, toZigString(moduleNameValue, globalObject),
sourceURL.isEmpty() ? ZigStringCwd : toZigString(sourceURL.fileSystemPath()));
if (!resolved.success) {
throwException(scope, resolved.result.err.message, globalObject);
return promise->rejectWithCaughtException(globalObject, scope);
}
auto result = JSC::importModule(globalObject, toIdentifier(resolved.result.value, globalObject), parameters, JSC::jsUndefined());
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
auto result = JSC::importModule(globalObject, toIdentifier(resolved.result.value, globalObject),
parameters, JSC::jsUndefined());
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
return result;
return result;
}
JSC::JSInternalPromise *GlobalObject::moduleLoaderFetch(JSGlobalObject *globalObject,
JSModuleLoader *loader, JSValue key,
JSValue value1, JSValue value2) {
JSC::VM &vm = globalObject->vm();
JSC::JSInternalPromise *promise =
JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, JSModuleLoader* loader, JSValue key, JSValue value1, JSValue value2) {
JSC::VM& vm = globalObject->vm();
JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
auto scope = DECLARE_THROW_SCOPE(vm);
auto scope = DECLARE_THROW_SCOPE(vm);
auto rejectWithError = [&](JSC::JSValue error) {
promise->reject(globalObject, error);
return promise;
};
auto moduleKey = key.toWTFString(globalObject);
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
auto moduleKeyZig = toZigString(moduleKey);
auto res = Zig__GlobalObject__fetch(
globalObject,
moduleKeyZig,
ZigStringEmpty
);
if (!res.success) {
throwException(scope, res.result.err.message, globalObject);
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
}
auto code = Zig::toString(res.result.value);
auto sourceCode = JSC::JSSourceCode::create(
vm,
JSC::makeSource(
code,
JSC::SourceOrigin { WTF::URL::fileURLWithFileSystemPath(moduleKey) },
WTFMove(moduleKey),
TextPosition(),
JSC::SourceProviderSourceType::Module
)
);
scope.release();
promise->resolve(globalObject, sourceCode);
globalObject->vm().drainMicrotasks();
auto rejectWithError = [&](JSC::JSValue error) {
promise->reject(globalObject, error);
return promise;
};
auto moduleKey = key.toWTFString(globalObject);
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
auto moduleKeyZig = toZigString(moduleKey);
auto res = Zig__GlobalObject__fetch(globalObject, moduleKeyZig, ZigStringEmpty);
if (!res.success) {
throwException(scope, res.result.err.message, globalObject);
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
}
auto code = Zig::toString(res.result.value.source_code);
auto provider = Zig::SourceProvider::create(res.result.value);
auto jsSourceCode = JSC::JSSourceCode::create(vm, JSC::SourceCode(provider));
// if (provider.ptr()->isBytecodeCacheEnabled()) {
// provider.ptr()->readOrGenerateByteCodeCache(vm, jsSourceCode->sourceCode());
// }
scope.release();
promise->resolve(globalObject, jsSourceCode);
globalObject->vm().drainMicrotasks();
return promise;
}
JSC::JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject, JSModuleLoader* loader, JSValue key, JSModuleRecord* record, JSValue val) {
return nullptr;
// auto res = Zig__GlobalObject__createImportMetaProperties(
// globalObject,
// loader,
// JSValue::encode(key),
// record,
// JSValue::encode(val)
// );
JSC::JSObject *GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject *globalObject,
JSModuleLoader *loader,
JSValue key,
JSModuleRecord *record,
JSValue val) {
return nullptr;
// auto res = Zig__GlobalObject__createImportMetaProperties(
// globalObject,
// loader,
// JSValue::encode(key),
// record,
// JSValue::encode(val)
// );
// return JSValue::decode(res).getObject();
// return JSValue::decode(res).getObject();
}
JSC::JSValue GlobalObject::moduleLoaderEvaluate(JSGlobalObject* globalObject, JSModuleLoader* moduleLoader, JSValue key, JSValue moduleRecordValue, JSValue scriptFetcher, JSValue sentValue, JSValue resumeMode) {
// VM& vm = globalObject->vm();
return moduleLoader->evaluateNonVirtual(globalObject, key, moduleRecordValue, scriptFetcher, sentValue, resumeMode);
JSC::JSValue GlobalObject::moduleLoaderEvaluate(JSGlobalObject *globalObject,
JSModuleLoader *moduleLoader, JSValue key,
JSValue moduleRecordValue, JSValue scriptFetcher,
JSValue sentValue, JSValue resumeMode) {
// VM& vm = globalObject->vm();
return moduleLoader->evaluateNonVirtual(globalObject, key, moduleRecordValue, scriptFetcher,
sentValue, resumeMode);
}
} // namespace Zig

View File

@@ -1,75 +1,71 @@
#include "root.h"
#pragma once
#pragma once
namespace JSC {
class Structure;
class Identifier;
}
class Structure;
class Identifier;
#include <JavaScriptCore/Structure.h>
#include <JavaScriptCore/JSGlobalObject.h>
#include <JavaScriptCore/JSTypeInfo.h>
} // namespace JSC
#include "ZigConsoleClient.h"
#include <JavaScriptCore/JSGlobalObject.h>
#include <JavaScriptCore/JSTypeInfo.h>
#include <JavaScriptCore/Structure.h>
namespace Zig {
class GlobalObject : public JSC::JSGlobalObject {
using Base = JSC::JSGlobalObject;
using Base = JSC::JSGlobalObject;
public:
public:
DECLARE_EXPORT_INFO;
static const JSC::GlobalObjectMethodTable s_globalObjectMethodTable;
DECLARE_EXPORT_INFO;
static const JSC::GlobalObjectMethodTable s_globalObjectMethodTable;
static constexpr bool needsDestruction = true;
template <typename CellType, JSC::SubspaceAccess mode>
static JSC::IsoSubspace *subspaceFor(JSC::VM &vm) {
return vm.globalObjectSpace<mode>();
}
static constexpr bool needsDestruction = true;
template<typename CellType, JSC::SubspaceAccess mode>
static JSC::IsoSubspace* subspaceFor(JSC::VM& vm)
{
return vm.globalObjectSpace<mode>();
}
static GlobalObject *create(JSC::VM &vm, JSC::Structure *structure) {
auto *object =
new (NotNull, JSC::allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
object->finishCreation(vm);
return object;
}
static GlobalObject* create(JSC::VM& vm, JSC::Structure* structure)
{
auto* object = new (NotNull, JSC::allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
object->finishCreation(vm);
return object;
}
static JSC::Structure *createStructure(JSC::VM &vm, JSC::JSValue prototype) {
auto *result = JSC::Structure::create(
vm, nullptr, prototype, JSC::TypeInfo(JSC::GlobalObjectType, Base::StructureFlags), info());
result->setTransitionWatchpointIsLikelyToBeFired(true);
return result;
}
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSValue prototype)
{
auto* result = JSC::Structure::create(vm, nullptr, prototype, JSC::TypeInfo(JSC::GlobalObjectType, Base::StructureFlags), info());
result->setTransitionWatchpointIsLikelyToBeFired(true);
return result;
}
static void reportUncaughtExceptionAtEventLoop(JSGlobalObject *, JSC::Exception *);
static void reportUncaughtExceptionAtEventLoop(JSGlobalObject*, JSC::Exception*);
static JSC::JSInternalPromise *moduleLoaderImportModule(JSGlobalObject *, JSC::JSModuleLoader *,
JSC::JSString *moduleNameValue,
JSC::JSValue parameters,
const JSC::SourceOrigin &);
static JSC::Identifier moduleLoaderResolve(JSGlobalObject *, JSC::JSModuleLoader *,
JSC::JSValue keyValue, JSC::JSValue referrerValue,
JSC::JSValue);
static JSC::JSInternalPromise *moduleLoaderFetch(JSGlobalObject *, JSC::JSModuleLoader *,
JSC::JSValue, JSC::JSValue, JSC::JSValue);
static JSC::JSObject *moduleLoaderCreateImportMetaProperties(JSGlobalObject *,
JSC::JSModuleLoader *, JSC::JSValue,
JSC::JSModuleRecord *, JSC::JSValue);
static JSC::JSValue moduleLoaderEvaluate(JSGlobalObject *, JSC::JSModuleLoader *, JSC::JSValue,
JSC::JSValue, JSC::JSValue, JSC::JSValue, JSC::JSValue);
static void promiseRejectionTracker(JSGlobalObject *, JSC::JSPromise *,
JSC::JSPromiseRejectionOperation);
void setConsole(void *console);
void installAPIGlobals(JSClassRef *globals, int count);
static JSC::JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSString* moduleNameValue, JSC::JSValue parameters, const JSC::SourceOrigin&);
static JSC::Identifier moduleLoaderResolve(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue keyValue, JSC::JSValue referrerValue, JSC::JSValue);
static JSC::JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
static JSC::JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSModuleRecord*, JSC::JSValue);
static JSC::JSValue moduleLoaderEvaluate(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue, JSC::JSValue, JSC::JSValue);
static void promiseRejectionTracker(JSGlobalObject*, JSC::JSPromise*, JSC::JSPromiseRejectionOperation);
void setConsole(void* console);
void installAPIGlobals(JSClassRef* globals, int count);
private:
GlobalObject(JSC::VM& vm, JSC::Structure* structure)
: JSC::JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
{
}
private:
GlobalObject(JSC::VM &vm, JSC::Structure *structure)
: JSC::JSGlobalObject(vm, structure, &s_globalObjectMethodTable) {}
};
}
} // namespace Zig

View File

@@ -0,0 +1,134 @@
#include "ZigSourceProvider.h"
#include "helpers.h"
#include <JavaScriptCore/BytecodeCacheError.h>
#include <JavaScriptCore/CodeCache.h>
#include <JavaScriptCore/Completion.h>
#include <sys/stat.h>
#include <wtf/FileSystem.h>
#include <wtf/Scope.h>
#include <wtf/text/StringHash.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;
Ref<SourceProvider> SourceProvider::create(ResolvedSource resolvedSource) {
return adoptRef(*new SourceProvider(
resolvedSource,
JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(toString(resolvedSource.source_url))),
toStringNotConst(resolvedSource.source_url), TextPosition(),
JSC::SourceProviderSourceType::Module));
}
unsigned SourceProvider::getHash() {
if (m_hash) { return m_hash; }
m_hash = WTF::StringHash::hash(WTF::String(WTF::StringImpl::createWithoutCopying(
m_resolvedSource.source_code.ptr, m_resolvedSource.source_code.len)));
return m_hash;
}
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;
}
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();
}
}
}
}
int SourceProvider::readCache(JSC::VM &vm, const JSC::SourceCode &sourceCode) {
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;
}
}
}; // namespace Zig

View File

@@ -0,0 +1,70 @@
#include "headers.h"
#include "root.h"
#pragma once
namespace JSC {
class Structure;
class Identifier;
} // namespace JSC
#include "ZigConsoleClient.h"
#include <JavaScriptCore/CachedBytecode.h>
#include <JavaScriptCore/JSGlobalObject.h>
#include <JavaScriptCore/JSTypeInfo.h>
#include <JavaScriptCore/SourceProvider.h>
#include <JavaScriptCore/Structure.h>
#include <wtf/FileSystem.h>
namespace Zig {
class SourceProvider final : public JSC::SourceProvider {
WTF_MAKE_FAST_ALLOCATED;
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(ResolvedSource resolvedSource);
~SourceProvider() { commitCachedBytecode(); }
unsigned hash() const { return m_hash; };
StringView source() const {
return StringView(m_resolvedSource.source_code.ptr, m_resolvedSource.source_code.len);
}
RefPtr<JSC::CachedBytecode> cachedBytecode() {
if (m_resolvedSource.bytecodecache_fd == 0) { return nullptr; }
return m_cachedBytecode;
};
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);
private:
SourceProvider(ResolvedSource resolvedSource, const SourceOrigin &sourceOrigin,
WTF::String &&sourceURL, const TextPosition &startPosition,
JSC::SourceProviderSourceType sourceType)
: Base(sourceOrigin, WTFMove(sourceURL), startPosition, sourceType) {
m_resolvedSource = resolvedSource;
m_hash = resolvedSource.hash;
getHash();
}
unsigned m_hash;
unsigned getHash();
RefPtr<JSC::CachedBytecode> m_cachedBytecode;
};
} // namespace Zig

View File

@@ -1,6 +1,7 @@
#include "helpers.h"
#include "root.h"
#include <JavaScriptCore/Completion.h>
#include <JavaScriptCore/ErrorInstance.h>
#include <JavaScriptCore/ExceptionScope.h>
#include <JavaScriptCore/FunctionConstructor.h>
#include <JavaScriptCore/Identifier.h>
@@ -15,6 +16,7 @@
#include <JavaScriptCore/JSSet.h>
#include <JavaScriptCore/JSString.h>
#include <JavaScriptCore/ParserError.h>
#include <JavaScriptCore/StackFrame.h>
#include <JavaScriptCore/VM.h>
#include <JavaScriptCore/WasmFaultSignalHandler.h>
#include <wtf/text/ExternalStringImpl.h>
@@ -572,7 +574,7 @@ JSC__JSValue JSC__JSValue__getPrototype(JSC__JSValue JSValue0, JSC__JSGlobalObje
return JSC::JSValue::encode(value.getPrototype(arg1));
}
bool JSC__JSValue__isException(JSC__JSValue JSValue0, JSC__VM *arg1) {
return JSC::jsDynamicCast<JSC::Exception>(*arg1, JSC::JSValue::decode(JSValue0)) != nullptr;
return JSC::jsDynamicCast<JSC::Exception *>(*arg1, JSC::JSValue::decode(JSValue0)) != nullptr;
}
bool JSC__JSValue__isAnyInt(JSC__JSValue JSValue0) {
return JSC::JSValue::decode(JSValue0).isAnyInt();
@@ -685,16 +687,100 @@ bWTF__String JSC__JSValue__toWTFString(JSC__JSValue JSValue0, JSC__JSGlobalObjec
return Wrap<WTF::String, bWTF__String>::wrap(value.toWTFString(arg1));
};
static ZigException fromErrorInstance(JSC::JSGlobalObject *global, JSC::ErrorInstance *err,
JSC::JSValue val) {
ZigException except = Zig::ZigExceptionNone;
JSC::JSObject *obj = JSC::jsDynamicCast<JSC::JSObject *>(global->vm(), val);
if (err->stackTrace() != nullptr && err->stackTrace()->size() > 0) {
JSC::StackFrame *stack = &err->stackTrace()->first();
except.sourceURL = Zig::toZigString(stack->sourceURL());
if (stack->hasLineAndColumnInfo()) {
unsigned lineNumber;
unsigned column;
stack->computeLineAndColumn(lineNumber, column);
except.line = lineNumber;
except.column = column;
}
} else {
// JSC::ErrorInstance marks these as protected.
// To work around that, we cast as a JSC::JSObject
// This code path triggers when there was an exception before the code was executed
// For example, ParserError becomes one of these
auto source_url_value = obj->getDirect(global->vm(), global->vm().propertyNames->sourceURL);
auto str = source_url_value.toWTFString(global);
except.sourceURL = Zig::toZigString(str);
except.line = obj->getDirect(global->vm(), global->vm().propertyNames->line).toInt32(global);
except.column =
obj->getDirect(global->vm(), global->vm().propertyNames->column).toInt32(global);
}
if (obj->hasProperty(global, global->vm().propertyNames->stack)) {
except.stack = Zig::toZigString(
obj->getDirect(global->vm(), global->vm().propertyNames->stack).toWTFString(global));
}
except.code = (unsigned char)err->errorType();
if (err->isStackOverflowError()) { except.code = 253; }
if (err->isOutOfMemoryError()) { except.code = 8; }
if (obj->hasProperty(global, global->vm().propertyNames->message)) {
except.message = Zig::toZigString(
obj->getDirect(global->vm(), global->vm().propertyNames->message).toWTFString(global));
} else {
except.message = Zig::toZigString(err->sanitizedMessageString(global));
}
except.name = Zig::toZigString(err->sanitizedNameString(global));
except.runtime_type = err->runtimeTypeForCause();
except.exception = err;
return except;
}
static ZigException exceptionFromString(WTF::String &str) {
ZigException except = Zig::ZigExceptionNone;
auto ref = OpaqueJSString::tryCreate(str);
except.message = ZigString{ref->characters8(), ref->length()};
ref->ref();
return except;
}
static ZigException exceptionFromString(JSC::JSValue value, JSC::JSGlobalObject *global) {
auto scope = DECLARE_THROW_SCOPE(global->vm());
auto str = value.toWTFString(global);
if (scope.exception()) {
scope.clearException();
scope.release();
return Zig::ZigExceptionNone;
}
scope.release();
ZigException except = Zig::ZigExceptionNone;
auto ref = OpaqueJSString::tryCreate(str);
except.message = ZigString{ref->characters8(), ref->length()};
ref->ref();
return except;
}
ZigException JSC__JSValue__toZigException(JSC__JSValue JSValue0, JSC__JSGlobalObject *arg1) {
JSC::JSValue value = JSC::JSValue::decode(JSValue0);
if (JSC::ErrorInstance *error =
JSC::jsDynamicCast<JSC::ErrorInstance>(*arg1, JSC::JSValue::decode(JSValue0))) {}
if (JSC::ErrorInstance *error = JSC::jsDynamicCast<JSC::ErrorInstance *>(arg1->vm(), value)) {
return fromErrorInstance(arg1, error, value);
}
if (JSC::Exception *exception =
JSC::jsDynamicCast<JSC::Exception>(*arg1, JSC::JSValue::decode(JSValue0))) {}
if (JSC::Exception *exception = JSC::jsDynamicCast<JSC::Exception *>(arg1->vm(), value)) {
if (JSC::ErrorInstance *error =
JSC::jsDynamicCast<JSC::ErrorInstance *>(arg1->vm(), exception->value())) {
return fromErrorInstance(arg1, error, value);
}
}
return Zig::ZigExceptionNone;
return exceptionFromString(value, arg1);
}
#pragma mark - JSC::PropertyName

View File

@@ -45,7 +45,7 @@ pub const ZigString = extern struct {
pub const Empty = ZigString{ .ptr = "", .len = 0 };
pub fn slice(this: *const ZigString) []const u8 {
return this.ptr[0..this.len];
return this.ptr[0..std.math.min(this.len, 4096)];
}
};
@@ -184,11 +184,11 @@ pub fn NewGlobalObject(comptime Type: type) type {
}
return ErrorableZigString.err(error.ResolveFailed, "resolve not implemented");
}
pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString {
pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableResolvedSource {
if (comptime @hasDecl(Type, "fetch")) {
return @call(.{ .modifier = .always_inline }, Type.fetch, .{ global, specifier, source });
}
return ErrorableZigString.err(error.FetchFailed, "Module fetch not implemented");
return ErrorableResolvedSource.err(error.FetchFailed, "Module fetch not implemented");
}
pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue {
if (comptime @hasDecl(Type, "promiseRejectionTracker")) {
@@ -687,18 +687,6 @@ pub const JSGlobalObject = extern struct {
pub const name = "JSC::JSGlobalObject";
pub const namespace = "JSC";
pub const ErrorType = enum(u8) {
Error = 0,
EvalError = 1,
RangeError = 2,
ReferenceError = 3,
SyntaxError = 4,
TypeError = 5,
URIError = 6,
AggregateError = 7,
OutOfMemoryError = 8,
};
// pub fn createError(globalObject: *JSGlobalObject, error_type: ErrorType, message: *String) *JSObject {
// return cppFn("createError", .{ globalObject, error_type, message });
// }
@@ -1173,6 +1161,14 @@ pub const JSValue = enum(i64) {
return cppFn("isCallable", .{ this, vm });
}
pub fn isException(this: JSValue, vm: *VM) bool {
return cppFn("isException", .{ this, vm });
}
pub fn toZigException(this: JSValue, global: *JSGlobalObject) ZigException {
return cppFn("toZigException", .{ this, global });
}
// On exception, this returns the empty string.
pub fn toString(this: JSValue, globalThis: *JSGlobalObject) *JSString {
return cppFn("toString", .{ this, globalThis });
@@ -1226,7 +1222,7 @@ pub const JSValue = enum(i64) {
});
}
pub const Extern = [_][]const u8{ "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "get", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isUndefined", "isNull", "isUndefinedOrNull", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" };
pub const Extern = [_][]const u8{ "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "get", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isUndefined", "isNull", "isUndefinedOrNull", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" };
};
pub const PropertyName = extern struct {

View File

@@ -47,7 +47,7 @@ pub const ZigGlobalObject = extern struct {
}
return @call(.{ .modifier = .always_inline }, Interface.resolve, .{ global, specifier, source });
}
pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString {
pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableResolvedSource {
if (comptime is_bindgen) {
unreachable;
}
@@ -128,6 +128,39 @@ pub const ZigErrorType = extern struct {
message: ZigString,
};
pub const JSErrorCode = enum(u8) {
Error = 0,
EvalError = 1,
RangeError = 2,
ReferenceError = 3,
SyntaxError = 4,
TypeError = 5,
URIError = 6,
AggregateError = 7,
// StackOverflow & OutOfMemoryError is not an ErrorType in <JavaScriptCore/ErrorType.h> within JSC, so the number here is just totally made up
OutOfMemoryError = 8,
StackOverflow = 253,
UserErrorCode = 254,
_,
};
pub const JSRuntimeType = enum(u16) {
Nothing = 0x0,
Function = 0x1,
Undefined = 0x2,
Null = 0x4,
Boolean = 0x8,
AnyInt = 0x10,
Number = 0x20,
String = 0x40,
Object = 0x80,
Symbol = 0x100,
BigInt = 0x200,
_,
};
pub fn Errorable(comptime Type: type) type {
return extern struct {
result: Result,
@@ -168,9 +201,47 @@ pub fn Errorable(comptime Type: type) type {
};
}
pub const ResolvedSource = extern struct {
pub const shim = Shimmer("Zig", "ResolvedSource", @This());
pub const name = "ResolvedSource";
pub const namespace = shim.namespace;
specifier: ZigString,
source_code: ZigString,
source_url: ZigString,
hash: u32,
// 0 means disabled
bytecodecache_fd: u64,
};
pub const ErrorableResolvedSource = Errorable(ResolvedSource);
pub const ErrorableZigString = Errorable(ZigString);
pub const ErrorableJSValue = Errorable(JSValue);
pub const ZigException = extern struct {
pub const shim = Shimmer("Zig", "Exception", @This());
pub const name = "ZigException";
pub const namespace = shim.namespace;
code: JSErrorCode,
runtime_type: JSRuntimeType,
name: ZigString,
message: ZigString,
sourceURL: ZigString,
line: i32,
column: i32,
stack: ZigString,
exception: ?*c_void,
pub fn fromException(exception: *Exception) ZigException {
return shim.cppFn("fromException", .{exception});
}
pub const Extern = [_][]const u8{"fromException"};
};
pub const ZigConsoleClient = struct {
pub const shim = Shimmer("Zig", "ConsoleClient", @This());
pub const Type = *c_void;

View File

@@ -600,12 +600,16 @@ pub fn HeaderGen(comptime import: type, comptime fname: []const u8) type {
\\#endif
\\typedef struct ZigString { const unsigned char* ptr; size_t len; } ZigString;
\\typedef struct ZigErrorType { ZigErrorCode code; ZigString message; } ZigErrorType;
\\typedef struct ZigException { unsigned char code; uint16_t runtime_type; ZigString name; ZigString message; ZigString sourceURL; int32_t line; int32_t column; ZigString stack; void* exception; } ZigException;
\\typedef union ErrorableZigStringResult { ZigString value; ZigErrorType err; } ErrorableZigStringResult;
\\typedef struct ErrorableZigString { ErrorableZigStringResult result; bool success; } ErrorableZigString;
\\typedef struct ResolvedSource { ZigString specifier; ZigString source_code; ZigString source_url; uint32_t hash; uint32_t bytecodecache_fd; } ResolvedSource;
\\typedef union ErrorableResolvedSourceResult { ResolvedSource value; ZigErrorType err; } ErrorableResolvedSourceResult;
\\typedef struct ErrorableResolvedSource { ErrorableResolvedSourceResult result; bool success; } ErrorableResolvedSource;
\\
) catch {};
impl.writer().print("//-- AUTOGENERATED FILE -- {d}\n", .{std.time.timestamp()}) catch unreachable;
impl.writer().print("//-- AUTOGENERATED FILE -- {d}\n// clang-format off\n", .{std.time.timestamp()}) catch unreachable;
impl.writer().writeAll(
\\#pragma once
\\

View File

@@ -1,4 +1,5 @@
//-- AUTOGENERATED FILE -- 1627515944
//-- AUTOGENERATED FILE -- 1627603981
// clang-format off
#pragma once
#include <stddef.h>
@@ -223,8 +224,8 @@ extern "C" const size_t Zig__GlobalObject_object_align_ = alignof(Zig::GlobalObj
extern "C" const size_t Zig__ConsoleClient_object_size_ = sizeof(Zig::ConsoleClient);
extern "C" const size_t Zig__ConsoleClient_object_align_ = alignof(Zig::ConsoleClient);
const size_t sizes[26] = {sizeof(JSC::JSObject), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(Inspector::ScriptArguments), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSModuleRecord), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::SourceOrigin), sizeof(JSC::SourceCode), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(WTF::URL), sizeof(WTF::String), sizeof(JSC::JSValue), sizeof(JSC::PropertyName), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(JSC::CallFrame), sizeof(JSC::Identifier), sizeof(WTF::StringImpl), sizeof(WTF::ExternalStringImpl), sizeof(WTF::StringView), sizeof(Zig::GlobalObject)};
const size_t sizes[27] = {sizeof(JSC::JSObject), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(Inspector::ScriptArguments), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSModuleRecord), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::SourceOrigin), sizeof(JSC::SourceCode), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(WTF::URL), sizeof(WTF::String), sizeof(JSC::JSValue), sizeof(JSC::PropertyName), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(JSC::CallFrame), sizeof(JSC::Identifier), sizeof(WTF::StringImpl), sizeof(WTF::ExternalStringImpl), sizeof(WTF::StringView), sizeof(Zig::GlobalObject), sizeof(ZigException)};
const char* names[26] = {"JSC__JSObject", "JSC__JSCell", "JSC__JSString", "Inspector__ScriptArguments", "JSC__JSModuleLoader", "JSC__JSModuleRecord", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__SourceOrigin", "JSC__SourceCode", "JSC__JSFunction", "JSC__JSGlobalObject", "WTF__URL", "WTF__String", "JSC__JSValue", "JSC__PropertyName", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "JSC__CallFrame", "JSC__Identifier", "WTF__StringImpl", "WTF__ExternalStringImpl", "WTF__StringView", "Zig__GlobalObject"};
const char* names[27] = {"JSC__JSObject", "JSC__JSCell", "JSC__JSString", "Inspector__ScriptArguments", "JSC__JSModuleLoader", "JSC__JSModuleRecord", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__SourceOrigin", "JSC__SourceCode", "JSC__JSFunction", "JSC__JSGlobalObject", "WTF__URL", "WTF__String", "JSC__JSValue", "JSC__PropertyName", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "JSC__CallFrame", "JSC__Identifier", "WTF__StringImpl", "WTF__ExternalStringImpl", "WTF__StringView", "Zig__GlobalObject", "ZigException"};
const size_t aligns[26] = {alignof(JSC::JSObject), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(Inspector::ScriptArguments), alignof(JSC::JSModuleLoader), alignof(JSC::JSModuleRecord), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::SourceOrigin), alignof(JSC::SourceCode), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(WTF::URL), alignof(WTF::String), alignof(JSC::JSValue), alignof(JSC::PropertyName), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(JSC::CallFrame), alignof(JSC::Identifier), alignof(WTF::StringImpl), alignof(WTF::ExternalStringImpl), alignof(WTF::StringView), alignof(Zig::GlobalObject)};
const size_t aligns[27] = {alignof(JSC::JSObject), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(Inspector::ScriptArguments), alignof(JSC::JSModuleLoader), alignof(JSC::JSModuleRecord), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::SourceOrigin), alignof(JSC::SourceCode), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(WTF::URL), alignof(WTF::String), alignof(JSC::JSValue), alignof(JSC::PropertyName), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(JSC::CallFrame), alignof(JSC::Identifier), alignof(WTF::StringImpl), alignof(WTF::ExternalStringImpl), alignof(WTF::StringView), alignof(Zig::GlobalObject), alignof(ZigException)};

View File

@@ -44,4 +44,8 @@ pub const bJSC__CatchScope = bindings.CatchScope;
pub const bJSC__CallFrame = bindings.CallFrame;
pub const bInspector__ScriptArguments = bindings.ScriptArguments;
pub const JSC__JSValue = bindings.JSValue;
// Inlined types
pub const ZigString = bindings.ZigString;
pub const ZigException = bindings.ZigException;
pub const ResolvedSource = bindings.ResolvedSource;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,182 +1,149 @@
#include "headers.h"
#include "root.h"
#include <JavaScriptCore/JSCInlines.h>
#include <JavaScriptCore/VM.h>
#include <JavaScriptCore/Identifier.h>
#include <JavaScriptCore/JSValue.h>
#include <JavaScriptCore/JSString.h>
#include <JavaScriptCore/ThrowScope.h>
#include <JavaScriptCore/Error.h>
#include <JavaScriptCore/Exception.h>
#include <JavaScriptCore/Identifier.h>
#include <JavaScriptCore/JSCInlines.h>
#include <JavaScriptCore/JSString.h>
#include <JavaScriptCore/JSValue.h>
#include <JavaScriptCore/ThrowScope.h>
#include <JavaScriptCore/VM.h>
template<class CppType, typename ZigType>
class Wrap {
public:
Wrap(){
};
template <class CppType, typename ZigType> class Wrap {
public:
Wrap(){};
Wrap(ZigType zig){
result = zig;
cpp = static_cast<CppType*>(static_cast<void*>(&zig));
};
Wrap(ZigType zig) {
result = zig;
cpp = static_cast<CppType *>(static_cast<void *>(&zig));
};
Wrap(ZigType* zig){
cpp = static_cast<CppType*>(static_cast<void*>(&zig));
};
Wrap(ZigType *zig) { cpp = static_cast<CppType *>(static_cast<void *>(&zig)); };
Wrap(CppType _cpp) {
auto buffer = alignedBuffer();
cpp = new (buffer) CppType(_cpp);
};
Wrap(CppType _cpp){
auto buffer = alignedBuffer();
cpp = new (buffer) CppType(_cpp);
};
~Wrap(){};
unsigned char *alignedBuffer() {
return result.bytes + alignof(CppType) -
reinterpret_cast<intptr_t>(result.bytes) % alignof(CppType);
}
~Wrap(){};
ZigType result;
CppType *cpp;
unsigned char* alignedBuffer() {
return result.bytes + alignof(CppType) - reinterpret_cast<intptr_t>(result.bytes) % alignof(CppType);
}
static ZigType wrap(CppType obj) { return *static_cast<ZigType *>(static_cast<void *>(&obj)); }
ZigType result;
CppType* cpp;
static CppType unwrap(ZigType obj) { return *static_cast<CppType *>(static_cast<void *>(&obj)); }
static ZigType wrap(CppType obj) {
return *static_cast<ZigType*>(static_cast<void*>(&obj));
}
static CppType unwrap(ZigType obj) {
return *static_cast<CppType*>(static_cast<void*>(&obj));
}
static CppType* unwrap(ZigType* obj) {
return static_cast<CppType*>(static_cast<void*>(obj));
}
static CppType *unwrap(ZigType *obj) { return static_cast<CppType *>(static_cast<void *>(obj)); }
};
template<class To, class From>
To cast(From v)
{
return *static_cast<To*>(static_cast<void*>(v));
template <class To, class From> To cast(From v) {
return *static_cast<To *>(static_cast<void *>(v));
}
template<class To, class From>
To ccast(From v)
{
return *static_cast<const To*>(static_cast<const void*>(v));
template <class To, class From> To ccast(From v) {
return *static_cast<const To *>(static_cast<const void *>(v));
}
typedef JSC__JSValue (* NativeCallbackFunction)(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2);
typedef JSC__JSValue (*NativeCallbackFunction)(void *arg0, JSC__JSGlobalObject *arg1,
JSC__CallFrame *arg2);
static const JSC::ArgList makeArgs(JSC__JSValue* v, size_t count) {
JSC::MarkedArgumentBuffer args = JSC::MarkedArgumentBuffer();
args.ensureCapacity(count);
for (size_t i = 0; i < count; ++i) {
args.append(JSC::JSValue::decode(v[i]));
}
static const JSC::ArgList makeArgs(JSC__JSValue *v, size_t count) {
JSC::MarkedArgumentBuffer args = JSC::MarkedArgumentBuffer();
args.ensureCapacity(count);
for (size_t i = 0; i < count; ++i) { args.append(JSC::JSValue::decode(v[i])); }
return JSC::ArgList(args);
return JSC::ArgList(args);
}
namespace Zig {
static const JSC::Identifier toIdentifier(ZigString str, JSC::JSGlobalObject *global) {
if (str.len == 0 || str.ptr == nullptr) { return JSC::Identifier::EmptyIdentifier; }
static const JSC::Identifier toIdentifier(ZigString str, JSC::JSGlobalObject* global) {
if (str.len == 0 || str.ptr == nullptr) {
return JSC::Identifier::EmptyIdentifier;
}
return JSC::Identifier::fromString(global->vm(), str.ptr, str.len);
return JSC::Identifier::fromString(global->vm(), str.ptr, str.len);
}
static const WTF::String toString(ZigString str) {
if (str.len == 0 || str.ptr == nullptr) {
return WTF::String();
}
if (str.len == 0 || str.ptr == nullptr) { return WTF::String(); }
return WTF::String(WTF::StringImpl::createWithoutCopying(str.ptr, str.len));
return WTF::String(WTF::StringImpl::createWithoutCopying(str.ptr, str.len));
}
static const JSC::JSString* toJSString(ZigString str, JSC::JSGlobalObject* global) {
return JSC::jsOwnedString(global->vm(), toString(str));
static WTF::String toStringNotConst(ZigString str) {
if (str.len == 0 || str.ptr == nullptr) { return WTF::String(); }
return WTF::String(WTF::StringImpl::createWithoutCopying(str.ptr, str.len));
}
static const JSC::JSString *toJSString(ZigString str, JSC::JSGlobalObject *global) {
return JSC::jsOwnedString(global->vm(), toString(str));
}
static const ZigString ZigStringEmpty = ZigString{nullptr, 0};
static const unsigned char __dot_char = '.';
static const unsigned char __dot_char = '.';
static const ZigString ZigStringCwd = ZigString{&__dot_char, 1};
static ZigString toZigString(WTF::String str) {
return str.isEmpty() ? ZigStringEmpty : ZigString{ str.characters8(), str.length() };
return str.isEmpty() ? ZigStringEmpty : ZigString{str.characters8(), str.length()};
}
static ZigString toZigString(WTF::String* str) {
return str->isEmpty() ? ZigStringEmpty : ZigString{ str->characters8(), str->length() };
static ZigString toZigString(WTF::String *str) {
return str->isEmpty() ? ZigStringEmpty : ZigString{str->characters8(), str->length()};
}
static ZigString toZigString(WTF::StringImpl& str) {
return str.isEmpty() ? ZigStringEmpty : ZigString{ str.characters8(), str.length() };
static ZigString toZigString(WTF::StringImpl &str) {
return str.isEmpty() ? ZigStringEmpty : ZigString{str.characters8(), str.length()};
}
static ZigString toZigString(WTF::StringView& str) {
return str.isEmpty() ? ZigStringEmpty : ZigString{ str.characters8(), str.length() };
static ZigString toZigString(WTF::StringView &str) {
return str.isEmpty() ? ZigStringEmpty : ZigString{str.characters8(), str.length()};
}
static ZigString toZigString(JSC::JSString& str, JSC::JSGlobalObject *global) {
return toZigString(str.value(global));
static ZigString toZigString(JSC::JSString &str, JSC::JSGlobalObject *global) {
return toZigString(str.value(global));
}
static ZigString toZigString(JSC::JSString* str, JSC::JSGlobalObject *global) {
return toZigString(str->value(global));
static ZigString toZigString(JSC::JSString *str, JSC::JSGlobalObject *global) {
return toZigString(str->value(global));
}
static ZigString toZigString(JSC::Identifier& str, JSC::JSGlobalObject *global) {
return toZigString(str.string());
static ZigString toZigString(JSC::Identifier &str, JSC::JSGlobalObject *global) {
return toZigString(str.string());
}
static ZigString toZigString(JSC::Identifier* str, JSC::JSGlobalObject *global) {
return toZigString(str->string());
static ZigString toZigString(JSC::Identifier *str, JSC::JSGlobalObject *global) {
return toZigString(str->string());
}
static WTF::StringView toStringView(ZigString str) { return WTF::StringView(str.ptr, str.len); }
static void throwException(JSC::ThrowScope& scope, ZigString msg, JSC::JSGlobalObject* global) {
auto str = toJSString(msg, global);
scope.throwException(global, JSC::Exception::create(global->vm(), JSC::JSValue(str)));
static void throwException(JSC::ThrowScope &scope, ZigString msg, JSC::JSGlobalObject *global) {
auto str = toJSString(msg, global);
scope.throwException(global, JSC::Exception::create(global->vm(), JSC::JSValue(str)));
}
static ZigString toZigString(JSC::JSValue val, JSC::JSGlobalObject *global) {
auto scope = DECLARE_THROW_SCOPE(global->vm());
WTF::String str = val.toWTFString(global);
static ZigString toZigString(JSC::JSValue val, JSC::JSGlobalObject* global) {
auto scope = DECLARE_THROW_SCOPE(global->vm());
WTF::String str = val.toWTFString(global);
if (scope.exception()) {
scope.clearException();
scope.release();
return ZigStringEmpty;
}
if (scope.exception()) {
scope.clearException();
scope.release();
return ZigStringEmpty;
}
scope.release();
return toZigString(str);
return toZigString(str);
}
}
static ZigException ZigExceptionNone = ZigException{
0, 0, ZigStringEmpty, ZigStringEmpty, ZigStringEmpty, -1, -1, ZigStringEmpty, nullptr};
} // namespace Zig

View File

@@ -65,20 +65,20 @@ pub const VirtualMachine = struct {
vm = try allocator.create(VirtualMachine);
var console = try allocator.create(ZigConsoleClient);
console.* = ZigConsoleClient.init(Output.errorWriter(), Output.writer());
const bundler = try Bundler.init(
allocator,
log,
try configureTransformOptionsForSpeedy(allocator, _args),
existing_bundle,
);
vm.* = VirtualMachine{
.global = undefined,
.allocator = allocator,
.require_cache = RequireCacheType.init(allocator),
.event_listeners = EventListenerMixin.Map.init(allocator),
.bundler = try Bundler.init(
allocator,
log,
try configureTransformOptionsForSpeedy(allocator, _args),
existing_bundle,
),
.bundler = bundler,
.console = console,
.node_modules = existing_bundle,
.node_modules = bundler.options.node_modules_bundle,
.log = log,
};
@@ -106,12 +106,39 @@ pub const VirtualMachine = struct {
threadlocal var source_code_printer: js_printer.BufferPrinter = undefined;
threadlocal var source_code_printer_loaded: bool = false;
inline fn _fetch(global: *JSGlobalObject, specifier: string, source: string) !string {
inline fn _fetch(global: *JSGlobalObject, specifier: string, source: string) !ResolvedSource {
std.debug.assert(VirtualMachine.vm_loaded);
std.debug.assert(VirtualMachine.vm.global == global);
if (strings.eqlComptime(specifier, Runtime.Runtime.Imports.Name)) {
return Runtime.Runtime.sourceContent();
if (vm.node_modules != null and strings.eql(vm.bundler.linker.nodeModuleBundleImportPath(), specifier)) {
// We kind of need an abstraction around this.
// Basically we should subclass JSC::SourceCode with:
// - hash
// - file descriptor for source input
// - file path + file descriptor for bytecode caching
// - separate bundles for server build vs browser build OR at least separate sections
const code = try vm.node_modules.?.readCodeAsStringSlow(vm.allocator);
return ResolvedSource{
.source_code = ZigString.init(code),
.specifier = ZigString.init(vm.bundler.linker.nodeModuleBundleImportPath()),
.source_url = ZigString.init(vm.bundler.options.node_modules_bundle_pretty_path),
.hash = 0, // TODO
.bytecodecache_fd = std.math.lossyCast(u64, vm.node_modules.?.fetchByteCodeCache(
vm.bundler.options.node_modules_bundle_pretty_path,
&vm.bundler.fs.fs,
) orelse 0),
};
} else if (strings.eqlComptime(specifier, Runtime.Runtime.Imports.Name)) {
return ResolvedSource{
.source_code = ZigString.init(Runtime.Runtime.sourceContent()),
.specifier = ZigString.init(Runtime.Runtime.Imports.Name),
.source_url = ZigString.init(Runtime.Runtime.Imports.Name),
.hash = Runtime.Runtime.versionHash(),
.bytecodecache_fd = std.math.lossyCast(
u64,
Runtime.Runtime.byteCodeCacheFile(&vm.bundler.fs.fs) orelse 0,
),
};
}
const result = vm.bundler.resolve_results.get(specifier) orelse return error.MissingResolveResult;
@@ -172,18 +199,32 @@ pub const VirtualMachine = struct {
return error.PrintingErrorWriteFailed;
}
return vm.allocator.dupe(u8, source_code_printer.ctx.written) catch unreachable;
return ResolvedSource{
.source_code = ZigString.init(vm.allocator.dupe(u8, source_code_printer.ctx.written) catch unreachable),
.specifier = ZigString.init(specifier),
.source_url = ZigString.init(path.pretty),
.hash = 0,
.bytecodecache_fd = 0,
};
},
else => {
return try strings.quotedAlloc(VirtualMachine.vm.allocator, path.pretty);
return ResolvedSource{
.source_code = ZigString.init(try strings.quotedAlloc(VirtualMachine.vm.allocator, path.pretty)),
.specifier = ZigString.init(path.text),
.source_url = ZigString.init(path.pretty),
.hash = 0,
.bytecodecache_fd = 0,
};
},
}
}
inline fn _resolve(global: *JSGlobalObject, specifier: string, source: string) !string {
std.debug.assert(VirtualMachine.vm_loaded);
std.debug.assert(VirtualMachine.vm.global == global);
if (strings.eqlComptime(specifier, Runtime.Runtime.Imports.Name)) {
if (vm.node_modules == null and strings.eqlComptime(specifier, Runtime.Runtime.Imports.Name)) {
return Runtime.Runtime.Imports.Name;
} else if (vm.node_modules != null and strings.eql(specifier, vm.bundler.linker.nodeModuleBundleImportPath())) {
return vm.bundler.linker.nodeModuleBundleImportPath();
}
const result: resolver.Result = vm.bundler.resolve_results.get(specifier) orelse brk: {
@@ -198,6 +239,47 @@ pub const VirtualMachine = struct {
break :brk res;
};
if (vm.node_modules != null and result.isLikelyNodeModule()) {
const node_modules_bundle = vm.node_modules.?;
node_module_checker: {
const package_json = result.package_json orelse brk: {
if (vm.bundler.linker.resolver.packageJSONForResolvedNodeModule(&result)) |pkg| {
break :brk pkg;
} else {
break :node_module_checker;
}
};
if (node_modules_bundle.getPackageIDByName(package_json.name)) |possible_pkg_ids| {
const pkg_id: u32 = brk: {
for (possible_pkg_ids) |pkg_id| {
const pkg = node_modules_bundle.bundle.packages[pkg_id];
if (pkg.hash == package_json.hash) {
break :brk pkg_id;
}
}
break :node_module_checker;
};
const package = &node_modules_bundle.bundle.packages[pkg_id];
if (isDebug) {
std.debug.assert(strings.eql(node_modules_bundle.str(package.name), package_json.name));
}
const package_relative_path = vm.bundler.fs.relative(
package_json.source.path.name.dirWithTrailingSlash(),
result.path_pair.primary.text,
);
if (node_modules_bundle.findModuleIDInPackage(package, package_relative_path) == null) break :node_module_checker;
return vm.bundler.linker.nodeModuleBundleImportPath();
}
}
}
return result.path_pair.primary.text;
}
@@ -213,15 +295,15 @@ pub const VirtualMachine = struct {
return ErrorableZigString.ok(ZigString.init(result));
}
pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) ErrorableZigString {
pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableResolvedSource {
const result = _fetch(global, specifier.slice(), source.slice()) catch |err| {
return ErrorableZigString.errFmt(err, "{s}: \"{s}\"", .{
return ErrorableResolvedSource.errFmt(err, "{s}: \"{s}\"", .{
@errorName(err),
specifier.slice(),
});
};
return ErrorableZigString.ok(ZigString.init(result));
return ErrorableResolvedSource.ok(result);
}
pub fn loadEntryPoint(this: *VirtualMachine, entry_point: string) !void {
@@ -230,9 +312,21 @@ pub const VirtualMachine = struct {
var promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(path));
this.global.vm().drainMicrotasks();
while (promise.status(this.global.vm()) == JSPromise.Status.Pending) {
this.global.vm().drainMicrotasks();
}
if (promise.status(this.global.vm()) == JSPromise.Status.Rejected) {
var str = promise.result(this.global.vm()).toWTFString(this.global);
Output.prettyErrorln("<r><red>Error<r>: <b>{s}<r>", .{str.slice()});
var exception = promise.result(this.global.vm()).toZigException(this.global);
Output.prettyErrorln("<r><red>{s}<r><d>:<r> <b>{s}<r>\n<blue>{s}<r>:{d}:{d}\n{s}", .{
exception.name.slice(),
exception.message.slice(),
exception.sourceURL.slice(),
exception.line,
exception.column,
exception.stack.slice(),
});
}
}
};