From d38f59d6315c3fcf89a9a24baadee57e51583d21 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 6 Sep 2023 17:28:09 +0200 Subject: [PATCH 01/21] Makefile: add install-netsurf Signed-off-by: Francis Bouvier --- Makefile | 58 +++++++++++++++++++++++++++++++++++++++++++- vendor/jsruntime-lib | 2 +- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fc05b195..04e8fe28 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ # --------- ZIG := zig +BC := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) # Infos # ----- @@ -63,7 +64,62 @@ install: install-submodule install-lexbor install-jsruntime ## Install and build dependencies for dev install-dev: install-submodule install-lexbor install-jsruntime-dev -## Install and build v8 engine for dev +BC_NS := $(BC)vendor/netsurf +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S), Darwin) + ICONV := /opt/homebrew/opt/libiconv +endif +# TODO: add Linux iconv path (I guess it depends on the distro) +# TODO: this way of linking libiconv is not ideal. We should have a more generic way +# and stick to a specif version. Maybe build from source. Anyway not now. +install-netsurf: + @printf "\e[36mInstalling NetSurf...\e[0m\n" && \ + ls $(ICONV) 1> /dev/null || (printf "\e[33mERROR: you need to install libiconv in your system (on MacOS on with Homebrew)\e[0m\n"; exit 1;) && \ + mkdir -p vendor/netfurf && \ + mkdir -p vendor/netfurf/build && \ + mkdir -p vendor/netfurf/netsurf-buildsystem && \ + export PREFIX=$(BC_NS) && \ + export LDFLAGS="-L$(ICONV)/lib" && \ + export CFLAGS="-I/$(ICONV)/include -I$(BC_NS)/libparserutils/include -I$(BC_NS)/libhubbub/include -I$(BC_NS)/libwapcaplet/include" && \ + printf "\e[33mInstalling libwapcaplet...\e[0m\n" && \ + cd vendor/netsurf/libwapcaplet && \ + BUILDDIR=$(BC_NS)/build/libwapcaplet make 2> /dev/null && \ + cd ../libparserutils && \ + printf "\e[33mInstalling libparserutils...\e[0m\n" && \ + BUILDDIR=$(BC_NS)/build/libparserutils make 2> /dev/null && \ + cd ../libhubbub && \ + printf "\e[33mInstalling libhubbub...\e[0m\n" && \ + BUILDDIR=$(BC_NS)/build/libhubbub make 2> /dev/null && \ + cd ../libdom && \ + printf "\e[33mInstalling libdom...\e[0m\n" && \ + BUILDDIR=$(BC_NS)/build/libdom make 2> /dev/null && \ + printf "\e[33mRunning libdom example...\e[0m\n" && \ + cd include/dom && \ + rm bindings && \ + ln -s ../../bindings bindings && \ + cd ../../examples && \ + rm -f a.out || true && \ + clang \ + -I$(ICONV)/include \ + -I$(BC_NS)/libdom/include \ + -I$(BC_NS)/libparserutils/include \ + -I$(BC_NS)/libhubbub/include \ + -I$(BC_NS)/libwapcaplet/include \ + -L$(ICONV)/lib \ + -L$(BC_NS)/build/libdom \ + -L$(BC_NS)/build/libparserutils \ + -L$(BC_NS)/build/libhubbub \ + -L$(BC_NS)/build/libwapcaplet \ + -liconv \ + -ldom \ + -lhubbub \ + -lparserutils \ + -lwapcaplet \ + dom-structure-dump.c && \ + ./a.out > /dev/null && \ + printf "\e[36mDone NetSurf $(OS)\e[0m\n" + + install-lexbor: @mkdir -p vendor/lexbor @cd vendor/lexbor && \ diff --git a/vendor/jsruntime-lib b/vendor/jsruntime-lib index 978b166c..4d19129b 160000 --- a/vendor/jsruntime-lib +++ b/vendor/jsruntime-lib @@ -1 +1 @@ -Subproject commit 978b166c651f11566df2a264fe869ea4d161c7d5 +Subproject commit 4d19129bb77f8a912727fe25638f4980949570fb From 97348cef5cf6a0f0499800f9805b7d802d5666d1 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 6 Sep 2023 17:51:43 +0200 Subject: [PATCH 02/21] Add netsurf submodules Signed-off-by: Francis Bouvier --- .gitignore | 1 + .gitmodules | 15 +++++++++++++++ Makefile | 4 +--- vendor/netsurf/libdom | 1 + vendor/netsurf/libhubbub | 1 + vendor/netsurf/libparserutils | 1 + vendor/netsurf/libwapcaplet | 1 + vendor/netsurf/share/netsurf-buildsystem | 1 + 8 files changed, 22 insertions(+), 3 deletions(-) create mode 160000 vendor/netsurf/libdom create mode 160000 vendor/netsurf/libhubbub create mode 160000 vendor/netsurf/libparserutils create mode 160000 vendor/netsurf/libwapcaplet create mode 160000 vendor/netsurf/share/netsurf-buildsystem diff --git a/.gitignore b/.gitignore index f78e00fb..f78426c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ zig-cache zig-out /vendor/lexbor/ +/vendor/netsurf/build/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 26181de6..622ee626 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,18 @@ [submodule "vendor/lexbor-src"] path = vendor/lexbor-src url = https://github.com/lexbor/lexbor +[submodule "vendor/netsurf/libwapcaplet"] + path = vendor/netsurf/libwapcaplet + url = https://source.netsurf-browser.org/libwapcaplet.git +[submodule "vendor/netsurf/libparserutils"] + path = vendor/netsurf/libparserutils + url = https://source.netsurf-browser.org/libparserutils.git +[submodule "vendor/netsurf/libdom"] + path = vendor/netsurf/libdom + url = https://source.netsurf-browser.org/libdom.git +[submodule "vendor/netsurf/share/netsurf-buildsystem"] + path = vendor/netsurf/share/netsurf-buildsystem + url = https://source.netsurf-browser.org/buildsystem.git +[submodule "vendor/netsurf/libhubbub"] + path = vendor/netsurf/libhubbub + url = https://source.netsurf-browser.org/libhubbub.git diff --git a/Makefile b/Makefile index 04e8fe28..077b5205 100644 --- a/Makefile +++ b/Makefile @@ -75,9 +75,7 @@ endif install-netsurf: @printf "\e[36mInstalling NetSurf...\e[0m\n" && \ ls $(ICONV) 1> /dev/null || (printf "\e[33mERROR: you need to install libiconv in your system (on MacOS on with Homebrew)\e[0m\n"; exit 1;) && \ - mkdir -p vendor/netfurf && \ mkdir -p vendor/netfurf/build && \ - mkdir -p vendor/netfurf/netsurf-buildsystem && \ export PREFIX=$(BC_NS) && \ export LDFLAGS="-L$(ICONV)/lib" && \ export CFLAGS="-I/$(ICONV)/include -I$(BC_NS)/libparserutils/include -I$(BC_NS)/libhubbub/include -I$(BC_NS)/libwapcaplet/include" && \ @@ -95,7 +93,7 @@ install-netsurf: BUILDDIR=$(BC_NS)/build/libdom make 2> /dev/null && \ printf "\e[33mRunning libdom example...\e[0m\n" && \ cd include/dom && \ - rm bindings && \ + rm -f bindings || true && \ ln -s ../../bindings bindings && \ cd ../../examples && \ rm -f a.out || true && \ diff --git a/vendor/netsurf/libdom b/vendor/netsurf/libdom new file mode 160000 index 00000000..176bab60 --- /dev/null +++ b/vendor/netsurf/libdom @@ -0,0 +1 @@ +Subproject commit 176bab60eb10beb68fbbb1a6185c68eeda2a6e95 diff --git a/vendor/netsurf/libhubbub b/vendor/netsurf/libhubbub new file mode 160000 index 00000000..873ed6e2 --- /dev/null +++ b/vendor/netsurf/libhubbub @@ -0,0 +1 @@ +Subproject commit 873ed6e236f7669afd3ef44259c34addc6dc95b6 diff --git a/vendor/netsurf/libparserutils b/vendor/netsurf/libparserutils new file mode 160000 index 00000000..96cdd0ff --- /dev/null +++ b/vendor/netsurf/libparserutils @@ -0,0 +1 @@ +Subproject commit 96cdd0ff114299f520e76538ab8fde39358b87f9 diff --git a/vendor/netsurf/libwapcaplet b/vendor/netsurf/libwapcaplet new file mode 160000 index 00000000..b5e42b12 --- /dev/null +++ b/vendor/netsurf/libwapcaplet @@ -0,0 +1 @@ +Subproject commit b5e42b12211a92339b0b62cb90f1a86a397e146e diff --git a/vendor/netsurf/share/netsurf-buildsystem b/vendor/netsurf/share/netsurf-buildsystem new file mode 160000 index 00000000..b4ba781f --- /dev/null +++ b/vendor/netsurf/share/netsurf-buildsystem @@ -0,0 +1 @@ +Subproject commit b4ba781fe22f356d7c53b1674dff91323af61458 From d6027b238b0edabee950b6c5470a6563136d330a Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Thu, 7 Sep 2023 16:51:29 +0200 Subject: [PATCH 03/21] build: link netsurf Signed-off-by: Francis Bouvier --- Makefile | 1 - build.zig | 30 ++++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 077b5205..ed40951b 100644 --- a/Makefile +++ b/Makefile @@ -75,7 +75,6 @@ endif install-netsurf: @printf "\e[36mInstalling NetSurf...\e[0m\n" && \ ls $(ICONV) 1> /dev/null || (printf "\e[33mERROR: you need to install libiconv in your system (on MacOS on with Homebrew)\e[0m\n"; exit 1;) && \ - mkdir -p vendor/netfurf/build && \ export PREFIX=$(BC_NS) && \ export LDFLAGS="-L$(ICONV)/lib" && \ export CFLAGS="-I/$(ICONV)/include -I$(BC_NS)/libparserutils/include -I$(BC_NS)/libhubbub/include -I$(BC_NS)/libwapcaplet/include" && \ diff --git a/build.zig b/build.zig index c6c75dd4..f2b22e02 100644 --- a/build.zig +++ b/build.zig @@ -78,6 +78,7 @@ fn common( ) !void { try jsruntime_pkgs.add(step, options); linkLexbor(step); + linkNetSurf(step); } fn linkLexbor(step: *std.build.LibExeObjStep) void { @@ -86,3 +87,32 @@ fn linkLexbor(step: *std.build.LibExeObjStep) void { step.addObjectFile(.{ .path = lib_path }); step.addIncludePath(.{ .path = "vendor/lexbor-src/source" }); } + +fn linkNetSurf(step: *std.build.LibExeObjStep) void { + + // iconv + var iconv_lib: []const u8 = undefined; + var iconv_include: []const u8 = undefined; + const os = step.target.getOsTag(); + if (os == .macos) { + iconv_lib = "/opt/homebrew/opt/libiconv/lib/libiconv.a"; + iconv_include = "/opt/homebrew/opt/libiconv/include"; + } else if (os == .linux) { + @panic("you need to modify build.zig to specify libiconv paths"); + } + step.addObjectFile(iconv_lib); + step.addIncludePath(iconv_include); + + // netsurf libs + const ns = "vendor/netsurf/"; + const libs: [4][]const u8 = .{ + "libdom", + "libhubbub", + "libparserutils", + "libwapcaplet", + }; + inline for (libs) |lib| { + step.addObjectFile(ns ++ "/build/" ++ lib ++ "/" ++ lib ++ ".a"); + step.addIncludePath(ns ++ lib ++ "/include"); + } +} From 1f61eaff9d2ddea488165b30211f8ac4217d8975 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 20 Sep 2023 22:42:06 +0200 Subject: [PATCH 04/21] Makefile: use make install for install-netsurf Signed-off-by: Francis Bouvier --- .gitignore | 4 +++- Makefile | 28 ++++++++++------------------ 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index f78426c9..b69e598b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ zig-cache zig-out /vendor/lexbor/ -/vendor/netsurf/build/ \ No newline at end of file +/vendor/netsurf/build/ +/vendor/netsurf/lib/ +/vendor/netsurf/include/ \ No newline at end of file diff --git a/Makefile b/Makefile index ed40951b..d57f993e 100644 --- a/Makefile +++ b/Makefile @@ -77,36 +77,27 @@ install-netsurf: ls $(ICONV) 1> /dev/null || (printf "\e[33mERROR: you need to install libiconv in your system (on MacOS on with Homebrew)\e[0m\n"; exit 1;) && \ export PREFIX=$(BC_NS) && \ export LDFLAGS="-L$(ICONV)/lib" && \ - export CFLAGS="-I/$(ICONV)/include -I$(BC_NS)/libparserutils/include -I$(BC_NS)/libhubbub/include -I$(BC_NS)/libwapcaplet/include" && \ + export CFLAGS="-I$(ICONV)/include" && \ printf "\e[33mInstalling libwapcaplet...\e[0m\n" && \ cd vendor/netsurf/libwapcaplet && \ - BUILDDIR=$(BC_NS)/build/libwapcaplet make 2> /dev/null && \ + BUILDDIR=$(BC_NS)/build/libwapcaplet make install && \ cd ../libparserutils && \ printf "\e[33mInstalling libparserutils...\e[0m\n" && \ - BUILDDIR=$(BC_NS)/build/libparserutils make 2> /dev/null && \ + BUILDDIR=$(BC_NS)/build/libparserutils make install && \ cd ../libhubbub && \ printf "\e[33mInstalling libhubbub...\e[0m\n" && \ - BUILDDIR=$(BC_NS)/build/libhubbub make 2> /dev/null && \ + BUILDDIR=$(BC_NS)/build/libhubbub make install && \ + rm src/treebuilder/autogenerated-element-type.c && \ cd ../libdom && \ printf "\e[33mInstalling libdom...\e[0m\n" && \ - BUILDDIR=$(BC_NS)/build/libdom make 2> /dev/null && \ + BUILDDIR=$(BC_NS)/build/libdom make install && \ printf "\e[33mRunning libdom example...\e[0m\n" && \ - cd include/dom && \ - rm -f bindings || true && \ - ln -s ../../bindings bindings && \ - cd ../../examples && \ - rm -f a.out || true && \ + cd examples && \ clang \ -I$(ICONV)/include \ - -I$(BC_NS)/libdom/include \ - -I$(BC_NS)/libparserutils/include \ - -I$(BC_NS)/libhubbub/include \ - -I$(BC_NS)/libwapcaplet/include \ + -I$(BC_NS)/include \ -L$(ICONV)/lib \ - -L$(BC_NS)/build/libdom \ - -L$(BC_NS)/build/libparserutils \ - -L$(BC_NS)/build/libhubbub \ - -L$(BC_NS)/build/libwapcaplet \ + -L$(BC_NS)/lib \ -liconv \ -ldom \ -lhubbub \ @@ -114,6 +105,7 @@ install-netsurf: -lwapcaplet \ dom-structure-dump.c && \ ./a.out > /dev/null && \ + rm a.out && \ printf "\e[36mDone NetSurf $(OS)\e[0m\n" From ef1ce6e8c2b93e0a5a20a28236116544966c5e9b Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 20 Sep 2023 22:44:02 +0200 Subject: [PATCH 05/21] Makefile: add clean-netsurf and test-netsurf Signed-off-by: Francis Bouvier --- Makefile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Makefile b/Makefile index d57f993e..0d62a01b 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,7 @@ test: # ------------ .PHONY: install-submodule .PHONY: install-lexbor install-jsruntime install-jsruntime-dev +.PHONY: install-netsurf clean-netsurf test-netsurf .PHONY: install-dev install ## Install and build dependencies for release @@ -108,6 +109,21 @@ install-netsurf: rm a.out && \ printf "\e[36mDone NetSurf $(OS)\e[0m\n" +clean-netsurf: + @printf "\e[36mCleaning NetSurf build...\e[0m\n" && \ + cd vendor/netsurf && \ + rm -R build && \ + rm -R lib && \ + rm -R include + +test-netsurf: + @printf "\e[36mTesting NetSurf...\e[0m\n" && \ + export PREFIX=$(BC_NS) && \ + export LDFLAGS="-L$(ICONV)/lib -L$(BC_NS)/lib" && \ + export CFLAGS="-I$(ICONV)/include -I$(BC_NS)/include" && \ + cd vendor/netsurf/libdom && \ + BUILDDIR=$(BC_NS)/build/libdom make test + install-lexbor: @mkdir -p vendor/lexbor From bb870559005d0dd68a4417a699fd138c9c0e477c Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 20 Sep 2023 22:45:39 +0200 Subject: [PATCH 06/21] build: adapt to zig 0.11 and use netsurf/include Signed-off-by: Francis Bouvier --- build.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index f2b22e02..5b9bdb74 100644 --- a/build.zig +++ b/build.zig @@ -100,8 +100,8 @@ fn linkNetSurf(step: *std.build.LibExeObjStep) void { } else if (os == .linux) { @panic("you need to modify build.zig to specify libiconv paths"); } - step.addObjectFile(iconv_lib); - step.addIncludePath(iconv_include); + step.addObjectFile(.{ .path = iconv_lib }); + step.addIncludePath(.{ .path = iconv_include }); // netsurf libs const ns = "vendor/netsurf/"; @@ -112,7 +112,7 @@ fn linkNetSurf(step: *std.build.LibExeObjStep) void { "libwapcaplet", }; inline for (libs) |lib| { - step.addObjectFile(ns ++ "/build/" ++ lib ++ "/" ++ lib ++ ".a"); - step.addIncludePath(ns ++ lib ++ "/include"); + step.addObjectFile(.{ .path = ns ++ "/lib/" ++ lib ++ ".a" }); } + step.addIncludePath(.{ .path = ns ++ "/include" }); } From f06d1396f7ef91cf9c469f872e40d95f71597be0 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 20 Sep 2023 22:48:44 +0200 Subject: [PATCH 07/21] netsurf: add wrapper Signed-off-by: Francis Bouvier --- build.zig | 6 +++ vendor/netsurf/wrapper/wrapper.c | 77 ++++++++++++++++++++++++++++++++ vendor/netsurf/wrapper/wrapper.h | 8 ++++ 3 files changed, 91 insertions(+) create mode 100644 vendor/netsurf/wrapper/wrapper.c create mode 100644 vendor/netsurf/wrapper/wrapper.h diff --git a/build.zig b/build.zig index 5b9bdb74..4e9cf6b9 100644 --- a/build.zig +++ b/build.zig @@ -115,4 +115,10 @@ fn linkNetSurf(step: *std.build.LibExeObjStep) void { step.addObjectFile(.{ .path = ns ++ "/lib/" ++ lib ++ ".a" }); } step.addIncludePath(.{ .path = ns ++ "/include" }); + + // wrapper + const flags = [_][]const u8{}; + const files: [1][]const u8 = .{ns ++ "wrapper/wrapper.c"}; + step.addCSourceFiles(&files, &flags); + step.addIncludePath(.{ .path = ns ++ "wrapper" }); } diff --git a/vendor/netsurf/wrapper/wrapper.c b/vendor/netsurf/wrapper/wrapper.c new file mode 100644 index 00000000..1f7c14bd --- /dev/null +++ b/vendor/netsurf/wrapper/wrapper.c @@ -0,0 +1,77 @@ +#include + +#include +#include + +/** + * Generate a LibDOM document DOM from an HTML file + * + * \param file The file path + * \return pointer to DOM document, or NULL on error + */ +dom_document *wr_create_doc_dom_from_file(char *filename) +{ + size_t buffer_size = 1024; + dom_hubbub_parser *parser = NULL; + FILE *handle; + int chunk_length; + dom_hubbub_error error; + dom_hubbub_parser_params params; + dom_document *doc; + unsigned char buffer[buffer_size]; + + params.enc = NULL; + params.fix_enc = true; + params.enable_script = false; + params.msg = NULL; + params.script = NULL; + params.ctx = NULL; + params.daf = NULL; + + /* Create Hubbub parser */ + error = dom_hubbub_parser_create(¶ms, &parser, &doc); + if (error != DOM_HUBBUB_OK) { + printf("Can't create Hubbub Parser\n"); + return NULL; + } + + /* Open input file */ + handle = fopen(filename, "rb"); + if (handle == NULL) { + dom_hubbub_parser_destroy(parser); + printf("Can't open test input file: %s\n", filename); + return NULL; + } + + /* Parse input file in chunks */ + chunk_length = buffer_size; + while (chunk_length == buffer_size) { + chunk_length = fread(buffer, 1, buffer_size, handle); + error = dom_hubbub_parser_parse_chunk(parser, buffer, + chunk_length); + if (error != DOM_HUBBUB_OK) { + dom_hubbub_parser_destroy(parser); + printf("Parsing errors occur\n"); + return NULL; + } + } + + /* Done parsing file */ + error = dom_hubbub_parser_completed(parser); + if (error != DOM_HUBBUB_OK) { + dom_hubbub_parser_destroy(parser); + printf("Parsing error when construct DOM\n"); + return NULL; + } + + /* Finished with parser */ + dom_hubbub_parser_destroy(parser); + + /* Close input file */ + if (fclose(handle) != 0) { + printf("Can't close test input file: %s\n", filename); + return NULL; + } + + return doc; +} diff --git a/vendor/netsurf/wrapper/wrapper.h b/vendor/netsurf/wrapper/wrapper.h new file mode 100644 index 00000000..05904ef1 --- /dev/null +++ b/vendor/netsurf/wrapper/wrapper.h @@ -0,0 +1,8 @@ +#ifndef wrapper_dom_h_ +#define wrapper_dom_h_ + +#include + +dom_document *wr_create_doc_dom_from_file(char *filename); + +#endif /* wrapper_dom_h_ */ From 26a38cc16ea9da3fb6222115f761da0e81936a55 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 20 Sep 2023 22:49:10 +0200 Subject: [PATCH 08/21] build: add netsurf private apis Signed-off-by: Francis Bouvier --- build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig b/build.zig index 4e9cf6b9..4ae1795f 100644 --- a/build.zig +++ b/build.zig @@ -113,6 +113,7 @@ fn linkNetSurf(step: *std.build.LibExeObjStep) void { }; inline for (libs) |lib| { step.addObjectFile(.{ .path = ns ++ "/lib/" ++ lib ++ ".a" }); + step.addIncludePath(.{ .path = ns ++ lib ++ "/src" }); } step.addIncludePath(.{ .path = ns ++ "/include" }); From 75e1b97cd6470a06edf1f0a0bd88ef8fb0295ef0 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 20 Sep 2023 22:49:55 +0200 Subject: [PATCH 09/21] netsurf: rename parser.zig to lexbor.zig Signed-off-by: Francis Bouvier --- src/{parser.zig => lexbor.zig} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{parser.zig => lexbor.zig} (100%) diff --git a/src/parser.zig b/src/lexbor.zig similarity index 100% rename from src/parser.zig rename to src/lexbor.zig From 766b7b4ed824e4acf871fffb45a8f3f7c95c3b3d Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 20 Sep 2023 23:04:16 +0200 Subject: [PATCH 10/21] netsurf: first adaptations Signed-off-by: Francis Bouvier --- src/dom/document.zig | 17 +++-------------- src/dom/element.zig | 2 +- src/dom/event_target.zig | 2 +- src/dom/node.zig | 2 +- src/html/document.zig | 15 ++++++++------- src/html/elements.zig | 6 +++--- src/main.zig | 8 ++++---- src/main_shell.zig | 8 ++++---- src/run_tests.zig | 9 +++------ 9 files changed, 28 insertions(+), 41 deletions(-) diff --git a/src/dom/document.zig b/src/dom/document.zig index 2d5558c3..d3622e78 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const parser = @import("../parser.zig"); +const parser = @import("../netsurf.zig"); const Node = @import("node.zig").Node; const Element = @import("element.zig").Element; @@ -15,19 +15,8 @@ pub const Document = struct { // return .{}; // } - pub fn getElementById(self: *parser.Document, elem: *parser.Element, id: []const u8) ?*parser.Element { - const collection = parser.collectionInit(self, 1); - defer parser.collectionDeinit(collection); - const case_sensitve = true; - parser.elementsByAttr(elem, collection, "id", id, case_sensitve) catch |err| { - std.debug.print("getElementById error: {s}\n", .{@errorName(err)}); - return null; - }; - if (collection.array.length == 0) { - // no results - return null; - } - return parser.collectionElement(collection, 0); + pub fn getElementById(self: *parser.Document, id: []const u8) ?*parser.Element { + return parser.documentGetElementById(self, id); } // JS funcs diff --git a/src/dom/element.zig b/src/dom/element.zig index 27e851a2..717da26a 100644 --- a/src/dom/element.zig +++ b/src/dom/element.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const parser = @import("../parser.zig"); +const parser = @import("../netsurf.zig"); const Node = @import("node.zig").Node; diff --git a/src/dom/event_target.zig b/src/dom/event_target.zig index 2e125aab..7d0fccdc 100644 --- a/src/dom/event_target.zig +++ b/src/dom/event_target.zig @@ -1,4 +1,4 @@ -const parser = @import("../parser.zig"); +const parser = @import("../netsurf.zig"); pub const EventTarget = struct { pub const Self = parser.EventTarget; diff --git a/src/dom/node.zig b/src/dom/node.zig index 6ad69380..da52b34f 100644 --- a/src/dom/node.zig +++ b/src/dom/node.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const parser = @import("../parser.zig"); +const parser = @import("../netsurf.zig"); const EventTarget = @import("event_target.zig").EventTarget; diff --git a/src/html/document.zig b/src/html/document.zig index 929cfcd8..51c59e28 100644 --- a/src/html/document.zig +++ b/src/html/document.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const parser = @import("../parser.zig"); +const parser = @import("../netsurf.zig"); const jsruntime = @import("jsruntime"); const Case = jsruntime.test_utils.Case; @@ -22,12 +22,13 @@ pub const HTMLDocument = struct { return parser.documentHTMLBody(self); } - pub fn _getElementById(self: *parser.DocumentHTML, id: []u8) ?*parser.HTMLElement { - const body_html = parser.documentHTMLBody(self); - const body_dom = @as(*parser.Element, @ptrCast(body_html)); - const doc_dom = @as(*parser.Document, @ptrCast(self)); - const elem_dom = Document.getElementById(doc_dom, body_dom, id); - return @as(*parser.HTMLElement, @ptrCast(elem_dom)); + pub fn _getElementById(self: *parser.DocumentHTML, id: []u8) ?*parser.ElementHTML { + const doc = parser.documentHTMLToDocument(self); + const elem = parser.documentGetElementById(doc, id); + if (elem) |value| { + return @as(*parser.ElementHTML, @ptrCast(value)); + } + return null; } pub fn _createElement(self: *parser.DocumentHTML, tag_name: []const u8) E.HTMLElements { diff --git a/src/html/elements.zig b/src/html/elements.zig index ba9f9653..056559b3 100644 --- a/src/html/elements.zig +++ b/src/html/elements.zig @@ -1,4 +1,4 @@ -const parser = @import("../parser.zig"); +const parser = @import("../netsurf.zig"); const generate = @import("../generate.zig"); const Element = @import("../dom/element.zig").Element; @@ -7,7 +7,7 @@ const Element = @import("../dom/element.zig").Element; // -------------- pub const HTMLElement = struct { - pub const Self = parser.HTMLElement; + pub const Self = parser.ElementHTML; pub const prototype = *Element; pub const mem_guarantied = true; }; @@ -455,7 +455,7 @@ pub const HTMLVideoElement = struct { }; pub fn ElementToHTMLElementInterface(elem: *parser.Element) HTMLElements { - const tag = parser.nodeTag(parser.elementNode(elem)); + const tag = parser.elementHTMLGetTagType(@as(*parser.ElementHTML, @ptrCast(elem))); return switch (tag) { .a => .{ .HTMLAnchorElement = @as(*parser.Anchor, @ptrCast(elem)) }, .area => .{ .HTMLAreaElement = @as(*parser.Area, @ptrCast(elem)) }, diff --git a/src/main.zig b/src/main.zig index 092ed443..fccb781b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,7 +2,7 @@ const std = @import("std"); const jsruntime = @import("jsruntime"); -const parser = @import("parser.zig"); +const parser = @import("netsurf.zig"); const DOM = @import("dom.zig"); const html_test = @import("html_test.zig").html; @@ -55,9 +55,6 @@ pub fn main() !void { defer vm.deinit(); // document - doc = parser.documentHTMLInit(); - defer parser.documentHTMLDeinit(doc); - try parser.documentHTMLParse(doc, html_test); // remove socket file of internal server // reuse_address (SO_REUSEADDR flag) does not seems to work on unix socket @@ -68,6 +65,9 @@ pub fn main() !void { return err; } }; + var f = "test.html".*; + doc = parser.documentHTMLParse(&f); + // TODO: defer doc? // alloc var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); diff --git a/src/main_shell.zig b/src/main_shell.zig index c7ce18f7..6d8b2819 100644 --- a/src/main_shell.zig +++ b/src/main_shell.zig @@ -2,7 +2,7 @@ const std = @import("std"); const jsruntime = @import("jsruntime"); -const parser = @import("parser.zig"); +const parser = @import("netsurf.zig"); const DOM = @import("dom.zig"); const html_test = @import("html_test.zig").html; @@ -32,9 +32,9 @@ pub fn main() !void { const apis = jsruntime.compile(DOM.Interfaces); // document - doc = parser.documentHTMLInit(); - defer parser.documentHTMLDeinit(doc); - try parser.documentHTMLParse(doc, html_test); + var f = "test.html".*; + doc = parser.documentHTMLParse(&f); + // TODO: defer doc? // create JS vm const vm = jsruntime.VM.init(); diff --git a/src/run_tests.zig b/src/run_tests.zig index ff579757..7bdff671 100644 --- a/src/run_tests.zig +++ b/src/run_tests.zig @@ -3,12 +3,10 @@ const std = @import("std"); const jsruntime = @import("jsruntime"); const generate = @import("generate.zig"); -const parser = @import("parser.zig"); +const parser = @import("netsurf.zig"); const DOM = @import("dom.zig"); const testExecFn = @import("html/document.zig").testExecFn; -const html_test = @import("html_test.zig").html; - var doc: *parser.DocumentHTML = undefined; fn testsExecFn( @@ -38,9 +36,8 @@ test { const apis = jsruntime.compile(DOM.Interfaces); // document - doc = parser.documentHTMLInit(); - defer parser.documentHTMLDeinit(doc); - try parser.documentHTMLParse(doc, html_test); + var f = "test.html".*; + doc = parser.documentHTMLParse(&f); // create JS vm const vm = jsruntime.VM.init(); From 95d04bb48e3a808d3a178d3beaa65ab5954dfd05 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 20 Sep 2023 23:04:55 +0200 Subject: [PATCH 11/21] netsurf: remove Node.make_tree Signed-off-by: Francis Bouvier --- src/dom/node.zig | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/dom/node.zig b/src/dom/node.zig index da52b34f..d5067c05 100644 --- a/src/dom/node.zig +++ b/src/dom/node.zig @@ -4,25 +4,8 @@ const parser = @import("../netsurf.zig"); const EventTarget = @import("event_target.zig").EventTarget; -pub fn create_tree(node: ?*parser.Node, _: ?*anyopaque) callconv(.C) parser.Action { - if (node == null) { - return parser.ActionStop; - } - const node_type = parser.nodeType(node.?); - const node_name = parser.nodeName(node.?); - std.debug.print("type: {any}, name: {s}\n", .{ node_type, node_name }); - if (node_type == parser.NodeType.element) { - std.debug.print("yes\n", .{}); - } - return parser.ActionOk; -} - pub const Node = struct { pub const Self = parser.Node; pub const prototype = *EventTarget; pub const mem_guarantied = true; - - pub fn make_tree(self: *parser.Node) !void { - try parser.nodeWalk(self, create_tree); - } }; From 5bfbaa1b774538d380ccd4d152f00e6d5050476e Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Wed, 20 Sep 2023 23:07:41 +0200 Subject: [PATCH 12/21] forgot netsurf zig API Signed-off-by: Francis Bouvier --- src/netsurf.zig | 369 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 src/netsurf.zig diff --git a/src/netsurf.zig b/src/netsurf.zig new file mode 100644 index 00000000..d60a2a5e --- /dev/null +++ b/src/netsurf.zig @@ -0,0 +1,369 @@ +const std = @import("std"); + +const cp = @cImport({ + @cInclude("wrapper.h"); +}); + +const c = @cImport({ + @cInclude("core/node.h"); + @cInclude("core/document.h"); + @cInclude("core/element.h"); + + @cInclude("html/html_document.h"); + @cInclude("html/html_element.h"); + @cInclude("html/html_anchor_element.h"); + @cInclude("html/html_area_element.h"); + @cInclude("html/html_br_element.h"); + @cInclude("html/html_base_element.h"); + @cInclude("html/html_body_element.h"); + @cInclude("html/html_button_element.h"); + @cInclude("html/html_canvas_element.h"); + @cInclude("html/html_dlist_element.h"); + @cInclude("html/html_div_element.h"); + @cInclude("html/html_fieldset_element.h"); + @cInclude("html/html_frameset_element.h"); + @cInclude("html/html_hr_element.h"); + @cInclude("html/html_head_element.h"); + @cInclude("html/html_heading_element.h"); + @cInclude("html/html_html_element.h"); + @cInclude("html/html_iframe_element.h"); + @cInclude("html/html_image_element.h"); + @cInclude("html/html_input_element.h"); + @cInclude("html/html_li_element.h"); + @cInclude("html/html_label_element.h"); + @cInclude("html/html_legend_element.h"); + @cInclude("html/html_link_element.h"); + @cInclude("html/html_map_element.h"); + @cInclude("html/html_meta_element.h"); + @cInclude("html/html_mod_element.h"); + @cInclude("html/html_olist_element.h"); + @cInclude("html/html_object_element.h"); + @cInclude("html/html_opt_group_element.h"); + @cInclude("html/html_option_element.h"); + @cInclude("html/html_paragraph_element.h"); + @cInclude("html/html_pre_element.h"); + @cInclude("html/html_quote_element.h"); + @cInclude("html/html_script_element.h"); + @cInclude("html/html_select_element.h"); + @cInclude("html/html_style_element.h"); + @cInclude("html/html_table_element.h"); + @cInclude("html/html_tablecell_element.h"); + @cInclude("html/html_tablecol_element.h"); + @cInclude("html/html_text_area_element.h"); + @cInclude("html/html_title_element.h"); + @cInclude("html/html_ulist_element.h"); +}); + +// Utils +const String = c.dom_string; + +inline fn stringToData(s: *String) []const u8 { + const data = c.dom_string_data(s); + return data[0..c.dom_string_byte_length(s)]; +} + +inline fn stringFromData(data: []const u8) *String { + var s: ?*String = null; + _ = c.dom_string_create(data.ptr, data.len, &s); + return s.?; +} + +// Tag + +pub const Tag = enum(u8) { + a = c.DOM_HTML_ELEMENT_TYPE_A, + area = c.DOM_HTML_ELEMENT_TYPE_AREA, + audio = c.DOM_HTML_ELEMENT_TYPE_AUDIO, + br = c.DOM_HTML_ELEMENT_TYPE_BR, + base = c.DOM_HTML_ELEMENT_TYPE_BASE, + body = c.DOM_HTML_ELEMENT_TYPE_BODY, + button = c.DOM_HTML_ELEMENT_TYPE_BUTTON, + canvas = c.DOM_HTML_ELEMENT_TYPE_CANVAS, + dl = c.DOM_HTML_ELEMENT_TYPE_DL, + dialog = c.DOM_HTML_ELEMENT_TYPE_DIALOG, + data = c.DOM_HTML_ELEMENT_TYPE_DATA, + div = c.DOM_HTML_ELEMENT_TYPE_DIV, + embed = c.DOM_HTML_ELEMENT_TYPE_EMBED, + fieldset = c.DOM_HTML_ELEMENT_TYPE_FIELDSET, + form = c.DOM_HTML_ELEMENT_TYPE_FORM, + frameset = c.DOM_HTML_ELEMENT_TYPE_FRAMESET, + hr = c.DOM_HTML_ELEMENT_TYPE_HR, + head = c.DOM_HTML_ELEMENT_TYPE_HEAD, + h1 = c.DOM_HTML_ELEMENT_TYPE_H1, + h2 = c.DOM_HTML_ELEMENT_TYPE_H2, + h3 = c.DOM_HTML_ELEMENT_TYPE_H3, + h4 = c.DOM_HTML_ELEMENT_TYPE_H4, + h5 = c.DOM_HTML_ELEMENT_TYPE_H5, + h6 = c.DOM_HTML_ELEMENT_TYPE_H6, + html = c.DOM_HTML_ELEMENT_TYPE_HTML, + iframe = c.DOM_HTML_ELEMENT_TYPE_IFRAME, + img = c.DOM_HTML_ELEMENT_TYPE_IMG, + input = c.DOM_HTML_ELEMENT_TYPE_INPUT, + li = c.DOM_HTML_ELEMENT_TYPE_LI, + label = c.DOM_HTML_ELEMENT_TYPE_LABEL, + legend = c.DOM_HTML_ELEMENT_TYPE_LEGEND, + link = c.DOM_HTML_ELEMENT_TYPE_LINK, + map = c.DOM_HTML_ELEMENT_TYPE_MAP, + meta = c.DOM_HTML_ELEMENT_TYPE_META, + meter = c.DOM_HTML_ELEMENT_TYPE_METER, + ins = c.DOM_HTML_ELEMENT_TYPE_INS, + del = c.DOM_HTML_ELEMENT_TYPE_DEL, + ol = c.DOM_HTML_ELEMENT_TYPE_OL, + object = c.DOM_HTML_ELEMENT_TYPE_OBJECT, + optgroup = c.DOM_HTML_ELEMENT_TYPE_OPTGROUP, + option = c.DOM_HTML_ELEMENT_TYPE_OPTION, + output = c.DOM_HTML_ELEMENT_TYPE_OUTPUT, + p = c.DOM_HTML_ELEMENT_TYPE_P, + picture = c.DOM_HTML_ELEMENT_TYPE_PICTURE, + pre = c.DOM_HTML_ELEMENT_TYPE_PRE, + progress = c.DOM_HTML_ELEMENT_TYPE_PROGRESS, + blockquote = c.DOM_HTML_ELEMENT_TYPE_BLOCKQUOTE, + q = c.DOM_HTML_ELEMENT_TYPE_Q, + script = c.DOM_HTML_ELEMENT_TYPE_SCRIPT, + select = c.DOM_HTML_ELEMENT_TYPE_SELECT, + source = c.DOM_HTML_ELEMENT_TYPE_SOURCE, + span = c.DOM_HTML_ELEMENT_TYPE_SPAN, + style = c.DOM_HTML_ELEMENT_TYPE_STYLE, + table = c.DOM_HTML_ELEMENT_TYPE_TABLE, + caption = c.DOM_HTML_ELEMENT_TYPE_CAPTION, + th = c.DOM_HTML_ELEMENT_TYPE_TH, + td = c.DOM_HTML_ELEMENT_TYPE_TD, + col = c.DOM_HTML_ELEMENT_TYPE_COL, + tr = c.DOM_HTML_ELEMENT_TYPE_TR, + thead = c.DOM_HTML_ELEMENT_TYPE_THEAD, + tbody = c.DOM_HTML_ELEMENT_TYPE_TBODY, + tfoot = c.DOM_HTML_ELEMENT_TYPE_TFOOT, + template = c.DOM_HTML_ELEMENT_TYPE_TEMPLATE, + textarea = c.DOM_HTML_ELEMENT_TYPE_TEXTAREA, + time = c.DOM_HTML_ELEMENT_TYPE_TIME, + title = c.DOM_HTML_ELEMENT_TYPE_TITLE, + track = c.DOM_HTML_ELEMENT_TYPE_TRACK, + ul = c.DOM_HTML_ELEMENT_TYPE_UL, + video = c.DOM_HTML_ELEMENT_TYPE_VIDEO, + undef = c.DOM_HTML_ELEMENT_TYPE__UNKNOWN, + + pub fn all() []Tag { + comptime { + const info = @typeInfo(Tag).Enum; + comptime var l: [info.fields.len]Tag = undefined; + inline for (info.fields, 0..) |field, i| { + l[i] = @as(Tag, @enumFromInt(field.value)); + } + return &l; + } + } + + pub fn allElements() [][]const u8 { + comptime { + const tags = all(); + var names: [tags.len][]const u8 = undefined; + inline for (tags, 0..) |tag, i| { + names[i] = tag.elementName(); + } + return &names; + } + } + + fn upperName(comptime name: []const u8) []const u8 { + comptime { + var upper_name: [name.len]u8 = undefined; + for (name, 0..) |char, i| { + var to_upper = false; + if (i == 0) { + to_upper = true; + } else if (i == 1 and name.len == 2) { + to_upper = true; + } + if (to_upper) { + upper_name[i] = std.ascii.toUpper(char); + } else { + upper_name[i] = char; + } + } + return &upper_name; + } + } + + fn elementName(comptime tag: Tag) []const u8 { + return switch (tag) { + .a => "Anchor", + .dl => "DList", + .fieldset => "FieldSet", + .frameset => "FrameSet", + .h1, .h2, .h3, .h4, .h5, .h6 => "Heading", + .iframe => "IFrame", + .img => "Image", + .ins, .del => "Mod", + .ol => "OList", + .optgroup => "OptGroup", + .p => "Paragraph", + .blockquote, .q => "Quote", + .caption => "TableCaption", + .th, .td => "TableCell", + .col => "TableCol", + .tr => "TableRow", + .thead, .tbody, .tfoot => "TableSection", + .textarea => "TextArea", + .ul => "UList", + .undef => "Unknown", + else => upperName(@tagName(tag)), + }; + } +}; + +// EventTarget +pub const EventTarget = c.dom_event_target; + +// Node +pub const Node = c.dom_node_internal; + +// Element +pub const Element = c.dom_element; + +pub fn elementLocalName(elem: *Element) []const u8 { + const elem_aligned: *align(8) Element = @alignCast(elem); + const node = @as(*Node, @ptrCast(elem_aligned)); + var s: ?*String = null; + _ = c._dom_node_get_local_name(node, &s); + var s_lower: ?*String = null; + _ = c.dom_string_tolower(s, true, &s_lower); + return stringToData(s_lower.?); +} + +// ElementHTML +pub const ElementHTML = c.dom_html_element; + +pub fn elementHTMLGetTagType(elem_html: *ElementHTML) Tag { + var tag_type: c.dom_html_element_type = undefined; + _ = c._dom_html_element_get_tag_type(elem_html, &tag_type); + return @as(Tag, @enumFromInt(tag_type)); +} + +// ElementsHTML + +pub const MediaElement = struct { base: c.dom_html_element }; + +pub const Unknown = struct { base: c.dom_html_element }; +pub const Anchor = c.dom_html_anchor_element; +pub const Area = c.dom_html_area_element; +pub const Audio = struct { base: c.dom_html_element }; +pub const BR = c.dom_html_br_element; +pub const Base = c.dom_html_base_element; +pub const Body = c.dom_html_body_element; +pub const Button = c.dom_html_button_element; +pub const Canvas = c.dom_html_canvas_element; +pub const DList = c.dom_html_dlist_element; +pub const Data = struct { base: c.dom_html_element }; +pub const Dialog = struct { base: c.dom_html_element }; +pub const Div = c.dom_html_div_element; +pub const Embed = struct { base: c.dom_html_element }; +pub const FieldSet = c.dom_html_field_set_element; +pub const Form = c.dom_html_form_element; +pub const FrameSet = c.dom_html_frame_set_element; +pub const HR = c.dom_html_hr_element; +pub const Head = c.dom_html_head_element; +pub const Heading = c.dom_html_heading_element; +pub const Html = c.dom_html_html_element; +pub const IFrame = c.dom_html_iframe_element; +pub const Image = c.dom_html_image_element; +pub const Input = c.dom_html_input_element; +pub const LI = c.dom_html_li_element; +pub const Label = c.dom_html_label_element; +pub const Legend = c.dom_html_legend_element; +pub const Link = c.dom_html_link_element; +pub const Map = c.dom_html_map_element; +pub const Meta = c.dom_html_meta_element; +pub const Meter = struct { base: c.dom_html_element }; +pub const Mod = c.dom_html_mod_element; +pub const OList = c.dom_html_olist_element; +pub const Object = c.dom_html_object_element; +pub const OptGroup = c.dom_html_opt_group_element; +pub const Option = c.dom_html_option_element; +pub const Output = struct { base: c.dom_html_element }; +pub const Paragraph = c.dom_html_paragraph_element; +pub const Picture = struct { base: c.dom_html_element }; +pub const Pre = c.dom_html_pre_element; +pub const Progress = struct { base: c.dom_html_element }; +pub const Quote = c.dom_html_quote_element; +pub const Script = c.dom_html_script_element; +pub const Select = c.dom_html_select_element; +pub const Source = struct { base: c.dom_html_element }; +pub const Span = struct { base: c.dom_html_element }; +pub const Style = c.dom_html_style_element; +pub const Table = c.dom_html_table_element; +pub const TableCaption = c.dom_html_table_caption_element; +pub const TableCell = c.dom_html_table_cell_element; +pub const TableCol = c.dom_html_table_col_element; +pub const TableRow = c.dom_html_table_row_element; +pub const TableSection = c.dom_html_table_section_element; +pub const Template = struct { base: c.dom_html_element }; +pub const TextArea = c.dom_html_text_area_element; +pub const Time = struct { base: c.dom_html_element }; +pub const Title = c.dom_html_title_element; +pub const Track = struct { base: c.dom_html_element }; +pub const UList = c.dom_html_u_list_element; +pub const Video = struct { base: c.dom_html_element }; + +// Document +pub const Document = c.dom_document; + +pub inline fn documentGetElementById(doc: *Document, id: []const u8) ?*Element { + var elem: ?*Element = null; + _ = c._dom_document_get_element_by_id(doc, stringFromData(id), &elem); + return elem; +} + +pub inline fn documentCreateElement(doc: *Document, tag_name: []const u8) *Element { + var elem: ?*Element = null; + _ = c._dom_html_document_create_element(doc, stringFromData(tag_name), &elem); + return elem.?; +} + +// DocumentHTML +pub const DocumentHTML = c.dom_html_document; + +pub fn documentHTMLParse(filename: []u8) *DocumentHTML { + const doc = cp.wr_create_doc_dom_from_file(filename.ptr); + if (doc == null) { + @panic("error parser"); + } + const doc_aligned: *align(@alignOf((DocumentHTML))) cp.dom_document = @alignCast(doc.?); + return @as(*DocumentHTML, @ptrCast(doc_aligned)); +} + +pub inline fn documentHTMLToDocument(doc_html: *DocumentHTML) *Document { + return @as(*Document, @ptrCast(doc_html)); +} + +pub inline fn documentHTMLBody(doc_html: *DocumentHTML) ?*Body { + var body: ?*ElementHTML = null; + _ = c._dom_html_document_get_body(doc_html, &body); + if (body) |value| { + return @as(*Body, @ptrCast(value)); + } + return null; +} + +// TODO: Old + +pub fn create_dom(filename: []u8) !void { + const doc = c.wr_create_doc_dom_from_file(filename.ptr); + if (doc == null) { + @panic("error parser"); + } + std.debug.print("doc: {any}\n", .{doc}); + const doc_html = @as(*DocumentHTML, @ptrCast(doc.?)); + + var root: ?*Element = null; + var exc = c.dom_document_get_document_element(doc, &root); + if (exc != c.DOM_NO_ERR) { + @panic("Exception raised for get_html_document_element"); + } + if (root == null) { + @panic("error root"); + } + std.debug.print("root: {any}\n", .{root}); + + const body = documentHTMLBody(doc_html); + std.debug.print("body: {any}\n", .{body}); +} From 8a9fbf03fb0c69a0ffcd3e9ed9131da76bd09cba Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Thu, 21 Sep 2023 15:20:55 +0200 Subject: [PATCH 13/21] netsurf: add other cInclude to avoid opaque types Signed-off-by: Francis Bouvier --- src/netsurf.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/netsurf.zig b/src/netsurf.zig index d60a2a5e..e2f6e83b 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -21,6 +21,7 @@ const c = @cImport({ @cInclude("html/html_dlist_element.h"); @cInclude("html/html_div_element.h"); @cInclude("html/html_fieldset_element.h"); + @cInclude("html/html_form_element.h"); @cInclude("html/html_frameset_element.h"); @cInclude("html/html_hr_element.h"); @cInclude("html/html_head_element.h"); @@ -47,8 +48,11 @@ const c = @cImport({ @cInclude("html/html_select_element.h"); @cInclude("html/html_style_element.h"); @cInclude("html/html_table_element.h"); + @cInclude("html/html_tablecaption_element.h"); @cInclude("html/html_tablecell_element.h"); @cInclude("html/html_tablecol_element.h"); + @cInclude("html/html_tablerow_element.h"); + @cInclude("html/html_tablesection_element.h"); @cInclude("html/html_text_area_element.h"); @cInclude("html/html_title_element.h"); @cInclude("html/html_ulist_element.h"); From 4708dbd6798167fc1dac76cfb746644ebd852f98 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Thu, 21 Sep 2023 17:06:27 +0200 Subject: [PATCH 14/21] netsurf: add test html file Signed-off-by: Francis Bouvier --- test.html | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 test.html diff --git a/test.html b/test.html new file mode 100644 index 00000000..cb54107e --- /dev/null +++ b/test.html @@ -0,0 +1,8 @@ +
+ OK +

