mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 14:33:47 +00:00
Merge pull request #1296 from lightpanda-io/v8-json-parser
Backport: Use V8 to parse JSON with fetch/xhr
This commit is contained in:
@@ -32,6 +32,7 @@ const ScriptManager = @import("../ScriptManager.zig");
|
|||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const PersistentObject = v8.Persistent(v8.Object);
|
const PersistentObject = v8.Persistent(v8.Object);
|
||||||
|
const PersistentValue = v8.Persistent(v8.Value);
|
||||||
const PersistentModule = v8.Persistent(v8.Module);
|
const PersistentModule = v8.Persistent(v8.Module);
|
||||||
const PersistentPromise = v8.Persistent(v8.Promise);
|
const PersistentPromise = v8.Persistent(v8.Promise);
|
||||||
const PersistentFunction = v8.Persistent(v8.Function);
|
const PersistentFunction = v8.Persistent(v8.Function);
|
||||||
@@ -85,6 +86,9 @@ identity_map: std.AutoHashMapUnmanaged(usize, PersistentObject) = .empty,
|
|||||||
// we now simply persist every time persist() is called.
|
// we now simply persist every time persist() is called.
|
||||||
js_object_list: std.ArrayListUnmanaged(PersistentObject) = .empty,
|
js_object_list: std.ArrayListUnmanaged(PersistentObject) = .empty,
|
||||||
|
|
||||||
|
// js_value_list tracks persisted js values.
|
||||||
|
js_value_list: std.ArrayListUnmanaged(PersistentValue) = .empty,
|
||||||
|
|
||||||
// Various web APIs depend on having a persistent promise resolver. They
|
// Various web APIs depend on having a persistent promise resolver. They
|
||||||
// require for this PromiseResolver to be valid for a lifetime longer than
|
// require for this PromiseResolver to be valid for a lifetime longer than
|
||||||
// the function that resolves/rejects them.
|
// the function that resolves/rejects them.
|
||||||
@@ -161,6 +165,10 @@ pub fn deinit(self: *Context) void {
|
|||||||
p.deinit();
|
p.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (self.js_value_list.items) |*p| {
|
||||||
|
p.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
for (self.persisted_promise_resolvers.items) |*p| {
|
for (self.persisted_promise_resolvers.items) |*p| {
|
||||||
p.deinit();
|
p.deinit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ const v8 = js.v8;
|
|||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
const PersistentValue = v8.Persistent(v8.Value);
|
||||||
|
|
||||||
const Value = @This();
|
const Value = @This();
|
||||||
js_val: v8.Value,
|
js_val: v8.Value,
|
||||||
context: *js.Context,
|
context: *js.Context,
|
||||||
@@ -49,6 +51,16 @@ pub fn fromJson(ctx: *js.Context, json: []const u8) !Value {
|
|||||||
return Value{ .context = ctx, .js_val = value };
|
return Value{ .context = ctx, .js_val = value };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn persist(self: Value) !Value {
|
||||||
|
const js_val = self.js_val;
|
||||||
|
var context = self.context;
|
||||||
|
|
||||||
|
const persisted = PersistentValue.init(context.isolate, js_val);
|
||||||
|
try context.js_value_list.append(context.arena, persisted);
|
||||||
|
|
||||||
|
return Value{ .context = context, .js_val = persisted.toValue() };
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toObject(self: Value) js.Object {
|
pub fn toObject(self: Value) js.Object {
|
||||||
return .{
|
return .{
|
||||||
.context = self.context,
|
.context = self.context,
|
||||||
|
|||||||
@@ -35,7 +35,9 @@
|
|||||||
|
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
testing.expectEqual('9000!!!', json.over);
|
testing.expectEqual('9000!!!', json.over);
|
||||||
|
testing.expectEqual("number", typeof json.updated_at);
|
||||||
|
testing.expectEqual(1765867200000, json.updated_at);
|
||||||
|
testing.expectEqual({over: '9000!!!',updated_at:1765867200000}, json);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,9 @@
|
|||||||
testing.expectEqual(200, req3.status);
|
testing.expectEqual(200, req3.status);
|
||||||
testing.expectEqual('OK', req3.statusText);
|
testing.expectEqual('OK', req3.statusText);
|
||||||
testing.expectEqual('9000!!!', req3.response.over);
|
testing.expectEqual('9000!!!', req3.response.over);
|
||||||
|
testing.expectEqual("number", typeof json.updated_at);
|
||||||
|
testing.expectEqual(1765867200000, json.updated_at);
|
||||||
|
testing.expectEqual({over: '9000!!!',updated_at:1765867200000}, json);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -120,15 +120,11 @@ pub fn getText(self: *const Response, page: *Page) !js.Promise {
|
|||||||
|
|
||||||
pub fn getJson(self: *Response, page: *Page) !js.Promise {
|
pub fn getJson(self: *Response, page: *Page) !js.Promise {
|
||||||
const body = self._body orelse "";
|
const body = self._body orelse "";
|
||||||
const value = std.json.parseFromSliceLeaky(
|
const value = js.Value.fromJson(page.js, body) catch |err| {
|
||||||
std.json.Value,
|
|
||||||
page.call_arena,
|
|
||||||
body,
|
|
||||||
.{},
|
|
||||||
) catch |err| {
|
|
||||||
return page.js.rejectPromise(.{@errorName(err)});
|
return page.js.rejectPromise(.{@errorName(err)});
|
||||||
};
|
};
|
||||||
return page.js.resolvePromise(value);
|
const pvalue = try value.persist();
|
||||||
|
return page.js.resolvePromise(pvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const JsApi = struct {
|
pub const JsApi = struct {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const ReadyState = enum(u8) {
|
|||||||
|
|
||||||
const Response = union(ResponseType) {
|
const Response = union(ResponseType) {
|
||||||
text: []const u8,
|
text: []const u8,
|
||||||
json: std.json.Value,
|
json: js.Value,
|
||||||
document: *Node.Document,
|
document: *Node.Document,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -254,8 +254,9 @@ pub fn getResponse(self: *XMLHttpRequest, page: *Page) !?Response {
|
|||||||
const res: Response = switch (self._response_type) {
|
const res: Response = switch (self._response_type) {
|
||||||
.text => .{ .text = data },
|
.text => .{ .text = data },
|
||||||
.json => blk: {
|
.json => blk: {
|
||||||
const parsed = try std.json.parseFromSliceLeaky(std.json.Value, page.call_arena, data, .{});
|
const value = try js.Value.fromJson(page.js, data);
|
||||||
break :blk .{ .json = parsed };
|
const pvalue = try value.persist();
|
||||||
|
break :blk .{ .json = pvalue };
|
||||||
},
|
},
|
||||||
.document => blk: {
|
.document => blk: {
|
||||||
const document = try page._factory.node(Node.Document{ ._proto = undefined, ._type = .generic });
|
const document = try page._factory.node(Node.Document{ ._proto = undefined, ._type = .generic });
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ fn testHTTPHandler(req: *std.http.Server.Request) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (std.mem.eql(u8, path, "/xhr/json")) {
|
if (std.mem.eql(u8, path, "/xhr/json")) {
|
||||||
return req.respond("{\"over\":\"9000!!!\"}", .{
|
return req.respond("{\"over\":\"9000!!!\",\"updated_at\":1765867200000}", .{
|
||||||
.extra_headers = &.{
|
.extra_headers = &.{
|
||||||
.{ .name = "Content-Type", .value = "application/json" },
|
.{ .name = "Content-Type", .value = "application/json" },
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user