JSClassRef globals work!

Former-commit-id: b1d3eb19872b2c09bda3e9e3b3a4c1f40c3b6a6d
This commit is contained in:
Jarred Sumner
2021-07-28 14:32:51 -07:00
parent 68fa7ec2d0
commit 86296897e5
15 changed files with 151 additions and 1572 deletions

View File

@@ -5,19 +5,20 @@ api:
peechy --schema src/api/schema.peechy --esm src/api/schema.js --ts src/api/schema.d.ts --zig src/api/schema.zig
jsc: jsc-build jsc-bindings
jsc-build: jsc-build-mac
jsc-build: jsc-build-mac jsc-copy-headers
jsc-bindings:
jsc-bindings-headers
jsc-bindings-mac
jsc-bindings-headers:
zig build headers
jsc-copy-headers:
find src/JavaScript/jsc/WebKit/WebKitBuild/Release/JavaScriptCore/Headers/JavaScriptCore/ -name "*.h" -exec cp {} src/JavaScript/jsc/WebKit/WebKitBuild/Release/JavaScriptCore/PrivateHeaders/JavaScriptCore \;
jsc-build-mac:
cd src/javascript/jsc/WebKit && ICU_INCLUDE_DIRS="/usr/local/opt/icu4c/include" ./Tools/Scripts/build-jsc --jsc-only --cmakeargs="-DENABLE_STATIC_JSC=ON -DCMAKE_BUILD_TYPE=relwithdebinfo" && echo "Ignore the \"has no symbols\" errors"
SRC_DIR := src/javascript/jsc/bindings
OBJ_DIR := src/javascript/jsc/bindings-obj
@@ -43,8 +44,6 @@ CLANG_FLAGS = -Isrc/JavaScript/jsc/WebKit/WebKitBuild/Release/JavaScriptCore/Pri
-std=gnu++1z \
-stdlib=libc++ \
-DDU_DISABLE_RENAMING=1 \
-Wall \
-Wextra \
-march=native
jsc-bindings-mac: $(OBJ_FILES)

View File

@@ -7,7 +7,11 @@ pub const JSContextRef = ?*const struct_OpaqueJSContext;
pub const JSGlobalContextRef = ?*struct_OpaqueJSContext;
pub const struct_OpaqueJSString = generic;
pub const JSStringRef = ?*struct_OpaqueJSString;
pub const struct_OpaqueJSClass = generic;
pub const struct_OpaqueJSClass = opaque {
pub const name = "JSClassRef";
pub const is_pointer = false;
pub const Type = "JSClassRef";
};
pub const JSClassRef = ?*struct_OpaqueJSClass;
pub const struct_OpaqueJSPropertyNameArray = generic;
pub const JSPropertyNameArrayRef = ?*struct_OpaqueJSPropertyNameArray;

View File

@@ -33,6 +33,8 @@
#include <cstdlib>
#include <exception>
#include <JavaScriptCore/JSClassRef.h>
#include <JavaScriptCore/JSCallbackObject.h>
using JSGlobalObject = JSC::JSGlobalObject;
using Exception = JSC::Exception;
@@ -42,36 +44,32 @@ using JSModuleLoader = JSC::JSModuleLoader;
using JSModuleRecord = JSC::JSModuleRecord;
using Identifier = JSC::Identifier;
using SourceOrigin = JSC::SourceOrigin;
using JSObject = JSC::JSObject;
using JSNonFinalObject = JSC::JSNonFinalObject;
namespace JSCastingHelpers = JSC::JSCastingHelpers;
extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(JSC__VM* arg0, void* console_client) {
// There are assertions that the apiLock is set while the JSGlobalObject is initialized.
if (arg0 != nullptr) {
JSC::VM& vm = *arg0;
JSC::JSLockHolder holder(vm);
auto globalObject = Zig::GlobalObject::create(vm, Zig::GlobalObject::createStructure(vm, JSC::jsNull()));
return static_cast<JSC__JSGlobalObject*>(globalObject);
}
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();
#if ENABLE(WEBASSEMBLY)
#if ENABLE(WEBASSEMBLY)
JSC::Wasm::enableFastMemory();
#endif
JSC::JSLockHolder locker(vm);
auto globalObject = Zig::GlobalObject::create(vm, Zig::GlobalObject::createStructure(vm, JSC::jsNull()));
globalObject->setConsole(console_client);
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);
}
JSC::gcProtect(globalObject);
vm.ref();
return globalObject;
}
@@ -114,6 +112,24 @@ void GlobalObject::setConsole(void* console) {
this->setConsoleClient(makeWeakPtr(m_console));
}
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];
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();
}
JSC::Identifier GlobalObject::moduleLoaderResolve(
JSGlobalObject* globalObject,
JSModuleLoader* loader,
@@ -219,4 +235,6 @@ JSC::JSValue GlobalObject::moduleLoaderEvaluate(JSGlobalObject* globalObject, JS
// VM& vm = globalObject->vm();
return moduleLoader->evaluateNonVirtual(globalObject, key, moduleRecordValue, scriptFetcher, sentValue, resumeMode);
}
}
} // namespace Zig

