Commit 3787d0af authored by Hitoshi Yoshida's avatar Hitoshi Yoshida Committed by Commit Bot

IDL compiler: Support default value '{}' for dictionaries

Web IDL spec allows to use '{}' as a default value for dictionaries,
to mean an empty dictionary.
This CL makes IDL compiler follows the spec.


Bug: 984949
Change-Id: I9979f590cfc7f17c2aeff50f9333f23f7baf87a0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1824758Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Commit-Queue: Hitoshi Yoshida <peria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#699667}
parent 8548fb8c
......@@ -509,6 +509,8 @@ class IdlLiteral(object):
return '%g' % self.value
if self.idl_type == 'boolean':
return 'true' if self.value else 'false'
if self.idl_type == 'dictionary':
return self.value
raise ValueError('Unsupported literal type: %s' % self.idl_type)
......@@ -537,6 +539,8 @@ def default_node_to_idl_literal(node):
return IdlLiteral(idl_type, value)
if idl_type == 'NULL':
return IdlLiteralNull()
if idl_type == 'dictionary':
return IdlLiteral(idl_type, value)
raise ValueError('Unrecognized default value type: %s' % idl_type)
......
......@@ -474,9 +474,11 @@ def argument_set_default_value(argument):
if not default_value:
return None
if idl_type.is_dictionary:
if not argument.default_value.is_null:
raise Exception('invalid default value for dictionary type')
return None
if argument.default_value.is_null:
return None
if argument.default_value.value == '{}':
return None
raise Exception('invalid default value for dictionary type')
if idl_type.is_array_or_sequence_type:
if default_value.value != '[]':
raise Exception('invalid default value for sequence type: %s' % default_value.value)
......
......@@ -1055,6 +1055,8 @@ def literal_cpp_value(idl_type, idl_literal):
literal_value = str(idl_literal)
if idl_type.base_type in ('octet', 'unsigned short', 'unsigned long'):
return literal_value + 'u'
if idl_type.is_dictionary and literal_value == '{}':
return 'MakeGarbageCollected<{}>()'.format(idl_type.base_type)
return literal_value
......
......@@ -74,6 +74,7 @@
void voidMethodNullableAndOptionalObjectArgs(object objectArg, object? nullableObjectArg, optional object optionalObjectArg);
void voidMethodUnrestrictedDoubleArgUnrestrictedFloatArg(unrestricted double unrestrictedDoubleArg, unrestricted float unrestrictedFloatArg);
void voidMethodTestEnumArg(TestEnum testEnumArg);
void voidOptionalDictArgWithEmptyDefault(optional TestDictionary testDict={});
[PerWorldBindings] void voidMethod();
// Anonymous indexed property operations
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
dictionary TestDictionary2 {
TestDictionary defaultEmptyDictionary = {};
};
......@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_for_each_iterator_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_node.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_test_dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_test_interface.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_test_interface_2.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_test_interface_empty.h"
......@@ -1634,6 +1635,23 @@ static void VoidMethodTestEnumArgMethod(const v8::FunctionCallbackInfo<v8::Value
impl->voidMethodTestEnumArg(test_enum_arg);
}
static void VoidOptionalDictArgWithEmptyDefaultMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
ExceptionState exception_state(info.GetIsolate(), ExceptionState::kExecutionContext, "TestInterface", "voidOptionalDictArgWithEmptyDefault");
TestInterfaceImplementation* impl = V8TestInterface::ToImpl(info.Holder());
TestDictionary* test_dict;
if (!info[0]->IsNullOrUndefined() && !info[0]->IsObject()) {
exception_state.ThrowTypeError("parameter 1 ('testDict') is not an object.");
return;
}
test_dict = NativeValueTraits<TestDictionary>::NativeValue(info.GetIsolate(), info[0], exception_state);
if (exception_state.HadException())
return;
impl->voidOptionalDictArgWithEmptyDefault(test_dict);
}
static void VoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
TestInterfaceImplementation* impl = V8TestInterface::ToImpl(info.Holder());
......@@ -3307,6 +3325,12 @@ void V8TestInterface::VoidMethodTestEnumArgMethodCallback(const v8::FunctionCall
test_interface_implementation_v8_internal::VoidMethodTestEnumArgMethod(info);
}
void V8TestInterface::VoidOptionalDictArgWithEmptyDefaultMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestInterfaceImplementation_voidOptionalDictArgWithEmptyDefault");
test_interface_implementation_v8_internal::VoidOptionalDictArgWithEmptyDefaultMethod(info);
}
void V8TestInterface::VoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestInterfaceImplementation_voidMethod");
......@@ -3726,6 +3750,7 @@ static constexpr V8DOMConfiguration::MethodConfiguration kV8TestInterfaceMethods
{"voidMethodNullableAndOptionalObjectArgs", V8TestInterface::VoidMethodNullableAndOptionalObjectArgsMethodCallback, 2, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
{"voidMethodUnrestrictedDoubleArgUnrestrictedFloatArg", V8TestInterface::VoidMethodUnrestrictedDoubleArgUnrestrictedFloatArgMethodCallback, 2, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
{"voidMethodTestEnumArg", V8TestInterface::VoidMethodTestEnumArgMethodCallback, 1, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
{"voidOptionalDictArgWithEmptyDefault", V8TestInterface::VoidOptionalDictArgWithEmptyDefaultMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
{"voidMethod", V8TestInterface::VoidMethodMethodCallbackForMainWorld, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kMainWorld},
{"voidMethod", V8TestInterface::VoidMethodMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kNonMainWorlds},
{"alwaysExposedMethod", V8TestInterface::AlwaysExposedMethodMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
......
......@@ -185,6 +185,7 @@ class V8TestInterface {
CORE_EXPORT static void VoidMethodNullableAndOptionalObjectArgsMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
CORE_EXPORT static void VoidMethodUnrestrictedDoubleArgUnrestrictedFloatArgMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
CORE_EXPORT static void VoidMethodTestEnumArgMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
CORE_EXPORT static void VoidOptionalDictArgWithEmptyDefaultMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
CORE_EXPORT static void VoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
CORE_EXPORT static void VoidMethodMethodCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>&);
CORE_EXPORT static void AlwaysExposedMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file has been auto-generated from the Jinja2 template
// third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl
// by the script code_generator_v8.py.
// DO NOT MODIFY!
// clang-format off
#include "third_party/blink/renderer/bindings/tests/results/modules/test_dictionary_2.h"
namespace blink {
TestDictionary2::TestDictionary2() {
setDefaultEmptyDictionary(MakeGarbageCollected<TestDictionary>());
}
TestDictionary2::~TestDictionary2() = default;
void TestDictionary2::setDefaultEmptyDictionary(TestDictionary* value) {
default_empty_dictionary_ = value;
}
void TestDictionary2::Trace(blink::Visitor* visitor) {
visitor->Trace(default_empty_dictionary_);
IDLDictionaryBase::Trace(visitor);
}
} // namespace blink
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file has been auto-generated from the Jinja2 template
// third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl
// by the script code_generator_v8.py.
// DO NOT MODIFY!
// clang-format off
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_TEST_DICTIONARY_2_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_TEST_DICTIONARY_2_H_
#include "third_party/blink/renderer/bindings/core/v8/idl_dictionary_base.h"
#include "third_party/blink/renderer/bindings/tests/idls/core/test_dictionary.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
class MODULES_EXPORT TestDictionary2 : public IDLDictionaryBase {
public:
static TestDictionary2* Create() { return MakeGarbageCollected<TestDictionary2>(); }
TestDictionary2();
virtual ~TestDictionary2();
bool hasDefaultEmptyDictionary() const { return default_empty_dictionary_; }
TestDictionary* defaultEmptyDictionary() const {
return default_empty_dictionary_;
}
void setDefaultEmptyDictionary(TestDictionary*);
v8::Local<v8::Value> ToV8Impl(v8::Local<v8::Object>, v8::Isolate*) const override;
void Trace(blink::Visitor*) override;
private:
Member<TestDictionary> default_empty_dictionary_;
friend class V8TestDictionary2;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_TEST_DICTIONARY_2_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file has been auto-generated from the Jinja2 template
// third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl
// by the script code_generator_v8.py.
// DO NOT MODIFY!
// clang-format off
#include "third_party/blink/renderer/bindings/tests/results/modules/v8_test_dictionary_2.h"
#include "base/stl_util.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_test_dictionary.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
static const v8::Eternal<v8::Name>* eternalV8TestDictionary2Keys(v8::Isolate* isolate) {
static const char* const kKeys[] = {
"defaultEmptyDictionary",
};
return V8PerIsolateData::From(isolate)->FindOrCreateEternalNameCache(
kKeys, kKeys, base::size(kKeys));
}
void V8TestDictionary2::ToImpl(v8::Isolate* isolate, v8::Local<v8::Value> v8_value, TestDictionary2* impl, ExceptionState& exception_state) {
if (IsUndefinedOrNull(v8_value)) {
return;
}
if (!v8_value->IsObject()) {
exception_state.ThrowTypeError("cannot convert to dictionary.");
return;
}
v8::Local<v8::Object> v8Object = v8_value.As<v8::Object>();
ALLOW_UNUSED_LOCAL(v8Object);
const v8::Eternal<v8::Name>* keys = eternalV8TestDictionary2Keys(isolate);
v8::TryCatch block(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::Value> default_empty_dictionary_value;
if (!v8Object->Get(context, keys[0].Get(isolate)).ToLocal(&default_empty_dictionary_value)) {
exception_state.RethrowV8Exception(block.Exception());
return;
}
if (default_empty_dictionary_value.IsEmpty() || default_empty_dictionary_value->IsUndefined()) {
// Do nothing.
} else {
TestDictionary* default_empty_dictionary_cpp_value = NativeValueTraits<TestDictionary>::NativeValue(isolate, default_empty_dictionary_value, exception_state);
if (exception_state.HadException())
return;
impl->setDefaultEmptyDictionary(default_empty_dictionary_cpp_value);
}
}
v8::Local<v8::Value> TestDictionary2::ToV8Impl(v8::Local<v8::Object> creationContext, v8::Isolate* isolate) const {
v8::Local<v8::Object> v8Object = v8::Object::New(isolate);
if (!toV8TestDictionary2(this, v8Object, creationContext, isolate))
return v8::Undefined(isolate);
return v8Object;
}
bool toV8TestDictionary2(const TestDictionary2* impl, v8::Local<v8::Object> dictionary, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
const v8::Eternal<v8::Name>* keys = eternalV8TestDictionary2Keys(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
auto create_property = [dictionary, context, keys, isolate](
size_t key_index, v8::Local<v8::Value> value) {
bool added_property;
v8::Local<v8::Name> key = keys[key_index].Get(isolate);
if (!dictionary->CreateDataProperty(context, key, value)
.To(&added_property)) {
return false;
}
return added_property;
};
v8::Local<v8::Value> default_empty_dictionary_value;
bool default_empty_dictionary_has_value_or_default = false;
if (impl->hasDefaultEmptyDictionary()) {
default_empty_dictionary_value = ToV8(impl->defaultEmptyDictionary(), creationContext, isolate);
default_empty_dictionary_has_value_or_default = true;
} else {
default_empty_dictionary_value = ToV8(MakeGarbageCollected<TestDictionary>(), creationContext, isolate);
default_empty_dictionary_has_value_or_default = true;
}
if (default_empty_dictionary_has_value_or_default &&
!create_property(0, default_empty_dictionary_value)) {
return false;
}
return true;
}
TestDictionary2* NativeValueTraits<TestDictionary2>::NativeValue(v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) {
TestDictionary2* impl = TestDictionary2::Create();
V8TestDictionary2::ToImpl(isolate, value, impl, exception_state);
return impl;
}
} // namespace blink
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file has been auto-generated from the Jinja2 template
// third_party/blink/renderer/bindings/templates/dictionary_v8.h.tmpl
// by the script code_generator_v8.py.
// DO NOT MODIFY!
// clang-format off
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_V8_TEST_DICTIONARY_2_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_V8_TEST_DICTIONARY_2_H_
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/tests/idls/modules/test_dictionary_2.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
class ExceptionState;
class V8TestDictionary2 {
public:
MODULES_EXPORT static void ToImpl(v8::Isolate*, v8::Local<v8::Value>, TestDictionary2* impl, ExceptionState&);
};
MODULES_EXPORT bool toV8TestDictionary2(const TestDictionary2*, v8::Local<v8::Object> dictionary, v8::Local<v8::Object> creationContext, v8::Isolate*);
template <class CallbackInfo>
inline void V8SetReturnValue(const CallbackInfo& callbackInfo, TestDictionary2* impl) {
V8SetReturnValue(callbackInfo, ToV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
}
template <class CallbackInfo>
inline void V8SetReturnValue(const CallbackInfo& callbackInfo, TestDictionary2* impl, v8::Local<v8::Object> creationContext) {
V8SetReturnValue(callbackInfo, ToV8(impl, creationContext, callbackInfo.GetIsolate()));
}
template <>
struct NativeValueTraits<TestDictionary2> : public NativeValueTraitsBase<TestDictionary2> {
MODULES_EXPORT static TestDictionary2* NativeValue(v8::Isolate*, v8::Local<v8::Value>, ExceptionState&);
};
template <>
struct V8TypeOf<TestDictionary2> {
typedef V8TestDictionary2 Type;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_V8_TEST_DICTIONARY_2_H_
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