-
Notifications
You must be signed in to change notification settings - Fork 30.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
src: implement whatwg's URLPattern spec #56452
base: main
Are you sure you want to change the base?
Conversation
Review requested:
|
@@ -24,4 +24,4 @@ for (const item of items) { | |||
leaks.push(item); | |||
} | |||
|
|||
assert.deepStrictEqual(leaks, []); | |||
assert.deepStrictEqual(leaks, ['URLPattern']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@legendecas Is this correct? How can I make sure it is not exposed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The interfaces exposed in lib/internal/bootstrap/web/exposed-wildcard.js
should be annotated in the WebIDL as [Exposed=*]
.
https://urlpattern.spec.whatwg.org/#urlpattern-class defines that URLPattern
is annotated as [Exposed=(Window,Worker)]
, so it should be exposed in lib/internal/bootstrap/web/exposed-window-or-worker.js
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reminds why not exposing URLPattern
as [Exposed=*]
. whatwg/urlpattern#236 is the pending work to do it.
Can you elaborate? libuv is a C library so I don't think exceptions exist there, and I'm pretty sure V8 is built with exceptions disabled. |
My bad UV does not enable exceptions. Referencing v8.gyp file:
|
This is not really V8. It's a build-time executable (torque) used to generate code for V8 |
ada::url_pattern_options options{}; | ||
Local<Value> ignore_case; | ||
if (obj->Get(env->context(), | ||
FIXED_ONE_BYTE_STRING(env->isolate(), "ignoreCase")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider adding to env-properties.h
|
||
MaybeLocal<Value> URLPattern::Hash() const { | ||
auto context = env()->context(); | ||
return ToV8Value(context, url_pattern_.get_hash()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the key challenge here is that this will copy the string on every call. Any chance of memoizing the string once created.
src/node_url_pattern.cc
Outdated
URLPattern::URLPattern(Environment* env, | ||
Local<Object> object, | ||
ada::url_pattern&& url_pattern) | ||
: BaseObject(env, object) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We likely should introduce this as experimental in the first release, even if it graduates from experimental quickly. There should likely be a warning emitted on the first construction.
@@ -1571,6 +1572,7 @@ module.exports = { | |||
toPathIfFileURL, | |||
installObjectURLMethods, | |||
URL, | |||
URLPattern, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs docs added.
if (!url_pattern->Protocol().ToLocal(&result)) { | ||
return; | ||
} | ||
info.GetReturnValue().Set(result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!url_pattern->Protocol().ToLocal(&result)) { | |
return; | |
} | |
info.GetReturnValue().Set(result); | |
if (url_pattern->Protocol().ToLocal(&result)) { | |
info.GetReturnValue().Set(result); | |
} |
a bit more compact to invert the checks on these.
void URLPattern::New(const FunctionCallbackInfo<Value>& args) { | ||
Environment* env = Environment::GetCurrent(args); | ||
|
||
CHECK(args.IsConstructCall()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since this constructor is exposed directly to users, this should throw an exception rather than abort
Can you also include a fairly simple benchmark? |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #56452 +/- ##
==========================================
- Coverage 88.54% 88.01% -0.54%
==========================================
Files 657 662 +5
Lines 190393 191249 +856
Branches 36552 36404 -148
==========================================
- Hits 168582 168326 -256
- Misses 14998 16031 +1033
- Partials 6813 6892 +79
|
BufferValue input_buffer(env->isolate(), args[0]); | ||
CHECK_NOT_NULL(*input_buffer); | ||
input = input_buffer.ToString(); | ||
} else if (args[0]->IsObject()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s not part of spec but can we add a “is URL instance” fast path here? To avoid re-normalizing each URL property (as with the JsObject route)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can. I haven't started working on optimizations yet due to the inconsistencies between the spec and WPT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think this is a good pattern to land in Node.js. Specifically, a server using this will create one per route and iterate in a loop. This will be slow, specifically if you need to match the last of the list.
(This feedback was provided when URLPattern was standardized and essentially ignored).
For this to be useful, we would need to have a Node.js-specific API to organize these URLPattern in a radix prefix trie and actually do the matching all at once.
I can possibly be persuaded that we need this for Web platform compatibility, but it’s not that popular either (unlike fetch()).
@jasnell I’ll try to build this and get a benchmark going against the ecosystem routers. |
Right now, this pull-request does not pass WPT, and not at all optimized. Any benchmarks will not be beneficial. |
It's not a great spec but it is implemented in Deno, |
@nodejs/tsc ... please review and weigh in. There is definite demand for this API as we'e had a number of folks ask over the years. It's also implemented in other runtimes and is a web platform API standard. On the downside it's not the best pattern or most performant approach. Ideally we'd be able to resolve without referring to a vote. To be certain, we know this approach isn't the most performant so how it performs relative to other router impls should not be part of the consideration here. |
I'm +1 on adding it to Node.js, I like more WP compatibility and I feel like it's an api that could be useful for libraries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have landed plenty of inefficient Web API's. Don't see why this would be different. I'm of the consistent opinion that we should implement them but strongly discourage their use for any performance sensitive code.
Just out of curiosity, why can't we port the Chromium's implementation but instead need to reimplement this ourselves? (I am not a maintainer) |
The chromium implementation depends on quite a few chromium/blink internals that we don't have here. That kind of reuse is difficult to just make happen. This ada-based implementation is standalone, has no other dependencies, etc. It's actually easier overall just to write it from scratch than to repurpose that other impl. |
65631d9
to
4e224f9
Compare
4982d63
to
022eefd
Compare
022eefd
to
af23313
Compare
One worry worth highlighting here is that, IIUC, the architecture of this PR will use a separate regexp library for the regexps that show up in the That could be confusing for developers, as I assume the feature overlap will not be the same. For example, I wonder what results you would get after this PR for: new URLPattern("https://example.com/:id([\\p{Decimal_Number}--[1-9]])").test("https://example.com/0");
new RegExp("[\\p{Decimal_Number}--[1-9]]", "v").test("0"); In Chromium we have architected our I suspect a similar architecture would not fit that well for you, given the different boundaries between Ada / Node.js. But maybe Ada could have some sort of regexp-matcher-callback system which would allow the use of V8's regexps instead of |
Co-authored-by: Daniel Lemire (@lemire)
Blocked
This is blocked from landing due to the old macOS machines we use in our infrastructure (cc @nodejs/build)
Notes:
TODOs
cc @nodejs/cpp-reviewers
Fixes #40844