mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-28 14:43:28 +00:00
Compare commits
1 Commits
c9dc4ef57a
...
compilatio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a9a4cbc01 |
@@ -119,7 +119,10 @@ pub const Page = struct {
|
||||
}),
|
||||
.main_context = undefined,
|
||||
};
|
||||
self.main_context = try session.executor.createJsContext(&self.window, self, self, true, Env.GlobalMissingCallback.init(&self.polyfill_loader));
|
||||
self.main_context = try session.executor.createJsContext(&self.window, self, self, true, .{
|
||||
.global_callback = Env.GlobalMissingCallback.init(&self.polyfill_loader),
|
||||
.compilation_callback = Env.CompilationCallback.init(&self.polyfill_loader),
|
||||
});
|
||||
|
||||
// message loop must run only non-test env
|
||||
if (comptime !builtin.is_test) {
|
||||
|
||||
@@ -50,6 +50,23 @@ pub const Loader = struct {
|
||||
@field(self.done, name) = true;
|
||||
}
|
||||
|
||||
// CompilationCallback implementation
|
||||
pub fn script(self: *Loader, src: []const u8, _: ?[]const u8, js_context: *Env.JsContext) void {
|
||||
if (!self.done.webcomponents and containsWebcomponents(src)) {
|
||||
const source = @import("webcomponents.zig").source;
|
||||
self.load("webcomponents", source, js_context);
|
||||
}
|
||||
}
|
||||
|
||||
// CompilationCallback implementation
|
||||
pub fn module(self: *Loader, src: []const u8, _: []const u8, js_context: *Env.JsContext) void {
|
||||
if (!self.done.webcomponents and containsWebcomponents(src)) {
|
||||
const source = @import("webcomponents.zig").source;
|
||||
self.load("webcomponents", source, js_context);
|
||||
}
|
||||
}
|
||||
|
||||
// GlobalMissingCallback implementation
|
||||
pub fn missing(self: *Loader, name: []const u8, js_context: *Env.JsContext) bool {
|
||||
// Avoid recursive calls during polyfill loading.
|
||||
if (self.state == .loading) {
|
||||
@@ -102,4 +119,8 @@ pub const Loader = struct {
|
||||
if (std.mem.eql(u8, name, "customElements")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
fn containsWebcomponents(src: []const u8) bool {
|
||||
return std.mem.indexOf(u8, src, " extends ") != null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,8 +13,6 @@ test "Browser.webcomponents" {
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{
|
||||
\\ window.customElements; // temporarily needed, lazy loading doesn't work!
|
||||
\\
|
||||
\\ class LightPanda extends HTMLElement {
|
||||
\\ constructor() {
|
||||
\\ super();
|
||||
|
||||
@@ -580,7 +580,10 @@ const IsolatedWorld = struct {
|
||||
page,
|
||||
{},
|
||||
false,
|
||||
Env.GlobalMissingCallback.init(&self.polyfill_loader),
|
||||
.{
|
||||
.global_callback = Env.GlobalMissingCallback.init(&self.polyfill_loader),
|
||||
.compilation_callback = Env.CompilationCallback.init(&self.polyfill_loader),
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -364,13 +364,25 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
||||
self.context_arena.deinit();
|
||||
}
|
||||
|
||||
pub const CreateJsContextOpt = struct {
|
||||
global_callback: ?GlobalMissingCallback = null,
|
||||
compilation_callback: ?CompilationCallback = null,
|
||||
};
|
||||
|
||||
// Only the top JsContext in the Main ExecutionWorld should hold a handle_scope.
|
||||
// A v8.HandleScope is like an arena. Once created, any "Local" that
|
||||
// v8 creates will be released (or at least, releasable by the v8 GC)
|
||||
// when the handle_scope is freed.
|
||||
// We also maintain our own "context_arena" which allows us to have
|
||||
// all page related memory easily managed.
|
||||
pub fn createJsContext(self: *ExecutionWorld, global: anytype, state: State, module_loader: anytype, enter: bool, global_callback: ?GlobalMissingCallback) !*JsContext {
|
||||
pub fn createJsContext(
|
||||
self: *ExecutionWorld,
|
||||
global: anytype,
|
||||
state: State,
|
||||
module_loader: anytype,
|
||||
enter: bool,
|
||||
opt: CreateJsContextOpt,
|
||||
) !*JsContext {
|
||||
std.debug.assert(self.js_context == null);
|
||||
|
||||
const ModuleLoader = switch (@typeInfo(@TypeOf(module_loader))) {
|
||||
@@ -401,7 +413,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
||||
|
||||
// Configure the missing property callback on the global
|
||||
// object.
|
||||
if (global_callback != null) {
|
||||
if (opt.global_callback != null) {
|
||||
const configuration = v8.NamedPropertyHandlerConfiguration{
|
||||
.getter = struct {
|
||||
fn callback(c_name: ?*const v8.C_Name, raw_info: ?*const v8.C_PropertyCallbackInfo) callconv(.c) u8 {
|
||||
@@ -505,7 +517,8 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
||||
.ptr = safe_module_loader,
|
||||
.func = ModuleLoader.fetchModuleSource,
|
||||
},
|
||||
.global_callback = global_callback,
|
||||
.global_callback = opt.global_callback,
|
||||
.compilation_callback = opt.compilation_callback,
|
||||
};
|
||||
|
||||
var js_context = &self.js_context.?;
|
||||
@@ -658,9 +671,12 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
||||
// necessary to lookup/store the dependent module in the module_cache.
|
||||
module_identifier: std.AutoHashMapUnmanaged(u32, []const u8) = .empty,
|
||||
|
||||
// Global callback is called on missing property.
|
||||
// Global callback is called when a property is missing on the
|
||||
// global object.
|
||||
global_callback: ?GlobalMissingCallback = null,
|
||||
|
||||
compilation_callback: ?CompilationCallback = null,
|
||||
|
||||
const ModuleLoader = struct {
|
||||
ptr: *anyopaque,
|
||||
func: *const fn (ptr: *anyopaque, specifier: []const u8) anyerror!?[]const u8,
|
||||
@@ -747,6 +763,8 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
||||
}
|
||||
|
||||
pub fn exec(self: *JsContext, src: []const u8, name: ?[]const u8) !Value {
|
||||
if (self.compilation_callback) |cbk| cbk.script(src, name, self);
|
||||
|
||||
const isolate = self.isolate;
|
||||
const v8_context = self.v8_context;
|
||||
|
||||
@@ -770,6 +788,8 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
||||
// compile and eval a JS module
|
||||
// It doesn't wait for callbacks execution
|
||||
pub fn module(self: *JsContext, src: []const u8, url: []const u8, cacheable: bool) !void {
|
||||
if (self.compilation_callback) |cbk| cbk.module(src, url, self);
|
||||
|
||||
if (!cacheable) {
|
||||
return self.moduleNoCache(src, url);
|
||||
}
|
||||
@@ -2604,6 +2624,43 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
||||
return self.missingFn(self.ptr, name, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
// CompilationCallback called before script and module compilation.
|
||||
pub const CompilationCallback = struct {
|
||||
ptr: *anyopaque,
|
||||
scriptFn: *const fn (ptr: *anyopaque, source: []const u8, name: ?[]const u8, ctx: *JsContext) void,
|
||||
moduleFn: *const fn (ptr: *anyopaque, source: []const u8, url: []const u8, ctx: *JsContext) void,
|
||||
|
||||
pub fn init(ptr: anytype) CompilationCallback {
|
||||
const T = @TypeOf(ptr);
|
||||
const ptr_info = @typeInfo(T);
|
||||
|
||||
const gen = struct {
|
||||
pub fn script(pointer: *anyopaque, source: []const u8, name: ?[]const u8, ctx: *JsContext) void {
|
||||
const self: T = @ptrCast(@alignCast(pointer));
|
||||
return ptr_info.pointer.child.script(self, source, name, ctx);
|
||||
}
|
||||
pub fn module(pointer: *anyopaque, source: []const u8, url: []const u8, ctx: *JsContext) void {
|
||||
const self: T = @ptrCast(@alignCast(pointer));
|
||||
return ptr_info.pointer.child.module(self, source, url, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
return .{
|
||||
.ptr = ptr,
|
||||
.scriptFn = gen.script,
|
||||
.moduleFn = gen.module,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn script(self: CompilationCallback, source: []const u8, name: ?[]const u8, ctx: *JsContext) void {
|
||||
return self.scriptFn(self.ptr, source, name, ctx);
|
||||
}
|
||||
|
||||
pub fn module(self: CompilationCallback, source: []const u8, url: []const u8, ctx: *JsContext) void {
|
||||
return self.moduleFn(self.ptr, source, url, ctx);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ pub fn Runner(comptime State: type, comptime Global: type, comptime types: anyty
|
||||
state,
|
||||
{},
|
||||
true,
|
||||
null,
|
||||
.{},
|
||||
);
|
||||
return self;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user