mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 07:03:29 +00:00
Implement ImportMeta callback
The first time `import.meta` is called within a module, this callback is called and we can populate it with whatever fields we want. For WebAPI, the important field is `url`: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta Depends on: https://github.com/lightpanda-io/zig-v8-fork/pull/80
This commit is contained in:
@@ -13,8 +13,8 @@
|
|||||||
.hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd",
|
.hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd",
|
||||||
},
|
},
|
||||||
.v8 = .{
|
.v8 = .{
|
||||||
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/23718cdb99aaa45105d0a7e0ca22587bf77d3b5f.tar.gz",
|
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/46ddf8c0a2861a4e5717e6f8d0d81a17e42fa0c9.tar.gz",
|
||||||
.hash = "v8-0.0.0-xddH68m2AwDf42Qp2Udz4wTMVH8p71si7yLlUoZkPeEz",
|
.hash = "v8-0.0.0-xddH6865AwDiDnu-HjMsqm9wXvP9OZOh_4clh_67iQsq",
|
||||||
},
|
},
|
||||||
//.v8 = .{ .path = "../zig-v8-fork" },
|
//.v8 = .{ .path = "../zig-v8-fork" },
|
||||||
//.tigerbeetle_io = .{ .path = "../tigerbeetle-io" },
|
//.tigerbeetle_io = .{ .path = "../tigerbeetle-io" },
|
||||||
|
|||||||
@@ -1001,7 +1001,11 @@ const Script = struct {
|
|||||||
try_catch.init(page.main_context);
|
try_catch.init(page.main_context);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
const src = self.src orelse page.url.raw;
|
const src: []const u8 = blk: {
|
||||||
|
const s = self.src orelse break :blk page.url.raw;
|
||||||
|
break :blk try URL.stitch(page.arena, s, page.url.raw, .{.alloc = .if_needed});
|
||||||
|
};
|
||||||
|
|
||||||
// if self.src is null, then this is an inline script, and it should
|
// if self.src is null, then this is an inline script, and it should
|
||||||
// not be cached.
|
// not be cached.
|
||||||
const cacheable = self.src != null;
|
const cacheable = self.src != null;
|
||||||
|
|||||||
@@ -580,7 +580,7 @@ fn parseCommonArg(
|
|||||||
var it = std.mem.splitScalar(u8, str, ',');
|
var it = std.mem.splitScalar(u8, str, ',');
|
||||||
while (it.next()) |part| {
|
while (it.next()) |part| {
|
||||||
try arr.append(allocator, std.meta.stringToEnum(log.Scope, part) orelse {
|
try arr.append(allocator, std.meta.stringToEnum(log.Scope, part) orelse {
|
||||||
log.fatal(.app, "invalid option choice", .{ .arg = "--log_scope_filter", .value = part });
|
log.fatal(.app, "invalid option choice", .{ .arg = "--log_filter_scopes", .value = part });
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,6 +197,16 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
|||||||
isolate.enter();
|
isolate.enter();
|
||||||
errdefer isolate.exit();
|
errdefer isolate.exit();
|
||||||
|
|
||||||
|
isolate.setHostInitializeImportMetaObjectCallback(struct {
|
||||||
|
fn callback(c_context: ?*v8.C_Context, c_module: ?*v8.C_Module, c_meta: ?*v8.C_Value) callconv(.C) void {
|
||||||
|
const v8_context = v8.Context{.handle = c_context.?};
|
||||||
|
const js_context: *JsContext = @ptrFromInt(v8_context.getEmbedderData(1).castTo(v8.BigInt).getUint64());
|
||||||
|
js_context.initializeImportMeta(v8.Module{.handle = c_module.?}, v8.Object{.handle = c_meta.?}) catch |err| {
|
||||||
|
log.err(.js, "import meta", .{ .err = err });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}.callback);
|
||||||
|
|
||||||
var temp_scope: v8.HandleScope = undefined;
|
var temp_scope: v8.HandleScope = undefined;
|
||||||
v8.HandleScope.init(&temp_scope, isolate);
|
v8.HandleScope.init(&temp_scope, isolate);
|
||||||
defer temp_scope.deinit();
|
defer temp_scope.deinit();
|
||||||
@@ -726,13 +736,15 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
|||||||
|
|
||||||
fn moduleNoCache(self: *JsContext, src: []const u8, url: []const u8) !void {
|
fn moduleNoCache(self: *JsContext, src: []const u8, url: []const u8) !void {
|
||||||
const m = try compileModule(self.isolate, src, url);
|
const m = try compileModule(self.isolate, src, url);
|
||||||
|
|
||||||
|
const arena = self.context_arena;
|
||||||
|
const owned_url = try arena.dupe(u8, url);
|
||||||
|
try self.module_identifier.putNoClobber(arena, m.getIdentityHash(), owned_url);
|
||||||
|
|
||||||
const v8_context = self.v8_context;
|
const v8_context = self.v8_context;
|
||||||
if (try m.instantiate(v8_context, resolveModuleCallback) == false) {
|
if (try m.instantiate(v8_context, resolveModuleCallback) == false) {
|
||||||
return error.ModuleInstantiationError;
|
return error.ModuleInstantiationError;
|
||||||
}
|
}
|
||||||
const arena = self.context_arena;
|
|
||||||
const owned_url = try arena.dupe(u8, url);
|
|
||||||
try self.module_identifier.putNoClobber(arena, m.getIdentityHash(), owned_url);
|
|
||||||
_ = try m.evaluate(v8_context);
|
_ = try m.evaluate(v8_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1279,6 +1291,20 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
|||||||
return self.createException(js_value);
|
return self.createException(js_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn initializeImportMeta(self: *JsContext, m: v8.Module, meta: v8.Object) !void {
|
||||||
|
const url = self.module_identifier.get(m.getIdentityHash()) orelse {
|
||||||
|
// Shouldn't be possible.
|
||||||
|
return error.UnknownModuleReferrer;
|
||||||
|
};
|
||||||
|
|
||||||
|
const js_key = v8.String.initUtf8(self.isolate, "url");
|
||||||
|
const js_value = try self.zigValueToJs(url);
|
||||||
|
const res = meta.defineOwnProperty(self.v8_context, js_key.toName(), js_value, 0) orelse false;
|
||||||
|
if (!res) {
|
||||||
|
return error.FailedToSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Callback from V8, asking us to load a module. The "specifier" is
|
// Callback from V8, asking us to load a module. The "specifier" is
|
||||||
// the src of the module to load.
|
// the src of the module to load.
|
||||||
fn resolveModuleCallback(
|
fn resolveModuleCallback(
|
||||||
@@ -1335,7 +1361,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
|||||||
try_catch.init(self);
|
try_catch.init(self);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
const m = compileModule(self.isolate, source, specifier) catch |err| {
|
const m = compileModule(self.isolate, source, normalized_specifier) catch |err| {
|
||||||
log.warn(.js, "compile resolved module", .{
|
log.warn(.js, "compile resolved module", .{
|
||||||
.specifier = specifier,
|
.specifier = specifier,
|
||||||
.stack = try_catch.stack(self.call_arena) catch null,
|
.stack = try_catch.stack(self.call_arena) catch null,
|
||||||
|
|||||||
19
src/url.zig
19
src/url.zig
@@ -111,7 +111,7 @@ pub const URL = struct {
|
|||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
var normalized_src = if (std.mem.startsWith(u8, src, "/")) src[1..] else src;
|
var normalized_src = src;
|
||||||
while (std.mem.startsWith(u8, normalized_src, "./")) {
|
while (std.mem.startsWith(u8, normalized_src, "./")) {
|
||||||
normalized_src = normalized_src[2..];
|
normalized_src = normalized_src[2..];
|
||||||
}
|
}
|
||||||
@@ -131,6 +131,13 @@ pub const URL = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (normalized_src[0] == '/') {
|
||||||
|
if (std.mem.indexOfScalarPos(u8, base, protocol_end, '/')) |pos| {
|
||||||
|
return std.fmt.allocPrint(allocator, "{s}{s}", .{ base[0..pos], normalized_src });
|
||||||
|
}
|
||||||
|
// not sure what to do here...error? Just let it fallthrough for now.
|
||||||
|
}
|
||||||
|
|
||||||
if (std.mem.lastIndexOfScalar(u8, base[protocol_end..], '/')) |index| {
|
if (std.mem.lastIndexOfScalar(u8, base[protocol_end..], '/')) |index| {
|
||||||
const last_slash_pos = index + protocol_end;
|
const last_slash_pos = index + protocol_end;
|
||||||
if (last_slash_pos == base.len - 1) {
|
if (last_slash_pos == base.len - 1) {
|
||||||
@@ -257,6 +264,16 @@ test "URL: Stitching Base & Src URLs (No Ending Slash)" {
|
|||||||
try testing.expectString("https://lightpanda.io/something.js", result);
|
try testing.expectString("https://lightpanda.io/something.js", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "URL: Stitching Base with absolute src" {
|
||||||
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
const base = "https://lightpanda.io/hello";
|
||||||
|
const src = "/abc/something.js";
|
||||||
|
const result = try URL.stitch(allocator, src, base, .{});
|
||||||
|
defer allocator.free(result);
|
||||||
|
try testing.expectString("https://lightpanda.io/abc/something.js", result);
|
||||||
|
}
|
||||||
|
|
||||||
test "URL: Stiching Base & Src URLs (Both Local)" {
|
test "URL: Stiching Base & Src URLs (Both Local)" {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user