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 = ...@@ -80,6 +80,44 @@ using IDLUSVStringOrNull =
using IDLStringTreatNullAsEmptyString = using IDLStringTreatNullAsEmptyString =
IDLStringBase<V8StringResourceMode::kTreatNullAsEmptyString>; 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 // Double
struct IDLDouble final : public IDLBaseHelper<double> {}; struct IDLDouble final : public IDLBaseHelper<double> {};
struct IDLUnrestrictedDouble final : public IDLBaseHelper<double> {}; struct IDLUnrestrictedDouble final : public IDLBaseHelper<double> {};
......
...@@ -341,6 +341,140 @@ struct NativeValueTraits<IDLUSVStringBase<Mode>> ...@@ -341,6 +341,140 @@ struct NativeValueTraits<IDLUSVStringBase<Mode>>
static String NullValue() { return String(); } 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 // Floats and doubles
template <> template <>
struct CORE_EXPORT NativeValueTraits<IDLDouble> struct CORE_EXPORT NativeValueTraits<IDLDouble>
......
...@@ -150,13 +150,12 @@ def blink_type_info(idl_type): ...@@ -150,13 +150,12 @@ def blink_type_info(idl_type):
"ScriptPromise", ref_fmt="{}&", const_ref_fmt="const {}&") "ScriptPromise", ref_fmt="{}&", const_ref_fmt="const {}&")
if real_type.is_union: if real_type.is_union:
def_obj = real_type.union_definition_object blink_impl_type = blink_class_name(real_type.union_definition_object)
blink_impl_type = blink_class_name(def_obj)
return TypeInfo( return TypeInfo(
blink_impl_type, blink_impl_type,
ref_fmt="{}&", ref_fmt="{}&",
const_ref_fmt="const {}&", const_ref_fmt="const {}&",
is_nullable=def_obj.does_include_nullable_type) is_nullable=True)
if real_type.is_nullable: if real_type.is_nullable:
inner_type = blink_type_info(real_type.inner_type) inner_type = blink_type_info(real_type.inner_type)
...@@ -176,10 +175,13 @@ def native_value_tag(idl_type): ...@@ -176,10 +175,13 @@ def native_value_tag(idl_type):
real_type = idl_type.unwrap(typedef=True) real_type = idl_type.unwrap(typedef=True)
if (real_type.is_boolean or real_type.is_numeric or real_type.is_string if (real_type.is_boolean or real_type.is_numeric or real_type.is_any
or real_type.is_any or real_type.is_object): or real_type.is_object):
return "IDL{}".format(real_type.type_name) 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: if real_type.is_symbol:
assert False, "Blink does not support/accept IDL symbol type." assert False, "Blink does not support/accept IDL symbol type."
...@@ -207,6 +209,8 @@ def native_value_tag(idl_type): ...@@ -207,6 +209,8 @@ def native_value_tag(idl_type):
if real_type.is_nullable: if real_type.is_nullable:
return "IDLNullable<{}>".format(native_value_tag(real_type.inner_type)) return "IDLNullable<{}>".format(native_value_tag(real_type.inner_type))
assert False
def make_default_value_expr(idl_type, default_value): def make_default_value_expr(idl_type, default_value):
""" """
...@@ -239,6 +243,9 @@ 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": elif type_info.value_t == "ScriptValue":
initializer = None # ScriptValue::IsEmpty() by default initializer = None # ScriptValue::IsEmpty() by default
assignment_value = "ScriptValue()" assignment_value = "ScriptValue()"
elif idl_type.unwrap().is_union:
initializer = None # <union_type>::IsNull() by default
assignment_value = "{}()".format(type_info.value_t)
else: else:
assert not type_info.is_nullable assert not type_info.is_nullable
initializer = None # !base::Optional::has_value() by default 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