Add API to convert UTF-8 string to external string if it fits ASCII range
Categories
(Core :: JavaScript Engine, task, P3)
Tracking
()
Tracking | Status | |
---|---|---|
firefox123 | --- | fixed |
People
(Reporter: arai, Assigned: arai)
References
Details
Attachments
(1 file)
Bug 1576076 added support for latin-1 external string.
we can extend it to receive UTF-8 string and use external string if it fits ASCII range.
that can be used by DOM UTF8String.
Assignee | ||
Comment 1•10 months ago
|
||
The idea here is to detect the smallest encoding in SpiderMonkey side.
the other option is to let the consumer track the smallest encoding and use latin-1 external strings API if applicable.
Comment 2•10 months ago
|
||
https://phabricator.services.mozilla.com/D44122 is likely of interest. It stalled due to my failure to find real-world performance numbers and, unfortunately, a synthetic benchmark didn't look so good.
Updated•10 months ago
|
Assignee | ||
Comment 3•9 months ago
|
||
Thanks for the pointer!
The expected consumer of this API is NonVoidUTF8StringToJsval
, which is currently calling JS_NewStringCopyUTF8N
, which already performs JS::FindSmallestEncoding
internally.
So, at least the cost of JS::FindSmallestEncoding
won't become troublesome with this change, as long as this doesn't increase the number of JS::FindSmallestEncoding
calls.
I'll look into benchmarks and see how the external string work well with it.
inline bool NonVoidUTF8StringToJsval(JSContext* cx, const nsACString& str,
JS::MutableHandle<JS::Value> rval) {
JSString* jsStr =
JS_NewStringCopyUTF8N(cx, {str.BeginReading(), str.Length()});
JS_PUBLIC_API JSString* JS_NewStringCopyUTF8N(JSContext* cx,
const JS::UTF8Chars s) {
...
return NewStringCopyUTF8N(cx, s);
JSLinearString* NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars utf8,
gc::Heap heap) {
JS::SmallestEncoding encoding = JS::FindSmallestEncoding(utf8);
if (encoding == JS::SmallestEncoding::ASCII) {
Assignee | ||
Comment 4•9 months ago
|
||
Given UTF8String isn't widely used right now and also nsStringBuffer
-backed string (which can be used in external string) is also limited,
this mostly targets localization code, where both directions of conversion between UTF8String and JSString happen.
UTF8String to JSString happens in the following:
already_AddRefed<Promise> Localization::FormatMessages(
const Sequence<OwningUTF8StringOrL10nIdArgs>& aKeys, ErrorResult& aRv) {
...
promise->MaybeResolve(std::move(messages));
void MaybeResolve(T&& aArg) {
MaybeSomething(std::forward<T>(aArg), &Promise::MaybeResolve);
void MaybeSomething(T&& aArgument, MaybeFunc aFunc) {
...
if (!ToJSValue(cx, std::forward<T>(aArgument), &val)) {
[[nodiscard]] std::enable_if_t<is_dom_dictionary<T>, bool> ToJSValue(
JSContext* aCx, const T& aArgument, JS::MutableHandle<JS::Value> aValue) {
return aArgument.ToObjectInternal(aCx, aValue);
bool
AttributeNameValue::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
...
if (!NonVoidUTF8StringToJsval(cx, currentValue, &temp)) {
...
if (!NonVoidUTF8StringToJsval(cx, currentValue, &temp)) {
inline bool NonVoidUTF8StringToJsval(JSContext* cx, const nsACString& str,
JS::MutableHandle<JS::Value> rval) {
JSString* jsStr =
JS_NewStringCopyUTF8N(cx, {str.BeginReading(), str.Length()});
and JSString to nsString happens in the following:
virtual void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
ErrorResult& aRv) override {
...
if (!slotPtr->SetValue().Init(aCx, temp)) {
L10nMessage::Init(JSContext* cx_, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
...
return Init(cx, val, sourceDescription, passedToJSImpl);
L10nMessage::Init(BindingCallContext& cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
...
if (!slot.Init(cx, temp, "Element of 'attributes' member of L10nMessage", passedToJSImpl)) {
AttributeNameValue::Init(BindingCallContext& cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
...
if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mName)) {
...
if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mValue)) {
static inline bool ConvertJSValueToString(
JSContext* cx, JS::Handle<JS::Value> v,
StringificationBehavior nullBehavior,
StringificationBehavior undefinedBehavior, T& result) {
...
return AssignJSString(cx, result, s);
inline bool AssignJSString(JSContext* cx, T& dest, JSString* s) {
...
auto maybe = JS_EncodeStringToUTF8BufferPartial(cx, s, handle.AsSpan());
Assignee | ||
Comment 5•9 months ago
|
||
Depends on D198057
Comment 7•9 months ago
|
||
bugherder |
Description
•