View File

@@ -20,7 +20,7 @@ namespace Zig {
class GlobalObject final : public JSC::JSGlobalObject {
class GlobalObject : public JSC::JSGlobalObject {
using Base = JSC::JSGlobalObject;
public:
@@ -58,7 +58,7 @@ public:
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:

View File

@@ -1,7 +1,4 @@
#include "headers.h"
#include "root.h"
#include "helpers.h"
#include <JavaScriptCore/ExceptionScope.h>
@@ -26,6 +23,11 @@
#include <JavaScriptCore/JSInternalPromise.h>
#include <JavaScriptCore/JSClassRef.h>
#include <JavaScriptCore/JSCallbackObject.h>
extern "C" {
// #pragma mark - JSC::PropertyNameArray
@@ -96,22 +98,14 @@ JSC__JSValue JSC__JSModuleLoader__evaluate(JSC__JSGlobalObject* arg0, const unsi
JSC::JSLockHolder locker(vm);
JSC::SourceCode sourceCode = JSC::makeSource(src, JSC::SourceOrigin { origin }, origin.lastPathComponent().toStringWithoutCopying(), WTF::TextPosition(), JSC::SourceProviderSourceType::Module);
auto val = JSC::loadAndEvaluateModule(arg0, sourceCode, JSC::JSValue());
vm.drainMicrotasks();
switch (val->status(vm)) {
case JSC::JSPromise::Status::Fulfilled: {
return JSC::JSValue::encode(val->result(vm));
break;
}
case JSC::JSPromise::Status::Rejected: {
*arg6 = JSC::JSValue::encode(val->result(vm));
return JSC::JSValue::encode(JSC::jsUndefined());
break;
}
WTF::NakedPtr<JSC::Exception> exception;
auto val = JSC::evaluate(arg0, sourceCode, JSC::JSValue(), exception);
if (exception.get()) {
*arg6 = JSC::JSValue::encode(JSC::JSValue(exception.get()));
}
vm.drainMicrotasks();
return JSC::JSValue::encode(val);

View File

@@ -1,7 +1,7 @@
usingnamespace @import("./bindings.zig");
usingnamespace @import("./shared.zig");
usingnamespace @import("../new.zig");
const Fs = @import("../../../fs.zig");
const CAPI = @import("../JavaScriptCore.zig");
const Handler = struct {
pub export fn global_signal_handler_fn(sig: i32, info: *const std.os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void {
@@ -21,7 +21,7 @@ pub const ZigGlobalObject = extern struct {
pub var sigaction: std.os.Sigaction = undefined;
pub var sigaction_installed = false;
pub fn create(vm: ?*VM, console: *c_void) *JSGlobalObject {
pub fn create(class_ref: [*]CAPI.JSClassRef, count: i32, console: *c_void) *JSGlobalObject {
if (!sigaction_installed) {
sigaction_installed = true;
@@ -31,7 +31,7 @@ pub const ZigGlobalObject = extern struct {
std.os.sigaction(std.os.SIGABRT, &sigaction, null);
}
return shim.cppFn("create", .{ vm, console });
return shim.cppFn("create", .{ class_ref, count, console });
}
pub fn import(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString {
@@ -53,7 +53,7 @@ pub const ZigGlobalObject = extern struct {
}
return @call(.{ .modifier = .always_inline }, Interface.fetch, .{ global, specifier, source });
}
pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue {
if (comptime is_bindgen) {
unreachable;
@@ -388,3 +388,7 @@ pub const ZigConsoleClient = struct {
// }
// }
// };
pub inline fn toGlobalContextRef(ptr: *JSGlobalObject) CAPI.JSGlobalContextRef {
return @ptrCast(CAPI.JSGlobalContextRef, ptr);
}

View File

@@ -336,13 +336,15 @@ pub const C_Generator = struct {
const formatted_name = comptime std.mem.span(&_formatted_name);
if (@hasDecl(TT, "is_pointer") and !TT.is_pointer) {
if (cTypeLabel(TT.Type)) |label| {
type_names.put(comptime label, formatted_name) catch unreachable;
if (@typeInfo(TT) == .Struct and @hasField(TT, "bytes")) {
size_map.put(comptime formatted_name, @as(u32, TT.shim.byte_size)) catch unreachable;
align_map.put(comptime formatted_name, @as(u29, TT.shim.align_size)) catch unreachable;
} else if (@typeInfo(TT) == .Opaque) {
opaque_types.insert(comptime label) catch unreachable;
if (@TypeOf(TT.Type) == type) {
if (cTypeLabel(TT.Type)) |label| {
type_names.put(comptime label, formatted_name) catch unreachable;
if (@typeInfo(TT) == .Struct and @hasField(TT, "bytes")) {
size_map.put(comptime formatted_name, @as(u32, TT.shim.byte_size)) catch unreachable;
align_map.put(comptime formatted_name, @as(u29, TT.shim.align_size)) catch unreachable;
} else if (@typeInfo(TT) == .Opaque) {
opaque_types.insert(comptime label) catch unreachable;
}
}
} else {
type_names.put(comptime TT.name, formatted_name) catch unreachable;
@@ -350,7 +352,7 @@ pub const C_Generator = struct {
size_map.put(comptime formatted_name, @as(u32, TT.shim.byte_size)) catch unreachable;
align_map.put(comptime formatted_name, @as(u29, TT.shim.align_size)) catch unreachable;
} else if (@typeInfo(TT) == .Opaque) {
opaque_types.insert(comptime label) catch unreachable;
opaque_types.insert(comptime TT.name) catch unreachable;
}
}
} else {
@@ -593,6 +595,9 @@ pub fn HeaderGen(comptime import: type, comptime fname: []const u8) type {
\\#define CPP_SIZE AUTO_EXTERN_C
\\
\\typedef uint16_t ZigErrorCode;
\\#ifndef __cplusplus
\\typedef void* JSClassRef;
\\#endif
\\typedef struct ZigString { const unsigned char* ptr; size_t len; } ZigString;
\\typedef struct ZigErrorType { ZigErrorCode code; ZigString message; } ZigErrorType;
\\typedef union ErrorableZigStringResult { ZigString value; ZigErrorType err; } ErrorableZigStringResult;

View File

@@ -1,4 +1,4 @@
//-- AUTOGENERATED FILE -- 1627447221
//-- AUTOGENERATED FILE -- 1627506357
#pragma once
#include <stddef.h>

View File

@@ -1,4 +1,5 @@
const bindings = @import("./bindings.zig");
pub usingnamespace @import("../JavaScriptCore.zig");
pub const struct_JSC__StringPrototype = bindings.StringPrototype;
pub const struct_JSC__SetIteratorPrototype = bindings.SetIteratorPrototype;

View File

@@ -1,4 +1,4 @@
//-- AUTOGENERATED FILE -- 1627447221
//-- AUTOGENERATED FILE -- 1627506357
#pragma once
#include <stddef.h>
@@ -15,6 +15,9 @@
#define CPP_SIZE AUTO_EXTERN_C
typedef uint16_t ZigErrorCode;
#ifndef __cplusplus
typedef void* JSClassRef;
#endif
typedef struct ZigString { const unsigned char* ptr; size_t len; } ZigString;
typedef struct ZigErrorType { ZigErrorCode code; ZigString message; } ZigErrorType;
typedef union ErrorableZigStringResult { ZigString value; ZigErrorType err; } ErrorableZigStringResult;
@@ -88,6 +91,7 @@ typedef struct ErrorableZigString { ErrorableZigStringResult result; bool succes
typedef bJSC__JSLock JSC__JSLock; // JSC::JSLock
typedef bJSC__JSModuleLoader JSC__JSModuleLoader; // JSC::JSModuleLoader
typedef bJSC__VM JSC__VM; // JSC::VM
typedef JSClassRef JSClassRef;
typedef struct JSC__AsyncGeneratorPrototype JSC__AsyncGeneratorPrototype; // JSC::AsyncGeneratorPrototype
typedef struct JSC__AsyncGeneratorFunctionPrototype JSC__AsyncGeneratorFunctionPrototype; // JSC::AsyncGeneratorFunctionPrototype
typedef bJSC__JSGlobalObject JSC__JSGlobalObject; // JSC::JSGlobalObject
@@ -169,6 +173,7 @@ typedef struct ErrorableZigString { ErrorableZigStringResult result; bool succes
}
typedef ErrorableZigString ErrorableZigString;
typedef JSClassRef JSClassRef;
typedef int64_t JSC__JSValue;
using JSC__JSCell = JSC::JSCell;
using JSC__Exception = JSC::Exception;
@@ -531,7 +536,7 @@ CPP_DECL size_t WTF__StringView__length(const WTF__StringView* arg0);
#pragma mark - Zig::GlobalObject
CPP_DECL JSC__JSGlobalObject* Zig__GlobalObject__create(JSC__VM* arg0, void* arg1);
CPP_DECL JSC__JSGlobalObject* Zig__GlobalObject__create(JSClassRef* arg0, int32_t arg1, void* arg2);
#ifdef __cplusplus

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,4 @@
usingnamespace @import("../../global.zig");
const std = @import("std");
const Fs = @import("../../fs.zig");

File diff suppressed because it is too large Load Diff

View File

@@ -1,99 +0,0 @@
const std = @import("std");
const Fs = @import("../../fs.zig");
const resolver = @import("../../resolver/resolver.zig");
const ast = @import("../../import_record.zig");
const NodeModuleBundle = @import("../../node_module_bundle.zig").NodeModuleBundle;
const logger = @import("../../logger.zig");
const Api = @import("../../api/schema.zig").Api;
const options = @import("../../options.zig");
const Bundler = @import("../../bundler.zig").ServeBundler;
const js_printer = @import("../../js_printer.zig");
const hash_map = @import("../../hash_map.zig");
const http = @import("../../http.zig");
usingnamespace @import("./node_env_buf_map.zig");
usingnamespace @import("./config.zig");
usingnamespace @import("./bindings/bindings.zig");
usingnamespace @import("./bindings/exports.zig");
pub const VirtualMachine = struct {
global: *JSGlobalObject,
allocator: *std.mem.Allocator,
node_modules: ?*NodeModuleBundle = null,
bundler: Bundler,
watcher: ?*http.Watcher = null,
console: ZigConsoleClient,
pub threadlocal var vm: *VirtualMachine = undefined;
pub fn init(
allocator: *std.mem.Allocator,
_args: Api.TransformOptions,
existing_bundle: ?*NodeModuleBundle,
_log: ?*logger.Log,
) !*VirtualMachine {
var log: *logger.Log = undefined;
if (_log) |__log| {
log = __log;
} else {
log = try allocator.create(logger.Log);
}
vm = try allocator.create(VirtualMachine);
vm.* = VirtualMachine{
.global = undefined,
.allocator = allocator,
.bundler = try Bundler.init(
allocator,
log,
try configureTransformOptionsForSpeedy(allocator, _args),
existing_bundle,
),
.console = ZigConsoleClient.init(Output.errorWriter(), Output.writer()),
.node_modules = existing_bundle,
.log = log,
};
vm.global = js.ZigGlobalObject.create(null, &vm.console);
return vm;
}
};
pub const ModuleLoader = struct {
pub threadlocal var global_error_buf: [4096]u8 = undefined;
pub const RequireCacheType = std.AutoHashMap(http.Watcher.HashType, *CommonJSModule);
pub threadlocal var require_cache: RequireCacheType = undefined;
pub fn require(global: *JSGlobalObject, input: []const u8, from: *CommonJSModule) anyerror!resolver.Result {}
pub inline fn hashid(input: []const u8) http.Watcher.HashType {
return http.Watcher.getHash(input);
}
pub inline fn resolve(global: *JSGlobalObject, input: []const u8, from: *CommonJSModule) anyerror!resolver.Result {
std.debug.assert(global == VirtualMachine.vm.global);
return try VirtualMachine.vm.bundler.resolver.resolve(input, from.path.dirWithTrailingSlash(), .require);
}
inline fn _requireResolve(global: *JSGlobalObject, specifier: []const u8, referrer: []const u8) anyerror![]const u8 {
std.debug.assert(global == VirtualMachine.vm.global);
var result: resolver.Result = try VirtualMachine.vm.bundler.resolver.resolve(specifier, Fs.PathName.init(referrer).dirWithTrailingSlash(), .import);
return result.path_pair.primary.text;
}
pub fn load(global: *JSGlobalObject, )
pub fn requireResolve(global: *JSGlobalObject, specifier: ZigString, referrer: ZigString) ErrorableZigString {
return _requireResolve(global, specifier.slice(), referrer.slice()) catch |err| {
return ErrorableZigString.err(err, std.fmt.bufPrint(
&global_error_buf,
"Resolve failed: {s} while resolving \"{s}\" in \"{s}\"",
.{
@errorName(err),
specifier.slice(),
referrer.slice(),
},
) catch "ResolveError");
};
}
};

View File

@@ -20,6 +20,7 @@ const bundler = @import("bundler.zig");
const fs = @import("fs.zig");
const NodeModuleBundle = @import("./node_module_bundle.zig").NodeModuleBundle;
const js = @import("javascript/jsc/bindings/bindings.zig");
usingnamespace @import("javascript/jsc/javascript.zig");
const allocators = @import("allocators.zig");
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn {
if (MainPanicHandler.Singleton) |singleton| {
@@ -363,27 +364,8 @@ pub const Cli = struct {
}
pub fn startTransform(allocator: *std.mem.Allocator, args: Api.TransformOptions, log: *logger.Log) anyerror!void {}
const StringS = struct {
pub const src = "import Bacon from \"import-test\";\n\nconsole.log('hi'); \"HELLO\";";
pub const src = "var headers = new Headers(); headers.set(\"hey\", \"hi\"); console.log(headers.get(\"hey\")); \"HELLO\";";
};
pub fn demo(allocator: *std.mem.Allocator) !void {
var global: *js.JSGlobalObject = js.ZigGlobalObject.create(null, console);
var exception = js.JSValue.jsUndefined();
var result = js.JSModuleLoader.evaluate(
global,
StringS.src,
StringS.src.len,
"/hi.js",
"/hi.js".len,
js.JSValue.jsUndefined(),
@ptrCast([*]js.JSValue, &exception),
);
if (!exception.isUndefined()) {
var str = exception.toWTFString(global);
var slice = str.slice();
_ = Output.errorWriter().write(slice) catch 0;
}
}
pub fn start(allocator: *std.mem.Allocator, stdout: anytype, stderr: anytype) anyerror!void {
const start_time = std.time.nanoTimestamp();
@@ -391,21 +373,35 @@ pub const Cli = struct {
var panicker = MainPanicHandler.init(&log);
MainPanicHandler.Singleton = &panicker;
// var args = try Arguments.parse(alloc.static, stdout, stderr);
// // var serve_bundler = try bundler.ServeBundler.init(allocator, &log, args);
// // var res = try serve_bundler.buildFile(&log, allocator, args.entry_points[0], std.fs.path.extension(args.entry_points[0]));
var args = try Arguments.parse(alloc.static, stdout, stderr);
// var serve_bundler = try bundler.ServeBundler.init(allocator, &log, args);
// var res = try serve_bundler.buildFile(&log, allocator, args.entry_points[0], std.fs.path.extension(args.entry_points[0]));
// // var results = try bundler.Bundler.bundle(allocator, &log, args);
// // var file = results.output_files[0];
// var vm = try js.VirtualMachine.init(allocator, args, null, &log);
// var results = try bundler.Bundler.bundle(allocator, &log, args);
// var file = results.output_files[0];
var vm = try VirtualMachine.init(allocator, args, null, &log);
// var resolved_entry_point = try vm.bundler.resolver.resolve(
// vm.bundler.fs.top_level_dir,
// vm.bundler.normalizeEntryPointPath(vm.bundler.options.entry_points[0]),
// .entry_point,
// );
// var exception: js.JSValueRef = null;
// var result = try js.Module.loadFromResolveResult(vm, vm.global.ctx, resolved_entry_point, &exception);
try demo(allocator);
var exception = js.JSValue.jsUndefined();
var result = js.JSModuleLoader.evaluate(
vm.global,
StringS.src,
StringS.src.len,
"/hi.js",
"/hi.js".len,
js.JSValue.jsUndefined(),
@ptrCast([*]js.JSValue, &exception),
);
if (!exception.isUndefined()) {
var str = exception.toWTFString(vm.global);
var slice = str.slice();
_ = Output.errorWriter().write(slice) catch 0;
}
}
};