Skip to content

Commit 07bfcc4

Browse files
anonrigjuanarbol
authored andcommitted
url: fix canParse false value when v8 optimizes
PR-URL: #48817 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Matthew Aitken <[email protected]> Reviewed-By: Stephen Belanger <[email protected]>
1 parent 227e6bd commit 07bfcc4

File tree

6 files changed

+39
-4
lines changed

6 files changed

+39
-4
lines changed

lib/internal/url.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1046,10 +1046,10 @@ class URL {
10461046
url = `${url}`;
10471047

10481048
if (base !== undefined) {
1049-
base = `${base}`;
1049+
return bindingUrl.canParseWithBase(url, `${base}`);
10501050
}
10511051

1052-
return bindingUrl.canParse(url, base);
1052+
return bindingUrl.canParse(url);
10531053
}
10541054
}
10551055

src/node_external_reference.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@ using CFunctionCallbackWithInt64 = void (*)(v8::Local<v8::Object> receiver,
1919
int64_t);
2020
using CFunctionCallbackWithBool = void (*)(v8::Local<v8::Object> receiver,
2121
bool);
22-
using CFunctionCallbackWithStrings =
22+
using CFunctionCallbackWithString =
2323
bool (*)(v8::Local<v8::Value>, const v8::FastOneByteString& input);
24+
using CFunctionCallbackWithStrings =
25+
bool (*)(v8::Local<v8::Value>,
26+
const v8::FastOneByteString& input,
27+
const v8::FastOneByteString& base);
2428
using CFunctionWithUint32 = uint32_t (*)(v8::Local<v8::Value>,
2529
const uint32_t input);
2630

@@ -36,6 +40,7 @@ class ExternalReferenceRegistry {
3640
V(CFunctionCallbackReturnDouble) \
3741
V(CFunctionCallbackWithInt64) \
3842
V(CFunctionCallbackWithBool) \
43+
V(CFunctionCallbackWithString) \
3944
V(CFunctionCallbackWithStrings) \
4045
V(CFunctionWithUint32) \
4146
V(const v8::CFunctionInfo*) \

src/node_url.cc

+17
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ bool BindingData::FastCanParse(Local<Value> receiver,
172172

173173
CFunction BindingData::fast_can_parse_(CFunction::Make(FastCanParse));
174174

175+
bool BindingData::FastCanParseWithBase(Local<Value> receiver,
176+
const FastOneByteString& input,
177+
const FastOneByteString& base) {
178+
auto base_view = std::string_view(base.data, base.length);
179+
return ada::can_parse(std::string_view(input.data, input.length), &base_view);
180+
}
181+
182+
CFunction BindingData::fast_can_parse_with_base_(
183+
CFunction::Make(FastCanParseWithBase));
184+
175185
void BindingData::Format(const FunctionCallbackInfo<Value>& args) {
176186
CHECK_GT(args.Length(), 4);
177187
CHECK(args[0]->IsString()); // url href
@@ -352,6 +362,11 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
352362
SetMethod(isolate, target, "update", Update);
353363
SetFastMethodNoSideEffect(
354364
isolate, target, "canParse", CanParse, &fast_can_parse_);
365+
SetFastMethodNoSideEffect(isolate,
366+
target,
367+
"canParseWithBase",
368+
CanParse,
369+
&fast_can_parse_with_base_);
355370
}
356371

357372
void BindingData::CreatePerContextProperties(Local<Object> target,
@@ -373,6 +388,8 @@ void BindingData::RegisterExternalReferences(
373388
registry->Register(CanParse);
374389
registry->Register(FastCanParse);
375390
registry->Register(fast_can_parse_.GetTypeInfo());
391+
registry->Register(FastCanParseWithBase);
392+
registry->Register(fast_can_parse_with_base_.GetTypeInfo());
376393
}
377394

378395
std::string FromFilePath(const std::string_view file_path) {

src/node_url.h

+4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ class BindingData : public SnapshotableObject {
5151
static void CanParse(const v8::FunctionCallbackInfo<v8::Value>& args);
5252
static bool FastCanParse(v8::Local<v8::Value> receiver,
5353
const v8::FastOneByteString& input);
54+
static bool FastCanParseWithBase(v8::Local<v8::Value> receiver,
55+
const v8::FastOneByteString& input,
56+
const v8::FastOneByteString& base);
5457

5558
static void Format(const v8::FunctionCallbackInfo<v8::Value>& args);
5659
static void GetOrigin(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -73,6 +76,7 @@ class BindingData : public SnapshotableObject {
7376
const ada::scheme::type type);
7477

7578
static v8::CFunction fast_can_parse_;
79+
static v8::CFunction fast_can_parse_with_base_;
7680
};
7781

7882
std::string FromFilePath(const std::string_view file_path);

test/parallel/test-whatwg-url-canparse.js

+8
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,11 @@ const { canParse } = internalBinding('url');
1919
// It should not throw when called without a base string
2020
assert.strictEqual(URL.canParse('https://example.org'), true);
2121
assert.strictEqual(canParse('https://example.org'), true);
22+
23+
// This for-loop is used to test V8 Fast API optimizations
24+
for (let i = 0; i < 100000; i++) {
25+
// This example is used because only parsing the first parameter
26+
// results in an invalid URL. They have to be used together to
27+
// produce truthy value.
28+
assert.strictEqual(URL.canParse('/', 'http://n'), true);
29+
}

typings/internalBinding/url.d.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ declare function InternalBinding(binding: 'url'): {
55

66
domainToASCII(input: string): string;
77
domainToUnicode(input: string): string;
8-
canParse(input: string, base?: string): boolean;
8+
canParse(input: string): boolean;
9+
canParseWithBase(input: string, base: string): boolean;
910
format(input: string, fragment?: boolean, unicode?: boolean, search?: boolean, auth?: boolean): string;
1011
parse(input: string, base?: string): string | false;
1112
update(input: string, actionType: typeof urlUpdateActions, value: string): string | false;

0 commit comments

Comments
 (0)