Skip to content

Commit

Permalink
Add ada-url dependency, initial impl of jsg::Url
Browse files Browse the repository at this point in the history
This will serve as the new underlying implementation of the
url-standard.{h|c++} class while also supporting handling of
module import specifiers as URLs.
  • Loading branch information
jasnell committed Oct 11, 2023
1 parent ea8b70b commit aaf0904
Show file tree
Hide file tree
Showing 12 changed files with 1,543 additions and 0 deletions.
1 change: 1 addition & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ build:windows --per_file_copt='external/ssl/src/crypto/poly1305/poly1305_vec\.c@
build:windows --per_file_copt='external/v8/src/objects/literal-objects\.cc@-imsvcC:\\Program Files\\LLVM\\lib\\clang\\16.0.6\\include' --host_per_file_copt='external/v8/src/objects/literal-objects.cc@-imsvcC:\\Program Files\\LLVM\\lib\\clang\\16.0.6\\include'
build:windows --per_file_copt='external/v8/src/runtime/runtime-object\.cc@-imsvcC:\\Program Files\\LLVM\\lib\\clang\\16.0.6\\include' --host_per_file_copt='external/v8/src/runtime/runtime-object.cc@-imsvcC:\\Program Files\\LLVM\\lib\\clang\\16.0.6\\include'
build:windows --per_file_copt='external/v8/src/objects/swiss-name-dictionary\.cc@-imsvcC:\\Program Files\\LLVM\\lib\\clang\\16.0.6\\include' --host_per_file_copt='external/v8/src/objects/swiss-name-dictionary.cc@-imsvcC:\\Program Files\\LLVM\\lib\\clang\\16.0.6\\include'
build:windows --per_file_copt='external/ada-url/ada\.cpp@-imsvcC:\\Program Files\\LLVM\\lib\\clang\\16.0.6\\include' --host_per_file_copt='external/ada-url/ada\.cpp@-imsvcC:\\Program Files\\LLVM\\lib\\clang\\16.0.6\\include'

# enable clang coverage: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
build:clang-coverage --copt="-fprofile-instr-generate" --linkopt="-fprofile-instr-generate"
Expand Down
1 change: 1 addition & 0 deletions .github/secret_scanning.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
paths-ignore:
- "src/workerd/api/node/crypto_keys-test.js"
- "src/workerd/api/node/crypto_dh-test.js"
- "src/workerd/jsg/url-test-corpus-success.h"
10 changes: 10 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ http_archive(
urls = ["https://github.com/google/brotli/tarball/ec107cf015139c791f79afac0f96c3a2c45e157f"],
)

http_archive(
name = "ada-url",
build_file = "//:build/BUILD.ada-url",
sha256 = "d6be6a559745a79be191bc63c1190015c702a30bacad10028d32b479644a0785",
type = "zip",
url = "https://github.com/ada-url/ada/releases/download/v2.7.0/singleheader.zip",
patches = [],
patch_args = ["-p1"],
)

# ========================================================================================
# Dawn
#
Expand Down
12 changes: 12 additions & 0 deletions build/BUILD.ada-url
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

cc_library(
name = "ada-url",
hdrs = ["ada.h", "ada_c.h"],
srcs = ["ada.cpp"],
visibility = ["//visibility:public"],
include_prefix = ".",
copts = ["-w"],
defines = [
"ADA_SSE2=1"
]
)
2 changes: 2 additions & 0 deletions compile_flags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
-nostdinc
-Ibazel-bin/external/com_googlesource_chromium_base_trace_event_common/_virtual_includes/trace_event_common
-Ibazel-bin/external/dawn/include
-Ibazel-bin/external/ada-url/_virtual_includes/ada-url/
-Ibazel-bin/external/com_cloudflare_lol_html/_virtual_includes/lolhtml
-Iexternal/com_google_benchmark/include/
-Iexternal/dawn/include
-Iexternal/ada-url/
-Isrc
-isystem/usr/include
-isystem/usr/include/x86_64-linux-gnu
Expand Down
12 changes: 12 additions & 0 deletions src/workerd/jsg/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ wd_cc_library(
":exception",
":modules_capnp",
":observer",
":url",
"//src/workerd/util",
"//src/workerd/util:sentry",
"//src/workerd/util:thread-scopes",
Expand All @@ -34,6 +35,17 @@ wd_cc_library(
],
)

wd_cc_library(
name = "url",
srcs = ["url.c++"],
hdrs = ["url.h"],
visibility = ["//visibility:public"],
deps = [
"@capnp-cpp//src/kj",
"@ada-url",
],
)

