Skip to content
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

JSG Completion: update URLPattern to use jsg::JsValue #1080

Merged
merged 1 commit into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 25 additions & 40 deletions src/workerd/api/urlpattern.c++
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ namespace {
// require the compatibility flag to be enabled. It will use the new parser
// internally.

using RegexAndNameList = std::pair<jsg::V8Ref<v8::RegExp>, kj::Array<jsg::UsvString>>;
using RegexAndNameList = std::pair<jsg::JsRef<jsg::JsRegExp>, kj::Array<jsg::UsvString>>;

constexpr const char* SYNTAX_ERROR = "Syntax error in URLPattern";
constexpr const char* BASEURL_ERROR = "A baseURL is not allowed when input is an object.";
Expand Down Expand Up @@ -379,15 +379,9 @@ Part::Modifier maybeTokenToModifier(kj::Maybe<Token&> modifierToken) {
// TODO (later): Investigate whether there is a more efficient way to handle this.
bool protocolComponentMatchesSpecialScheme(jsg::Lock& js, URLPatternComponent& component) {
auto handle = component.regex.getHandle(js);
auto context = js.v8Context();

const auto checkIt = [&handle, &js, &context](const char* name) {
return !jsg::check(handle->Exec(context, jsg::v8StrIntern(js.v8Isolate, name)))
->IsNullOrUndefined();
};

return js.tryCatch([&] {
#define V(name) if (checkIt(#name)) return true;
#define V(name) if (handle(js, #name) != nullptr) return true;
SPECIAL_SCHEME(V)
#undef V
return false;
Expand Down Expand Up @@ -1117,14 +1111,11 @@ RegexAndNameList generateRegularExpressionAndNameList(
// regular expression syntax is invalid as opposed to the default SyntaxError
// that V8 throws.
return js.tryCatch([&]() {
auto context = js.v8Context();
return RegexAndNameList {
js.v8Ref(jsg::check(v8::RegExp::New(context,
v8Str(js.v8Isolate, result.finish()),
v8::RegExp::Flags::kUnicode)).As<v8::RegExp>()),
js.regexp(result.finish().toStr(), jsg::Lock::RegExpFlags::kUNICODE).addRef(js),
nameList.releaseAsArray(),
};
}, [&](jsg::Value reason) -> RegexAndNameList {
}, [&](auto reason) -> RegexAndNameList {
JSG_FAIL_REQUIRE(TypeError, "Invalid regular expression syntax.");
});
}
Expand Down Expand Up @@ -1827,37 +1818,31 @@ kj::Maybe<URLPattern::URLPatternComponentResult> execRegex(
jsg::UsvStringPtr input) {
using Groups = jsg::Dict<jsg::UsvString, jsg::UsvString>;

auto context = js.v8Context();

auto execResult =
jsg::check(component.regex.getHandle(js)->Exec(
context, jsg::v8Str(js.v8Isolate, input)));
auto handle = component.regex.getHandle(js);
KJ_IF_MAYBE(array, handle(js, input.toStr())) {
// Starting at 1 here looks a bit odd but it is intentional. The result of the regex
// is an array and we're skipping the first element.
uint32_t index = 1;
uint32_t length = array->size();
kj::Vector<Groups::Field> fields(length - 1);

while (index < length) {
auto value = array->get(js, index);
fields.add(Groups::Field {
.name = jsg::usv(component.nameList[index - 1]),
.value = value.isUndefined() ? jsg::usv() : jsg::usv(js, value),
});
index++;
}

if (execResult->IsNullOrUndefined()) {
return nullptr;
}
return URLPattern::URLPatternComponentResult {
.input = jsg::usv(input),
.groups = Groups { .fields = fields.releaseAsArray() },
};

KJ_ASSERT(execResult->IsArray());
v8::Local<v8::Array> resultsArray = execResult.As<v8::Array>();
// Starting at 1 here looks a bit odd but it is intentional. The result of the regex
// is an array and we're skipping the first element.
uint32_t index = 1;
uint32_t length = resultsArray->Length();
kj::Vector<Groups::Field> fields(length - 1);

while (index < length) {
auto value = js.v8Get(resultsArray, index);
fields.add(Groups::Field {
.name = jsg::usv(component.nameList[index - 1]),
.value = value->IsUndefined() ? jsg::usv() : jsg::usv(js.v8Isolate, value),
});
index++;
}

return URLPattern::URLPatternComponentResult {
.input = jsg::usv(input),
.groups = Groups { .fields = fields.releaseAsArray() },
};
return nullptr;
}

} // namespace
Expand Down
2 changes: 1 addition & 1 deletion src/workerd/api/urlpattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace workerd::api {
struct URLPatternComponent {
// An individual compiled component of a URLPattern
jsg::UsvString pattern;
jsg::V8Ref<v8::RegExp> regex;
jsg::JsRef<jsg::JsRegExp> regex;
kj::Array<jsg::UsvString> nameList;
};

Expand Down
4 changes: 4 additions & 0 deletions src/workerd/jsg/string.c++
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ UsvString usv(v8::Isolate* isolate, v8::Local<v8::Value> value) {
return UsvString(writeFromV8String(isolate, value));
}

UsvString usv(Lock& js, const jsg::JsValue& value) {
return UsvString(writeFromV8String(js.v8Isolate, value));
}

UsvString usv(kj::ArrayPtr<uint16_t> string) {
return UsvString(transcodeToUtf32(string));
}
Expand Down
6 changes: 6 additions & 0 deletions src/workerd/jsg/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,12 @@ KJ_WARN_UNUSED_RESULT
UsvString usv(v8::Isolate* isolate, v8::Local<v8::Value> value);

// Make a JavaScript String in v8's Heap from a UsvString.
KJ_WARN_UNUSED_RESULT
UsvString usv(Lock& js, const JsValue& value);
// Make a UsvString from a JavaScript value reinterpreted first as a string,
// and then as a sequence of utf16_t Unicode code units. The underlying
// storage of utf16_t code units will be heap allocated.

KJ_WARN_UNUSED_RESULT
v8::Local<v8::String> v8Str(v8::Isolate* isolate,
UsvStringPtr str,
Expand Down
Loading