+ +

+

And

+ +
From b5b4659c87aa059aa0706491d24f97a6a7b2ed10 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Thu, 21 Sep 2023 17:05:38 +0200 Subject: [PATCH 15/21] backport some node_lexbor modifications Signed-off-by: Francis Bouvier --- src/dom.zig | 14 ++-- src/dom/node.zig | 12 +++ src/generate.zig | 189 +++++++++++++++++++++++++++++------------- src/html/document.zig | 20 ++--- src/html/elements.zig | 10 +-- 5 files changed, 166 insertions(+), 79 deletions(-) diff --git a/src/dom.zig b/src/dom.zig index 6d481fe3..d0fcd42f 100644 --- a/src/dom.zig +++ b/src/dom.zig @@ -4,12 +4,13 @@ const Console = @import("jsruntime").Console; // DOM const EventTarget = @import("dom/event_target.zig").EventTarget; -const Node = @import("dom/node.zig").Node; +const N = @import("dom/node.zig"); const Element = @import("dom/element.zig").Element; const Document = @import("dom/document.zig").Document; // HTML pub const HTMLDocument = @import("html/document.zig").HTMLDocument; +const HTMLElem = @import("html/elements.zig"); const E = @import("html/elements.zig"); @@ -19,14 +20,15 @@ const interfaces = .{ // DOM EventTarget, - Node, + N.Node, + N.Types, Element, Document, // HTML HTMLDocument, - E.HTMLElement, - E.HTMLMediaElement, - E.HTMLElementsTypes, + HTMLElem.HTMLElement, + HTMLElem.HTMLMediaElement, + HTMLElem.Types, }; -pub const Interfaces = generate.TupleInst(generate.TupleT(interfaces), interfaces); +pub const Interfaces = generate.Tuple(interfaces); diff --git a/src/dom/node.zig b/src/dom/node.zig index d5067c05..f2daf427 100644 --- a/src/dom/node.zig +++ b/src/dom/node.zig @@ -1,11 +1,23 @@ const std = @import("std"); +const generate = @import("../generate.zig"); + const parser = @import("../netsurf.zig"); const EventTarget = @import("event_target.zig").EventTarget; +const HTMLDocument = @import("../html/document.zig").HTMLDocument; +const HTMLElem = @import("../html/elements.zig"); pub const Node = struct { pub const Self = parser.Node; pub const prototype = *EventTarget; pub const mem_guarantied = true; }; + +pub const Types = generate.Tuple(.{ + HTMLElem.Types, + HTMLDocument, +}); +const Generated = generate.Union.compile(Types); +pub const Union = Generated._union; +pub const Tags = Generated._enum; diff --git a/src/generate.zig b/src/generate.zig index 553197c9..36ec653e 100644 --- a/src/generate.zig +++ b/src/generate.zig @@ -1,13 +1,33 @@ const std = @import("std"); const builtin = @import("builtin"); +// Utils +// ----- + +fn itoa(comptime i: u8) ![]u8 { + var len: usize = undefined; + if (i < 10) { + len = 1; + } else if (i < 100) { + len = 2; + } else { + return error.GenerateTooMuchMembers; + } + var buf: [len]u8 = undefined; + return try std.fmt.bufPrint(buf[0..], "{d}", .{i}); +} + fn fmtName(comptime T: type) []const u8 { var it = std.mem.splitBackwards(u8, @typeName(T), "."); return it.first(); } +// Union +// ----- + // Generate a flatten tagged Union from various structs and union of structs // TODO: make this function more generic +// TODO: dedup pub const Union = struct { _enum: type, _union: type, @@ -152,38 +172,15 @@ pub const Union = struct { } }; -fn itoa(comptime i: u8) ![]u8 { - var len: usize = undefined; - if (i < 10) { - len = 1; - } else if (i < 100) { - len = 2; - } else { - return error.GenerateTooMuchMembers; - } - var buf: [len]u8 = undefined; - return try std.fmt.bufPrint(buf[0..], "{d}", .{i}); -} +// Tuple +// ----- -// Generate a flatten tuple type from various structs and tuple of structs. -// TODO: make this function more generic -pub fn TupleT(comptime tuple: anytype) type { - - // check types provided - const tuple_T = @TypeOf(tuple); - const tuple_info = @typeInfo(tuple_T); - if (tuple_info != .Struct or !tuple_info.Struct.is_tuple) { - @compileError("GenerateArgNotTuple"); - } - - const tuple_members = tuple_info.Struct.fields; - - // first iteration to get the total number of members - var members_nb = 0; - for (tuple_members) |member| { +fn tupleNb(comptime tuple: anytype) usize { + var nb = 0; + for (@typeInfo(@TypeOf(tuple)).Struct.fields) |member| { const member_T = @field(tuple, member.name); if (@TypeOf(member_T) == type) { - members_nb += 1; + nb += 1; } else { const member_info = @typeInfo(@TypeOf(member_T)); if (member_info != .Struct and !member_info.Struct.is_tuple) { @@ -194,14 +191,82 @@ pub fn TupleT(comptime tuple: anytype) type { @compileError("GenerateMemberTupleChildNotType"); } } - members_nb += member_info.Struct.fields.len; + nb += member_info.Struct.fields.len; } } + return nb; +} - // second iteration to generate the tuple type - var fields: [members_nb]std.builtin.Type.StructField = undefined; +fn tupleTypes(comptime nb: usize, comptime tuple: anytype) [nb]type { + var types: [nb]type = undefined; var done = 0; - while (done < members_nb) { + for (@typeInfo(@TypeOf(tuple)).Struct.fields) |member| { + const T = @field(tuple, member.name); + if (@TypeOf(T) == type) { + types[done] = T; + done += 1; + } else { + const info = @typeInfo(@TypeOf(T)); + for (info.Struct.fields) |field| { + types[done] = @field(T, field.name); + done += 1; + } + } + } + return types; +} + +fn isDup(comptime nb: usize, comptime list: [nb]type, comptime T: type, comptime i: usize) bool { + for (list, 0..) |item, index| { + if (i >= index) { + // check sequentially + continue; + } + if (T == item) { + return true; + } + } + return false; +} + +fn dedupIndexes(comptime nb: usize, comptime types: [nb]type) [nb]i32 { + var dedup_indexes: [nb]i32 = undefined; + for (types, 0..) |T, i| { + if (isDup(nb, types, T, i)) { + dedup_indexes[i] = -1; + } else { + dedup_indexes[i] = i; + } + } + return dedup_indexes; +} + +fn dedupNb(comptime nb: usize, comptime dedup_indexes: [nb]i32) usize { + var dedup_nb = 0; + for (dedup_indexes) |index| { + if (index != -1) { + dedup_nb += 1; + } + } + return dedup_nb; +} + +fn TupleT(comptime tuple: anytype) type { + @setEvalBranchQuota(100000); + + // logic + const nb = tupleNb(tuple); + const types = tupleTypes(nb, tuple); + const dedup_indexes = dedupIndexes(nb, types); + const dedup_nb = dedupNb(nb, dedup_indexes); + + // generate the tuple type + var fields: [dedup_nb]std.builtin.Type.StructField = undefined; + var done = 0; + for (dedup_indexes) |index| { + if (index == -1) { + continue; + } fields[done] = .{ .name = try itoa(done), .type = type, @@ -221,39 +286,36 @@ pub fn TupleT(comptime tuple: anytype) type { return @Type(std.builtin.Type{ .Struct = info }); } -// Instantiate a flatten tuple from various structs and tuple of structs -// You need to call first TupleT to generate the according type +// Create a flatten tuple from various structs and tuple of structs +// Duplicates will be removed. // TODO: make this function more generic -pub fn TupleInst(comptime T: type, comptime tuple: anytype) T { +pub fn Tuple(comptime tuple: anytype) TupleT(tuple) { // check types provided const tuple_T = @TypeOf(tuple); const tuple_info = @typeInfo(tuple_T); - const tuple_members = tuple_info.Struct.fields; + if (tuple_info != .Struct or !tuple_info.Struct.is_tuple) { + @compileError("GenerateArgNotTuple"); + } + + // generate the type + const T = TupleT(tuple); + + // logic + const nb = tupleNb(tuple); + const types = tupleTypes(nb, tuple); + const dedup_indexes = dedupIndexes(nb, types); // instantiate the tuple var t: T = undefined; var done = 0; - for (tuple_members) |member| { - const member_T = @field(tuple, member.name); - var member_info: std.builtin.Type = undefined; - if (@TypeOf(member_T) == type) { - member_info = @typeInfo(member_T); - } else { - member_info = @typeInfo(@TypeOf(member_T)); - } - var member_detail = member_info.Struct; - if (member_detail.is_tuple) { - for (member_detail.fields) |field| { - const name = try itoa(done); - @field(t, name) = @field(member_T, field.name); - done += 1; - } - } else { - const name = try itoa(done); - @field(t, name) = @field(tuple, member.name); - done += 1; + for (dedup_indexes) |index| { + if (index == -1) { + continue; } + const name = try itoa(done); + @field(t, name) = types[index]; + done += 1; } return t; } @@ -322,7 +384,7 @@ pub fn tests() !void { // Tuple from structs const tuple_structs = .{ Astruct, Bstruct }; - const tFromStructs = TupleInst(TupleT(tuple_structs), tuple_structs); + const tFromStructs = Tuple(tuple_structs); const t_from_structs = @typeInfo(@TypeOf(tFromStructs)); try std.testing.expect(t_from_structs == .Struct); try std.testing.expect(t_from_structs.Struct.is_tuple); @@ -332,7 +394,7 @@ pub fn tests() !void { // Tuple from tuple and structs const tuple_mix = .{ tFromStructs, Cstruct }; - const tFromMix = TupleInst(TupleT(tuple_mix), tuple_mix); + const tFromMix = Tuple(tuple_mix); const t_from_mix = @typeInfo(@TypeOf(tFromMix)); try std.testing.expect(t_from_mix == .Struct); try std.testing.expect(t_from_mix.Struct.is_tuple); @@ -341,5 +403,16 @@ pub fn tests() !void { try std.testing.expect(@field(tFromMix, "1") == Bstruct); try std.testing.expect(@field(tFromMix, "2") == Cstruct); + // Tuple with dedup + const tuple_dedup = .{ Cstruct, Astruct, tFromStructs, Bstruct }; + const tFromDedup = Tuple(tuple_dedup); + const t_from_dedup = @typeInfo(@TypeOf(tFromDedup)); + try std.testing.expect(t_from_dedup == .Struct); + try std.testing.expect(t_from_dedup.Struct.is_tuple); + try std.testing.expect(t_from_dedup.Struct.fields.len == 3); + try std.testing.expect(@field(tFromDedup, "0") == Cstruct); + try std.testing.expect(@field(tFromDedup, "1") == Astruct); + try std.testing.expect(@field(tFromDedup, "2") == Bstruct); + std.debug.print("Generate Tuple: OK\n", .{}); } diff --git a/src/html/document.zig b/src/html/document.zig index 51c59e28..8738d307 100644 --- a/src/html/document.zig +++ b/src/html/document.zig @@ -7,8 +7,7 @@ const Case = jsruntime.test_utils.Case; const checkCases = jsruntime.test_utils.checkCases; const Document = @import("../dom/document.zig").Document; - -const E = @import("elements.zig"); +const HTMLElem = @import("elements.zig"); pub const HTMLDocument = struct { pub const Self = parser.DocumentHTML; @@ -22,19 +21,19 @@ pub const HTMLDocument = struct { return parser.documentHTMLBody(self); } - pub fn _getElementById(self: *parser.DocumentHTML, id: []u8) ?*parser.ElementHTML { + pub fn _getElementById(self: *parser.DocumentHTML, id: []u8) ?HTMLElem.Union { const doc = parser.documentHTMLToDocument(self); - const elem = parser.documentGetElementById(doc, id); - if (elem) |value| { - return @as(*parser.ElementHTML, @ptrCast(value)); + const elem_dom = parser.documentGetElementById(doc, id); + if (elem_dom) |elem| { + return HTMLElem.toInterface(HTMLElem.Union, elem); } return null; } - pub fn _createElement(self: *parser.DocumentHTML, tag_name: []const u8) E.HTMLElements { + pub fn _createElement(self: *parser.DocumentHTML, tag_name: []const u8) HTMLElem.Union { const doc_dom = parser.documentHTMLToDocument(self); const base = parser.documentCreateElement(doc_dom, tag_name); - return E.ElementToHTMLElementInterface(base); + return HTMLElem.toInterface(HTMLElem.Union, base); } }; @@ -51,13 +50,14 @@ pub fn testExecFn( .{ .src = "document.__proto__.__proto__.constructor.name", .ex = "Document" }, .{ .src = "document.__proto__.__proto__.__proto__.constructor.name", .ex = "Node" }, .{ .src = "document.__proto__.__proto__.__proto__.__proto__.constructor.name", .ex = "EventTarget" }, + .{ .src = "document.body.localName === 'body'", .ex = "true" }, }; try checkCases(js_env, &constructor); var getElementById = [_]Case{ .{ .src = "let getElementById = document.getElementById('content')", .ex = "undefined" }, - .{ .src = "getElementById.constructor.name", .ex = "HTMLElement" }, - .{ .src = "getElementById.localName", .ex = "main" }, + .{ .src = "getElementById.constructor.name", .ex = "HTMLDivElement" }, + .{ .src = "getElementById.localName", .ex = "div" }, }; try checkCases(js_env, &getElementById); diff --git a/src/html/elements.zig b/src/html/elements.zig index 056559b3..012bec3d 100644 --- a/src/html/elements.zig +++ b/src/html/elements.zig @@ -12,7 +12,7 @@ pub const HTMLElement = struct { pub const mem_guarantied = true; }; -pub const HTMLElementsTypes = .{ +pub const Types = .{ HTMLUnknownElement, HTMLAnchorElement, HTMLAreaElement, @@ -74,9 +74,9 @@ pub const HTMLElementsTypes = .{ HTMLUListElement, HTMLVideoElement, }; -const HTMLElementsGenerated = generate.Union.compile(HTMLElementsTypes); -pub const HTMLElements = HTMLElementsGenerated._union; -pub const HTMLElementsTags = HTMLElementsGenerated._enum; +const Generated = generate.Union.compile(Types); +pub const Union = Generated._union; +pub const Tags = Generated._enum; // Deprecated HTMLElements in Chrome (2023/03/15) // HTMLContentelement @@ -454,7 +454,7 @@ pub const HTMLVideoElement = struct { pub const mem_guarantied = true; }; -pub fn ElementToHTMLElementInterface(elem: *parser.Element) HTMLElements { +pub fn toInterface(comptime T: type, elem: *parser.Element) T { const tag = parser.elementHTMLGetTagType(@as(*parser.ElementHTML, @ptrCast(elem))); return switch (tag) { .a => .{ .HTMLAnchorElement = @as(*parser.Anchor, @ptrCast(elem)) }, From d7fec31b8a80c1cc7a3653756ddf6a29c9aa7f01 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Fri, 22 Sep 2023 16:10:22 +0200 Subject: [PATCH 16/21] build libiconv from sources --- .gitignore | 3 ++- Makefile | 25 ++++++++++++++++--------- README.md | 10 +++++++++- build.zig | 13 ++----------- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index b69e598b..a5e9840f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ zig-out /vendor/lexbor/ /vendor/netsurf/build/ /vendor/netsurf/lib/ -/vendor/netsurf/include/ \ No newline at end of file +/vendor/netsurf/include/ +/vendor/libiconv/ diff --git a/Makefile b/Makefile index 0d62a01b..0668f854 100644 --- a/Makefile +++ b/Makefile @@ -55,30 +55,28 @@ test: # Install and build required dependencies commands # ------------ .PHONY: install-submodule -.PHONY: install-lexbor install-jsruntime install-jsruntime-dev +.PHONY: install-lexbor install-jsruntime install-jsruntime-dev install-libiconv .PHONY: install-netsurf clean-netsurf test-netsurf .PHONY: install-dev install ## Install and build dependencies for release -install: install-submodule install-lexbor install-jsruntime +install: install-submodule install-lexbor install-jsruntime install-netsurf ## Install and build dependencies for dev -install-dev: install-submodule install-lexbor install-jsruntime-dev +install-dev: install-submodule install-lexbor install-jsruntime-dev install-netsurf BC_NS := $(BC)vendor/netsurf UNAME_S := $(shell uname -s) -ifeq ($(UNAME_S), Darwin) - ICONV := /opt/homebrew/opt/libiconv -endif +ICONV := $(BC)vendor/libiconv # TODO: add Linux iconv path (I guess it depends on the distro) # TODO: this way of linking libiconv is not ideal. We should have a more generic way # and stick to a specif version. Maybe build from source. Anyway not now. -install-netsurf: +install-netsurf: install-libiconv @printf "\e[36mInstalling NetSurf...\e[0m\n" && \ ls $(ICONV) 1> /dev/null || (printf "\e[33mERROR: you need to install libiconv in your system (on MacOS on with Homebrew)\e[0m\n"; exit 1;) && \ export PREFIX=$(BC_NS) && \ - export LDFLAGS="-L$(ICONV)/lib" && \ - export CFLAGS="-I$(ICONV)/include" && \ + export OPTLDFLAGS="-L$(ICONV)/lib" && \ + export OPTCFLAGS="-I$(ICONV)/include" && \ printf "\e[33mInstalling libwapcaplet...\e[0m\n" && \ cd vendor/netsurf/libwapcaplet && \ BUILDDIR=$(BC_NS)/build/libwapcaplet make install && \ @@ -124,6 +122,15 @@ test-netsurf: cd vendor/netsurf/libdom && \ BUILDDIR=$(BC_NS)/build/libdom make test +install-libiconv: +ifeq ("$(wildcard vendor/libiconv/lib/libiconv.a)","") + @mkdir -p vendor/libiconv + @cd vendor/libiconv && \ + curl https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.17.tar.gz | tar -xvzf - + @cd vendor/libiconv/libiconv-1.17 && \ + ./configure --prefix=$(BC)vendor/libiconv --enable-static && \ + make && make install +endif install-lexbor: @mkdir -p vendor/lexbor diff --git a/README.md b/README.md index 241f5be9..617d9d08 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ For Debian/Ubuntu based Linux: sudo apt install xz-utils \ python3 ca-certificates git \ pkg-config libglib2.0-dev \ - cmake + libexpat1-dev \ + cmake clang ``` For MacOS, you only need Python 3 and cmake. @@ -35,6 +36,13 @@ directory. make install-submodule ``` +### Build netsurf + +The command `make install-netsurf` will build netsurf libs used by browsercore. +``` +make install-netsurf +``` + ### Build lexbor The command `make install-lexbor` will build lexbor lib used by browsercore. diff --git a/build.zig b/build.zig index 4ae1795f..ed3f9e25 100644 --- a/build.zig +++ b/build.zig @@ -91,17 +91,8 @@ fn linkLexbor(step: *std.build.LibExeObjStep) void { fn linkNetSurf(step: *std.build.LibExeObjStep) void { // iconv - var iconv_lib: []const u8 = undefined; - var iconv_include: []const u8 = undefined; - const os = step.target.getOsTag(); - if (os == .macos) { - iconv_lib = "/opt/homebrew/opt/libiconv/lib/libiconv.a"; - iconv_include = "/opt/homebrew/opt/libiconv/include"; - } else if (os == .linux) { - @panic("you need to modify build.zig to specify libiconv paths"); - } - step.addObjectFile(.{ .path = iconv_lib }); - step.addIncludePath(.{ .path = iconv_include }); + step.addObjectFile(.{ .path = "vendor/libiconv/lib/libiconv.a" }); + step.addIncludePath(.{ .path = "vendor/libiconv/include" }); // netsurf libs const ns = "vendor/netsurf/"; From f5a1279d52f22b39d36336fcf67ddfd2093f46bd Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Fri, 22 Sep 2023 16:13:15 +0200 Subject: [PATCH 17/21] gperf is required by netsurf to compile --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 617d9d08..1bc4e01d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ For Debian/Ubuntu based Linux: sudo apt install xz-utils \ python3 ca-certificates git \ pkg-config libglib2.0-dev \ - libexpat1-dev \ + gperf libexpat1-dev \ cmake clang ``` From 59b5e0a58385549ea6b66b91c0302519707a8a26 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Mon, 25 Sep 2023 09:56:32 +0200 Subject: [PATCH 18/21] netsurf: use zigg cc to compile statically libdom example --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0668f854..0b1cba85 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,7 @@ install-netsurf: install-libiconv BUILDDIR=$(BC_NS)/build/libdom make install && \ printf "\e[33mRunning libdom example...\e[0m\n" && \ cd examples && \ - clang \ + zig cc \ -I$(ICONV)/include \ -I$(BC_NS)/include \ -L$(ICONV)/lib \ @@ -102,7 +102,9 @@ install-netsurf: install-libiconv -lhubbub \ -lparserutils \ -lwapcaplet \ - dom-structure-dump.c && \ + -o a.out \ + dom-structure-dump.c \ + $(ICONV)/lib/libiconv.a && \ ./a.out > /dev/null && \ rm a.out && \ printf "\e[36mDone NetSurf $(OS)\e[0m\n" From 725675636a7f609c034c88cd7aa921f0e27c223e Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Mon, 25 Sep 2023 13:43:40 +0200 Subject: [PATCH 19/21] Update jsruntime Signed-off-by: Francis Bouvier --- vendor/jsruntime-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/jsruntime-lib b/vendor/jsruntime-lib index 4d19129b..1dbd2349 160000 --- a/vendor/jsruntime-lib +++ b/vendor/jsruntime-lib @@ -1 +1 @@ -Subproject commit 4d19129bb77f8a912727fe25638f4980949570fb +Subproject commit 1dbd2349f980817317d54daba1ce9cb3653ab148 From 02025998c956581f9587ff578716790e7267a6c9 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Mon, 25 Sep 2023 16:40:31 +0200 Subject: [PATCH 20/21] netsurf: use undefined instead of null for C pointers declarations Signed-off-by: Francis Bouvier --- src/netsurf.zig | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/src/netsurf.zig b/src/netsurf.zig index e2f6e83b..e0ae2e7d 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -312,13 +312,13 @@ pub const Video = struct { base: c.dom_html_element }; pub const Document = c.dom_document; pub inline fn documentGetElementById(doc: *Document, id: []const u8) ?*Element { - var elem: ?*Element = null; + var elem: ?*Element = undefined; _ = c._dom_document_get_element_by_id(doc, stringFromData(id), &elem); return elem; } pub inline fn documentCreateElement(doc: *Document, tag_name: []const u8) *Element { - var elem: ?*Element = null; + var elem: ?*Element = undefined; _ = c._dom_html_document_create_element(doc, stringFromData(tag_name), &elem); return elem.?; } @@ -340,34 +340,10 @@ pub inline fn documentHTMLToDocument(doc_html: *DocumentHTML) *Document { } pub inline fn documentHTMLBody(doc_html: *DocumentHTML) ?*Body { - var body: ?*ElementHTML = null; + var body: ?*ElementHTML = undefined; _ = c._dom_html_document_get_body(doc_html, &body); if (body) |value| { return @as(*Body, @ptrCast(value)); } return null; } - -// TODO: Old - -pub fn create_dom(filename: []u8) !void { - const doc = c.wr_create_doc_dom_from_file(filename.ptr); - if (doc == null) { - @panic("error parser"); - } - std.debug.print("doc: {any}\n", .{doc}); - const doc_html = @as(*DocumentHTML, @ptrCast(doc.?)); - - var root: ?*Element = null; - var exc = c.dom_document_get_document_element(doc, &root); - if (exc != c.DOM_NO_ERR) { - @panic("Exception raised for get_html_document_element"); - } - if (root == null) { - @panic("error root"); - } - std.debug.print("root: {any}\n", .{root}); - - const body = documentHTMLBody(doc_html); - std.debug.print("body: {any}\n", .{body}); -} From e06922df75d0563bc69d338eb98e1baeb64f3c15 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Mon, 25 Sep 2023 16:41:32 +0200 Subject: [PATCH 21/21] generate: return const string in itoa utils Signed-off-by: Francis Bouvier --- src/generate.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generate.zig b/src/generate.zig index 36ec653e..8814eaa5 100644 --- a/src/generate.zig +++ b/src/generate.zig @@ -4,7 +4,7 @@ const builtin = @import("builtin"); // Utils // ----- -fn itoa(comptime i: u8) ![]u8 { +fn itoa(comptime i: u8) ![]const u8 { var len: usize = undefined; if (i < 10) { len = 1;