wd_cc_library(
name = "exception",
srcs = ["exception.c++"],
Expand Down
1 change: 1 addition & 0 deletions src/workerd/jsg/jsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -2333,3 +2333,4 @@ inline v8::Local<v8::Context> JsContext<T>::getHandle(Lock& js) {
#include "function.h"
#include "iterator.h"
#include "jsvalue.h"
#include "url.h"
273 changes: 273 additions & 0 deletions src/workerd/jsg/url-test-corpus-failures.h

Large diffs are not rendered by default.

549 changes: 549 additions & 0 deletions src/workerd/jsg/url-test-corpus-success.h

Large diffs are not rendered by default.

104 changes: 104 additions & 0 deletions src/workerd/jsg/url-test.c++
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) 2017-2022 Cloudflare, Inc.
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
// https://opensource.org/licenses/Apache-2.0

#include "jsg-test.h"
#include "url.h"
#include <kj/table.h>

namespace workerd::jsg::test {
namespace {

KJ_TEST("Basics") {
Url theUrl = nullptr;
KJ_IF_SOME(url, Url::tryParse("http://example.org:81"_kj)) {
KJ_ASSERT(url.getOrigin() == "http://example.org:81"_kj);
KJ_ASSERT(url.getHref() == "http://example.org:81/"_kj);
KJ_ASSERT(url.getProtocol() == "http:"_kj);
KJ_ASSERT(url.getHostname() == "example.org"_kj);
KJ_ASSERT(url.getHost() == "example.org:81"_kj);
KJ_ASSERT(url.getPort() == "81"_kj);
KJ_ASSERT(url.getPathname() == "/"_kj);
KJ_ASSERT(url.getSchemeType() == Url::SchemeType::HTTP);
KJ_ASSERT(url.getHostType() == Url::HostType::DEFAULT);
KJ_ASSERT(url.getUsername() == ""_kj);
KJ_ASSERT(url.getPassword() == ""_kj);
KJ_ASSERT(url.getHash() == ""_kj);
KJ_ASSERT(url.getSearch() == ""_kj);

theUrl = url.clone();
KJ_ASSERT(theUrl == url);
theUrl = kj::mv(url);

auto res = KJ_ASSERT_NONNULL(theUrl.resolve("abc"_kj));
KJ_ASSERT(res.getHref() == "http://example.org:81/abc"_kj);

// jsg::Urls support KJ_STRINGIFY
KJ_ASSERT(kj::str(res) == "http://example.org:81/abc");

// jsg::Urls are suitable to be used as keys in a hashset, hashmap
kj::HashSet<Url> urls;
urls.insert(res.clone());
KJ_ASSERT(urls.contains(res));

kj::HashMap<Url, int> urlmap;
urlmap.insert(res.clone(), 1);
KJ_ASSERT(KJ_ASSERT_NONNULL(urlmap.find(res)) == 1);
} else {
KJ_FAIL_ASSERT("url could not be parsed");
}

KJ_ASSERT(Url::idnToAscii("täst.de"_kj) == "xn--tst-qla.de"_kj);
KJ_ASSERT(Url::idnToUnicode("xn--tst-qla.de"_kj) == "täst.de"_kj);
}

KJ_TEST("Non-special URL") {
auto url = KJ_ASSERT_NONNULL(Url::tryParse("abc://123"_kj));
KJ_ASSERT(url.getOrigin() == "null"_kj);
KJ_ASSERT(url.getProtocol() == "abc:"_kj);
}

KJ_TEST("Invalid Urls") {
#include "url-test-corpus-failures.h"
}

void test(kj::StringPtr input,
kj::Maybe<kj::StringPtr> base,
kj::StringPtr href) {
KJ_ASSERT(Url::canParse(input, base));
auto url = KJ_ASSERT_NONNULL(Url::tryParse(input, base));
KJ_ASSERT(url.getHref() == href);
}

KJ_TEST("Valid Urls") {
KJ_ASSERT_NONNULL(Url::tryParse(""_kj, "http://example.org"_kj));
#include "url-test-corpus-success.h"
}

KJ_TEST("Search params (1)") {
UrlSearchParams params;
params.append("foo"_kj, "bar"_kj);
KJ_ASSERT(params.toStr() == "foo=bar"_kj);
}

KJ_TEST("Search params (2)") {
auto params = KJ_ASSERT_NONNULL(UrlSearchParams::tryParse("foo=bar&a=b&a=c"_kj));
KJ_ASSERT(params.has("a"_kj));
KJ_ASSERT(params.has("foo"_kj, kj::Maybe("bar"_kj)));
KJ_ASSERT(!params.has("foo"_kj, kj::Maybe("baz"_kj)));
KJ_ASSERT(KJ_ASSERT_NONNULL(params.get("a"_kj)) == "b"_kj);

auto all = params.getAll("a"_kj);
KJ_ASSERT(all.size() == 2);
KJ_ASSERT(all[0] == "b"_kj);
KJ_ASSERT(all[1] == "c"_kj);

params.delete_("foo"_kj);
params.delete_("a"_kj, kj::Maybe("c"_kj));

params.set("a"_kj, "z"_kj);
KJ_ASSERT(kj::str(params) == "a=z");
}

} // namespace
} // namespace workerd::jsg::test
Loading

0 comments on commit aaf0904

Please sign in to comment.