Commit 1f6515df authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

bind-gen: Implement NativeValueTraits<IDLStringV2>

The old bindings generator uses V8StringResource without
NativeValueTraits, and existing NativeValueTraits<IDLString> is not
as much performative as V8StringResource.

This patch introduces NativeValueTraits<IDLStringV2> which uses the
same technique as V8StringResource so that the new bindings
generator can use NativeValueTraits for all the types without
performance regression.

Bug: 839389
Change-Id: Ibf7f40ba36d10affdef70d489f0f56a005bf73f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1993360
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#730159}
parent d7534174
......@@ -80,6 +80,44 @@ using IDLUSVStringOrNull =
using IDLStringTreatNullAsEmptyString =
IDLStringBase<V8StringResourceMode::kTreatNullAsEmptyString>;
// Strings for the new bindings generator
namespace bindings {
enum class NativeValueTraitsStringConv {
kDefault,
kNullable,
kTreatNullAsEmptyString,
};
} // namespace bindings
// ByteString
template <bindings::NativeValueTraitsStringConv mode>
struct IDLByteStringBaseV2 final : public IDLBaseHelper<String> {};
using IDLByteStringV2 =
IDLByteStringBaseV2<bindings::NativeValueTraitsStringConv::kDefault>;
using IDLByteStringOrNullV2 =
IDLByteStringBaseV2<bindings::NativeValueTraitsStringConv::kNullable>;
// DOMString
template <bindings::NativeValueTraitsStringConv mode>
struct IDLStringBaseV2 final : public IDLBaseHelper<String> {};
using IDLStringV2 =
IDLStringBaseV2<bindings::NativeValueTraitsStringConv::kDefault>;
using IDLStringOrNullV2 =
IDLStringBaseV2<bindings::NativeValueTraitsStringConv::kNullable>;
using IDLStringTreatNullAsEmptyStringV2 = IDLStringBaseV2<
bindings::NativeValueTraitsStringConv::kTreatNullAsEmptyString>;
// USVString
template <bindings::NativeValueTraitsStringConv mode>
struct IDLUSVStringBaseV2 final : public IDLBaseHelper<String> {};
using IDLUSVStringV2 =
IDLUSVStringBaseV2<bindings::NativeValueTraitsStringConv::kDefault>;
using IDLUSVStringOrNullV2 =
IDLUSVStringBaseV2<bindings::NativeValueTraitsStringConv::kNullable>;
// Double
struct IDLDouble final : public IDLBaseHelper<double> {};
struct IDLUnrestrictedDouble final : public IDLBaseHelper<double> {};
......
......@@ -341,6 +341,140 @@ struct NativeValueTraits<IDLUSVStringBase<Mode>>
static String NullValue() { return String(); }
};
// Strings for the new bindings generator
namespace bindings {
// ToBlinkString implements AtomicString- and String-specific conversions from
// v8::String. NativeValueTraitsStringAdapter helps select the best conversion.
//
// Example:
// void F(const AtomicString& s);
// void G(const String& s);
//
// const NativeValueTraitsStringAdapter& x = ...;
// F(x); // ToBlinkString<AtomicString> is used.
// G(x); // ToBlinkString<String> is used.
class NativeValueTraitsStringAdapter {
public:
NativeValueTraitsStringAdapter() = default;
NativeValueTraitsStringAdapter(const NativeValueTraitsStringAdapter&) =
default;
NativeValueTraitsStringAdapter(NativeValueTraitsStringAdapter&&) = default;
NativeValueTraitsStringAdapter(v8::Local<v8::String> value)
: v8_string_(value) {}
NativeValueTraitsStringAdapter(const String& value) : wtf_string_(value) {}
NativeValueTraitsStringAdapter(int32_t value)
: wtf_string_(ToBlinkString(value)) {}
NativeValueTraitsStringAdapter& operator=(
const NativeValueTraitsStringAdapter&) = default;
NativeValueTraitsStringAdapter& operator=(NativeValueTraitsStringAdapter&&) =
default;
operator String() const { return ToString<String>(); }
operator AtomicString() const { return ToString<AtomicString>(); }
private:
template <class StringType>
StringType ToString() const {
if (LIKELY(!v8_string_.IsEmpty()))
return ToBlinkString<StringType>(v8_string_, kExternalize);
return StringType(wtf_string_);
}
v8::Local<v8::String> v8_string_;
String wtf_string_;
};
} // namespace bindings
template <bindings::NativeValueTraitsStringConv mode>
struct NativeValueTraits<IDLByteStringBaseV2<mode>>
: public NativeValueTraitsBase<IDLByteStringBaseV2<mode>> {
// http://heycam.github.io/webidl/#es-ByteString
static bindings::NativeValueTraitsStringAdapter NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (value->IsString() and value.As<v8::String>()->ContainsOnlyOneByte())
return bindings::NativeValueTraitsStringAdapter(value.As<v8::String>());
if (value->IsInt32()) {
return bindings::NativeValueTraitsStringAdapter(
value.As<v8::Int32>()->Value());
}
if (mode == bindings::NativeValueTraitsStringConv::kNullable) {
if (value->IsNullOrUndefined())
return bindings::NativeValueTraitsStringAdapter();
}
v8::TryCatch try_catch(isolate);
v8::Local<v8::String> v8_string;
if (!value->ToString(isolate->GetCurrentContext()).ToLocal(&v8_string)) {
exception_state.RethrowV8Exception(try_catch.Exception());
return bindings::NativeValueTraitsStringAdapter();
}
if (!v8_string->ContainsOnlyOneByte()) {
exception_state.ThrowTypeError(
"String contains non ISO-8859-1 code point.");
return bindings::NativeValueTraitsStringAdapter();
}
return bindings::NativeValueTraitsStringAdapter(v8_string);
}
};
template <bindings::NativeValueTraitsStringConv mode>
struct NativeValueTraits<IDLStringBaseV2<mode>>
: public NativeValueTraitsBase<IDLStringBaseV2<mode>> {
// https://heycam.github.io/webidl/#es-DOMString
static bindings::NativeValueTraitsStringAdapter NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (value->IsString())
return bindings::NativeValueTraitsStringAdapter(value.As<v8::String>());
if (value->IsInt32()) {
return bindings::NativeValueTraitsStringAdapter(
value.As<v8::Int32>()->Value());
}
if (mode == bindings::NativeValueTraitsStringConv::kNullable) {
if (value->IsNullOrUndefined())
return bindings::NativeValueTraitsStringAdapter();
}
if (mode ==
bindings::NativeValueTraitsStringConv::kTreatNullAsEmptyString) {
if (value->IsNull())
return bindings::NativeValueTraitsStringAdapter(g_empty_string);
}
v8::TryCatch try_catch(isolate);
v8::Local<v8::String> v8_string;
if (!value->ToString(isolate->GetCurrentContext()).ToLocal(&v8_string)) {
exception_state.RethrowV8Exception(try_catch.Exception());
return bindings::NativeValueTraitsStringAdapter();
}
return bindings::NativeValueTraitsStringAdapter(v8_string);
}
};
template <bindings::NativeValueTraitsStringConv mode>
struct NativeValueTraits<IDLUSVStringBaseV2<mode>>
: public NativeValueTraitsBase<IDLUSVStringBaseV2<mode>> {
// http://heycam.github.io/webidl/#es-USVString
static String NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
String string = NativeValueTraits<IDLStringBaseV2<mode>>::NativeValue(
isolate, value, exception_state);
if (exception_state.HadException())
return String();
return ReplaceUnmatchedSurrogates(string);
}
};
// Floats and doubles
template <>
struct CORE_EXPORT NativeValueTraits<IDLDouble>
......
......@@ -150,13 +150,12 @@ def blink_type_info(idl_type):
"ScriptPromise", ref_fmt="{}&", const_ref_fmt="const {}&")
if real_type.is_union:
def_obj = real_type.union_definition_object
blink_impl_type = blink_class_name(def_obj)
blink_impl_type = blink_class_name(real_type.union_definition_object)
return TypeInfo(
blink_impl_type,
ref_fmt="{}&",
const_ref_fmt="const {}&",
is_nullable=def_obj.does_include_nullable_type)
is_nullable=True)
if real_type.is_nullable:
inner_type = blink_type_info(real_type.inner_type)
......@@ -176,10 +175,13 @@ def native_value_tag(idl_type):
real_type = idl_type.unwrap(typedef=True)
if (real_type.is_boolean or real_type.is_numeric or real_type.is_string
or real_type.is_any or real_type.is_object):
if (real_type.is_boolean or real_type.is_numeric or real_type.is_any
or real_type.is_object):
return "IDL{}".format(real_type.type_name)
if real_type.unwrap(nullable=True).is_string:
return "IDL{}V2".format(real_type.type_name)
if real_type.is_symbol:
assert False, "Blink does not support/accept IDL symbol type."
......@@ -207,6 +209,8 @@ def native_value_tag(idl_type):
if real_type.is_nullable:
return "IDLNullable<{}>".format(native_value_tag(real_type.inner_type))
assert False
def make_default_value_expr(idl_type, default_value):
"""
......@@ -239,6 +243,9 @@ def make_default_value_expr(idl_type, default_value):
elif type_info.value_t == "ScriptValue":
initializer = None # ScriptValue::IsEmpty() by default
assignment_value = "ScriptValue()"
elif idl_type.unwrap().is_union:
initializer = None # <union_type>::IsNull() by default
assignment_value = "{}()".format(type_info.value_t)
else:
assert not type_info.is_nullable
initializer = None # !base::Optional::has_value() by default
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment