Import Cobalt 16.140175
Change-Id: I1874a9229c64dffde87b3c3d5664ef915a6b9977
diff --git a/src/build/file_exists.py b/src/build/file_exists.py
new file mode 100644
index 0000000..9af5d79
--- /dev/null
+++ b/src/build/file_exists.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# Copyright 2018 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Writes True if the argument is a file."""
+
+import os.path
+import sys
+
+def main():
+ sys.stdout.write(str(os.path.isfile(sys.argv[1])))
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/src/cobalt/audio/audio_buffer_source_node.cc b/src/cobalt/audio/audio_buffer_source_node.cc
index 49ba2ad..adbfc95 100644
--- a/src/cobalt/audio/audio_buffer_source_node.cc
+++ b/src/cobalt/audio/audio_buffer_source_node.cc
@@ -111,35 +111,38 @@
size_t channels = static_cast<size_t>(buffer_->number_of_channels());
if (sample_type == kSampleTypeFloat32) {
- std::vector<float*> audio_buffer(channels, NULL);
+ std::vector<scoped_refptr<dom::Float32Array>> audio_buffer_storages(
+ channels);
+ std::vector<float*> audio_buffers(channels, NULL);
for (size_t i = 0; i < channels; ++i) {
scoped_refptr<dom::Float32Array> buffer_data =
buffer_->GetChannelData(static_cast<uint32>(i), NULL);
- scoped_refptr<dom::Float32Array> sub_array = buffer_data->Subarray(
+ audio_buffer_storages[i] = buffer_data->Subarray(
NULL, read_index_, read_index_ + number_of_frames);
- audio_buffer[i] = sub_array->data();
+ audio_buffers[i] = audio_buffer_storages[i]->data();
}
read_index_ += number_of_frames;
- scoped_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(static_cast<size_t>(number_of_frames), audio_buffer));
+ scoped_ptr<ShellAudioBus> audio_bus(new ShellAudioBus(
+ static_cast<size_t>(number_of_frames), audio_buffers));
return audio_bus.Pass();
} else if (sample_type == kSampleTypeInt16) {
- std::vector<int16*> audio_buffer(channels, NULL);
+ std::vector<scoped_refptr<dom::Int16Array>> audio_buffer_storages(channels);
+ std::vector<int16*> audio_buffers(channels, NULL);
for (size_t i = 0; i < channels; ++i) {
scoped_refptr<dom::Int16Array> buffer_data =
buffer_->GetChannelDataInt16(static_cast<uint32>(i), NULL);
- scoped_refptr<dom::Int16Array> sub_array = buffer_data->Subarray(
+ audio_buffer_storages[i] = buffer_data->Subarray(
NULL, read_index_, read_index_ + number_of_frames);
- audio_buffer[i] = sub_array->data();
+ audio_buffers[i] = audio_buffer_storages[i]->data();
}
read_index_ += number_of_frames;
- scoped_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(static_cast<size_t>(number_of_frames), audio_buffer));
+ scoped_ptr<ShellAudioBus> audio_bus(new ShellAudioBus(
+ static_cast<size_t>(number_of_frames), audio_buffers));
return audio_bus.Pass();
}
diff --git a/src/cobalt/audio/audio_device.cc b/src/cobalt/audio/audio_device.cc
index 28d1bce..53d041d 100644
--- a/src/cobalt/audio/audio_device.cc
+++ b/src/cobalt/audio/audio_device.cc
@@ -170,14 +170,14 @@
*frames_in_buffer = static_cast<int>(frames_rendered_ - frames_consumed_);
if ((kFramesPerChannel - *frames_in_buffer) >= kRenderBufferSizeFrames) {
- bool silence = false;
-
// If there was silence last time we were called, then the buffer has
// already been zeroed out and we don't need to do it again.
if (!was_silence_last_update_) {
input_audio_bus_.ZeroAllFrames();
}
+ bool silence = true;
+
// Fill our temporary buffer with planar PCM float samples.
render_callback_->FillAudioBus(&input_audio_bus_, &silence);
@@ -345,7 +345,7 @@
if ((kFramesPerChannel - *total_frames) >= kRenderBufferSizeFrames) {
// Fill our temporary buffer with PCM float samples.
- bool silence = false;
+ bool silence = true;
render_callback_->FillAudioBus(&audio_bus_, &silence);
if (!silence) {
diff --git a/src/cobalt/audio/audio_device.h b/src/cobalt/audio/audio_device.h
index fec6cea..dd5f898 100644
--- a/src/cobalt/audio/audio_device.h
+++ b/src/cobalt/audio/audio_device.h
@@ -38,6 +38,10 @@
typedef ::media::ShellAudioBus ShellAudioBus;
#endif // defined(COBALT_MEDIA_SOURCE_2016)
+ // |silence| will be set to true before calling if |audio_buffer| contains
+ // only silence samples, it will be set to |false| otherwise. On return
+ // FillAudioBus() will set |silence| to |false| if it has modified
+ // |audio_buffer|.
virtual void FillAudioBus(ShellAudioBus* audio_buffer, bool* silence) = 0;
protected:
diff --git a/src/cobalt/audio/audio_node_input.cc b/src/cobalt/audio/audio_node_input.cc
index 2e76dcf..529986d 100644
--- a/src/cobalt/audio/audio_node_input.cc
+++ b/src/cobalt/audio/audio_node_input.cc
@@ -231,8 +231,6 @@
// This is called by Audio thread.
owner_node_->audio_lock()->AssertLocked();
- *silence = true;
-
// TODO: Consider computing computedNumberOfChannels and do up-mix or
// down-mix base on computedNumberOfChannels. The current implementation
// is based on the fact that the channelCountMode is max.
@@ -251,8 +249,12 @@
output_audio_bus->sample_type());
if (audio_bus) {
- MixAudioBuffer(owner_node_->channel_interpretation(), audio_bus.get(),
- output_audio_bus);
+ if (*silence && audio_bus->channels() == output_audio_bus->channels()) {
+ output_audio_bus->Assign(*audio_bus);
+ } else {
+ MixAudioBuffer(owner_node_->channel_interpretation(), audio_bus.get(),
+ output_audio_bus);
+ }
*silence = false;
}
}
diff --git a/src/cobalt/base/accessibility_caption_settings_changed_event.h b/src/cobalt/base/accessibility_caption_settings_changed_event.h
new file mode 100644
index 0000000..d0c0a69
--- /dev/null
+++ b/src/cobalt/base/accessibility_caption_settings_changed_event.h
@@ -0,0 +1,35 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_BASE_ACCESSIBILITY_CAPTION_SETTINGS_CHANGED_EVENT_H_
+#define COBALT_BASE_ACCESSIBILITY_CAPTION_SETTINGS_CHANGED_EVENT_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/string_util.h"
+#include "cobalt/base/event.h"
+
+namespace base {
+
+class AccessibilityCaptionSettingsChangedEvent : public Event {
+ public:
+ AccessibilityCaptionSettingsChangedEvent() {}
+
+ BASE_EVENT_SUBCLASS(AccessibilityCaptionSettingsChangedEvent);
+};
+
+} // namespace base
+
+#endif // COBALT_BASE_ACCESSIBILITY_CAPTION_SETTINGS_CHANGED_EVENT_H_
diff --git a/src/cobalt/base/base.gyp b/src/cobalt/base/base.gyp
index 2f25385..c5eadee 100644
--- a/src/cobalt/base/base.gyp
+++ b/src/cobalt/base/base.gyp
@@ -78,6 +78,8 @@
'unused.h',
'user_log.cc',
'user_log.h',
+ 'version_compatibility.cc',
+ 'version_compatibility.h',
],
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
diff --git a/src/cobalt/base/version_compatibility.cc b/src/cobalt/base/version_compatibility.cc
new file mode 100644
index 0000000..b912f6f
--- /dev/null
+++ b/src/cobalt/base/version_compatibility.cc
@@ -0,0 +1,52 @@
+// Copyright 2018 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+
+#include "cobalt/base/version_compatibility.h"
+
+#include "base/logging.h"
+
+namespace base {
+
+VersionCompatibility* VersionCompatibility::GetInstance() {
+ return Singleton<VersionCompatibility,
+ StaticMemorySingletonTraits<VersionCompatibility> >::get();
+}
+
+VersionCompatibility::VersionCompatibility()
+ : violation_count(
+ "Count.VersionCompatibilityViolation", 0,
+ "The number of Cobalt version compatibility violations encountered."),
+ minimum_version_(0) {}
+
+void VersionCompatibility::SetMinimumVersion(int minimum_version) {
+ base::subtle::NoBarrier_Store(&minimum_version_, minimum_version);
+}
+
+int VersionCompatibility::GetMinimumVersion() const {
+ return base::subtle::NoBarrier_Load(&minimum_version_);
+}
+
+void VersionCompatibility::ReportViolation(
+ const std::string& violation_message) {
+ const std::string kVersionCompatibilityViolationTag =
+ "[VERSION COMPATIBILITY VIOLATION]";
+ LOG(ERROR) << kVersionCompatibilityViolationTag << " " << violation_message;
+ ++violation_count;
+}
+
+} // namespace base
+
+#endif // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
diff --git a/src/cobalt/base/version_compatibility.h b/src/cobalt/base/version_compatibility.h
new file mode 100644
index 0000000..4a776d7
--- /dev/null
+++ b/src/cobalt/base/version_compatibility.h
@@ -0,0 +1,63 @@
+// Copyright 2018 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_BASE_VERSION_COMPATIBILITY_H_
+#define COBALT_BASE_VERSION_COMPATIBILITY_H_
+
+#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+
+#include <string>
+
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+#include "cobalt/base/c_val.h"
+
+namespace base {
+
+// This thread-safe singleton class provides basic support for Cobalt version
+// compatibility validations.
+// NOTE: This class exists for convenience and can be removed when we create a
+// better mechanism for dependency injection in Cobalt.
+class VersionCompatibility {
+ public:
+ // Method to get the singleton instance of this class.
+ static VersionCompatibility* GetInstance();
+
+ void SetMinimumVersion(int minimum_version);
+ int GetMinimumVersion() const;
+
+ // Called when a version compatibility violation is encountered.
+ void ReportViolation(const std::string& violation_info);
+
+ private:
+ friend struct StaticMemorySingletonTraits<VersionCompatibility>;
+
+ VersionCompatibility();
+ ~VersionCompatibility() = default;
+
+ // The number of violations that have been encountered.
+ base::CVal<int, base::CValDebug> violation_count;
+
+ // The minimum version of Cobalt to validate compatibility against.
+ base::subtle::Atomic32 minimum_version_;
+
+ DISALLOW_COPY_AND_ASSIGN(VersionCompatibility);
+};
+
+} // namespace base
+
+#endif // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+
+#endif // COBALT_BASE_VERSION_COMPATIBILITY_H_
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.h b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.h
index 01fdd20..82fa889 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.h
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.h
@@ -41,9 +41,11 @@
const scoped_refptr<script::Wrappable>& callback_this,
const scoped_refptr<ArbitraryInterface>& value,
bool* had_exception) const override;
+
JSObject* handle() const { return implementing_object_.GetObject(); }
const JS::Value& value() const { return implementing_object_.GetValue(); }
bool WasCollected() const { return implementing_object_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { implementing_object_.Trace(js_tracer); }
private:
JSContext* context_;
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.cc
index 7b85687..47af2a9 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,113 @@
namespace {
+const int kInterfaceUniqueId = 0;
+
+
+
+
+
+void IndexedPropertyGetterCallback(
+ uint32_t index,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get();
+ if (index >= impl->length()) {
+ // |index| is out of bounds, so return undefined.
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->AnonymousIndexedGetter(index),
+ &result_value);
+ }
+ info.GetReturnValue().Set(result_value);
+}
+
+void IndexedPropertyDescriptorCallback(
+ uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+void IndexedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get();
+ const uint32_t length = impl->length();
+ v8::Local<v8::Array> array = v8::Array::New(isolate, length);
+ for (uint32_t i = 0; i < length; ++i) {
+ array->Set(i, v8::Integer::New(isolate, i));
+ }
+ info.GetReturnValue().Set(array);
+}
+
+void IndexedPropertyDefinerCallback(
+ uint32_t index, const v8::PropertyDescriptor& desc,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+
+void IndexedPropertySetterCallback(
+ uint32_t index,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get();
+ if (index >= impl->length()) {
+ return;
+ }
+ TypeTraits<uint32_t>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->AnonymousIndexedSetter(index, native_value);
+ result_value = v8::Undefined(isolate);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(value);
+}
+
+
void lengthAttributeGetter(
@@ -127,52 +231,141 @@
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "AnonymousIndexedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "AnonymousIndexedGetterInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "length",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- lengthAttributeGetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "length");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ lengthAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 0;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "AnonymousIndexedGetterInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+ {
+ v8::IndexedPropertyHandlerConfiguration indexed_property_handler_configuration = {
+ IndexedPropertyGetterCallback,
+ IndexedPropertySetterCallback,
+ IndexedPropertyDescriptorCallback,
+ nullptr,
+ IndexedPropertyEnumeratorCallback,
+ IndexedPropertyDefinerCallback
+ };
+ instance_template->SetHandler(indexed_property_handler_configuration);
+ }
+
}
} // namespace
-v8::Local<v8::Object> V8cAnonymousIndexedGetterInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cAnonymousIndexedGetterInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -182,14 +375,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cAnonymousIndexedGetterInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cAnonymousIndexedGetterInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.h
index 8d168df..4af4572 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.h
@@ -39,8 +39,7 @@
class V8cAnonymousIndexedGetterInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.cc
index 587bce5..ab85a2f 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,49 +84,226 @@
namespace {
+const int kInterfaceUniqueId = 1;
+
+
+void NamedPropertyGetterCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ if (!impl->CanQueryNamedProperty(property_name)) {
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->AnonymousNamedGetter(property_name),
+ &result_value);
+ }
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(result_value);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+void NamedPropertyQueryCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ bool result = impl->CanQueryNamedProperty(property_name);
+ if (!result) {
+ return;
+ }
+ // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
+ // 2.7. If |O| implements an interface with a named property setter, then set
+ // desc.[[Writable]] to true, otherwise set it to false.
+ // 2.8. If |O| implements an interface with the
+ // [LegacyUnenumerableNamedProperties] extended attribute, then set
+ // desc.[[Enumerable]] to false, otherwise set it to true.
+ info.GetReturnValue().Set(v8::DontEnum | v8::ReadOnly);
+}
+
+void NamedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedGetterInterface>().get();
+ v8::Local<v8::Array> array = v8::Array::New(isolate);
+ V8cPropertyEnumerator property_enumerator(isolate, &array);
+ impl->EnumerateNamedProperties(&property_enumerator);
+ info.GetReturnValue().Set(array);
+}
+
+
+void NamedPropertySetterCallback(
+ v8::Local<v8::Name> property,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ TypeTraits<std::string>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->AnonymousNamedSetter(property_name, native_value);
+ result_value = v8::Undefined(isolate);
+ DCHECK(!exception_state.is_exception_set());
+}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "AnonymousNamedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+
+
+
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "AnonymousNamedGetterInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "AnonymousNamedGetterInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+ {
+ v8::NamedPropertyHandlerConfiguration named_property_handler_configuration = {
+ NamedPropertyGetterCallback,
+ NamedPropertySetterCallback,
+ NamedPropertyQueryCallback,
+ nullptr,
+ NamedPropertyEnumeratorCallback,
+ v8::Local<v8::Value>(),
+ static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kNonMasking) | int(v8::PropertyHandlerFlags::kOnlyInterceptStrings))
+ };
+ instance_template->SetHandler(named_property_handler_configuration);
+ }
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 1;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cAnonymousNamedGetterInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cAnonymousNamedGetterInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -139,14 +313,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cAnonymousNamedGetterInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cAnonymousNamedGetterInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.h
index 6e3f21b..190de7f 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.h
@@ -39,8 +39,7 @@
class V8cAnonymousNamedGetterInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.cc
index 1d2d4c1..3947292 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,221 @@
namespace {
+const int kInterfaceUniqueId = 2;
+
+
+void NamedPropertyGetterCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ if (!impl->CanQueryNamedProperty(property_name)) {
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->AnonymousNamedGetter(property_name),
+ &result_value);
+ }
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(result_value);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+void NamedPropertyQueryCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ bool result = impl->CanQueryNamedProperty(property_name);
+ if (!result) {
+ return;
+ }
+ // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
+ // 2.7. If |O| implements an interface with a named property setter, then set
+ // desc.[[Writable]] to true, otherwise set it to false.
+ // 2.8. If |O| implements an interface with the
+ // [LegacyUnenumerableNamedProperties] extended attribute, then set
+ // desc.[[Enumerable]] to false, otherwise set it to true.
+ info.GetReturnValue().Set(v8::DontEnum | v8::ReadOnly);
+}
+
+void NamedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+ v8::Local<v8::Array> array = v8::Array::New(isolate);
+ V8cPropertyEnumerator property_enumerator(isolate, &array);
+ impl->EnumerateNamedProperties(&property_enumerator);
+ info.GetReturnValue().Set(array);
+}
+
+
+void NamedPropertySetterCallback(
+ v8::Local<v8::Name> property,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ TypeTraits<std::string>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->AnonymousNamedSetter(property_name, native_value);
+ result_value = v8::Undefined(isolate);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+
+
+void IndexedPropertyGetterCallback(
+ uint32_t index,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+ if (index >= impl->length()) {
+ // |index| is out of bounds, so return undefined.
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->AnonymousIndexedGetter(index),
+ &result_value);
+ }
+ info.GetReturnValue().Set(result_value);
+}
+
+void IndexedPropertyDescriptorCallback(
+ uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+void IndexedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+ const uint32_t length = impl->length();
+ v8::Local<v8::Array> array = v8::Array::New(isolate, length);
+ for (uint32_t i = 0; i < length; ++i) {
+ array->Set(i, v8::Integer::New(isolate, i));
+ }
+ info.GetReturnValue().Set(array);
+}
+
+void IndexedPropertyDefinerCallback(
+ uint32_t index, const v8::PropertyDescriptor& desc,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+
+void IndexedPropertySetterCallback(
+ uint32_t index,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ AnonymousNamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+ if (index >= impl->length()) {
+ return;
+ }
+ TypeTraits<uint32_t>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->AnonymousIndexedSetter(index, native_value);
+ result_value = v8::Undefined(isolate);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(value);
+}
+
+
void lengthAttributeGetter(
@@ -127,52 +339,153 @@
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "AnonymousNamedIndexedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "AnonymousNamedIndexedGetterInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "length",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- lengthAttributeGetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "length");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ lengthAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 2;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "AnonymousNamedIndexedGetterInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+ {
+ v8::NamedPropertyHandlerConfiguration named_property_handler_configuration = {
+ NamedPropertyGetterCallback,
+ NamedPropertySetterCallback,
+ NamedPropertyQueryCallback,
+ nullptr,
+ NamedPropertyEnumeratorCallback,
+ v8::Local<v8::Value>(),
+ static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kNonMasking) | int(v8::PropertyHandlerFlags::kOnlyInterceptStrings))
+ };
+ instance_template->SetHandler(named_property_handler_configuration);
+ }
+
+ {
+ v8::IndexedPropertyHandlerConfiguration indexed_property_handler_configuration = {
+ IndexedPropertyGetterCallback,
+ IndexedPropertySetterCallback,
+ IndexedPropertyDescriptorCallback,
+ nullptr,
+ IndexedPropertyEnumeratorCallback,
+ IndexedPropertyDefinerCallback
+ };
+ instance_template->SetHandler(indexed_property_handler_configuration);
+ }
+
}
} // namespace
-v8::Local<v8::Object> V8cAnonymousNamedIndexedGetterInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cAnonymousNamedIndexedGetterInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -182,14 +495,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cAnonymousNamedIndexedGetterInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cAnonymousNamedIndexedGetterInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.h
index 59b1d60..fd83275 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.h
@@ -39,8 +39,7 @@
class V8cAnonymousNamedIndexedGetterInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.cc
index f644082..627c95d 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 3;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -211,64 +216,164 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "ArbitraryInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "ArbitraryInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "arbitraryProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- arbitraryPropertyAttributeGetter
- ,arbitraryPropertyAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, arbitraryFunctionMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "arbitraryFunction",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "arbitraryProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ arbitraryPropertyAttributeGetter,
+ arbitraryPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "arbitraryFunction");
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 3;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, arbitraryFunctionMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "arbitraryFunction"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "ArbitraryInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cArbitraryInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cArbitraryInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -278,14 +383,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cArbitraryInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cArbitraryInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.h
index 89dfb9a..1ac26dd 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.h
@@ -39,8 +39,7 @@
class V8cArbitraryInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.cc
index fd2ca14..e447a9c 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 4;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -174,63 +179,164 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "BaseInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "BaseInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "baseAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- baseAttributeAttributeGetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, baseOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "baseOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "baseAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ baseAttributeAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "baseOperation");
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 4;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, baseOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "baseOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "BaseInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cBaseInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cBaseInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -240,14 +346,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cBaseInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cBaseInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.h
index aaecf17..64c0f77 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.h
@@ -39,8 +39,7 @@
class V8cBaseInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.cc
index 4425931..a3706ab 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 5;
+
+
+
+
+
+
+
void booleanPropertyAttributeGetter(
@@ -246,75 +251,196 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "BooleanTypeTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "BooleanTypeTestInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "booleanProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- booleanPropertyAttributeGetter
- ,booleanPropertyAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, booleanArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "booleanArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "booleanProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ booleanPropertyAttributeGetter,
+ booleanPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, booleanReturnOperationMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "booleanArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, booleanArgumentOperationMethod);
method_template->RemovePrototype();
+ method_template->SetLength(1);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "booleanReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "booleanArgumentOperation"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "booleanReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, booleanReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "booleanReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "BooleanTypeTestInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 5;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+
}
} // namespace
-v8::Local<v8::Object> V8cBooleanTypeTestInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cBooleanTypeTestInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -324,14 +450,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cBooleanTypeTestInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cBooleanTypeTestInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.h
index d2af8d7..64ffe39 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.h
@@ -39,8 +39,7 @@
class V8cBooleanTypeTestInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.cc
index 74dbe19..1328e44 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,14 @@
namespace {
+const int kInterfaceUniqueId = 6;
+
+
+
+
+
+
+
void callbackAttributeAttributeGetter(
@@ -167,6 +172,7 @@
return;
}
+
void nullableCallbackAttributeAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -472,115 +478,329 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "CallbackFunctionInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "CallbackFunctionInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "callbackAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- callbackAttributeAttributeGetter
- ,callbackAttributeAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "nullableCallbackAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nullableCallbackAttributeAttributeGetter
- ,nullableCallbackAttributeAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, takesFunctionThatReturnsStringMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "takesFunctionThatReturnsString",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "callbackAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ callbackAttributeAttributeGetter,
+ callbackAttributeAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableCallbackAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nullableCallbackAttributeAttributeGetter,
+ nullableCallbackAttributeAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, takesFunctionWithNullableParametersMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "takesFunctionThatReturnsString");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, takesFunctionThatReturnsStringMethod);
method_template->RemovePrototype();
+ method_template->SetLength(1);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "takesFunctionWithNullableParameters",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "takesFunctionThatReturnsString"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "takesFunctionWithNullableParameters");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, takesFunctionWithNullableParametersMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "takesFunctionWithNullableParameters"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "takesFunctionWithOneParameter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, takesFunctionWithOneParameterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "takesFunctionWithOneParameter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "takesFunctionWithSeveralParameters");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, takesFunctionWithSeveralParametersMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "takesFunctionWithSeveralParameters"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "takesVoidFunction");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, takesVoidFunctionMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "takesVoidFunction"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, takesFunctionWithOneParameterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "takesFunctionWithOneParameter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, takesFunctionWithSeveralParametersMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "takesFunctionWithSeveralParameters",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, takesVoidFunctionMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "takesVoidFunction",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "CallbackFunctionInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 6;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cCallbackFunctionInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cCallbackFunctionInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -590,14 +810,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cCallbackFunctionInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cCallbackFunctionInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.h
index a6cf0f1..f54da19 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.h
@@ -39,8 +39,7 @@
class V8cCallbackFunctionInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.cc
index c582b3b..6f254dc 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,14 @@
namespace {
+const int kInterfaceUniqueId = 7;
+
+
+
+
+
+
+
void callbackAttributeAttributeGetter(
@@ -244,75 +249,196 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "CallbackInterfaceInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "CallbackInterfaceInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "callbackAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- callbackAttributeAttributeGetter
- ,callbackAttributeAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, registerCallbackMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "registerCallback",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "callbackAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ callbackAttributeAttributeGetter,
+ callbackAttributeAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, someOperationMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "registerCallback");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, registerCallbackMethod);
method_template->RemovePrototype();
+ method_template->SetLength(1);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "someOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "registerCallback"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "someOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, someOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "someOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "CallbackInterfaceInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 7;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+
}
} // namespace
-v8::Local<v8::Object> V8cCallbackInterfaceInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cCallbackInterfaceInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -322,14 +448,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cCallbackInterfaceInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cCallbackInterfaceInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.h
index 64a407e..9fc8f8f 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.h
@@ -39,8 +39,7 @@
class V8cCallbackInterfaceInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.cc
index 42eb6bb..28b4236 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -60,7 +62,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -68,18 +69,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -89,9 +86,17 @@
namespace {
+const int kInterfaceUniqueId = 8;
+
+
+
+
+
+
#if defined(ENABLE_CONDITIONAL_PROPERTY)
+
void enabledAttributeAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -168,6 +173,7 @@
#endif // ENABLE_CONDITIONAL_PROPERTY
#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
+
void disabledAttributeAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -308,90 +314,238 @@
#endif // ENABLE_CONDITIONAL_PROPERTY
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "ConditionalInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "ConditionalInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
-#if defined(ENABLE_CONDITIONAL_PROPERTY)
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "enabledAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- enabledAttributeAttributeGetter
- ,enabledAttributeAttributeSetter
- );
-#endif // defined(ENABLE_CONDITIONAL_PROPERTY)
-#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "disabledAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- disabledAttributeAttributeGetter
- ,disabledAttributeAttributeSetter
- );
-#endif // defined(NO_ENABLE_CONDITIONAL_PROPERTY)
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
-#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, disabledOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "disabledOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-#endif // defined(NO_ENABLE_CONDITIONAL_PROPERTY)
-
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
#if defined(ENABLE_CONDITIONAL_PROPERTY)
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, enabledOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "enabledOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "enabledAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ enabledAttributeAttributeGetter,
+ enabledAttributeAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
-#endif // defined(ENABLE_CONDITIONAL_PROPERTY)
+#endif // ENABLE_CONDITIONAL_PROPERTY
+#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "disabledAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ disabledAttributeAttributeGetter,
+ disabledAttributeAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 8;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+#endif // NO_ENABLE_CONDITIONAL_PROPERTY
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "disabledOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, disabledOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "disabledOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+#endif // NO_ENABLE_CONDITIONAL_PROPERTY
+#if defined(ENABLE_CONDITIONAL_PROPERTY)
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "enabledOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, enabledOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "enabledOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+#endif // ENABLE_CONDITIONAL_PROPERTY
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "ConditionalInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cConditionalInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cConditionalInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -401,14 +555,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cConditionalInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cConditionalInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.h
index a98041d..212639b 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.h
@@ -41,8 +41,7 @@
class V8cConditionalInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.cc
index 4077c2d..ea5e9af 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,73 +84,158 @@
namespace {
-
-void INTEGER_CONSTANTAttributeGetter(
- v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
- // TODO: Consider just attaching a constant instead.
- v8::Local<v8::Value> result_value;
- ToJSValue(info.GetIsolate(), 5, &result_value);
- info.GetReturnValue().Set(result_value);
-}
-void DOUBLE_CONSTANTAttributeGetter(
- v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
- // TODO: Consider just attaching a constant instead.
- v8::Local<v8::Value> result_value;
- ToJSValue(info.GetIsolate(), 2.718, &result_value);
- info.GetReturnValue().Set(result_value);
-}
+const int kInterfaceUniqueId = 9;
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "ConstantsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+
+
+
+
+
+
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "ConstantsInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
- prototype_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "INTEGER_CONSTANT",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- INTEGER_CONSTANTAttributeGetter);
- prototype_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "DOUBLE_CONSTANT",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- DOUBLE_CONSTANTAttributeGetter);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ {
+ // The name of the property is the identifier of the constant.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "INTEGER_CONSTANT");
+
+ // The value of the property is that which is obtained by converting the
+ // constant's IDL value to an ECMAScript value.
+ v8::Local<v8::Value> constant_value;
+ ToJSValue(isolate, 5, &constant_value);
+
+ // The property has attributes { [[Writable]]: false, [[Enumerable]]: true,
+ // [[Configurable]]: false }.
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ v8::ReadOnly | v8::DontDelete);
+
+ // The location of the property is determined as follows:
+ // Otherwise, if the interface has an interface prototype object, then the
+ // property exists on it.
+ prototype_template->Set(name, constant_value, attributes);
+
+ // In addition, a property with the same characteristics must exist on the
+ // interface object or the legacy callback interface object, if either of
+ // those objects exists.
+ function_template->Set(name, constant_value, attributes);
+ }
+ {
+ // The name of the property is the identifier of the constant.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "DOUBLE_CONSTANT");
+
+ // The value of the property is that which is obtained by converting the
+ // constant's IDL value to an ECMAScript value.
+ v8::Local<v8::Value> constant_value;
+ ToJSValue(isolate, 2.718, &constant_value);
+
+ // The property has attributes { [[Writable]]: false, [[Enumerable]]: true,
+ // [[Configurable]]: false }.
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ v8::ReadOnly | v8::DontDelete);
+
+ // The location of the property is determined as follows:
+ // Otherwise, if the interface has an interface prototype object, then the
+ // property exists on it.
+ prototype_template->Set(name, constant_value, attributes);
+
+ // In addition, a property with the same characteristics must exist on the
+ // interface object or the legacy callback interface object, if either of
+ // those objects exists.
+ function_template->Set(name, constant_value, attributes);
+ }
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "ConstantsInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 9;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cConstantsInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cConstantsInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -163,14 +245,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cConstantsInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cConstantsInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.h
index 9ea42b7..c30024c 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.h
@@ -39,8 +39,7 @@
class V8cConstantsInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.cc
index 0aef9a1..48c0906 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 10;
+
+
+
+
+
+
+
void Constructor1(
const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -172,46 +177,96 @@
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "ConstructorInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "ConstructorInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "ConstructorInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
-
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 10;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cConstructorInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cConstructorInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -221,14 +276,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cConstructorInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cConstructorInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.h
index 21cc81d..857b2cf 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.h
@@ -39,8 +39,7 @@
class V8cConstructorInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.cc
index 6723e45..0903cc0 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 11;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -184,6 +189,7 @@
}
+
void booleanArgAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -221,6 +227,7 @@
}
+
void stringArgAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -259,64 +266,199 @@
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "ConstructorWithArgumentsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 2);
+ function_template->SetLength(2);
+ function_template->SetClassName(NewInternalString(isolate, "ConstructorWithArgumentsInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "longArg",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- longArgAttributeGetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "booleanArg",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- booleanArgAttributeGetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "stringArg",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- stringArgAttributeGetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longArg");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ longArgAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 11;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "booleanArg");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ booleanArgAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "stringArg");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ stringArgAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "ConstructorWithArgumentsInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cConstructorWithArgumentsInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cConstructorWithArgumentsInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -326,14 +468,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cConstructorWithArgumentsInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cConstructorWithArgumentsInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.h
index 6c01a6e..a5b004c 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.h
@@ -39,8 +39,7 @@
class V8cConstructorWithArgumentsInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.cc
index 2acd721..f2d42d6 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,221 @@
namespace {
+const int kInterfaceUniqueId = 14;
+
+
+void NamedPropertyGetterCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ DerivedGetterSetterInterface* impl =
+ wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ if (!impl->CanQueryNamedProperty(property_name)) {
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->AnonymousNamedGetter(property_name),
+ &result_value);
+ }
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(result_value);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+void NamedPropertyQueryCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ DerivedGetterSetterInterface* impl =
+ wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ bool result = impl->CanQueryNamedProperty(property_name);
+ if (!result) {
+ return;
+ }
+ // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
+ // 2.7. If |O| implements an interface with a named property setter, then set
+ // desc.[[Writable]] to true, otherwise set it to false.
+ // 2.8. If |O| implements an interface with the
+ // [LegacyUnenumerableNamedProperties] extended attribute, then set
+ // desc.[[Enumerable]] to false, otherwise set it to true.
+ info.GetReturnValue().Set(v8::DontEnum | v8::ReadOnly);
+}
+
+void NamedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ DerivedGetterSetterInterface* impl =
+ wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+ v8::Local<v8::Array> array = v8::Array::New(isolate);
+ V8cPropertyEnumerator property_enumerator(isolate, &array);
+ impl->EnumerateNamedProperties(&property_enumerator);
+ info.GetReturnValue().Set(array);
+}
+
+
+void NamedPropertySetterCallback(
+ v8::Local<v8::Name> property,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ DerivedGetterSetterInterface* impl =
+ wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ TypeTraits<std::string>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->AnonymousNamedSetter(property_name, native_value);
+ result_value = v8::Undefined(isolate);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+
+
+void IndexedPropertyGetterCallback(
+ uint32_t index,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ DerivedGetterSetterInterface* impl =
+ wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+ if (index >= impl->length()) {
+ // |index| is out of bounds, so return undefined.
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->DerivedIndexedGetter(index),
+ &result_value);
+ }
+ info.GetReturnValue().Set(result_value);
+}
+
+void IndexedPropertyDescriptorCallback(
+ uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+void IndexedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ DerivedGetterSetterInterface* impl =
+ wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+ const uint32_t length = impl->length();
+ v8::Local<v8::Array> array = v8::Array::New(isolate, length);
+ for (uint32_t i = 0; i < length; ++i) {
+ array->Set(i, v8::Integer::New(isolate, i));
+ }
+ info.GetReturnValue().Set(array);
+}
+
+void IndexedPropertyDefinerCallback(
+ uint32_t index, const v8::PropertyDescriptor& desc,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+
+void IndexedPropertySetterCallback(
+ uint32_t index,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ DerivedGetterSetterInterface* impl =
+ wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+ if (index >= impl->length()) {
+ return;
+ }
+ TypeTraits<uint32_t>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->DerivedIndexedSetter(index, native_value);
+ result_value = v8::Undefined(isolate);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(value);
+}
+
+
void lengthAttributeGetter(
@@ -130,6 +342,7 @@
}
+
void propertyOnDerivedClassAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -343,94 +556,297 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "DerivedGetterSetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "DerivedGetterSetterInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
- v8::Local<v8::FunctionTemplate> parent_template = V8cNamedIndexedGetterInterface::CreateTemplate(isolate);
- function_template->Inherit(parent_template);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
-
-
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "length",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- lengthAttributeGetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "propertyOnDerivedClass",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- propertyOnDerivedClassAttributeGetter
- ,propertyOnDerivedClassAttributeSetter
- );
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, derivedIndexedGetterMethod);
+ // An interface can be defined to inherit from another interface. If the
+ // identifier of the interface is followed by a U+003A COLON (":") character
+ // and an identifier, then that identifier identifies the inherited
+ // interface. An object that implements an interface that inherits from
+ // another also implements that inherited interface. The object therefore
+ // will also have members that correspond to the interface members from the
+ // inherited interface.
+ v8::Local<v8::FunctionTemplate> parent_template = V8cNamedIndexedGetterInterface::GetTemplate(isolate);
+ function_template->Inherit(parent_template);
+ }
+
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "length");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ lengthAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "propertyOnDerivedClass");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ propertyOnDerivedClassAttributeGetter,
+ propertyOnDerivedClassAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "derivedIndexedGetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, derivedIndexedGetterMethod);
method_template->RemovePrototype();
+ method_template->SetLength(1);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "derivedIndexedGetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "derivedIndexedGetter"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "derivedIndexedSetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, derivedIndexedSetterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(2);
+ prototype_template->Set(
+ NewInternalString(isolate, "derivedIndexedSetter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "operationOnDerivedClass");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, operationOnDerivedClassMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "operationOnDerivedClass"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "DerivedGetterSetterInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+ {
+ v8::NamedPropertyHandlerConfiguration named_property_handler_configuration = {
+ NamedPropertyGetterCallback,
+ NamedPropertySetterCallback,
+ NamedPropertyQueryCallback,
+ nullptr,
+ NamedPropertyEnumeratorCallback,
+ v8::Local<v8::Value>(),
+ static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kNonMasking) | int(v8::PropertyHandlerFlags::kOnlyInterceptStrings))
+ };
+ instance_template->SetHandler(named_property_handler_configuration);
}
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, derivedIndexedSetterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "derivedIndexedSetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ v8::IndexedPropertyHandlerConfiguration indexed_property_handler_configuration = {
+ IndexedPropertyGetterCallback,
+ IndexedPropertySetterCallback,
+ IndexedPropertyDescriptorCallback,
+ nullptr,
+ IndexedPropertyEnumeratorCallback,
+ IndexedPropertyDefinerCallback
+ };
+ instance_template->SetHandler(indexed_property_handler_configuration);
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, operationOnDerivedClassMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "operationOnDerivedClass",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
-
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 14;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cDerivedGetterSetterInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cDerivedGetterSetterInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -440,14 +856,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cDerivedGetterSetterInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cDerivedGetterSetterInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.h
index a938db4..1c50e6d 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.h
@@ -40,8 +40,7 @@
class V8cDerivedGetterSetterInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.cc
index 9e13e18..db63e88 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,14 @@
namespace {
+const int kInterfaceUniqueId = 15;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -178,65 +183,175 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "DerivedInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "DerivedInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
- v8::Local<v8::FunctionTemplate> parent_template = V8cBaseInterface::CreateTemplate(isolate);
- function_template->Inherit(parent_template);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
-
-
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "derivedAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- derivedAttributeAttributeGetter
- );
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, derivedOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "derivedOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // An interface can be defined to inherit from another interface. If the
+ // identifier of the interface is followed by a U+003A COLON (":") character
+ // and an identifier, then that identifier identifies the inherited
+ // interface. An object that implements an interface that inherits from
+ // another also implements that inherited interface. The object therefore
+ // will also have members that correspond to the interface members from the
+ // inherited interface.
+ v8::Local<v8::FunctionTemplate> parent_template = V8cBaseInterface::GetTemplate(isolate);
+ function_template->Inherit(parent_template);
}
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
- interface_data->function_template.Set(isolate, function_template);
-}
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "derivedAttribute");
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 15;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ derivedAttributeAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "derivedOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, derivedOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "derivedOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "DerivedInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cDerivedInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cDerivedInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -246,14 +361,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cDerivedInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cDerivedInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.h
index ff15ad0..1814d02 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.h
@@ -40,8 +40,7 @@
class V8cDerivedInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.cc
index a2de658..48ee0bd 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.cc
@@ -36,12 +36,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -64,7 +66,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -72,18 +73,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -93,6 +90,14 @@
namespace {
+const int kInterfaceUniqueId = 16;
+
+
+
+
+
+
+
void dictionarySequenceAttributeGetter(
@@ -308,86 +313,229 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "DictionaryInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "DictionaryInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "dictionarySequence",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- dictionarySequenceAttributeGetter
- ,dictionarySequenceAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, derivedDictionaryOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "derivedDictionaryOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "dictionarySequence");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ dictionarySequenceAttributeGetter,
+ dictionarySequenceAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, dictionaryOperationMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "derivedDictionaryOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, derivedDictionaryOperationMethod);
method_template->RemovePrototype();
+ method_template->SetLength(1);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "dictionaryOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "derivedDictionaryOperation"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "dictionaryOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, dictionaryOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "dictionaryOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "testOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, testOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "testOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, testOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "testOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "DictionaryInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 16;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cDictionaryInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cDictionaryInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -397,14 +545,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cDictionaryInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cDictionaryInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.h
index 7c976d4..ef0a08a 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.h
@@ -39,8 +39,7 @@
class V8cDictionaryInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.cc
index d800dbc..d14ac28 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -60,7 +62,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -68,18 +69,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -89,6 +86,14 @@
namespace {
+const int kInterfaceUniqueId = 18;
+
+
+
+
+
+
+
void disabledPropertyAttributeGetter(
@@ -196,64 +201,163 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "DisabledInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "DisabledInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "disabledProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- disabledPropertyAttributeGetter
- ,disabledPropertyAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, disabledFunctionMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "disabledFunction",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "disabledProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ disabledPropertyAttributeGetter,
+ disabledPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "disabledFunction");
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 18;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, disabledFunctionMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "disabledFunction"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "DisabledInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cDisabledInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cDisabledInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -263,14 +367,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cDisabledInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cDisabledInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.h
index ff9b4ee..e5734ce 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.h
@@ -41,8 +41,7 @@
class V8cDisabledInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.cc
index ac89400..d9fb0da 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 12;
+
+
+
+
+
+
+
void propertyAttributeGetter(
@@ -163,6 +168,7 @@
return;
}
+
void readOnlyPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -200,6 +206,7 @@
}
+
void readOnlyTokenPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -237,6 +244,7 @@
}
+
void nullIsEmptyPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -311,6 +319,7 @@
return;
}
+
void undefinedIsEmptyPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -385,6 +394,7 @@
return;
}
+
void nullableUndefinedIsEmptyPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -460,86 +470,300 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "DOMStringTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "DOMStringTestInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "property",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- propertyAttributeGetter
- ,propertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "readOnlyProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- readOnlyPropertyAttributeGetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "readOnlyTokenProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- readOnlyTokenPropertyAttributeGetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "nullIsEmptyProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nullIsEmptyPropertyAttributeGetter
- ,nullIsEmptyPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "undefinedIsEmptyProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- undefinedIsEmptyPropertyAttributeGetter
- ,undefinedIsEmptyPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "nullableUndefinedIsEmptyProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nullableUndefinedIsEmptyPropertyAttributeGetter
- ,nullableUndefinedIsEmptyPropertyAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "property");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ propertyAttributeGetter,
+ propertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 12;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "readOnlyProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ readOnlyPropertyAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "readOnlyTokenProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ readOnlyTokenPropertyAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullIsEmptyProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nullIsEmptyPropertyAttributeGetter,
+ nullIsEmptyPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "undefinedIsEmptyProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ undefinedIsEmptyPropertyAttributeGetter,
+ undefinedIsEmptyPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableUndefinedIsEmptyProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nullableUndefinedIsEmptyPropertyAttributeGetter,
+ nullableUndefinedIsEmptyPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "DOMStringTestInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cDOMStringTestInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cDOMStringTestInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -549,14 +773,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cDOMStringTestInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cDOMStringTestInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.h
index fbda377..e8fd6c3 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.h
@@ -39,8 +39,7 @@
class V8cDOMStringTestInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.cc
index 68e0e21..ba0038b 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.cc
@@ -34,12 +34,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -60,7 +62,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -68,18 +69,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -89,6 +86,14 @@
namespace {
+const int kInterfaceUniqueId = 19;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -228,64 +233,164 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "EnumerationInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "EnumerationInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "enumProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- enumPropertyAttributeGetter
- ,enumPropertyAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, optionalEnumWithDefaultMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "optionalEnumWithDefault",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "enumProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ enumPropertyAttributeGetter,
+ enumPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "optionalEnumWithDefault");
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 19;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, optionalEnumWithDefaultMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "optionalEnumWithDefault"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "EnumerationInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cEnumerationInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cEnumerationInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -295,14 +400,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cEnumerationInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cEnumerationInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.h
index 677d83d..7554cfc 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.h
@@ -39,8 +39,7 @@
class V8cEnumerationInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.cc
index a389979..8c19687 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 20;
+
+
+
+
+
+
+
void errorAttributeGetter(
@@ -126,6 +131,7 @@
}
+
void messageAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -164,59 +170,175 @@
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "ExceptionObjectInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "ExceptionObjectInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
- NOTIMPLEMENTED();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ {
+ // A spicy hack from Chromium in order to achieve
+ // https://heycam.github.io/webidl/#es-DOMException-specialness
+ // See https://cs.chromium.org/chromium/src/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl?l=630&rcl=0f7c2c752bb24ad08c17017e4e68401093fe76a0
+ v8::Local<v8::FunctionTemplate> intrinsic_error_prototype_interface_template =
+ v8::FunctionTemplate::New(isolate);
+ intrinsic_error_prototype_interface_template->RemovePrototype();
+ intrinsic_error_prototype_interface_template->SetIntrinsicDataProperty(
+ NewInternalString(isolate, "prototype"), v8::kErrorPrototype);
+ function_template->Inherit(intrinsic_error_prototype_interface_template);
+ }
+
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "error");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "error",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- errorAttributeGetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "message",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- messageAttributeGetter
- );
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ errorAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "message");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ messageAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 20;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "ExceptionObjectInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cExceptionObjectInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cExceptionObjectInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -226,14 +348,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cExceptionObjectInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cExceptionObjectInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.h
index 7e8832a..0ec5d1b 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.h
@@ -39,8 +39,7 @@
class V8cExceptionObjectInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.cc
index 574bb64..2476ba1 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 21;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -215,64 +220,164 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "ExceptionsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "ExceptionsInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "attributeThrowsException",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- attributeThrowsExceptionAttributeGetter
- ,attributeThrowsExceptionAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, functionThrowsExceptionMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "functionThrowsException",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "attributeThrowsException");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ attributeThrowsExceptionAttributeGetter,
+ attributeThrowsExceptionAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "functionThrowsException");
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 21;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, functionThrowsExceptionMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "functionThrowsException"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "ExceptionsInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cExceptionsInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cExceptionsInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -282,14 +387,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cExceptionsInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cExceptionsInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.h
index 32e436b..13eb669 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.h
@@ -39,8 +39,7 @@
class V8cExceptionsInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.cc
index 65e53a8..5de530d 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 22;
+
+
+
+
+
+
+
void defaultAttributeGetter(
@@ -241,75 +246,196 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "ExtendedIDLAttributesInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "ExtendedIDLAttributesInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "default",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- defaultAttributeGetter
- ,defaultAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, callWithSettingsMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "callWithSettings",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "default");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ defaultAttributeGetter,
+ defaultAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, clampArgumentMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "callWithSettings");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, callWithSettingsMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "clampArgument",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "callWithSettings"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "clampArgument");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, clampArgumentMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "clampArgument"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "ExtendedIDLAttributesInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 22;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+
}
} // namespace
-v8::Local<v8::Object> V8cExtendedIDLAttributesInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cExtendedIDLAttributesInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -319,14 +445,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cExtendedIDLAttributesInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cExtendedIDLAttributesInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.h
index a23c50d..ae2015d 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.h
@@ -39,8 +39,7 @@
class V8cExtendedIDLAttributesInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.cc
index 95e9107..d6ded64 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,14 @@
namespace {
+const int kInterfaceUniqueId = 23;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -184,6 +189,7 @@
return;
}
+
void nextAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -259,60 +265,165 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "GarbageCollectionTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "GarbageCollectionTestInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "previous",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- previousAttributeGetter
- ,previousAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "next",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nextAttributeGetter
- ,nextAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "previous");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ previousAttributeGetter,
+ previousAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 23;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "next");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nextAttributeGetter,
+ nextAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "GarbageCollectionTestInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cGarbageCollectionTestInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cGarbageCollectionTestInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -322,14 +433,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cGarbageCollectionTestInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cGarbageCollectionTestInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.h
index 8b5f975..b452e3f 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.h
@@ -39,8 +39,7 @@
class V8cGarbageCollectionTestInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.cc
index c1f2c66..d25a0d6 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,13 @@
namespace {
+const int kInterfaceUniqueId = 24;
+
+
+
+
+
+
@@ -120,57 +124,129 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "GlobalInterfaceParent",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "GlobalInterfaceParent"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, parentOperationMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "parentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, parentOperationMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "parentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "parentOperation"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "GlobalInterfaceParent"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 24;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+
}
} // namespace
-v8::Local<v8::Object> V8cGlobalInterfaceParent::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cGlobalInterfaceParent::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -180,14 +256,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cGlobalInterfaceParent::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cGlobalInterfaceParent::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.h
index 5ad1e1e..bbccc96 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.h
@@ -39,8 +39,7 @@
class V8cGlobalInterfaceParent {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.cc
index a59977c..92f94ea 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,140 @@
namespace {
+const int kInterfaceUniqueId = 26;
+
+
+
+
+
+void IndexedPropertyGetterCallback(
+ uint32_t index,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ IndexedGetterInterface* impl =
+ wrapper_private->wrappable<IndexedGetterInterface>().get();
+ if (index >= impl->length()) {
+ // |index| is out of bounds, so return undefined.
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->IndexedGetter(index),
+ &result_value);
+ }
+ info.GetReturnValue().Set(result_value);
+}
+
+void IndexedPropertyDescriptorCallback(
+ uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+void IndexedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ IndexedGetterInterface* impl =
+ wrapper_private->wrappable<IndexedGetterInterface>().get();
+ const uint32_t length = impl->length();
+ v8::Local<v8::Array> array = v8::Array::New(isolate, length);
+ for (uint32_t i = 0; i < length; ++i) {
+ array->Set(i, v8::Integer::New(isolate, i));
+ }
+ info.GetReturnValue().Set(array);
+}
+
+void IndexedPropertyDefinerCallback(
+ uint32_t index, const v8::PropertyDescriptor& desc,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+
+void IndexedPropertySetterCallback(
+ uint32_t index,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ IndexedGetterInterface* impl =
+ wrapper_private->wrappable<IndexedGetterInterface>().get();
+ if (index >= impl->length()) {
+ return;
+ }
+ TypeTraits<uint32_t>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->IndexedSetter(index, native_value);
+ result_value = v8::Undefined(isolate);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(value);
+}
+
+void IndexedPropertyDeleterCallback(
+ uint32_t index,
+ const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ IndexedGetterInterface* impl =
+ wrapper_private->wrappable<IndexedGetterInterface>().get();
+ if (index >= impl->length()) {
+ return;
+ }
+
+ impl->IndexedDeleter(index);
+ result_value = v8::Undefined(isolate);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(v8::Boolean::New(isolate, true));
+}
+
void lengthAttributeGetter(
@@ -281,85 +412,240 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "IndexedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "IndexedGetterInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "length",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- lengthAttributeGetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, indexedDeleterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "indexedDeleter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "length");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ lengthAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, indexedGetterMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "indexedDeleter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, indexedDeleterMethod);
method_template->RemovePrototype();
+ method_template->SetLength(1);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "indexedGetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "indexedDeleter"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "indexedGetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, indexedGetterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "indexedGetter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "indexedSetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, indexedSetterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(2);
+ prototype_template->Set(
+ NewInternalString(isolate, "indexedSetter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "IndexedGetterInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, indexedSetterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "indexedSetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ v8::IndexedPropertyHandlerConfiguration indexed_property_handler_configuration = {
+ IndexedPropertyGetterCallback,
+ IndexedPropertySetterCallback,
+ IndexedPropertyDescriptorCallback,
+ IndexedPropertyDeleterCallback,
+ IndexedPropertyEnumeratorCallback,
+ IndexedPropertyDefinerCallback
+ };
+ instance_template->SetHandler(indexed_property_handler_configuration);
}
-
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 26;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cIndexedGetterInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cIndexedGetterInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -369,14 +655,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cIndexedGetterInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cIndexedGetterInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.h
index 530f38a..f80fdc4 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.h
@@ -39,8 +39,7 @@
class V8cIndexedGetterInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.cc
index d150da6..22fbc8e 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 27;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -107,7 +112,6 @@
-
void getAnyMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::Object> object = info.This();
@@ -189,68 +193,163 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "InterfaceWithAny",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "InterfaceWithAny"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getAnyMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getAny");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getAnyMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getAny",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "getAny"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setAny");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setAnyMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setAny"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setAnyMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setAny",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "InterfaceWithAny"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 27;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cInterfaceWithAny::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cInterfaceWithAny::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -260,14 +359,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cInterfaceWithAny::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cInterfaceWithAny::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.h
index c088986..7f029c4 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.h
@@ -39,8 +39,7 @@
class V8cInterfaceWithAny {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.cc
index 27fb410..d707a52 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 28;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -107,7 +112,6 @@
-
void getAnyMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::Object> object = info.This();
@@ -261,90 +265,229 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "InterfaceWithAnyDictionary",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "InterfaceWithAnyDictionary"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getAnyMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getAny");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getAnyMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getAny",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "getAny"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "hasAny");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, hasAnyMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "hasAny"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "hasAnyDefault");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, hasAnyDefaultMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "hasAnyDefault"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setAny");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setAnyMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setAny"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, hasAnyMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "hasAny",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, hasAnyDefaultMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "hasAnyDefault",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setAnyMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setAny",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "InterfaceWithAnyDictionary"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 28;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cInterfaceWithAnyDictionary::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cInterfaceWithAnyDictionary::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -354,14 +497,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cInterfaceWithAnyDictionary::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cInterfaceWithAnyDictionary::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.h
index af10b0a..124c7ab 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.h
@@ -39,8 +39,7 @@
class V8cInterfaceWithAnyDictionary {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_date.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_date.cc
index 0451ae2..4539d83 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_date.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_date.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 29;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -107,7 +112,6 @@
-
void getDateMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::Object> object = info.This();
@@ -189,68 +193,163 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "InterfaceWithDate",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "InterfaceWithDate"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getDateMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getDate");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getDateMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getDate",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "getDate"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setDate");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setDateMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setDate"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setDateMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setDate",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "InterfaceWithDate"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 29;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cInterfaceWithDate::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cInterfaceWithDate::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -260,14 +359,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cInterfaceWithDate::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cInterfaceWithDate::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_date.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_date.h
index 9154494..49a1bc0 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_date.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_date.h
@@ -39,8 +39,7 @@
class V8cInterfaceWithDate {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.cc
index fd54ff0..c815e50 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 30;
+
+
+
+
+
+
+
void supportedAttributeAttributeGetter(
@@ -127,52 +132,130 @@
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "InterfaceWithUnsupportedProperties",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "InterfaceWithUnsupportedProperties"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "supportedAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- supportedAttributeAttributeGetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "supportedAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ supportedAttributeAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 30;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "InterfaceWithUnsupportedProperties"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cInterfaceWithUnsupportedProperties::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cInterfaceWithUnsupportedProperties::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -182,14 +265,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cInterfaceWithUnsupportedProperties::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cInterfaceWithUnsupportedProperties::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.h
index 5d68181..dfd519f 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.h
@@ -39,8 +39,7 @@
class V8cInterfaceWithUnsupportedProperties {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.cc
index fffa517..692da5b 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 31;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -107,46 +112,96 @@
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "NamedConstructorInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "NamedConstructorInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "NamedConstructorInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
-
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 31;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cNamedConstructorInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cNamedConstructorInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -156,14 +211,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cNamedConstructorInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cNamedConstructorInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.h
index b08e649..76fcdb2 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.h
@@ -39,8 +39,7 @@
class V8cNamedConstructorInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.cc
index 4c63633..9d39173 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,146 @@
namespace {
+const int kInterfaceUniqueId = 32;
+
+
+void NamedPropertyGetterCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedGetterInterface* impl =
+ wrapper_private->wrappable<NamedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ if (!impl->CanQueryNamedProperty(property_name)) {
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->NamedGetter(property_name),
+ &result_value);
+ }
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(result_value);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+void NamedPropertyQueryCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedGetterInterface* impl =
+ wrapper_private->wrappable<NamedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ bool result = impl->CanQueryNamedProperty(property_name);
+ if (!result) {
+ return;
+ }
+ // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
+ // 2.7. If |O| implements an interface with a named property setter, then set
+ // desc.[[Writable]] to true, otherwise set it to false.
+ // 2.8. If |O| implements an interface with the
+ // [LegacyUnenumerableNamedProperties] extended attribute, then set
+ // desc.[[Enumerable]] to false, otherwise set it to true.
+ info.GetReturnValue().Set(v8::DontEnum | v8::ReadOnly);
+}
+
+void NamedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedGetterInterface* impl =
+ wrapper_private->wrappable<NamedGetterInterface>().get();
+ v8::Local<v8::Array> array = v8::Array::New(isolate);
+ V8cPropertyEnumerator property_enumerator(isolate, &array);
+ impl->EnumerateNamedProperties(&property_enumerator);
+ info.GetReturnValue().Set(array);
+}
+
+
+void NamedPropertySetterCallback(
+ v8::Local<v8::Name> property,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedGetterInterface* impl =
+ wrapper_private->wrappable<NamedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ TypeTraits<std::string>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->NamedSetter(property_name, native_value);
+ result_value = v8::Undefined(isolate);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+void NamedPropertyDeleterCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedGetterInterface* impl =
+ wrapper_private->wrappable<NamedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ if (!impl->CanQueryNamedProperty(property_name)) {
+ return;
+ }
+
+ impl->NamedDeleter(property_name);
+ result_value = v8::Undefined(isolate);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+
+
@@ -244,79 +381,207 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "NamedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "NamedGetterInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, namedDeleterMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "namedDeleter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, namedDeleterMethod);
method_template->RemovePrototype();
+ method_template->SetLength(1);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "namedDeleter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "namedDeleter"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "namedGetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, namedGetterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "namedGetter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "namedSetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, namedSetterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(2);
+ prototype_template->Set(
+ NewInternalString(isolate, "namedSetter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, namedGetterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "namedGetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "NamedGetterInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, namedSetterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "namedSetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ v8::NamedPropertyHandlerConfiguration named_property_handler_configuration = {
+ NamedPropertyGetterCallback,
+ NamedPropertySetterCallback,
+ NamedPropertyQueryCallback,
+ NamedPropertyDeleterCallback,
+ NamedPropertyEnumeratorCallback,
+ v8::Local<v8::Value>(),
+ static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kNonMasking) | int(v8::PropertyHandlerFlags::kOnlyInterceptStrings))
+ };
+ instance_template->SetHandler(named_property_handler_configuration);
}
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 32;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cNamedGetterInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cNamedGetterInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -326,14 +591,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cNamedGetterInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cNamedGetterInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.h
index 2160453..12f0ec7 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.h
@@ -39,8 +39,7 @@
class V8cNamedGetterInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.cc
index f90afa4..ff6c171 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,221 @@
namespace {
+const int kInterfaceUniqueId = 33;
+
+
+void NamedPropertyGetterCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ if (!impl->CanQueryNamedProperty(property_name)) {
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->NamedGetter(property_name),
+ &result_value);
+ }
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(result_value);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+void NamedPropertyQueryCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ bool result = impl->CanQueryNamedProperty(property_name);
+ if (!result) {
+ return;
+ }
+ // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
+ // 2.7. If |O| implements an interface with a named property setter, then set
+ // desc.[[Writable]] to true, otherwise set it to false.
+ // 2.8. If |O| implements an interface with the
+ // [LegacyUnenumerableNamedProperties] extended attribute, then set
+ // desc.[[Enumerable]] to false, otherwise set it to true.
+ info.GetReturnValue().Set(v8::DontEnum | v8::ReadOnly);
+}
+
+void NamedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+ v8::Local<v8::Array> array = v8::Array::New(isolate);
+ V8cPropertyEnumerator property_enumerator(isolate, &array);
+ impl->EnumerateNamedProperties(&property_enumerator);
+ info.GetReturnValue().Set(array);
+}
+
+
+void NamedPropertySetterCallback(
+ v8::Local<v8::Name> property,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ TypeTraits<std::string>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->NamedSetter(property_name, native_value);
+ result_value = v8::Undefined(isolate);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+
+
+void IndexedPropertyGetterCallback(
+ uint32_t index,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+ if (index >= impl->length()) {
+ // |index| is out of bounds, so return undefined.
+ return;
+ }
+
+ if (!exception_state.is_exception_set()) {
+ ToJSValue(isolate,
+ impl->IndexedGetter(index),
+ &result_value);
+ }
+ info.GetReturnValue().Set(result_value);
+}
+
+void IndexedPropertyDescriptorCallback(
+ uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+void IndexedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+ const uint32_t length = impl->length();
+ v8::Local<v8::Array> array = v8::Array::New(isolate, length);
+ for (uint32_t i = 0; i < length; ++i) {
+ array->Set(i, v8::Integer::New(isolate, i));
+ }
+ info.GetReturnValue().Set(array);
+}
+
+void IndexedPropertyDefinerCallback(
+ uint32_t index, const v8::PropertyDescriptor& desc,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+
+void IndexedPropertySetterCallback(
+ uint32_t index,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state{isolate};
+ v8::Local<v8::Value> result_value;
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+ if (!wrapper_private) {
+ NOTIMPLEMENTED();
+ return;
+ }
+ NamedIndexedGetterInterface* impl =
+ wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+ if (index >= impl->length()) {
+ return;
+ }
+ TypeTraits<uint32_t>::ConversionType native_value;
+ FromJSValue(isolate, value, kNoConversionFlags,
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+
+ impl->IndexedSetter(index, native_value);
+ result_value = v8::Undefined(isolate);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(value);
+}
+
+
void lengthAttributeGetter(
@@ -126,6 +338,7 @@
}
+
void propertyOnBaseClassAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -447,114 +660,352 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "NamedIndexedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "NamedIndexedGetterInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "length",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- lengthAttributeGetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "propertyOnBaseClass",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- propertyOnBaseClassAttributeGetter
- ,propertyOnBaseClassAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "length");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ lengthAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "propertyOnBaseClass");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ propertyOnBaseClassAttributeGetter,
+ propertyOnBaseClassAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "indexedGetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, indexedGetterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "indexedGetter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "indexedSetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, indexedSetterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(2);
+ prototype_template->Set(
+ NewInternalString(isolate, "indexedSetter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "namedGetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, namedGetterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "namedGetter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "namedSetter");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, namedSetterMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(2);
+ prototype_template->Set(
+ NewInternalString(isolate, "namedSetter"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "operationOnBaseClass");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, operationOnBaseClassMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "operationOnBaseClass"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "NamedIndexedGetterInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, indexedGetterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "indexedGetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ v8::NamedPropertyHandlerConfiguration named_property_handler_configuration = {
+ NamedPropertyGetterCallback,
+ NamedPropertySetterCallback,
+ NamedPropertyQueryCallback,
+ nullptr,
+ NamedPropertyEnumeratorCallback,
+ v8::Local<v8::Value>(),
+ static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kNonMasking) | int(v8::PropertyHandlerFlags::kOnlyInterceptStrings))
+ };
+ instance_template->SetHandler(named_property_handler_configuration);
}
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, indexedSetterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "indexedSetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ v8::IndexedPropertyHandlerConfiguration indexed_property_handler_configuration = {
+ IndexedPropertyGetterCallback,
+ IndexedPropertySetterCallback,
+ IndexedPropertyDescriptorCallback,
+ nullptr,
+ IndexedPropertyEnumeratorCallback,
+ IndexedPropertyDefinerCallback
+ };
+ instance_template->SetHandler(indexed_property_handler_configuration);
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, namedGetterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "namedGetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, namedSetterMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "namedSetter",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, operationOnBaseClassMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "operationOnBaseClass",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
-
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 33;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cNamedIndexedGetterInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cNamedIndexedGetterInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -564,14 +1015,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cNamedIndexedGetterInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cNamedIndexedGetterInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.h
index f0d55dc..ea787aa 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.h
@@ -39,8 +39,7 @@
class V8cNamedIndexedGetterInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.cc
index e61240f..e0f5669 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,14 @@
namespace {
+const int kInterfaceUniqueId = 34;
+
+
+
+
+
+
+
void nestedForwardingAttributeAttributeGetter(
@@ -190,53 +195,130 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "NestedPutForwardsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "NestedPutForwardsInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "nestedForwardingAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nestedForwardingAttributeAttributeGetter
- ,nestedForwardingAttributeAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nestedForwardingAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nestedForwardingAttributeAttributeGetter,
+ nestedForwardingAttributeAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 34;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "NestedPutForwardsInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cNestedPutForwardsInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cNestedPutForwardsInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -246,14 +328,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cNestedPutForwardsInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cNestedPutForwardsInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.h
index d052834..25633dc 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.h
@@ -39,8 +39,7 @@
class V8cNestedPutForwardsInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.cc
index ccda656..570064a 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,49 +84,106 @@
namespace {
+const int kInterfaceUniqueId = 35;
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "NoConstructorInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+
+
+
+
+
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "NoConstructorInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "NoConstructorInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
-
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 35;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cNoConstructorInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cNoConstructorInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -139,14 +193,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cNoConstructorInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cNoConstructorInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.h
index b5065a6..7b08cf2 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.h
@@ -39,8 +39,7 @@
class V8cNoConstructorInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.cc
index 640f64e..3bc962c 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,49 +84,106 @@
namespace {
+const int kInterfaceUniqueId = 36;
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "NoInterfaceObjectInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+
+
+
+
+
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "NoInterfaceObjectInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "NoInterfaceObjectInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
-
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 36;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cNoInterfaceObjectInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cNoInterfaceObjectInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -139,14 +193,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cNoInterfaceObjectInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cNoInterfaceObjectInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.h
index cad6f66..77e220c 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.h
@@ -39,7 +39,7 @@
class V8cNoInterfaceObjectInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.cc
index 7cc380e..8ab1042 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,14 @@
namespace {
+const int kInterfaceUniqueId = 37;
+
+
+
+
+
+
+
void nullableBooleanPropertyAttributeGetter(
@@ -167,6 +172,7 @@
return;
}
+
void nullableNumericPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -241,6 +247,7 @@
return;
}
+
void nullableStringPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -315,6 +322,7 @@
return;
}
+
void nullableObjectPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -718,162 +726,496 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "NullableTypesTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "NullableTypesTestInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "nullableBooleanProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nullableBooleanPropertyAttributeGetter
- ,nullableBooleanPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "nullableNumericProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nullableNumericPropertyAttributeGetter
- ,nullableNumericPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "nullableStringProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nullableStringPropertyAttributeGetter
- ,nullableStringPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "nullableObjectProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nullableObjectPropertyAttributeGetter
- ,nullableObjectPropertyAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, nullableBooleanArgumentMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "nullableBooleanArgument",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableBooleanProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nullableBooleanPropertyAttributeGetter,
+ nullableBooleanPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableNumericProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nullableNumericPropertyAttributeGetter,
+ nullableNumericPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableStringProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nullableStringPropertyAttributeGetter,
+ nullableStringPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableObjectProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nullableObjectPropertyAttributeGetter,
+ nullableObjectPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, nullableBooleanOperationMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableBooleanArgument");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, nullableBooleanArgumentMethod);
method_template->RemovePrototype();
+ method_template->SetLength(1);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "nullableBooleanOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "nullableBooleanArgument"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableBooleanOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, nullableBooleanOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "nullableBooleanOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableNumericArgument");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, nullableNumericArgumentMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "nullableNumericArgument"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableNumericOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, nullableNumericOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "nullableNumericOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableObjectArgument");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, nullableObjectArgumentMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "nullableObjectArgument"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableObjectOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, nullableObjectOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "nullableObjectOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableStringArgument");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, nullableStringArgumentMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "nullableStringArgument"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableStringOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, nullableStringOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "nullableStringOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, nullableNumericArgumentMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "nullableNumericArgument",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, nullableNumericOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "nullableNumericOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, nullableObjectArgumentMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "nullableObjectArgument",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, nullableObjectOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "nullableObjectOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, nullableStringArgumentMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "nullableStringArgument",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, nullableStringOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "nullableStringOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "NullableTypesTestInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 37;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cNullableTypesTestInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cNullableTypesTestInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -883,14 +1225,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cNullableTypesTestInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cNullableTypesTestInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.h
index baa094a..0374822 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.h
@@ -39,8 +39,7 @@
class V8cNullableTypesTestInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.cc
index 167152d..e866d90 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 38;
+
+
+
+
+
+
+
void bytePropertyAttributeGetter(
@@ -163,6 +168,7 @@
return;
}
+
void byteClampPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -237,6 +243,7 @@
return;
}
+
void octetPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -311,6 +318,7 @@
return;
}
+
void octetClampPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -385,6 +393,7 @@
return;
}
+
void shortPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -459,6 +468,7 @@
return;
}
+
void shortClampPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -533,6 +543,7 @@
return;
}
+
void unsignedShortPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -607,6 +618,7 @@
return;
}
+
void unsignedShortClampPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -681,6 +693,7 @@
return;
}
+
void longPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -755,6 +768,7 @@
return;
}
+
void longClampPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -829,6 +843,7 @@
return;
}
+
void unsignedLongPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -903,6 +918,7 @@
return;
}
+
void unsignedLongClampPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -977,6 +993,7 @@
return;
}
+
void longLongPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -1051,6 +1068,7 @@
return;
}
+
void longLongClampPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -1125,6 +1143,7 @@
return;
}
+
void unsignedLongLongPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -1199,6 +1218,7 @@
return;
}
+
void unsignedLongLongClampPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -1273,6 +1293,7 @@
return;
}
+
void doublePropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -1347,6 +1368,7 @@
return;
}
+
void unrestrictedDoublePropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -2242,392 +2264,1368 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "NumericTypesTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "NumericTypesTestInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "byteProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- bytePropertyAttributeGetter
- ,bytePropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "byteClampProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- byteClampPropertyAttributeGetter
- ,byteClampPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "octetProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- octetPropertyAttributeGetter
- ,octetPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "octetClampProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- octetClampPropertyAttributeGetter
- ,octetClampPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "shortProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- shortPropertyAttributeGetter
- ,shortPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "shortClampProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- shortClampPropertyAttributeGetter
- ,shortClampPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unsignedShortProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unsignedShortPropertyAttributeGetter
- ,unsignedShortPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unsignedShortClampProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unsignedShortClampPropertyAttributeGetter
- ,unsignedShortClampPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "longProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- longPropertyAttributeGetter
- ,longPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "longClampProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- longClampPropertyAttributeGetter
- ,longClampPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unsignedLongProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unsignedLongPropertyAttributeGetter
- ,unsignedLongPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unsignedLongClampProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unsignedLongClampPropertyAttributeGetter
- ,unsignedLongClampPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "longLongProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- longLongPropertyAttributeGetter
- ,longLongPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "longLongClampProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- longLongClampPropertyAttributeGetter
- ,longLongClampPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unsignedLongLongProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unsignedLongLongPropertyAttributeGetter
- ,unsignedLongLongPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unsignedLongLongClampProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unsignedLongLongClampPropertyAttributeGetter
- ,unsignedLongLongClampPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "doubleProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- doublePropertyAttributeGetter
- ,doublePropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unrestrictedDoubleProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unrestrictedDoublePropertyAttributeGetter
- ,unrestrictedDoublePropertyAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, byteArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "byteArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "byteProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ bytePropertyAttributeGetter,
+ bytePropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "byteClampProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ byteClampPropertyAttributeGetter,
+ byteClampPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "octetProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ octetPropertyAttributeGetter,
+ octetPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "octetClampProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ octetClampPropertyAttributeGetter,
+ octetClampPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "shortProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ shortPropertyAttributeGetter,
+ shortPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "shortClampProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ shortClampPropertyAttributeGetter,
+ shortClampPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedShortProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unsignedShortPropertyAttributeGetter,
+ unsignedShortPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedShortClampProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unsignedShortClampPropertyAttributeGetter,
+ unsignedShortClampPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ longPropertyAttributeGetter,
+ longPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longClampProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ longClampPropertyAttributeGetter,
+ longClampPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedLongProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unsignedLongPropertyAttributeGetter,
+ unsignedLongPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedLongClampProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unsignedLongClampPropertyAttributeGetter,
+ unsignedLongClampPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longLongProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ longLongPropertyAttributeGetter,
+ longLongPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longLongClampProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ longLongClampPropertyAttributeGetter,
+ longLongClampPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedLongLongProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unsignedLongLongPropertyAttributeGetter,
+ unsignedLongLongPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedLongLongClampProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unsignedLongLongClampPropertyAttributeGetter,
+ unsignedLongLongClampPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "doubleProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ doublePropertyAttributeGetter,
+ doublePropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unrestrictedDoubleProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unrestrictedDoublePropertyAttributeGetter,
+ unrestrictedDoublePropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, byteReturnOperationMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "byteArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, byteArgumentOperationMethod);
method_template->RemovePrototype();
+ method_template->SetLength(1);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "byteReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "byteArgumentOperation"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "byteReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, byteReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "byteReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "doubleArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, doubleArgumentOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "doubleArgumentOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "doubleReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, doubleReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "doubleReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, longArgumentOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "longArgumentOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longLongArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, longLongArgumentOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "longLongArgumentOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longLongReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, longLongReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "longLongReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, longReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "longReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "octetArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, octetArgumentOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "octetArgumentOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "octetReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, octetReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "octetReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "shortArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, shortArgumentOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "shortArgumentOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "shortReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, shortReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "shortReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unrestrictedDoubleArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, unrestrictedDoubleArgumentOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "unrestrictedDoubleArgumentOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unrestrictedDoubleReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, unrestrictedDoubleReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "unrestrictedDoubleReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedLongArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, unsignedLongArgumentOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "unsignedLongArgumentOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedLongLongArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, unsignedLongLongArgumentOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "unsignedLongLongArgumentOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedLongLongReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, unsignedLongLongReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "unsignedLongLongReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedLongReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, unsignedLongReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "unsignedLongReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedShortArgumentOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, unsignedShortArgumentOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "unsignedShortArgumentOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unsignedShortReturnOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, unsignedShortReturnOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "unsignedShortReturnOperation"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, doubleArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "doubleArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, doubleReturnOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "doubleReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, longArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "longArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, longLongArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "longLongArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, longLongReturnOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "longLongReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, longReturnOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "longReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, octetArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "octetArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, octetReturnOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "octetReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, shortArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "shortArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, shortReturnOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "shortReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unrestrictedDoubleArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "unrestrictedDoubleArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unrestrictedDoubleReturnOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "unrestrictedDoubleReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedLongArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "unsignedLongArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedLongLongArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "unsignedLongLongArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedLongLongReturnOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "unsignedLongLongReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedLongReturnOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "unsignedLongReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedShortArgumentOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "unsignedShortArgumentOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedShortReturnOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "unsignedShortReturnOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "NumericTypesTestInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 38;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cNumericTypesTestInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cNumericTypesTestInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -2637,14 +3635,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cNumericTypesTestInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cNumericTypesTestInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.h
index 5f80b25..1a65152 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.h
@@ -39,8 +39,7 @@
class V8cNumericTypesTestInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.cc
index f99b365..de2e838 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.cc
@@ -39,12 +39,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -70,7 +72,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -78,18 +79,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -99,6 +96,14 @@
namespace {
+const int kInterfaceUniqueId = 39;
+
+
+
+
+
+
+
void arbitraryObjectAttributeGetter(
@@ -175,6 +180,7 @@
return;
}
+
void baseInterfaceAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -212,6 +218,7 @@
}
+
void derivedInterfaceAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -286,6 +293,7 @@
return;
}
+
void objectPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -361,73 +369,232 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "ObjectTypeBindingsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "ObjectTypeBindingsInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "arbitraryObject",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- arbitraryObjectAttributeGetter
- ,arbitraryObjectAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "baseInterface",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- baseInterfaceAttributeGetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "derivedInterface",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- derivedInterfaceAttributeGetter
- ,derivedInterfaceAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "objectProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- objectPropertyAttributeGetter
- ,objectPropertyAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "arbitraryObject");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ arbitraryObjectAttributeGetter,
+ arbitraryObjectAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 39;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "baseInterface");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ baseInterfaceAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "derivedInterface");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ derivedInterfaceAttributeGetter,
+ derivedInterfaceAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "objectProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ objectPropertyAttributeGetter,
+ objectPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "ObjectTypeBindingsInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cObjectTypeBindingsInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cObjectTypeBindingsInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -437,14 +604,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cObjectTypeBindingsInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cObjectTypeBindingsInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.h
index b17754e..7ddbe67 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.h
@@ -39,8 +39,7 @@
class V8cObjectTypeBindingsInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.cc
index 4d404e0..93a3e46 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,13 @@
namespace {
+const int kInterfaceUniqueId = 40;
+
+
+
+
+
+
@@ -1244,200 +1248,592 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "OperationsTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "OperationsTestInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, longFunctionNoArgsMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "longFunctionNoArgs");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, longFunctionNoArgsMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "longFunctionNoArgs",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "longFunctionNoArgs"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "objectFunctionNoArgs");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, objectFunctionNoArgsMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "objectFunctionNoArgs"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "optionalArgumentWithDefault");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, optionalArgumentWithDefaultMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "optionalArgumentWithDefault"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "optionalArguments");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, optionalArgumentsMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "optionalArguments"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "optionalNullableArgumentsWithDefaults");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, optionalNullableArgumentsWithDefaultsMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "optionalNullableArgumentsWithDefaults"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "overloadedFunction");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, overloadedFunctionMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "overloadedFunction"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "overloadedNullable");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, overloadedNullableMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "overloadedNullable"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "stringFunctionNoArgs");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, stringFunctionNoArgsMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "stringFunctionNoArgs"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "variadicPrimitiveArguments");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, variadicPrimitiveArgumentsMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "variadicPrimitiveArguments"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "variadicStringArgumentsAfterOptionalArgument");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, variadicStringArgumentsAfterOptionalArgumentMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "variadicStringArgumentsAfterOptionalArgument"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "voidFunctionLongArg");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, voidFunctionLongArgMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "voidFunctionLongArg"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "voidFunctionNoArgs");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, voidFunctionNoArgsMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "voidFunctionNoArgs"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "voidFunctionObjectArg");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, voidFunctionObjectArgMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "voidFunctionObjectArg"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "voidFunctionStringArg");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, voidFunctionStringArgMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "voidFunctionStringArg"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "overloadedFunction");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // If the operation is static, then the property exists on the interface
+ // object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, overloadedFunctionStaticMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ function_template->Set(
+ NewInternalString(isolate, "overloadedFunction"),
+ method_template);
+
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, objectFunctionNoArgsMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "objectFunctionNoArgs",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, optionalArgumentWithDefaultMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "optionalArgumentWithDefault",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, optionalArgumentsMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "optionalArguments",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, optionalNullableArgumentsWithDefaultsMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "optionalNullableArgumentsWithDefaults",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, overloadedFunctionMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "overloadedFunction",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, overloadedNullableMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "overloadedNullable",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, stringFunctionNoArgsMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "stringFunctionNoArgs",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, variadicPrimitiveArgumentsMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "variadicPrimitiveArguments",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, variadicStringArgumentsAfterOptionalArgumentMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "variadicStringArgumentsAfterOptionalArgument",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, voidFunctionLongArgMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "voidFunctionLongArg",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, voidFunctionNoArgsMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "voidFunctionNoArgs",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, voidFunctionObjectArgMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "voidFunctionObjectArg",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, voidFunctionStringArgMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "voidFunctionStringArg",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "OperationsTestInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 40;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cOperationsTestInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cOperationsTestInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -1447,14 +1843,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cOperationsTestInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cOperationsTestInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.h
index 782fac0..7d1fe92 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.h
@@ -39,8 +39,7 @@
class V8cOperationsTestInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.cc
index f506f7c..88abc4d 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,13 @@
namespace {
+const int kInterfaceUniqueId = 41;
+
+
+
+
+
+
@@ -264,101 +268,261 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "PromiseInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "PromiseInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, onSuccessMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "onSuccess");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, onSuccessMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "onSuccess",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "onSuccess"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "returnBooleanPromise");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, returnBooleanPromiseMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "returnBooleanPromise"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "returnInterfacePromise");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, returnInterfacePromiseMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "returnInterfacePromise"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "returnStringPromise");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, returnStringPromiseMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "returnStringPromise"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "returnVoidPromise");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, returnVoidPromiseMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "returnVoidPromise"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, returnBooleanPromiseMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "returnBooleanPromise",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, returnInterfacePromiseMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "returnInterfacePromise",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, returnStringPromiseMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "returnStringPromise",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, returnVoidPromiseMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "returnVoidPromise",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "PromiseInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 41;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cPromiseInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cPromiseInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -368,14 +532,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cPromiseInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cPromiseInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.h
index dc20fe6..e533a30 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.h
@@ -39,8 +39,7 @@
class V8cPromiseInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.cc
index 3b85279..ee735c0 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,14 @@
namespace {
+const int kInterfaceUniqueId = 42;
+
+
+
+
+
+
+
void forwardingAttributeAttributeGetter(
@@ -178,6 +183,7 @@
} // End scope of scoped_refptr<ArbitraryInterface> forwarded_impl.
}
+
void staticForwardingAttributeStaticAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -231,53 +237,168 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "PutForwardsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "PutForwardsInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "forwardingAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- forwardingAttributeAttributeGetter
- ,forwardingAttributeAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "forwardingAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ forwardingAttributeAttributeGetter,
+ forwardingAttributeAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 42;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "staticForwardingAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Operations installed on the interface object must be static methods, so
+ // no need to specify a signature, i.e. no need to do type check against a
+ // holder.
+
+ // If the attribute is a static attribute, then there is a single
+ // corresponding property and it exists on the interface's interface object.
+ function_template->SetNativeDataProperty(
+ name,
+ staticForwardingAttributeStaticAttributeGetter,
+ staticForwardingAttributeStaticAttributeSetter,
+ v8::Local<v8::Value>(),
+ attributes);
+
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "PutForwardsInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cPutForwardsInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cPutForwardsInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -287,14 +408,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cPutForwardsInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cPutForwardsInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.h
index 7d6e2da..093d146 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.h
@@ -39,8 +39,7 @@
class V8cPutForwardsInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.cc
index 465ef2e..ec73494 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,14 @@
namespace {
+const int kInterfaceUniqueId = 43;
+
+
+
+
+
+
+
void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -111,7 +116,6 @@
-
void getInterfaceSequenceMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::Object> object = info.This();
@@ -685,200 +689,559 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "SequenceUser",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetLength(0);
+ function_template->SetClassName(NewInternalString(isolate, "SequenceUser"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getInterfaceSequenceMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getInterfaceSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getInterfaceSequenceMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getInterfaceSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "getInterfaceSequence"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getInterfaceSequenceSequenceSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getInterfaceSequenceSequenceSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "getInterfaceSequenceSequenceSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getLongSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getLongSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "getLongSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getStringSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getStringSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "getStringSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getStringSequenceSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getStringSequenceSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "getStringSequenceSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getUnionOfStringAndStringSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getUnionOfStringAndStringSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "getUnionOfStringAndStringSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getUnionSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getUnionSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "getUnionSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setInterfaceSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setInterfaceSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setInterfaceSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setInterfaceSequenceSequenceSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setInterfaceSequenceSequenceSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setInterfaceSequenceSequenceSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setLongSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setLongSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setLongSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setStringSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setStringSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setStringSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setStringSequenceSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setStringSequenceSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setStringSequenceSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setUnionOfStringAndStringSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setUnionOfStringAndStringSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setUnionOfStringAndStringSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setUnionSequence");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setUnionSequenceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ prototype_template->Set(
+ NewInternalString(isolate, "setUnionSequence"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getInterfaceSequenceSequenceSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getInterfaceSequenceSequenceSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getLongSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getLongSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getStringSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getStringSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getStringSequenceSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getStringSequenceSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getUnionOfStringAndStringSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getUnionOfStringAndStringSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getUnionSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getUnionSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setInterfaceSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setInterfaceSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setInterfaceSequenceSequenceSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setInterfaceSequenceSequenceSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setLongSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setLongSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setStringSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setStringSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setStringSequenceSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setStringSequenceSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setUnionOfStringAndStringSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setUnionOfStringAndStringSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
-
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setUnionSequenceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setUnionSequence",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "SequenceUser"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 43;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cSequenceUser::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cSequenceUser::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -888,14 +1251,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cSequenceUser::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cSequenceUser::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.h
index b13e2e9..48eac36 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.h
@@ -39,8 +39,7 @@
class V8cSequenceUser {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.cc
index 3ff1a99..f5b78d7 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.cc
@@ -26,6 +26,7 @@
#include "cobalt/script/logging_exception_state.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/v8c_callback_interface.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
#include "v8/include/v8.h"
@@ -40,6 +41,7 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::FromJSValue;
using cobalt::script::v8c::GetCallableForCallbackInterface;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::V8cGlobalEnvironment;
} // namespace
@@ -52,53 +54,52 @@
const scoped_refptr<script::Wrappable>& callback_this,
const scoped_refptr<ArbitraryInterface>& value,
bool* had_exception) const {
+ bool success = false;
base::optional<int32_t > cobalt_return_value;
- DCHECK(!this->IsEmpty());
DCHECK(isolate_);
+ if (this->IsEmpty()) {
+ goto done;
+ }
+ {
+ EntryScope entry_scope(isolate_);
+ v8::Local<v8::Context> context = isolate_->GetCurrentContext();
+ v8::TryCatch try_catch(isolate_);
- EntryScope entry_scope(isolate_);
- v8::Local<v8::Context> context = isolate_->GetCurrentContext();
+ v8::Local<v8::Value> implementing_value = this->NewLocal(isolate_);
+ if (!implementing_value->IsObject()) {
+ LOG(WARNING) << "Implementing object is NULL";
+ goto done;
+ }
- v8::MaybeLocal<v8::Object> maybe_implementing_object = this->NewLocal(isolate_)->ToObject(context);
- v8::Local<v8::Object> implementing_object;
- if (!maybe_implementing_object.ToLocal(&implementing_object)) {
- *had_exception = true;
- return cobalt_return_value;
+ v8::Local<v8::Function> callable;
+ if (!GetCallableForCallbackInterface(
+ isolate_, implementing_value.As<v8::Object>(),
+ NewInternalString(isolate_, "handleCallback"))
+ .ToLocal(&callable)) {
+ goto done;
+ }
+
+ v8::Local<v8::Value> this_value;
+ ToJSValue(isolate_, callback_this, &this_value);
+
+ const int kNumArguments = 1;
+ v8::Local<v8::Value> argv[kNumArguments];
+ ToJSValue(isolate_, value, &argv[0]);
+
+ v8::Local<v8::Value> return_value;
+ if (!callable->Call(context, this_value, kNumArguments, argv)
+ .ToLocal(&return_value)) {
+ goto done;
+ }
+ LoggingExceptionState exception_state;
+ FromJSValue(isolate_, return_value, 0, &exception_state,
+ &cobalt_return_value);
+ success = !exception_state.is_exception_set();
}
- v8::MaybeLocal<v8::Object> maybe_callable =
- GetCallableForCallbackInterface(isolate_, implementing_object, "handleCallback");
- v8::Local<v8::Object> callable;
- if (!maybe_callable.ToLocal(&callable)) {
- NOTIMPLEMENTED();
- *had_exception = true;
- return cobalt_return_value;
- }
- DCHECK(callable->IsCallable());
-
- v8::Local<v8::Value> this_value;
- ToJSValue(isolate_, callback_this, &this_value);
-
- const int kNumArguments = 1;
- v8::Local<v8::Value> argv[kNumArguments];
-
- ToJSValue(isolate_, value, &argv[0]);
-
- v8::MaybeLocal<v8::Value> maybe_return_value =
- callable->CallAsFunction(isolate_->GetCurrentContext(), this_value, kNumArguments, argv);
- v8::Local<v8::Value> return_value;
- if (!maybe_return_value.ToLocal(&return_value)) {
- *had_exception = true;
- return cobalt_return_value;
- }
-
- LoggingExceptionState exception_state;
- FromJSValue(isolate_, return_value, 0, &exception_state, &cobalt_return_value);
- if (exception_state.is_exception_set()) {
- *had_exception = true;
- }
-
+done:
+ *had_exception = !success;
return cobalt_return_value;
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.cc
index f454dde..491198b 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.cc
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -62,7 +64,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -70,18 +71,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -91,6 +88,14 @@
namespace {
+const int kInterfaceUniqueId = 45;
+
+
+
+
+
+
+
void staticAttributeStaticAttributeGetter(
@@ -370,46 +375,168 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "StaticPropertiesInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "StaticPropertiesInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "staticAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Operations installed on the interface object must be static methods, so
+ // no need to specify a signature, i.e. no need to do type check against a
+ // holder.
+
+ // If the attribute is a static attribute, then there is a single
+ // corresponding property and it exists on the interface's interface object.
+ function_template->SetNativeDataProperty(
+ name,
+ staticAttributeStaticAttributeGetter,
+ staticAttributeStaticAttributeSetter,
+ v8::Local<v8::Value>(),
+ attributes);
+
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "staticFunction");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // If the operation is static, then the property exists on the interface
+ // object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, staticFunctionStaticMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ function_template->Set(
+ NewInternalString(isolate, "staticFunction"),
+ method_template);
+
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "StaticPropertiesInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
-
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 45;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cStaticPropertiesInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cStaticPropertiesInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -419,14 +546,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cStaticPropertiesInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cStaticPropertiesInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.h
index c95919c..4a767c1 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.h
@@ -39,8 +39,7 @@
class V8cStaticPropertiesInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.cc
index b3bc42b..2afe72f 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,49 +84,145 @@
namespace {
+const int kInterfaceUniqueId = 46;
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "StringifierAnonymousOperationInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+
+
+
+
+
+void Stringifier(v8::Local<v8::String> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state(isolate);
+
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
+ if (!wrapper_factory->DoesObjectImplementInterface(
+ object, base::GetTypeId<StringifierAnonymousOperationInterface>())) {
+ V8cExceptionState exception(isolate);
+ exception.SetSimpleException(script::kDoesNotImplementInterface);
+ return;
+ }
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+
+ // |WrapperPrivate::GetFromObject| can fail if |object| is not a |Wrapper|
+ // object.
+ if (!wrapper_private) {
+ exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
+ return;
+ }
+
+ StringifierAnonymousOperationInterface* impl =
+ wrapper_private->wrappable<StringifierAnonymousOperationInterface>().get();
+ if (!impl) {
+ exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
+ NOTREACHED();
+ return;
+ }
+ std::string stringified = impl->AnonymousStringifier();
+
+ v8::Local<v8::Value> v8_stringified;
+ ToJSValue(isolate, stringified, &v8_stringified);
+
+ info.GetReturnValue().Set(v8_stringified);
+}
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "StringifierAnonymousOperationInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "StringifierAnonymousOperationInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
-
- interface_data->function_template.Set(isolate, function_template);
-}
-
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 46;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cStringifierAnonymousOperationInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cStringifierAnonymousOperationInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -139,14 +232,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cStringifierAnonymousOperationInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cStringifierAnonymousOperationInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.h
index 2034125..250fba9 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.h
@@ -39,8 +39,7 @@
class V8cStringifierAnonymousOperationInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.cc
index 9b3a293..bdfb6ec 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,14 @@
namespace {
+const int kInterfaceUniqueId = 47;
+
+
+
+
+
+
+
void theStringifierAttributeAttributeGetter(
@@ -164,53 +169,169 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "StringifierAttributeInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+void Stringifier(v8::Local<v8::String> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state(isolate);
+
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
+ if (!wrapper_factory->DoesObjectImplementInterface(
+ object, base::GetTypeId<StringifierAttributeInterface>())) {
+ V8cExceptionState exception(isolate);
+ exception.SetSimpleException(script::kDoesNotImplementInterface);
+ return;
+ }
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+
+ // |WrapperPrivate::GetFromObject| can fail if |object| is not a |Wrapper|
+ // object.
+ if (!wrapper_private) {
+ exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
+ return;
+ }
+
+ StringifierAttributeInterface* impl =
+ wrapper_private->wrappable<StringifierAttributeInterface>().get();
+ if (!impl) {
+ exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
+ NOTREACHED();
+ return;
+ }
+ std::string stringified = impl->the_stringifier_attribute();
+
+ v8::Local<v8::Value> v8_stringified;
+ ToJSValue(isolate, stringified, &v8_stringified);
+
+ info.GetReturnValue().Set(v8_stringified);
+}
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "StringifierAttributeInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "theStringifierAttribute",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- theStringifierAttributeAttributeGetter
- ,theStringifierAttributeAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "theStringifierAttribute");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ theStringifierAttributeAttributeGetter,
+ theStringifierAttributeAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 47;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "StringifierAttributeInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cStringifierAttributeInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cStringifierAttributeInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -220,14 +341,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cStringifierAttributeInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cStringifierAttributeInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.h
index 2af0546..954bea1 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.h
@@ -39,8 +39,7 @@
class V8cStringifierAttributeInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.cc
index 3096de4..3954c44 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,13 @@
namespace {
+const int kInterfaceUniqueId = 48;
+
+
+
+
+
+
@@ -126,57 +130,168 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "StringifierOperationInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+void Stringifier(v8::Local<v8::String> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state(isolate);
+
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
+ if (!wrapper_factory->DoesObjectImplementInterface(
+ object, base::GetTypeId<StringifierOperationInterface>())) {
+ V8cExceptionState exception(isolate);
+ exception.SetSimpleException(script::kDoesNotImplementInterface);
+ return;
+ }
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+
+ // |WrapperPrivate::GetFromObject| can fail if |object| is not a |Wrapper|
+ // object.
+ if (!wrapper_private) {
+ exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
+ return;
+ }
+
+ StringifierOperationInterface* impl =
+ wrapper_private->wrappable<StringifierOperationInterface>().get();
+ if (!impl) {
+ exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
+ NOTREACHED();
+ return;
+ }
+ std::string stringified = impl->TheStringifierOperation();
+
+ v8::Local<v8::Value> v8_stringified;
+ ToJSValue(isolate, stringified, &v8_stringified);
+
+ info.GetReturnValue().Set(v8_stringified);
+}
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "StringifierOperationInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, theStringifierOperationMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "theStringifierOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, theStringifierOperationMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "theStringifierOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "theStringifierOperation"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "StringifierOperationInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 48;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+
}
} // namespace
-v8::Local<v8::Object> V8cStringifierOperationInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cStringifierOperationInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -186,14 +301,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cStringifierOperationInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cStringifierOperationInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.h
index d8bde96..8cbb7df 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.h
@@ -39,8 +39,7 @@
class V8cStringifierOperationInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.cc
index 70950ab..5e0cdbf 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.cc
@@ -33,12 +33,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -58,7 +60,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -66,18 +67,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -87,6 +84,13 @@
namespace {
+const int kInterfaceUniqueId = 49;
+
+
+
+
+
+
@@ -150,68 +154,162 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "TargetInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "TargetInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, implementedInterfaceFunctionMethod);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "implementedInterfaceFunction");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, implementedInterfaceFunctionMethod);
method_template->RemovePrototype();
+ method_template->SetLength(0);
prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "implementedInterfaceFunction",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ NewInternalString(isolate, "implementedInterfaceFunction"),
method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "partialInterfaceFunction");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, partialInterfaceFunctionMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ prototype_template->Set(
+ NewInternalString(isolate, "partialInterfaceFunction"),
+ method_template);
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
}
- {
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, partialInterfaceFunctionMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "partialInterfaceFunction",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "TargetInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
- interface_data->function_template.Set(isolate, function_template);
-}
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 49;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
} // namespace
-v8::Local<v8::Object> V8cTargetInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cTargetInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -221,14 +319,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cTargetInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cTargetInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.h
index 43d3d35..5ebf82e 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.h
@@ -39,8 +39,7 @@
class V8cTargetInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_enum.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_enum.cc
index 37d454c..2d077b1 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_enum.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_enum.cc
@@ -25,6 +25,7 @@
#include "v8c_gen_type_conversion.h"
#include "base/logging.h"
#include "cobalt/script/exception_state.h"
+#include "cobalt/script/v8c/helpers.h"
#include "v8/include/v8.h"
using cobalt::bindings::testing::TestEnum;
@@ -82,37 +83,37 @@
bool match = false;
// 3. Return the enumeration value of type E that is equal to S.
if (
- v8::String::NewFromUtf8(isolate, "alpha", v8::NewStringType::kInternalized).ToLocalChecked()->Equals(value))
+ NewInternalString(isolate, "alpha")->Equals(value))
{
*out_enum = cobalt::bindings::testing::kTestEnumAlpha;
}
else if (
- v8::String::NewFromUtf8(isolate, "beta", v8::NewStringType::kInternalized).ToLocalChecked()->Equals(value))
+ NewInternalString(isolate, "beta")->Equals(value))
{
*out_enum = cobalt::bindings::testing::kTestEnumBeta;
}
else if (
- v8::String::NewFromUtf8(isolate, "gamma", v8::NewStringType::kInternalized).ToLocalChecked()->Equals(value))
+ NewInternalString(isolate, "gamma")->Equals(value))
{
*out_enum = cobalt::bindings::testing::kTestEnumGamma;
}
else if (
- v8::String::NewFromUtf8(isolate, "enum-with-dashes", v8::NewStringType::kInternalized).ToLocalChecked()->Equals(value))
+ NewInternalString(isolate, "enum-with-dashes")->Equals(value))
{
*out_enum = cobalt::bindings::testing::kTestEnumEnumWithDashes;
}
else if (
- v8::String::NewFromUtf8(isolate, "enum with spaces", v8::NewStringType::kInternalized).ToLocalChecked()->Equals(value))
+ NewInternalString(isolate, "enum with spaces")->Equals(value))
{
*out_enum = cobalt::bindings::testing::kTestEnumEnumWithSpaces;
}
else if (
- v8::String::NewFromUtf8(isolate, "terrible----enum", v8::NewStringType::kInternalized).ToLocalChecked()->Equals(value))
+ NewInternalString(isolate, "terrible----enum")->Equals(value))
{
*out_enum = cobalt::bindings::testing::kTestEnumTerribleEnum;
}
else if (
- v8::String::NewFromUtf8(isolate, "this is a terrible @#$%#$% enum", v8::NewStringType::kInternalized).ToLocalChecked()->Equals(value))
+ NewInternalString(isolate, "this is a terrible @#$%#$% enum")->Equals(value))
{
*out_enum = cobalt::bindings::testing::kTestEnumThisIsATerribleEnum;
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.cc
index 1322f56..4700703 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.cc
@@ -37,12 +37,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -66,7 +68,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -74,18 +75,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -95,6 +92,14 @@
namespace {
+const int kInterfaceUniqueId = 51;
+
+
+
+
+
+
+
void unionPropertyAttributeGetter(
@@ -171,6 +176,7 @@
return;
}
+
void unionWithNullableMemberPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -245,6 +251,7 @@
return;
}
+
void nullableUnionPropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -319,6 +326,7 @@
return;
}
+
void unionBasePropertyAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -394,74 +402,232 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "UnionTypesInterface",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "UnionTypesInterface"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unionProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unionPropertyAttributeGetter
- ,unionPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unionWithNullableMemberProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unionWithNullableMemberPropertyAttributeGetter
- ,unionWithNullableMemberPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "nullableUnionProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- nullableUnionPropertyAttributeGetter
- ,nullableUnionPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "unionBaseProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- unionBasePropertyAttributeGetter
- ,unionBasePropertyAttributeSetter
- );
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unionProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unionPropertyAttributeGetter,
+ unionPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 51;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unionWithNullableMemberProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unionWithNullableMemberPropertyAttributeGetter,
+ unionWithNullableMemberPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "nullableUnionProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ nullableUnionPropertyAttributeGetter,
+ nullableUnionPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "unionBaseProperty");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ unionBasePropertyAttributeGetter,
+ unionBasePropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+ }
+
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "UnionTypesInterface"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cUnionTypesInterface::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+
+v8::Local<v8::Object> V8cUnionTypesInterface::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -471,14 +637,13 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> V8cUnionTypesInterface::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cUnionTypesInterface::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.h
index 515c0be..416e149 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.h
@@ -39,8 +39,7 @@
class V8cUnionTypesInterface {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.cc
index e83ec7a..f50864a 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.cc
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.cc
@@ -133,12 +133,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -266,7 +268,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -274,18 +275,14 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
} // namespace
namespace cobalt {
@@ -295,6 +292,14 @@
namespace {
+const int kInterfaceUniqueId = 53;
+
+
+
+
+
+
+
void windowPropertyAttributeGetter(
@@ -371,6 +376,7 @@
return;
}
+
void windowAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -408,6 +414,7 @@
}
+
void onEventAttributeGetter(
v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
@@ -636,118 +643,322 @@
}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "Window",
- v8::NewStringType::kInternalized).ToLocalChecked());
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+ function_template->SetClassName(NewInternalString(isolate, "Window"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
- v8::Local<v8::FunctionTemplate> parent_template = V8cGlobalInterfaceParent::CreateTemplate(isolate);
- function_template->Inherit(parent_template);
-
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
-
-
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "windowProperty",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- windowPropertyAttributeGetter
- ,windowPropertyAttributeSetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "window",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- windowAttributeGetter
- );
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "onEvent",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- onEventAttributeGetter
- ,onEventAttributeSetter
- );
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, getStackTraceMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "getStackTrace",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // An interface can be defined to inherit from another interface. If the
+ // identifier of the interface is followed by a U+003A COLON (":") character
+ // and an identifier, then that identifier identifies the inherited
+ // interface. An object that implements an interface that inherits from
+ // another also implements that inherited interface. The object therefore
+ // will also have members that correspond to the interface members from the
+ // inherited interface.
+ v8::Local<v8::FunctionTemplate> parent_template = V8cGlobalInterfaceParent::GetTemplate(isolate);
+ function_template->Inherit(parent_template);
}
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
+
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, setTimeoutMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "setTimeout",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
- }
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "windowProperty");
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, if the attribute is unforgeable on the interface or if the
+ // interface was declared with the [Global] extended attribute, then the
+ // property exists on every object that implements the interface.
+ instance_template->SetAccessor(
+ name,
+ windowPropertyAttributeGetter,
+ windowPropertyAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+
+ }
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, windowOperationMethod);
- method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "windowOperation",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- method_template);
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "window");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, if the attribute is unforgeable on the interface or if the
+ // interface was declared with the [Global] extended attribute, then the
+ // property exists on every object that implements the interface.
+ instance_template->SetAccessor(
+ name,
+ windowAttributeGetter,
+ 0,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+
+ }
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "onEvent");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+
+ // The location of the property is determined as follows:
+ // Otherwise, if the attribute is unforgeable on the interface or if the
+ // interface was declared with the [Global] extended attribute, then the
+ // property exists on every object that implements the interface.
+ instance_template->SetAccessor(
+ name,
+ onEventAttributeGetter,
+ onEventAttributeSetter,
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+
}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "getStackTrace");
- interface_data->function_template.Set(isolate, function_template);
-}
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = 53;
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+ // The location of the property is determined as follows:
+ // Otherwise, if the operation is unforgeable on the interface or if the
+ // interface was declared with the [Global] extended attribute, then the
+ // property exists on every object that implements the interface.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, getStackTraceMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ instance_template->Set(
+ NewInternalString(isolate, "getStackTrace"),
+ method_template);
+
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "setTimeout");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, if the operation is unforgeable on the interface or if the
+ // interface was declared with the [Global] extended attribute, then the
+ // property exists on every object that implements the interface.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, setTimeoutMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(1);
+ instance_template->Set(
+ NewInternalString(isolate, "setTimeout"),
+ method_template);
+
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+ {
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "windowOperation");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = true;
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+ // Otherwise, if the operation is unforgeable on the interface or if the
+ // interface was declared with the [Global] extended attribute, then the
+ // property exists on every object that implements the interface.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, windowOperationMethod);
+ method_template->RemovePrototype();
+ method_template->SetLength(0);
+ instance_template->Set(
+ NewInternalString(isolate, "windowOperation"),
+ method_template);
+
+
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "Window"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+
+
+
}
} // namespace
-v8::Local<v8::Object> V8cWindow::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
- EscapableEntryScope entry_scope(isolate);
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- DCHECK(!interface_data->function_template.IsEmpty());
-
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
- DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
- v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
- DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
-
- // This |WrapperPrivate|'s lifetime will be managed by V8.
- new WrapperPrivate(isolate, wrappable, object);
- return entry_scope.Escape(object);
+// The global interface is special. Just give them the global object proxy.
+v8::Local<v8::Object> V8cWindow::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>&) {
+ return isolate->GetCurrentContext()->Global();
}
-v8::Local<v8::FunctionTemplate> V8cWindow::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> V8cWindow::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
@@ -764,260 +975,11 @@
void V8cGlobalEnvironment::CreateGlobalObject(
const scoped_refptr<GlobalInterface>& global_interface,
EnvironmentSettings* environment_settings) {
+ TRACE_EVENT0("cobalt::script", "V8cGlobalEnvironment::CreateGlobalObject()");
// Intentionally not an |EntryScope|, since the context doesn't exist yet.
v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope handle_scope(isolate_);
- v8::Local<v8::ObjectTemplate> global_object_template = V8cWindow::CreateTemplate(isolate_)->InstanceTemplate();
-
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "AnonymousIndexedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cAnonymousIndexedGetterInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "AnonymousNamedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cAnonymousNamedGetterInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "AnonymousNamedIndexedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cAnonymousNamedIndexedGetterInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ArbitraryInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cArbitraryInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "BaseInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cBaseInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "BooleanTypeTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cBooleanTypeTestInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "CallbackFunctionInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cCallbackFunctionInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "CallbackInterfaceInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cCallbackInterfaceInterface::CreateTemplate(isolate_));
-#if defined(ENABLE_CONDITIONAL_INTERFACE)
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ConditionalInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cConditionalInterface::CreateTemplate(isolate_));
-#endif // defined(ENABLE_CONDITIONAL_INTERFACE)
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ConstantsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cConstantsInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ConstructorInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cConstructorInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ConstructorWithArgumentsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cConstructorWithArgumentsInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "DOMStringTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cDOMStringTestInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "DerivedGetterSetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cDerivedGetterSetterInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "DerivedInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cDerivedInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "DictionaryInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cDictionaryInterface::CreateTemplate(isolate_));
-#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "DisabledInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cDisabledInterface::CreateTemplate(isolate_));
-#endif // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "EnumerationInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cEnumerationInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ExceptionObjectInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cExceptionObjectInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ExceptionsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cExceptionsInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ExtendedIDLAttributesInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cExtendedIDLAttributesInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "GarbageCollectionTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cGarbageCollectionTestInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "GlobalInterfaceParent",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cGlobalInterfaceParent::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ImplementedInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cImplementedInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "IndexedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cIndexedGetterInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "InterfaceWithAny",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cInterfaceWithAny::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "InterfaceWithAnyDictionary",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cInterfaceWithAnyDictionary::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "InterfaceWithDate",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cInterfaceWithDate::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "InterfaceWithUnsupportedProperties",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cInterfaceWithUnsupportedProperties::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "NamedConstructorInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cNamedConstructorInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "NamedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cNamedGetterInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "NamedIndexedGetterInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cNamedIndexedGetterInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "NestedPutForwardsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cNestedPutForwardsInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "NoConstructorInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cNoConstructorInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "NoInterfaceObjectInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cNoInterfaceObjectInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "NullableTypesTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cNullableTypesTestInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "NumericTypesTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cNumericTypesTestInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "ObjectTypeBindingsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cObjectTypeBindingsInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "OperationsTestInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cOperationsTestInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "PromiseInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cPromiseInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "PutForwardsInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cPutForwardsInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "SequenceUser",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cSequenceUser::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "StaticPropertiesInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cStaticPropertiesInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "StringifierAnonymousOperationInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cStringifierAnonymousOperationInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "StringifierAttributeInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cStringifierAttributeInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "StringifierOperationInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cStringifierOperationInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "TargetInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cTargetInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "UnionTypesInterface",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cUnionTypesInterface::CreateTemplate(isolate_));
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "Window",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8cWindow::CreateTemplate(isolate_));
+ v8::Local<v8::ObjectTemplate> global_object_template = V8cWindow::GetTemplate(isolate_)->InstanceTemplate();
v8::Local<v8::Context> context =
v8::Context::New(isolate_, nullptr, global_object_template);
@@ -1029,207 +991,212 @@
environment_settings_ = environment_settings;
EvaluateAutomatics();
+ v8::Local<v8::Object> global_object = context->Global();
+ new WrapperPrivate(isolate_, global_interface, global_object);
+
+ auto actual_global_object = global_object->GetPrototype()->ToObject();
+ new WrapperPrivate(isolate_, global_interface, actual_global_object);
+
wrapper_factory_->RegisterWrappableType(
AnonymousIndexedGetterInterface::AnonymousIndexedGetterInterfaceWrappableType(),
base::Bind(V8cAnonymousIndexedGetterInterface::CreateWrapper),
- base::Bind(V8cAnonymousIndexedGetterInterface::CreateTemplate));
+ base::Bind(V8cAnonymousIndexedGetterInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
AnonymousNamedGetterInterface::AnonymousNamedGetterInterfaceWrappableType(),
base::Bind(V8cAnonymousNamedGetterInterface::CreateWrapper),
- base::Bind(V8cAnonymousNamedGetterInterface::CreateTemplate));
+ base::Bind(V8cAnonymousNamedGetterInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
AnonymousNamedIndexedGetterInterface::AnonymousNamedIndexedGetterInterfaceWrappableType(),
base::Bind(V8cAnonymousNamedIndexedGetterInterface::CreateWrapper),
- base::Bind(V8cAnonymousNamedIndexedGetterInterface::CreateTemplate));
+ base::Bind(V8cAnonymousNamedIndexedGetterInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
ArbitraryInterface::ArbitraryInterfaceWrappableType(),
base::Bind(V8cArbitraryInterface::CreateWrapper),
- base::Bind(V8cArbitraryInterface::CreateTemplate));
+ base::Bind(V8cArbitraryInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
BaseInterface::BaseInterfaceWrappableType(),
base::Bind(V8cBaseInterface::CreateWrapper),
- base::Bind(V8cBaseInterface::CreateTemplate));
+ base::Bind(V8cBaseInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
BooleanTypeTestInterface::BooleanTypeTestInterfaceWrappableType(),
base::Bind(V8cBooleanTypeTestInterface::CreateWrapper),
- base::Bind(V8cBooleanTypeTestInterface::CreateTemplate));
+ base::Bind(V8cBooleanTypeTestInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
CallbackFunctionInterface::CallbackFunctionInterfaceWrappableType(),
base::Bind(V8cCallbackFunctionInterface::CreateWrapper),
- base::Bind(V8cCallbackFunctionInterface::CreateTemplate));
+ base::Bind(V8cCallbackFunctionInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
CallbackInterfaceInterface::CallbackInterfaceInterfaceWrappableType(),
base::Bind(V8cCallbackInterfaceInterface::CreateWrapper),
- base::Bind(V8cCallbackInterfaceInterface::CreateTemplate));
+ base::Bind(V8cCallbackInterfaceInterface::GetTemplate));
#if defined(ENABLE_CONDITIONAL_INTERFACE)
wrapper_factory_->RegisterWrappableType(
ConditionalInterface::ConditionalInterfaceWrappableType(),
base::Bind(V8cConditionalInterface::CreateWrapper),
- base::Bind(V8cConditionalInterface::CreateTemplate));
+ base::Bind(V8cConditionalInterface::GetTemplate));
#endif // defined(ENABLE_CONDITIONAL_INTERFACE)
wrapper_factory_->RegisterWrappableType(
ConstantsInterface::ConstantsInterfaceWrappableType(),
base::Bind(V8cConstantsInterface::CreateWrapper),
- base::Bind(V8cConstantsInterface::CreateTemplate));
+ base::Bind(V8cConstantsInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
ConstructorInterface::ConstructorInterfaceWrappableType(),
base::Bind(V8cConstructorInterface::CreateWrapper),
- base::Bind(V8cConstructorInterface::CreateTemplate));
+ base::Bind(V8cConstructorInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
ConstructorWithArgumentsInterface::ConstructorWithArgumentsInterfaceWrappableType(),
base::Bind(V8cConstructorWithArgumentsInterface::CreateWrapper),
- base::Bind(V8cConstructorWithArgumentsInterface::CreateTemplate));
+ base::Bind(V8cConstructorWithArgumentsInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
DOMStringTestInterface::DOMStringTestInterfaceWrappableType(),
base::Bind(V8cDOMStringTestInterface::CreateWrapper),
- base::Bind(V8cDOMStringTestInterface::CreateTemplate));
+ base::Bind(V8cDOMStringTestInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
DerivedGetterSetterInterface::DerivedGetterSetterInterfaceWrappableType(),
base::Bind(V8cDerivedGetterSetterInterface::CreateWrapper),
- base::Bind(V8cDerivedGetterSetterInterface::CreateTemplate));
+ base::Bind(V8cDerivedGetterSetterInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
DerivedInterface::DerivedInterfaceWrappableType(),
base::Bind(V8cDerivedInterface::CreateWrapper),
- base::Bind(V8cDerivedInterface::CreateTemplate));
+ base::Bind(V8cDerivedInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
DictionaryInterface::DictionaryInterfaceWrappableType(),
base::Bind(V8cDictionaryInterface::CreateWrapper),
- base::Bind(V8cDictionaryInterface::CreateTemplate));
+ base::Bind(V8cDictionaryInterface::GetTemplate));
#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
wrapper_factory_->RegisterWrappableType(
DisabledInterface::DisabledInterfaceWrappableType(),
base::Bind(V8cDisabledInterface::CreateWrapper),
- base::Bind(V8cDisabledInterface::CreateTemplate));
+ base::Bind(V8cDisabledInterface::GetTemplate));
#endif // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
wrapper_factory_->RegisterWrappableType(
EnumerationInterface::EnumerationInterfaceWrappableType(),
base::Bind(V8cEnumerationInterface::CreateWrapper),
- base::Bind(V8cEnumerationInterface::CreateTemplate));
+ base::Bind(V8cEnumerationInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
ExceptionObjectInterface::ExceptionObjectInterfaceWrappableType(),
base::Bind(V8cExceptionObjectInterface::CreateWrapper),
- base::Bind(V8cExceptionObjectInterface::CreateTemplate));
+ base::Bind(V8cExceptionObjectInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
ExceptionsInterface::ExceptionsInterfaceWrappableType(),
base::Bind(V8cExceptionsInterface::CreateWrapper),
- base::Bind(V8cExceptionsInterface::CreateTemplate));
+ base::Bind(V8cExceptionsInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
ExtendedIDLAttributesInterface::ExtendedIDLAttributesInterfaceWrappableType(),
base::Bind(V8cExtendedIDLAttributesInterface::CreateWrapper),
- base::Bind(V8cExtendedIDLAttributesInterface::CreateTemplate));
+ base::Bind(V8cExtendedIDLAttributesInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
GarbageCollectionTestInterface::GarbageCollectionTestInterfaceWrappableType(),
base::Bind(V8cGarbageCollectionTestInterface::CreateWrapper),
- base::Bind(V8cGarbageCollectionTestInterface::CreateTemplate));
+ base::Bind(V8cGarbageCollectionTestInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
GlobalInterfaceParent::GlobalInterfaceParentWrappableType(),
base::Bind(V8cGlobalInterfaceParent::CreateWrapper),
- base::Bind(V8cGlobalInterfaceParent::CreateTemplate));
+ base::Bind(V8cGlobalInterfaceParent::GetTemplate));
wrapper_factory_->RegisterWrappableType(
ImplementedInterface::ImplementedInterfaceWrappableType(),
base::Bind(V8cImplementedInterface::CreateWrapper),
- base::Bind(V8cImplementedInterface::CreateTemplate));
+ base::Bind(V8cImplementedInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
IndexedGetterInterface::IndexedGetterInterfaceWrappableType(),
base::Bind(V8cIndexedGetterInterface::CreateWrapper),
- base::Bind(V8cIndexedGetterInterface::CreateTemplate));
+ base::Bind(V8cIndexedGetterInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
InterfaceWithAny::InterfaceWithAnyWrappableType(),
base::Bind(V8cInterfaceWithAny::CreateWrapper),
- base::Bind(V8cInterfaceWithAny::CreateTemplate));
+ base::Bind(V8cInterfaceWithAny::GetTemplate));
wrapper_factory_->RegisterWrappableType(
InterfaceWithAnyDictionary::InterfaceWithAnyDictionaryWrappableType(),
base::Bind(V8cInterfaceWithAnyDictionary::CreateWrapper),
- base::Bind(V8cInterfaceWithAnyDictionary::CreateTemplate));
+ base::Bind(V8cInterfaceWithAnyDictionary::GetTemplate));
wrapper_factory_->RegisterWrappableType(
InterfaceWithDate::InterfaceWithDateWrappableType(),
base::Bind(V8cInterfaceWithDate::CreateWrapper),
- base::Bind(V8cInterfaceWithDate::CreateTemplate));
+ base::Bind(V8cInterfaceWithDate::GetTemplate));
wrapper_factory_->RegisterWrappableType(
InterfaceWithUnsupportedProperties::InterfaceWithUnsupportedPropertiesWrappableType(),
base::Bind(V8cInterfaceWithUnsupportedProperties::CreateWrapper),
- base::Bind(V8cInterfaceWithUnsupportedProperties::CreateTemplate));
+ base::Bind(V8cInterfaceWithUnsupportedProperties::GetTemplate));
wrapper_factory_->RegisterWrappableType(
NamedConstructorInterface::NamedConstructorInterfaceWrappableType(),
base::Bind(V8cNamedConstructorInterface::CreateWrapper),
- base::Bind(V8cNamedConstructorInterface::CreateTemplate));
+ base::Bind(V8cNamedConstructorInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
NamedGetterInterface::NamedGetterInterfaceWrappableType(),
base::Bind(V8cNamedGetterInterface::CreateWrapper),
- base::Bind(V8cNamedGetterInterface::CreateTemplate));
+ base::Bind(V8cNamedGetterInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
NamedIndexedGetterInterface::NamedIndexedGetterInterfaceWrappableType(),
base::Bind(V8cNamedIndexedGetterInterface::CreateWrapper),
- base::Bind(V8cNamedIndexedGetterInterface::CreateTemplate));
+ base::Bind(V8cNamedIndexedGetterInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
NestedPutForwardsInterface::NestedPutForwardsInterfaceWrappableType(),
base::Bind(V8cNestedPutForwardsInterface::CreateWrapper),
- base::Bind(V8cNestedPutForwardsInterface::CreateTemplate));
+ base::Bind(V8cNestedPutForwardsInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
NoConstructorInterface::NoConstructorInterfaceWrappableType(),
base::Bind(V8cNoConstructorInterface::CreateWrapper),
- base::Bind(V8cNoConstructorInterface::CreateTemplate));
+ base::Bind(V8cNoConstructorInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
NoInterfaceObjectInterface::NoInterfaceObjectInterfaceWrappableType(),
base::Bind(V8cNoInterfaceObjectInterface::CreateWrapper),
- base::Bind(V8cNoInterfaceObjectInterface::CreateTemplate));
+ base::Bind(V8cNoInterfaceObjectInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
NullableTypesTestInterface::NullableTypesTestInterfaceWrappableType(),
base::Bind(V8cNullableTypesTestInterface::CreateWrapper),
- base::Bind(V8cNullableTypesTestInterface::CreateTemplate));
+ base::Bind(V8cNullableTypesTestInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
NumericTypesTestInterface::NumericTypesTestInterfaceWrappableType(),
base::Bind(V8cNumericTypesTestInterface::CreateWrapper),
- base::Bind(V8cNumericTypesTestInterface::CreateTemplate));
+ base::Bind(V8cNumericTypesTestInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
ObjectTypeBindingsInterface::ObjectTypeBindingsInterfaceWrappableType(),
base::Bind(V8cObjectTypeBindingsInterface::CreateWrapper),
- base::Bind(V8cObjectTypeBindingsInterface::CreateTemplate));
+ base::Bind(V8cObjectTypeBindingsInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
OperationsTestInterface::OperationsTestInterfaceWrappableType(),
base::Bind(V8cOperationsTestInterface::CreateWrapper),
- base::Bind(V8cOperationsTestInterface::CreateTemplate));
+ base::Bind(V8cOperationsTestInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
PromiseInterface::PromiseInterfaceWrappableType(),
base::Bind(V8cPromiseInterface::CreateWrapper),
- base::Bind(V8cPromiseInterface::CreateTemplate));
+ base::Bind(V8cPromiseInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
PutForwardsInterface::PutForwardsInterfaceWrappableType(),
base::Bind(V8cPutForwardsInterface::CreateWrapper),
- base::Bind(V8cPutForwardsInterface::CreateTemplate));
+ base::Bind(V8cPutForwardsInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
SequenceUser::SequenceUserWrappableType(),
base::Bind(V8cSequenceUser::CreateWrapper),
- base::Bind(V8cSequenceUser::CreateTemplate));
+ base::Bind(V8cSequenceUser::GetTemplate));
wrapper_factory_->RegisterWrappableType(
StaticPropertiesInterface::StaticPropertiesInterfaceWrappableType(),
base::Bind(V8cStaticPropertiesInterface::CreateWrapper),
- base::Bind(V8cStaticPropertiesInterface::CreateTemplate));
+ base::Bind(V8cStaticPropertiesInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
StringifierAnonymousOperationInterface::StringifierAnonymousOperationInterfaceWrappableType(),
base::Bind(V8cStringifierAnonymousOperationInterface::CreateWrapper),
- base::Bind(V8cStringifierAnonymousOperationInterface::CreateTemplate));
+ base::Bind(V8cStringifierAnonymousOperationInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
StringifierAttributeInterface::StringifierAttributeInterfaceWrappableType(),
base::Bind(V8cStringifierAttributeInterface::CreateWrapper),
- base::Bind(V8cStringifierAttributeInterface::CreateTemplate));
+ base::Bind(V8cStringifierAttributeInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
StringifierOperationInterface::StringifierOperationInterfaceWrappableType(),
base::Bind(V8cStringifierOperationInterface::CreateWrapper),
- base::Bind(V8cStringifierOperationInterface::CreateTemplate));
+ base::Bind(V8cStringifierOperationInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
TargetInterface::TargetInterfaceWrappableType(),
base::Bind(V8cTargetInterface::CreateWrapper),
- base::Bind(V8cTargetInterface::CreateTemplate));
+ base::Bind(V8cTargetInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
UnionTypesInterface::UnionTypesInterfaceWrappableType(),
base::Bind(V8cUnionTypesInterface::CreateWrapper),
- base::Bind(V8cUnionTypesInterface::CreateTemplate));
+ base::Bind(V8cUnionTypesInterface::GetTemplate));
wrapper_factory_->RegisterWrappableType(
Window::WindowWrappableType(),
- base::Bind(DummyFunctor),
- base::Bind(V8cWindow::CreateTemplate));
-
+ base::Bind(V8cWindow::CreateWrapper),
+ base::Bind(V8cWindow::GetTemplate));
}
} // namespace v8c
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.h
index 64a834e..bd47282 100644
--- a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.h
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.h
@@ -40,8 +40,7 @@
class V8cWindow {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
} // namespace testing
diff --git a/src/cobalt/bindings/mozjs45/templates/callback-interface.h.template b/src/cobalt/bindings/mozjs45/templates/callback-interface.h.template
index 81d024c..26e2245 100644
--- a/src/cobalt/bindings/mozjs45/templates/callback-interface.h.template
+++ b/src/cobalt/bindings/mozjs45/templates/callback-interface.h.template
@@ -42,9 +42,11 @@
bool* had_exception) const override;
{% endfor %}
{% endfor %}
+
JSObject* handle() const { return implementing_object_.GetObject(); }
const JS::Value& value() const { return implementing_object_.GetValue(); }
bool WasCollected() const { return implementing_object_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { implementing_object_.Trace(js_tracer); }
private:
JSContext* context_;
diff --git a/src/cobalt/bindings/testing/garbage_collection_test.cc b/src/cobalt/bindings/testing/garbage_collection_test.cc
index 03a61e8..4fab7d5 100644
--- a/src/cobalt/bindings/testing/garbage_collection_test.cc
+++ b/src/cobalt/bindings/testing/garbage_collection_test.cc
@@ -14,7 +14,6 @@
#include "cobalt/bindings/testing/bindings_test_base.h"
#include "cobalt/bindings/testing/garbage_collection_test_interface.h"
-
#include "testing/gtest/include/gtest/gtest.h"
namespace cobalt {
@@ -101,6 +100,31 @@
#endif
}
+TEST_F(GarbageCollectionTest, ReachableScriptValuesKeptAlive) {
+ // Ensure that platform objects attached to |Wrappable|s as script values
+ // survive GC.
+ EXPECT_EQ(GarbageCollectionTestInterface::instances().size(), 0);
+
+ const char script[] = R"(
+ const root = new InterfaceWithAny();
+ (() => {
+ const gcti = new GarbageCollectionTestInterface();
+ gcti.bicycle = 7;
+ root.setAny(gcti);
+ })();
+ )";
+ EXPECT_TRUE(EvaluateScript(script));
+
+ EXPECT_EQ(GarbageCollectionTestInterface::instances().size(), 1);
+
+ CollectGarbage();
+
+ std::string result;
+ EXPECT_TRUE(EvaluateScript("root.getAny().bicycle;", &result));
+ EXPECT_STREQ("7", result.c_str());
+ EXPECT_EQ(GarbageCollectionTestInterface::instances().size(), 1);
+}
+
TEST_F(GarbageCollectionTest, JSObjectRetainsCustomProperty) {
// Build a linked-list structure.
EXPECT_EQ(GarbageCollectionTestInterface::instances().size(), 0);
diff --git a/src/cobalt/bindings/testing/garbage_collection_test_interface.cc b/src/cobalt/bindings/testing/garbage_collection_test_interface.cc
index 75b7da9..ca5aa16 100644
--- a/src/cobalt/bindings/testing/garbage_collection_test_interface.cc
+++ b/src/cobalt/bindings/testing/garbage_collection_test_interface.cc
@@ -19,12 +19,18 @@
namespace cobalt {
namespace bindings {
namespace testing {
+
namespace {
base::LazyInstance<
GarbageCollectionTestInterface::GarbageCollectionTestInterfaceVector>
instances;
} // namespace
+GarbageCollectionTestInterface::GarbageCollectionTestInterfaceVector&
+GarbageCollectionTestInterface::instances() {
+ return ::cobalt::bindings::testing::instances.Get();
+}
+
GarbageCollectionTestInterface::GarbageCollectionTestInterface()
: previous_(NULL) {
instances().push_back(this);
@@ -58,6 +64,17 @@
Join(this, next.get());
}
+void GarbageCollectionTestInterface::Join(
+ GarbageCollectionTestInterface* first,
+ GarbageCollectionTestInterface* second) {
+ if (first) {
+ first->next_ = second;
+ }
+ if (second) {
+ second->previous_ = first;
+ }
+}
+
void GarbageCollectionTestInterface::MakeHead() {
if (previous_) {
DCHECK(previous_->next_ == this);
@@ -74,22 +91,6 @@
next_ = NULL;
}
-void GarbageCollectionTestInterface::Join(
- GarbageCollectionTestInterface* first,
- GarbageCollectionTestInterface* second) {
- if (first) {
- first->next_ = second;
- }
- if (second) {
- second->previous_ = first;
- }
-}
-
-GarbageCollectionTestInterface::GarbageCollectionTestInterfaceVector&
-GarbageCollectionTestInterface::instances() {
- return ::cobalt::bindings::testing::instances.Get();
-}
-
void GarbageCollectionTestInterface::TraceMembers(script::Tracer* tracer) {
tracer->Trace(previous_);
tracer->Trace(next_);
diff --git a/src/cobalt/bindings/testing/garbage_collection_test_interface.h b/src/cobalt/bindings/testing/garbage_collection_test_interface.h
index c65ebe1..26adcde 100644
--- a/src/cobalt/bindings/testing/garbage_collection_test_interface.h
+++ b/src/cobalt/bindings/testing/garbage_collection_test_interface.h
@@ -31,6 +31,8 @@
typedef std::vector<GarbageCollectionTestInterface*>
GarbageCollectionTestInterfaceVector;
+ static GarbageCollectionTestInterfaceVector& instances();
+
GarbageCollectionTestInterface();
~GarbageCollectionTestInterface();
@@ -45,18 +47,16 @@
void set_next(const scoped_refptr<GarbageCollectionTestInterface>& next);
scoped_refptr<GarbageCollectionTestInterface> next() { return next_; }
- static GarbageCollectionTestInterfaceVector& instances();
-
DEFINE_WRAPPABLE_TYPE(GarbageCollectionTestInterface);
void TraceMembers(script::Tracer* tracer) override;
private:
- void MakeHead();
- void MakeTail();
-
static void Join(GarbageCollectionTestInterface* first,
GarbageCollectionTestInterface* second);
+ void MakeHead();
+ void MakeTail();
+
// Raw pointers going upstream, strong pointers going downstream to prevent
// reference cycles.
GarbageCollectionTestInterface* previous_;
diff --git a/src/cobalt/bindings/testing/interface_object_test.cc b/src/cobalt/bindings/testing/interface_object_test.cc
index 1096554..e141ddf 100644
--- a/src/cobalt/bindings/testing/interface_object_test.cc
+++ b/src/cobalt/bindings/testing/interface_object_test.cc
@@ -92,15 +92,6 @@
EXPECT_STREQ("true", result.c_str());
}
-// If [NoInterfaceObject] extended attribute is specified, there should be no
-// constructor property on the prototype.
-TEST_F(NoInterfaceObjectTest, NoConstructorProperty) {
- std::string result;
- EXPECT_TRUE(EvaluateScript(
- "Object.getPrototypeOf(test).hasOwnProperty(\"constructor\");", &result));
- EXPECT_STREQ("false", result.c_str());
-}
-
// Interface object for non-callback interface is a function object.
TEST_F(NoInterfaceObjectTest, NoInterfaceObjectGlobalProperty) {
std::string result;
diff --git a/src/cobalt/bindings/testing/interface_with_any.h b/src/cobalt/bindings/testing/interface_with_any.h
index 9f126c7..0109870 100644
--- a/src/cobalt/bindings/testing/interface_with_any.h
+++ b/src/cobalt/bindings/testing/interface_with_any.h
@@ -37,13 +37,14 @@
}
void SetAny(const script::ValueHandleHolder& value) {
- value_.reset(new script::ValueHandleHolder::Reference(this, value));
+ value_.reset(new script::ValueHandleHolder::TracedReference(value));
}
DEFINE_WRAPPABLE_TYPE(InterfaceWithAny);
+ void TraceMembers(script::Tracer* tracer) override { tracer->Trace(value_); }
private:
- scoped_ptr<script::ValueHandleHolder::Reference> value_;
+ scoped_ptr<script::ValueHandleHolder::TracedReference> value_;
};
} // namespace testing
diff --git a/src/cobalt/bindings/testing/stack_trace_test.cc b/src/cobalt/bindings/testing/stack_trace_test.cc
index b900b72..05ed0ec 100644
--- a/src/cobalt/bindings/testing/stack_trace_test.cc
+++ b/src/cobalt/bindings/testing/stack_trace_test.cc
@@ -41,27 +41,27 @@
" return foo(depth - 1);\n"
" }\n"
"}\n"
- "foo(4)";
+ "foo(4);";
EXPECT_TRUE(EvaluateScript(script, &result));
// Expect that bar is on top.
std::string match_line = "bar @ [object BindingsTestBase]:2";
size_t position = result.find(match_line);
- EXPECT_TRUE(position != std::string::npos);
+ EXPECT_TRUE(position != std::string::npos) << result;
// Expect a foo at line 6.
match_line = "foo @ [object BindingsTestBase]:6";
position = result.find(match_line, ++position);
- EXPECT_TRUE(position != std::string::npos);
+ EXPECT_TRUE(position != std::string::npos) << result;
// Expect 4 subsequent foos at line 8.
match_line = "foo @ [object BindingsTestBase]:8";
for (int i = 0; i < 4; ++i) {
position = result.find(match_line, ++position);
- EXPECT_TRUE(position != std::string::npos);
+ EXPECT_TRUE(position != std::string::npos) << result;
}
// Expect global code at line 11.
- match_line = "global code @ [object BindingsTestBase]:11";
+ match_line = " @ [object BindingsTestBase]:11";
position = result.find(match_line, ++position);
- EXPECT_TRUE(position != std::string::npos);
+ EXPECT_TRUE(position != std::string::npos) << result;
}
TEST_F(StackTraceTest, UnnamedFunction) {
@@ -73,14 +73,13 @@
" return fun();\n"
"}\n"
"foo(function() { return getStackTrace();})";
- EXPECT_TRUE(EvaluateScript(script, &result));
+ EXPECT_TRUE(EvaluateScript(script, &result)) << result;
std::string match_line = "[object BindingsTestBase]:4";
size_t position = result.find(match_line);
- EXPECT_TRUE(position != std::string::npos);
+ EXPECT_TRUE(position != std::string::npos) << result;
}
-#if defined(ENGINE_SUPPORTS_STACK_TRACE_COLUMNS)
// Test for column numbers in stack trace. Behavior varies somewhat
// across engines & versions so, don't check actual column values.
TEST_F(StackTraceTest, GetStackTraceColumns) {
@@ -99,10 +98,9 @@
EXPECT_TRUE(EvaluateScript(script, &result));
const std::string expected =
"bar @ \\[object BindingsTestBase\\]:3:\\d+\n"
- "global code @ \\[object BindingsTestBase\\]:8:\\d+";
+ " @ \\[object BindingsTestBase\\]:8:\\d+";
EXPECT_THAT(result, MatchesRegex(expected));
}
-#endif // ENGINE_SUPPORTS_STACK_TRACE_COLUMNS
} // namespace testing
} // namespace bindings
diff --git a/src/cobalt/bindings/v8c/code_generator_v8c.py b/src/cobalt/bindings/v8c/code_generator_v8c.py
index 80bdcec..c353d62 100644
--- a/src/cobalt/bindings/v8c/code_generator_v8c.py
+++ b/src/cobalt/bindings/v8c/code_generator_v8c.py
@@ -50,6 +50,19 @@
templates_dir = os.path.normpath(os.path.join(module_path, 'templates'))
super(CodeGeneratorV8c, self).__init__(templates_dir, *args, **kwargs)
+ def build_interface_context(self, interface, interface_info, definitions):
+ # Due to a V8 internals quirks, named constructor attributes MUST come
+ # first, as V8 will use the key that we use to set them on something else
+ # as the "name" property on the function template value, overriding the
+ # originally selected name from |FunctionTemplate::SetClassName|. Efforts
+ # to document/modify this behavior in V8 are underway.
+ context = super(CodeGeneratorV8c, self).build_interface_context(
+ interface, interface_info, definitions)
+ context['all_attributes_v8_order_quirk'] = sorted(
+ [a for a in context['attributes'] + context['static_attributes']],
+ key=lambda a: not a.get('is_named_constructor_attribute', False))
+ return context
+
@property
def generated_file_prefix(self):
return 'v8c'
diff --git a/src/cobalt/bindings/v8c/templates/callback-interface.cc.template b/src/cobalt/bindings/v8c/templates/callback-interface.cc.template
index 682f0b8..eeebf75 100644
--- a/src/cobalt/bindings/v8c/templates/callback-interface.cc.template
+++ b/src/cobalt/bindings/v8c/templates/callback-interface.cc.template
@@ -21,6 +21,7 @@
#include "cobalt/script/logging_exception_state.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/v8c_callback_interface.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
#include "v8/include/v8.h"
@@ -32,6 +33,7 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::FromJSValue;
using cobalt::script::v8c::GetCallableForCallbackInterface;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::V8cGlobalEnvironment;
{% endblock using_directives %}
@@ -49,57 +51,56 @@
{{arg.arg_type}} {{arg.name}},
{% endfor %}
bool* had_exception) const {
+ bool success = false;
{% if overload.type != 'void' %}
{{overload.type}} cobalt_return_value;
{% endif %}
- DCHECK(!this->IsEmpty());
DCHECK(isolate_);
-
- EntryScope entry_scope(isolate_);
- v8::Local<v8::Context> context = isolate_->GetCurrentContext();
-
- v8::MaybeLocal<v8::Object> maybe_implementing_object = this->NewLocal(isolate_)->ToObject(context);
- v8::Local<v8::Object> implementing_object;
- if (!maybe_implementing_object.ToLocal(&implementing_object)) {
- *had_exception = true;
- return cobalt_return_value;
+ if (this->IsEmpty()) {
+ goto done;
}
+ {
+ EntryScope entry_scope(isolate_);
+ v8::Local<v8::Context> context = isolate_->GetCurrentContext();
+ v8::TryCatch try_catch(isolate_);
- v8::MaybeLocal<v8::Object> maybe_callable =
- GetCallableForCallbackInterface(isolate_, implementing_object, "{{overload.idl_name}}");
- v8::Local<v8::Object> callable;
- if (!maybe_callable.ToLocal(&callable)) {
- NOTIMPLEMENTED();
- *had_exception = true;
- return cobalt_return_value;
- }
- DCHECK(callable->IsCallable());
+ v8::Local<v8::Value> implementing_value = this->NewLocal(isolate_);
+ if (!implementing_value->IsObject()) {
+ LOG(WARNING) << "Implementing object is NULL";
+ goto done;
+ }
- v8::Local<v8::Value> this_value;
- ToJSValue(isolate_, callback_this, &this_value);
+ v8::Local<v8::Function> callable;
+ if (!GetCallableForCallbackInterface(
+ isolate_, implementing_value.As<v8::Object>(),
+ NewInternalString(isolate_, "{{overload.idl_name}}"))
+ .ToLocal(&callable)) {
+ goto done;
+ }
- const int kNumArguments = {{overload.arguments|length}};
- v8::Local<v8::Value> argv[kNumArguments];
+ v8::Local<v8::Value> this_value;
+ ToJSValue(isolate_, callback_this, &this_value);
+ const int kNumArguments = {{overload.arguments|length}};
+ v8::Local<v8::Value> argv[kNumArguments];
{% for arg in overload.arguments %}
- ToJSValue(isolate_, {{arg.name}}, &argv[{{loop.index0}}]);
+ ToJSValue(isolate_, {{arg.name}}, &argv[{{loop.index0}}]);
{% endfor %}
- v8::MaybeLocal<v8::Value> maybe_return_value =
- callable->CallAsFunction(isolate_->GetCurrentContext(), this_value, kNumArguments, argv);
- v8::Local<v8::Value> return_value;
- if (!maybe_return_value.ToLocal(&return_value)) {
- *had_exception = true;
- return cobalt_return_value;
+ v8::Local<v8::Value> return_value;
+ if (!callable->Call(context, this_value, kNumArguments, argv)
+ .ToLocal(&return_value)) {
+ goto done;
+ }
+ LoggingExceptionState exception_state;
+ FromJSValue(isolate_, return_value, 0, &exception_state,
+ &cobalt_return_value);
+ success = !exception_state.is_exception_set();
}
- LoggingExceptionState exception_state;
- FromJSValue(isolate_, return_value, 0, &exception_state, &cobalt_return_value);
- if (exception_state.is_exception_set()) {
- *had_exception = true;
- }
-
+done:
+ *had_exception = !success;
{% if overload.type != 'void' %}
return cobalt_return_value;
{% endif %}
diff --git a/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template b/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template
index f8cc3d3..2d0da59 100644
--- a/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template
+++ b/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template
@@ -40,6 +40,7 @@
#include "{{generated_conversion_include}}"
#include "base/logging.h"
#include "cobalt/script/exception_state.h"
+#include "cobalt/script/v8c/helpers.h"
#include "v8/include/v8.h"
using {{fully_qualified_name}};
@@ -82,7 +83,7 @@
// 3. Return the enumeration value of type E that is equal to S.
{% for value, idl_value in value_pairs %}
{{-" else " if not loop.first}} if (
- v8::String::NewFromUtf8(isolate, "{{idl_value}}", v8::NewStringType::kInternalized).ToLocalChecked()->Equals(value))
+ NewInternalString(isolate, "{{idl_value}}")->Equals(value))
{
*out_enum = {{namespace}}::{{value}};
}
diff --git a/src/cobalt/bindings/v8c/templates/interface.cc.template b/src/cobalt/bindings/v8c/templates/interface.cc.template
index 5759ac8..24464b7 100644
--- a/src/cobalt/bindings/v8c/templates/interface.cc.template
+++ b/src/cobalt/bindings/v8c/templates/interface.cc.template
@@ -35,12 +35,14 @@
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
@@ -52,7 +54,6 @@
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
-using cobalt::script::v8c::InterfaceData;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
@@ -60,10 +61,12 @@
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
{% endblock using_directives %}
@@ -85,18 +88,210 @@
{% endblock enumeration_declarations %}
{% block top_level_unnamed_namespace %}
-
-v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
- NOTIMPLEMENTED();
- return {};
-}
-
{% endblock top_level_unnamed_namespace %}
{% block implementation %}
namespace {
+const int kInterfaceUniqueId = {{unique_id}};
+
+{% if named_property_getter %}
+
+void NamedPropertyGetterCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+{{ nonstatic_function_prologue(impl_class) }}
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ if (!impl->CanQueryNamedProperty(property_name)) {
+ return;
+ }
+{{ call_cobalt_function(impl_class, named_property_getter.type,
+ named_property_getter.name, ["property_name"],
+ named_property_getter.raises_exception,
+ named_property_getter.call_with) }}
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(result_value);
+ DCHECK(!exception_state.is_exception_set());
+}
+
+void NamedPropertyQueryCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+{{ get_impl_class_instance(impl_class) }}
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ bool result = impl->CanQueryNamedProperty(property_name);
+ if (!result) {
+ return;
+ }
+ // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
+ // 2.7. If |O| implements an interface with a named property setter, then set
+ // desc.[[Writable]] to true, otherwise set it to false.
+ // 2.8. If |O| implements an interface with the
+ // [LegacyUnenumerableNamedProperties] extended attribute, then set
+ // desc.[[Enumerable]] to false, otherwise set it to true.
+ info.GetReturnValue().Set(v8::DontEnum | v8::ReadOnly);
+}
+
+void NamedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+{{ get_impl_class_instance(impl_class) }}
+ v8::Local<v8::Array> array = v8::Array::New(isolate);
+ V8cPropertyEnumerator property_enumerator(isolate, &array);
+ impl->EnumerateNamedProperties(&property_enumerator);
+ info.GetReturnValue().Set(array);
+}
+
+{% endif %}
+
+{% if named_property_setter %}
+void NamedPropertySetterCallback(
+ v8::Local<v8::Name> property,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+{{ nonstatic_function_prologue(impl_class) }}
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ TypeTraits<{{named_property_setter.type}}>::ConversionType native_value;
+ FromJSValue(isolate, value, {{named_property_setter.conversion_flags}},
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+{{ call_cobalt_function(impl_class, "void",
+ named_property_setter.name, ["property_name", "native_value"],
+ named_property_setter.raises_exception,
+ named_property_setter.call_with) }}
+ DCHECK(!exception_state.is_exception_set());
+}
+{% endif %}
+
+{% if named_property_deleter %}
+void NamedPropertyDeleterCallback(
+ v8::Local<v8::Name> property,
+ const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+{{ nonstatic_function_prologue(impl_class) }}
+ std::string property_name = *v8::String::Utf8Value(isolate, property);
+ if (!impl->CanQueryNamedProperty(property_name)) {
+ return;
+ }
+{{ call_cobalt_function(impl_class, "void",
+ named_property_deleter.name, ["property_name"],
+ named_property_deleter.raises_exception,
+ named_property_deleter.call_with) }}
+ DCHECK(!exception_state.is_exception_set());
+}
+{% endif %}
+
+{% if indexed_property_getter %}
+
+void IndexedPropertyGetterCallback(
+ uint32_t index,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+{{ nonstatic_function_prologue(impl_class) }}
+ if (index >= impl->length()) {
+ // |index| is out of bounds, so return undefined.
+ return;
+ }
+{{ call_cobalt_function(impl_class, indexed_property_getter.type,
+ indexed_property_getter.name, ["index"],
+ indexed_property_getter.raises_exception,
+ indexed_property_getter.call_with) }}
+ info.GetReturnValue().Set(result_value);
+}
+
+void IndexedPropertyDescriptorCallback(
+ uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+void IndexedPropertyEnumeratorCallback(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+{{ get_impl_class_instance(impl_class) }}
+ const uint32_t length = impl->length();
+ v8::Local<v8::Array> array = v8::Array::New(isolate, length);
+ for (uint32_t i = 0; i < length; ++i) {
+ array->Set(i, v8::Integer::New(isolate, i));
+ }
+ info.GetReturnValue().Set(array);
+}
+
+void IndexedPropertyDefinerCallback(
+ uint32_t index, const v8::PropertyDescriptor& desc,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ // TODO: Figure out under what conditions this gets called. It's not
+ // getting called in our tests.
+ NOTIMPLEMENTED();
+}
+
+{% endif %}
+
+{% if indexed_property_setter %}
+void IndexedPropertySetterCallback(
+ uint32_t index,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+{{ nonstatic_function_prologue(impl_class) }}
+ if (index >= impl->length()) {
+ return;
+ }
+ TypeTraits<{{indexed_property_setter.type}}>::ConversionType native_value;
+ FromJSValue(isolate, value, {{indexed_property_setter.conversion_flags}},
+ &exception_state, &native_value);
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+{{ call_cobalt_function(impl_class, "void",
+ indexed_property_setter.name, ["index", "native_value"],
+ indexed_property_setter.raises_exception,
+ indexed_property_setter.call_with) }}
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(value);
+}
+{% endif %}
+
+{% if indexed_property_deleter %}
+void IndexedPropertyDeleterCallback(
+ uint32_t index,
+ const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+{{ nonstatic_function_prologue(impl_class) }}
+ if (index >= impl->length()) {
+ return;
+ }
+{{ call_cobalt_function(impl_class, "void",
+ indexed_property_deleter.name, ["index"],
+ indexed_property_deleter.raises_exception,
+ indexed_property_deleter.call_with) }}
+ if (exception_state.is_exception_set()) {
+ return;
+ }
+ info.GetReturnValue().Set(v8::Boolean::New(isolate, true));
+}
+{% endif %}
+
{% if constructor %}
{% for overload in constructor.overloads if constructor.overloads|length > 1 %}
@@ -117,29 +312,13 @@
}
{% endif %}
-{% for constant in constants %}
-void {{constant.idl_name}}AttributeGetter(
- v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
- // TODO: Consider just attaching a constant instead.
- v8::Local<v8::Value> result_value;
- ToJSValue(info.GetIsolate(), {{constant.value}}, &result_value);
- info.GetReturnValue().Set(result_value);
-}
-{% endfor %}
-
{% for attribute in attributes + static_attributes %}
{% if attribute.conditional %}
#if defined({{attribute.conditional}})
{% endif %}
+
{% if attribute.is_constructor_attribute %}
-void {{attribute.idl_name}}AttributeGetter(
- v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
- v8::Isolate* isolate = info.GetIsolate();
- v8::Local<v8::Object> object = info.This();
- v8::Local<v8::Object> global_object = info.GetIsolate()->GetCurrentContext()->Global();
- v8::Local<v8::Object> interface_object = V8c{{attribute.interface_name}}::GetInterfaceObject(isolate, global_object);
- info.GetReturnValue().Set(interface_object);
-}
+// Nothing for {{attribute}}. We will just give them the v8::FunctionTemplate.
{% else %}
{% if attribute.is_static %}
void {{attribute.idl_name}}StaticAttributeGetter(
@@ -221,95 +400,404 @@
{% endif %}
{% endfor %}
-void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
- v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
- function_template->SetClassName(
- v8::String::NewFromUtf8(isolate, "{{interface_name}}",
- v8::NewStringType::kInternalized).ToLocalChecked());
+{% if stringifier %}
+void Stringifier(v8::Local<v8::String> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> object = info.This();
+ V8cExceptionState exception_state(isolate);
+
+ {{ check_if_object_implements_interface() }}
+
+ WrapperPrivate* wrapper_private =
+ WrapperPrivate::GetFromWrapperObject(object);
+
+ // |WrapperPrivate::GetFromObject| can fail if |object| is not a |Wrapper|
+ // object.
+ if (!wrapper_private) {
+ exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
+ return;
+ }
+
+ {{impl_class}}* impl =
+ wrapper_private->wrappable<{{impl_class}}>().get();
+ if (!impl) {
+ exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
+ NOTREACHED();
+ return;
+ }
+ std::string stringified = impl->{{stringifier.name}}();
+
+ v8::Local<v8::Value> v8_stringified;
+ ToJSValue(isolate, stringified, &v8_stringified);
+
+ info.GetReturnValue().Set(v8_stringified);
+}
+{% endif %}
+
+void InitializeTemplate(v8::Isolate* isolate) {
+ // https://heycam.github.io/webidl/#interface-object
+ // 3.6.1. Interface object
+ //
+ // The interface object for a given interface is a built-in function object.
+ // It has properties that correspond to the constants and static operations
+ // defined on that interface, as described in sections 3.6.6 Constants and
+ // 3.6.8 Operations.
+ //
+ // If the interface is declared with a [Constructor] extended attribute,
+ // then the interface object can be called as a constructor to create an
+ // object that implements that interface. Calling that interface as a
+ // function will throw an exception.
+ //
+ // Interface objects whose interfaces are not declared with a [Constructor]
+ // extended attribute will throw when called, both as a function and as a
+ // constructor.
+ //
+ // An interface object for a non-callback interface has an associated object
+ // called the interface prototype object. This object has properties that
+ // correspond to the regular attributes and regular operations defined on
+ // the interface, and is described in more detail in 3.6.3 Interface
+ // prototype object.
+{% if constructor %}
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ Constructor,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ {{constructor.length}});
+ function_template->SetLength({{constructor.length}});
+{% else %}
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(
+ isolate,
+ nullptr,
+ v8::Local<v8::Value>(),
+ v8::Local<v8::Signature>(),
+ 0);
+{% endif %}
+ function_template->SetClassName(NewInternalString(isolate, "{{interface_name}}"));
+ function_template->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);
+
{% if parent_interface %}
- v8::Local<v8::FunctionTemplate> parent_template = {{parent_interface}}::CreateTemplate(isolate);
- function_template->Inherit(parent_template);
+ {
+ // An interface can be defined to inherit from another interface. If the
+ // identifier of the interface is followed by a U+003A COLON (":") character
+ // and an identifier, then that identifier identifies the inherited
+ // interface. An object that implements an interface that inherits from
+ // another also implements that inherited interface. The object therefore
+ // will also have members that correspond to the interface members from the
+ // inherited interface.
+ v8::Local<v8::FunctionTemplate> parent_template = {{parent_interface}}::GetTemplate(isolate);
+ function_template->Inherit(parent_template);
+ }
{% elif is_exception_interface %}
- NOTIMPLEMENTED();
+ {
+ // A spicy hack from Chromium in order to achieve
+ // https://heycam.github.io/webidl/#es-DOMException-specialness
+ // See https://cs.chromium.org/chromium/src/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl?l=630&rcl=0f7c2c752bb24ad08c17017e4e68401093fe76a0
+ v8::Local<v8::FunctionTemplate> intrinsic_error_prototype_interface_template =
+ v8::FunctionTemplate::New(isolate);
+ intrinsic_error_prototype_interface_template->RemovePrototype();
+ intrinsic_error_prototype_interface_template->SetIntrinsicDataProperty(
+ NewInternalString(isolate, "prototype"), v8::kErrorPrototype);
+ function_template->Inherit(intrinsic_error_prototype_interface_template);
+ }
{% endif %}
- v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
-
+ // https://heycam.github.io/webidl/#es-constants
+ // 3.6.6. Constants
+ //
+ // For each exposed constant defined on an interface A, there must be a
+ // corresponding property. The property has the following characteristics:
{% for constant in constants %}
- prototype_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "{{constant.idl_name}}",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- {{constant.idl_name}}AttributeGetter);
+ {
+ // The name of the property is the identifier of the constant.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "{{constant.idl_name}}");
+
+ // The value of the property is that which is obtained by converting the
+ // constant's IDL value to an ECMAScript value.
+ v8::Local<v8::Value> constant_value;
+ ToJSValue(isolate, {{constant.value}}, &constant_value);
+
+ // The property has attributes { [[Writable]]: false, [[Enumerable]]: true,
+ // [[Configurable]]: false }.
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ v8::ReadOnly | v8::DontDelete);
+
+ // The location of the property is determined as follows:
+{% if is_global_interface %}
+ // If the interface was declared with the [Global] extended attribute, then
+ // the property exists on the single object that implements the interface.
+ instance_template->Set(name, constant_value, attributes);
+
+{% else %}
+ // Otherwise, if the interface has an interface prototype object, then the
+ // property exists on it.
+ prototype_template->Set(name, constant_value, attributes);
+{% endif %}
+
+ // In addition, a property with the same characteristics must exist on the
+ // interface object or the legacy callback interface object, if either of
+ // those objects exists.
+ function_template->Set(name, constant_value, attributes);
+ }
{% endfor %}
-{% for attribute in attributes if not attribute.is_constructor_attribute %}
+ // https://heycam.github.io/webidl/#es-attributes
+ // 3.6.7. Attributes
+ //
+ // For each exposed attribute of the interface there must exist a
+ // corresponding property. The characteristics of this property are as
+ // follows:
+{% for attribute in all_attributes_v8_order_quirk %}
{% if attribute.conditional %}
#if defined({{attribute.conditional}})
{% endif %}
- instance_template->SetAccessor(
- v8::String::NewFromUtf8(isolate, "{{attribute.idl_name}}",
- v8::NewStringType::kInternalized)
- .ToLocalChecked(),
- {{attribute.idl_name}}AttributeGetter
+ {
+ // The name of the property is the identifier of the attribute.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "{{attribute.idl_name}}");
+
+ // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where: configurable is false if
+ // the attribute was declared with the [Unforgeable] extended attribute and
+ // true otherwise;
+ bool configurable = {{ "false" if attribute.is_unforgeable else "true"}};
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ configurable ? v8::None : v8::DontDelete);
+
+ // G is the attribute getter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property;
+ // and
+ //
+ // S is the attribute setter created given the attribute, the interface, and
+ // the relevant Realm of the object that is the location of the property.
+
+{% if not attribute.is_constructor_attribute %}
+
+ // The location of the property is determined as follows:
+{% if attribute.is_static %}
+ // Operations installed on the interface object must be static methods, so
+ // no need to specify a signature, i.e. no need to do type check against a
+ // holder.
+
+ // If the attribute is a static attribute, then there is a single
+ // corresponding property and it exists on the interface's interface object.
+ function_template->SetNativeDataProperty(
+ name,
+ {{attribute.idl_name}}StaticAttributeGetter,
{% if attribute.has_setter %}
- ,{{attribute.idl_name}}AttributeSetter
+ {{attribute.idl_name}}StaticAttributeSetter,
+{% else %}
+ 0
{% endif %}
- );
+ v8::Local<v8::Value>(),
+ attributes);
+
+{% elif attribute.is_unforgeable or is_global_interface %}
+ // Otherwise, if the attribute is unforgeable on the interface or if the
+ // interface was declared with the [Global] extended attribute, then the
+ // property exists on every object that implements the interface.
+ instance_template->SetAccessor(
+ name,
+ {{attribute.idl_name}}AttributeGetter,
+{% if attribute.has_setter %}
+ {{attribute.idl_name}}AttributeSetter,
+{% else %}
+ 0,
+{% endif %}
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+
+{% else %}
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ prototype_template->SetAccessor(
+ name,
+ {{attribute.idl_name}}AttributeGetter,
+{% if attribute.has_setter %}
+ {{attribute.idl_name}}AttributeSetter,
+{% else %}
+ 0,
+{% endif %}
+ v8::Local<v8::Value>(),
+ v8::DEFAULT,
+ attributes);
+{% endif %}
+
+{% else %} {#- not attribute.is_constructor_attribute #}
+ {
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "{{attribute.idl_name}}");
+ instance_template->Set(
+ name,
+{% if attribute.interface_name == interface_name %}
+ function_template
+{% else %}
+ // Note that we use "attribute.interface_name", and not
+ // "attribute.idl_name", because of named constructors.
+ V8c{{attribute.interface_name}}::GetTemplate(isolate)
+{% endif %}
+ );
+ }
+
+{% endif %} {#- not attribute.is_constructor_attribute #}
+ }
{% if attribute.conditional %}
-#endif // defined({{attribute.conditional}})
+#endif // {{attribute.conditional}}
{% endif %}
{% endfor %}
-{% for operation in operations %}
+ // https://heycam.github.io/webidl/#es-operations
+ // 3.6.8. Operations
+ //
+ // For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the effective
+ // overload set for that identifier and operation and with an argument count
+ // of 0 has no entries.
+ //
+ // The characteristics of this property are as follows:
+{% for operation in operations + static_operations %}
{% if operation.conditional %}
#if defined({{operation.conditional}})
{% endif %}
{
- v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, {{operation.idl_name}}Method);
+ // The name of the property is the identifier.
+ v8::Local<v8::String> name = NewInternalString(
+ isolate,
+ "{{operation.idl_name}}");
+
+ // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
+ // [[Configurable]]: B }, where B is false if the operation is unforgeable
+ // on the interface, and true otherwise.
+ bool B = {{ "false" if operation.is_unforgeable else "true"}};
+ v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
+ B ? v8::None : (v8::ReadOnly | v8::DontDelete));
+
+ // The location of the property is determined as follows:
+{% if operation.is_static %}
+ // If the operation is static, then the property exists on the interface
+ // object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, {{operation.idl_name}}StaticMethod);
method_template->RemovePrototype();
- prototype_template->Set(
- v8::String::NewFromUtf8(
- isolate,
- "{{operation.idl_name}}",
- v8::NewStringType::kInternalized).ToLocalChecked(),
+ method_template->SetLength({{operation.length}});
+ function_template->Set(
+ NewInternalString(isolate, "{{operation.idl_name}}"),
method_template);
- }
-{% if operation.conditional %}
-#endif // defined({{operation.conditional}})
+
+{% elif operation.is_unforgeable or is_global_interface %}
+ // Otherwise, if the operation is unforgeable on the interface or if the
+ // interface was declared with the [Global] extended attribute, then the
+ // property exists on every object that implements the interface.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, {{operation.idl_name}}Method);
+ method_template->RemovePrototype();
+ method_template->SetLength({{operation.length}});
+ instance_template->Set(
+ NewInternalString(isolate, "{{operation.idl_name}}"),
+ method_template);
+
+{% else %}
+ // Otherwise, the property exists solely on the interface's interface
+ // prototype object.
+ v8::Local<v8::FunctionTemplate> method_template =
+ v8::FunctionTemplate::New(isolate, {{operation.idl_name}}Method);
+ method_template->RemovePrototype();
+ method_template->SetLength({{operation.length}});
+ prototype_template->Set(
+ NewInternalString(isolate, "{{operation.idl_name}}"),
+ method_template);
{% endif %}
+ // The value of the property is the result of creating an operation function
+ // given the operation, the interface, and the relevant Realm of the object
+ // that is the location of the property.
+
+ // Note: that is, even if an includes statement was used to make an
+ // operation available on the interface, we pass in the interface which
+ // includes the interface mixin, and not the interface mixin on which the
+ // operation was originally declared.
+ }
+{% if operation.conditional %}
+#endif // {{operation.conditional}}
+{% endif %}
{% endfor %}
- interface_data->function_template.Set(isolate, function_template);
-}
+ // https://heycam.github.io/webidl/#es-stringifier
+ // 3.6.8.2. Stringifiers
+ prototype_template->Set(
+ v8::Symbol::GetToStringTag(isolate),
+ NewInternalString(isolate, "{{interface_name}}"),
+ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
-inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
- const int kInterfaceUniqueId = {{unique_id}};
- // By convention, the |V8cGlobalEnvironment| that we are associated with
- // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
- // for it to be there in the first place, and could not have conflicted with
- // any other interface.
- return global_environment->GetInterfaceData(kInterfaceUniqueId);
+{% if named_property_getter %}
+ {
+ v8::NamedPropertyHandlerConfiguration named_property_handler_configuration = {
+ NamedPropertyGetterCallback,
+ {{ "NamedPropertySetterCallback" if named_property_setter else "nullptr" }},
+ NamedPropertyQueryCallback,
+ {{ "NamedPropertyDeleterCallback" if named_property_deleter else "nullptr" }},
+ NamedPropertyEnumeratorCallback,
+ v8::Local<v8::Value>(),
+ static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kNonMasking) | int(v8::PropertyHandlerFlags::kOnlyInterceptStrings))
+ };
+ instance_template->SetHandler(named_property_handler_configuration);
+ }
+{% endif %}
+
+{% if indexed_property_getter %}
+ {
+ v8::IndexedPropertyHandlerConfiguration indexed_property_handler_configuration = {
+ IndexedPropertyGetterCallback,
+ {{ "IndexedPropertySetterCallback" if indexed_property_setter else "nullptr" }},
+ IndexedPropertyDescriptorCallback,
+ {{ "IndexedPropertyDeleterCallback" if indexed_property_deleter else "nullptr" }},
+ IndexedPropertyEnumeratorCallback,
+ IndexedPropertyDefinerCallback
+ };
+ instance_template->SetHandler(indexed_property_handler_configuration);
+ }
+{% endif %}
+
}
} // namespace
-v8::Local<v8::Object> {{binding_class}}::CreateWrapper(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
+{% if is_global_interface %}
+
+// The global interface is special. Just give them the global object proxy.
+v8::Local<v8::Object> {{binding_class}}::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>&) {
+ return isolate->GetCurrentContext()->Global();
+}
+
+{% else %}
+
+v8::Local<v8::Object> {{binding_class}}::CreateWrapper(
+ v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
EscapableEntryScope entry_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
}
- DCHECK(!interface_data->function_template.IsEmpty());
+ v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);
- v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
@@ -319,14 +807,14 @@
return entry_scope.Escape(object);
}
-v8::Local<v8::FunctionTemplate> {{binding_class}}::CreateTemplate(v8::Isolate* isolate) {
- V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
- InterfaceData* interface_data = GetInterfaceData(global_environment);
- if (interface_data->function_template.IsEmpty()) {
- InitializeTemplateAndInterfaceObject(isolate, interface_data);
- }
+{% endif %}
- return interface_data->function_template.Get(isolate);
+v8::Local<v8::FunctionTemplate> {{binding_class}}::GetTemplate(v8::Isolate* isolate) {
+ V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
+ if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
+ InitializeTemplate(isolate);
+ }
+ return global_environment->GetInterfaceData(kInterfaceUniqueId);
}
{% endblock implementation %}
@@ -341,24 +829,11 @@
void V8cGlobalEnvironment::CreateGlobalObject(
const scoped_refptr<GlobalInterface>& global_interface,
EnvironmentSettings* environment_settings) {
+ TRACE_EVENT0("cobalt::script", "V8cGlobalEnvironment::CreateGlobalObject()");
// Intentionally not an |EntryScope|, since the context doesn't exist yet.
v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope handle_scope(isolate_);
- v8::Local<v8::ObjectTemplate> global_object_template = {{binding_class}}::CreateTemplate(isolate_)->InstanceTemplate();
-
-{% for interface in all_interfaces %}
-{% if interface.conditional %}
-#if defined({{interface.conditional}})
-{% endif %}
- global_object_template->Set(
- v8::String::NewFromUtf8(
- isolate_, "{{interface.name}}",
- v8::NewStringType::kInternalized).ToLocalChecked(),
- V8c{{interface.name}}::CreateTemplate(isolate_));
-{% if interface.conditional %}
-#endif // defined({{interface.conditional}})
-{% endif %}
-{% endfor %}
+ v8::Local<v8::ObjectTemplate> global_object_template = {{binding_class}}::GetTemplate(isolate_)->InstanceTemplate();
v8::Local<v8::Context> context =
v8::Context::New(isolate_, nullptr, global_object_template);
@@ -370,27 +845,24 @@
environment_settings_ = environment_settings;
EvaluateAutomatics();
+ v8::Local<v8::Object> global_object = context->Global();
+ new WrapperPrivate(isolate_, global_interface, global_object);
+
+ auto actual_global_object = global_object->GetPrototype()->ToObject();
+ new WrapperPrivate(isolate_, global_interface, actual_global_object);
+
{% for interface in all_interfaces %}
{% if interface.conditional %}
#if defined({{interface.conditional}})
{% endif %}
- {# Pass in a dummy CreateProxy for global interface #}
- {% if interface.name == impl_class %}
- wrapper_factory_->RegisterWrappableType(
- {{interface.name}}::{{interface.name}}WrappableType(),
- base::Bind(DummyFunctor),
- base::Bind(V8c{{interface.name}}::CreateTemplate));
- {% else %}
wrapper_factory_->RegisterWrappableType(
{{interface.name}}::{{interface.name}}WrappableType(),
base::Bind(V8c{{interface.name}}::CreateWrapper),
- base::Bind(V8c{{interface.name}}::CreateTemplate));
- {% endif %}
+ base::Bind(V8c{{interface.name}}::GetTemplate));
{% if interface.conditional %}
#endif // defined({{interface.conditional}})
{% endif %}
{% endfor %}
-
}
} // namespace v8c
@@ -447,7 +919,7 @@
// 3. Return the enumeration value of type E that is equal to S.
{% for value, idl_value in enumeration.value_pairs %}
{{-" else " if not loop.first}}
- if (string == v8::String::NewFromUtf8(isolate, "{{id_value}}", v8::NewStringType::kInternalized).ToLocalChecked()) {
+ if (string == NewInternalString(isolate, "{{id_value}}")) {
*out_enum = {{impl_class}}::{{value}};
}
{% endfor %}
diff --git a/src/cobalt/bindings/v8c/templates/interface.h.template b/src/cobalt/bindings/v8c/templates/interface.h.template
index 5cc385e..aa164fb 100644
--- a/src/cobalt/bindings/v8c/templates/interface.h.template
+++ b/src/cobalt/bindings/v8c/templates/interface.h.template
@@ -26,9 +26,6 @@
class {{binding_class}} {
public:
static v8::Local<v8::Object> CreateWrapper(v8::Isolate* isolate, const scoped_refptr<script::Wrappable>& wrappable);
- static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate);
-{% if has_interface_object %}
- static v8::Local<v8::Object> GetInterfaceObject(v8::Isolate* isolate, v8::Local<v8::Object> global_object);
-{% endif %}
+ static v8::Local<v8::FunctionTemplate> GetTemplate(v8::Isolate* isolate);
};
{% endblock implementation %}
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 3cf2f4f..006245e 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -29,6 +29,7 @@
#include "base/string_util.h"
#include "base/time.h"
#include "build/build_config.h"
+#include "cobalt/base/accessibility_caption_settings_changed_event.h"
#include "cobalt/base/accessibility_settings_changed_event.h"
#include "cobalt/base/application_event.h"
#include "cobalt/base/cobalt_paths.h"
@@ -43,6 +44,9 @@
#include "cobalt/base/on_screen_keyboard_shown_event.h"
#include "cobalt/base/startup_timer.h"
#include "cobalt/base/user_log.h"
+#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+#include "cobalt/base/version_compatibility.h"
+#endif // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
#include "cobalt/base/window_size_changed_event.h"
#include "cobalt/browser/memory_settings/auto_mem_settings.h"
#include "cobalt/browser/memory_tracker/tool.h"
@@ -53,7 +57,7 @@
#include "cobalt/script/javascript_engine.h"
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
#include "cobalt/storage/savegame_fake.h"
-#endif
+#endif // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
#include "cobalt/system_window/input_event.h"
#include "cobalt/trace_event/scoped_trace_to_file.h"
#include "googleurl/src/gurl.h"
@@ -493,7 +497,22 @@
options.storage_manager_options.savegame_options.factory =
&storage::SavegameFake::Create;
}
-#endif
+#endif // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
+
+#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+ constexpr int kDefaultMinCompatibilityVersion = 1;
+ int minimum_version = kDefaultMinCompatibilityVersion;
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
+ if (command_line->HasSwitch(browser::switches::kMinCompatibilityVersion)) {
+ std::string switch_value =
+ command_line->GetSwitchValueASCII(switches::kMinCompatibilityVersion);
+ if (!base::StringToInt(switch_value, &minimum_version)) {
+ DLOG(ERROR) << "Invalid min_compatibility_version provided.";
+ }
+ }
+#endif // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
+ base::VersionCompatibility::GetInstance()->SetMinimumVersion(minimum_version);
+#endif // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
base::optional<std::string> partition_key;
if (command_line->HasSwitch(browser::switches::kLocalStoragePartitionUrl)) {
@@ -655,6 +674,13 @@
base::OnScreenKeyboardBlurredEvent::TypeId(),
on_screen_keyboard_blurred_event_callback_);
#endif // SB_HAS(ON_SCREEN_KEYBOARD)
+
+#if SB_HAS(CAPTIONS)
+ event_dispatcher_.AddEventCallback(
+ base::AccessibilityCaptionSettingsChangedEvent::TypeId(),
+ base::Bind(&Application::OnCaptionSettingsChangedEvent,
+ base::Unretained(this)));
+#endif // SB_HAS(CAPTIONS)
#if defined(ENABLE_WEBDRIVER)
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
bool create_webdriver_module =
@@ -809,6 +835,12 @@
case kSbEventTypeAccessiblitySettingsChanged:
DispatchEventInternal(new base::AccessibilitySettingsChangedEvent());
break;
+#if SB_HAS(CAPTIONS)
+ case kSbEventTypeAccessibilityCaptionSettingsChanged:
+ DispatchEventInternal(
+ new base::AccessibilityCaptionSettingsChangedEvent());
+ break;
+#endif // SB_HAS(CAPTIONS)
default:
DLOG(WARNING) << "Unhandled Starboard event of type: "
<< starboard_event->type;
@@ -946,6 +978,16 @@
}
#endif // SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_HAS(CAPTIONS)
+void Application::OnCaptionSettingsChangedEvent(const base::Event* event) {
+ TRACE_EVENT0("cobalt::browser",
+ "Application::OnCaptionSettingsChangedEvent()");
+ browser_module_->OnCaptionSettingsChanged(
+ base::polymorphic_downcast<
+ const base::AccessibilityCaptionSettingsChangedEvent*>(event));
+}
+#endif // SB_HAS(CAPTIONS)
+
void Application::WebModuleRecreated() {
TRACE_EVENT0("cobalt::browser", "Application::WebModuleRecreated()");
#if defined(ENABLE_WEBDRIVER)
diff --git a/src/cobalt/browser/application.h b/src/cobalt/browser/application.h
index 8ba1cdc..1344ac3 100644
--- a/src/cobalt/browser/application.h
+++ b/src/cobalt/browser/application.h
@@ -82,6 +82,10 @@
void OnOnScreenKeyboardBlurredEvent(const base::Event* event);
#endif // SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_HAS(CAPTIONS)
+ void OnCaptionSettingsChangedEvent(const base::Event* event);
+#endif // SB_HAS(CAPTIONS)
+
// Called when a navigation occurs in the BrowserModule.
void WebModuleRecreated();
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index 49c4b18..d4ed23e 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -241,6 +241,10 @@
network_module_(&storage_manager_, event_dispatcher_,
options_.network_module_options),
splash_screen_cache_(new SplashScreenCache()),
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+ on_screen_keyboard_bridge_(new OnScreenKeyboardStarboardBridge(
+ base::Bind(&BrowserModule::GetSbWindow, base::Unretained(this)))),
+#endif // SB_HAS(ON_SCREEN_KEYBOARD)
web_module_loaded_(true /* manually_reset */,
false /* initially_signalled */),
web_module_recreated_callback_(options_.web_module_recreated_callback),
@@ -265,10 +269,6 @@
kScreenshotCommandShortHelp, kScreenshotCommandLongHelp)),
#endif // defined(ENABLE_SCREENSHOT)
#endif // defined(ENABLE_DEBUG_CONSOLE)
-#if SB_HAS(ON_SCREEN_KEYBOARD)
- on_screen_keyboard_bridge_(new OnScreenKeyboardStarboardBridge(
- base::Bind(&BrowserModule::GetSbWindow, base::Unretained(this)))),
-#endif // SB_HAS(ON_SCREEN_KEYBOARD)
has_resumed_(true, false),
#if defined(COBALT_CHECK_RENDER_TIMEOUT)
timeout_polling_thread_(kTimeoutPollingThreadName),
@@ -333,8 +333,8 @@
base::Bind(&CreateExtensionInterface);
}
-#if defined(ENABLE_DEBUG_CONSOLE) && defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
CommandLine* command_line = CommandLine::ForCurrentProcess();
+#if defined(ENABLE_DEBUG_CONSOLE) && defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
if (command_line->HasSwitch(switches::kInputFuzzer)) {
OnFuzzerToggle(std::string());
}
@@ -367,6 +367,10 @@
lifecycle_observers_.AddObserver(debug_console_.get());
#endif // defined(ENABLE_DEBUG_CONSOLE)
+ if (command_line->HasSwitch(switches::kEnableMapToMeshRectanglar)) {
+ options_.web_module_options.enable_map_to_mesh_rectangular = true;
+ }
+
fallback_splash_screen_url_ = options.fallback_splash_screen_url;
// Synchronously construct our WebModule object.
Navigate(url);
@@ -644,10 +648,16 @@
return;
}
- if (splash_screen_ && !splash_screen_->ShutdownSignaled()) {
- splash_screen_->Shutdown();
+ if (splash_screen_) {
+ if (on_screen_keyboard_show_called_) {
+ // Hide the splash screen as quickly as possible.
+ DestroySplashScreen(base::TimeDelta());
+ } else if (!splash_screen_->ShutdownSignaled()) {
+ splash_screen_->Shutdown();
+ }
}
if (application_state_ == base::kApplicationStatePreloading) {
+ layout_results.on_rasterized_callback.Run();
return;
}
@@ -769,7 +779,9 @@
#if SB_HAS(ON_SCREEN_KEYBOARD)
void BrowserModule::OnOnScreenKeyboardShown(
const base::OnScreenKeyboardShownEvent* event) {
+ DCHECK_EQ(MessageLoop::current(), self_message_loop_);
// Only inject shown events to the main WebModule.
+ on_screen_keyboard_show_called_ = true;
if (web_module_) {
web_module_->InjectOnScreenKeyboardShownEvent(event->ticket());
}
@@ -777,6 +789,7 @@
void BrowserModule::OnOnScreenKeyboardHidden(
const base::OnScreenKeyboardHiddenEvent* event) {
+ DCHECK_EQ(MessageLoop::current(), self_message_loop_);
// Only inject hidden events to the main WebModule.
if (web_module_) {
web_module_->InjectOnScreenKeyboardHiddenEvent(event->ticket());
@@ -785,6 +798,7 @@
void BrowserModule::OnOnScreenKeyboardFocused(
const base::OnScreenKeyboardFocusedEvent* event) {
+ DCHECK_EQ(MessageLoop::current(), self_message_loop_);
// Only inject focused events to the main WebModule.
if (web_module_) {
web_module_->InjectOnScreenKeyboardFocusedEvent(event->ticket());
@@ -793,6 +807,7 @@
void BrowserModule::OnOnScreenKeyboardBlurred(
const base::OnScreenKeyboardBlurredEvent* event) {
+ DCHECK_EQ(MessageLoop::current(), self_message_loop_);
// Only inject blurred events to the main WebModule.
if (web_module_) {
web_module_->InjectOnScreenKeyboardBlurredEvent(event->ticket());
@@ -800,6 +815,15 @@
}
#endif // SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_HAS(CAPTIONS)
+void BrowserModule::OnCaptionSettingsChanged(
+ const base::AccessibilityCaptionSettingsChangedEvent* /*event*/) {
+ if (web_module_) {
+ web_module_->InjectCaptionSettingsChangedEvent();
+ }
+}
+#endif // SB_HAS(CAPTIONS)
+
#if defined(ENABLE_DEBUG_CONSOLE)
void BrowserModule::OnFuzzerToggle(const std::string& message) {
if (MessageLoop::current() != self_message_loop_) {
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index f26099b..4b3a05c 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -25,6 +25,7 @@
#include "base/threading/thread.h"
#include "base/timer.h"
#include "cobalt/account/account_manager.h"
+#include "cobalt/base/accessibility_caption_settings_changed_event.h"
#include "cobalt/base/application_state.h"
#include "cobalt/base/message_queue.h"
#include "cobalt/base/on_screen_keyboard_blurred_event.h"
@@ -181,6 +182,11 @@
const base::OnScreenKeyboardBlurredEvent* event);
#endif // SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_HAS(CAPTIONS)
+ void OnCaptionSettingsChanged(
+ const base::AccessibilityCaptionSettingsChangedEvent* event);
+#endif // SB_HAS(CAPTIONS)
+
private:
#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
static void CoreDumpHandler(void* browser_module_as_void);
@@ -464,6 +470,9 @@
// The splash screen cache.
scoped_ptr<SplashScreenCache> splash_screen_cache_;
+ scoped_ptr<dom::OnScreenKeyboardBridge> on_screen_keyboard_bridge_;
+ bool on_screen_keyboard_show_called_ = false;
+
// Sets up everything to do with web page management, from loading and
// parsing the web page and all referenced files to laying it out. The
// web module will ultimately produce a render tree that can be passed
@@ -518,8 +527,6 @@
// the splash screen is currently displayed.
scoped_ptr<SplashScreen> splash_screen_;
- scoped_ptr<dom::OnScreenKeyboardBridge> on_screen_keyboard_bridge_;
-
// Reset when the browser is paused, signalled to resume.
base::WaitableEvent has_resumed_;
diff --git a/src/cobalt/browser/h5vcc_url_handler.cc b/src/cobalt/browser/h5vcc_url_handler.cc
index d02a4a3..e476110 100644
--- a/src/cobalt/browser/h5vcc_url_handler.cc
+++ b/src/cobalt/browser/h5vcc_url_handler.cc
@@ -57,13 +57,13 @@
DLOG(WARNING) << "Query parameter " << name << " not found in URL.";
return "";
}
- size_t name_end = query.find("=", name_start);
+ size_t name_end = query.find('=', name_start);
if (name_end == std::string::npos) {
DLOG(WARNING) << "Value of " << name << " not found in URL.";
return "";
}
size_t value_start = name_end - name_start + 1;
- size_t value_end = query.find_first_of("&", value_start);
+ size_t value_end = query.find_first_of('&', value_start);
if (value_end != std::string::npos) {
value_end -= value_start;
}
diff --git a/src/cobalt/browser/lib/cobalt.def b/src/cobalt/browser/lib/cobalt.def
index 2f36ae8..4aa31cc 100644
--- a/src/cobalt/browser/lib/cobalt.def
+++ b/src/cobalt/browser/lib/cobalt.def
@@ -10,6 +10,9 @@
; From cobalt/network/lib/user_agent.h:
CbLibUserAgentSetPlatformNameSuffix
+ CbLibUserAgentSetDeviceTypeOverride
+ CbLibUserAgentSetBrandNameOverride
+ CbLibUserAgentSetModelNameOverride
; From cobalt/browser/lib/exported/main.h:
CbLibMainSetCallbackRegistrationReadyCallback
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index e7432ef..eb8db8f 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -73,6 +73,11 @@
const char kMemoryTrackerHelp[] =
"Enables memory tracking by installing the memory tracker on startup.";
+const char kMinCompatibilityVersion[] = "min_compatibility_version";
+const char kMinCompatibilityVersionHelp[] =
+ "The minimum version of Cobalt that will be checked during compatibility "
+ "validations.";
+
const char kMinLogLevel[] = "min_log_level";
const char kMinLogLevelHelp[] =
"Set the minimum logging level: info|warning|error|fatal.";
@@ -165,6 +170,15 @@
const char kDisableJavaScriptJitHelp[] =
"Specifies that javascript jit should be disabled.";
+const char kEnableMapToMeshRectanglar[] = "enable_map_to_mesh_rectangular";
+const char kEnableMapToMeshRectanglarHelp[] =
+ "If toggled and map-to-mesh is supported on this platform, this allows it "
+ "to accept the 'rectangular' keyword. Useful to get rectangular stereo "
+ "video on platforms that do not support stereoscopy natively, letting the "
+ "client apply a stereo mesh projection (one that differs for each eye).";
+
+// If toggled, framerate statistics will be printed to stdout after each
+// animation completes, or after a maximum number of frames has been collected.
const char kFPSPrint[] = "fps_stdout";
const char kFPSPrintHelp[] =
"If toggled, framerate statistics will be printed to stdout after each "
@@ -310,6 +324,7 @@
{kFakeMicrophone, kFakeMicrophoneHelp},
{kIgnoreCertificateErrors, kIgnoreCertificateErrorsHelp},
{kInputFuzzer, kInputFuzzerHelp}, {kMemoryTracker, kMemoryTrackerHelp},
+ {kMinCompatibilityVersion, kMinCompatibilityVersionHelp},
{kMinLogLevel, kMinLogLevelHelp},
{kNullAudioStreamer, kNullAudioStreamerHelp},
{kNullSavegame, kNullSavegameHelp},
@@ -328,6 +343,7 @@
#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
{kDisableJavaScriptJit, kDisableJavaScriptJitHelp},
+ {kEnableMapToMeshRectanglar, kEnableMapToMeshRectanglarHelp},
{kFPSPrint, kFPSPrintHelp}, {kFPSOverlay, kFPSOverlayHelp},
{kHelp, kHelpHelp},
{kImageCacheSizeInBytes, kImageCacheSizeInBytesHelp},
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index 1280a2d..a46e11b 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -45,6 +45,8 @@
extern const char kInputFuzzerHelp[];
extern const char kMemoryTracker[];
extern const char kMemoryTrackerHelp[];
+extern const char kMinCompatibilityVersion[];
+extern const char kMinCompatibilityVersionHelp[];
extern const char kMinLogLevel[];
extern const char kMinLogLevelHelp[];
extern const char kNullAudioStreamer[];
@@ -85,6 +87,7 @@
extern const char kDisableJavaScriptJit[];
extern const char kDisableJavaScriptJitHelp[];
+extern const char kEnableMapToMeshRectanglar[];
extern const char kFPSPrint[];
extern const char kFPSPrintHelp[];
extern const char kFPSOverlay[];
diff --git a/src/cobalt/browser/trace_manager.cc b/src/cobalt/browser/trace_manager.cc
index 5a5769f..3a28d07 100644
--- a/src/cobalt/browser/trace_manager.cc
+++ b/src/cobalt/browser/trace_manager.cc
@@ -90,7 +90,8 @@
if (trace_to_file_) {
LOG(INFO) << "Ending trace.";
- LOG(INFO) << "Trace results in file \"" << kOutputTraceFilename << "\"";
+ LOG(INFO) << "Trace results in file \""
+ << trace_to_file_->absolute_output_path().value() << "\"";
trace_to_file_.reset();
} else {
if (IsTracing()) {
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 39431de..dbb2ba4 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -27,6 +27,7 @@
#include "base/message_loop_proxy.h"
#include "base/optional.h"
#include "base/stringprintf.h"
+#include "cobalt/base/c_val.h"
#include "cobalt/base/language.h"
#include "cobalt/base/startup_timer.h"
#include "cobalt/base/tokens.h"
@@ -183,6 +184,8 @@
// will be called. The event is not directed at a specific element.
void InjectBeforeUnloadEvent();
+ void InjectCaptionSettingsChangedEvent();
+
// Executes JavaScript in this WebModule. Sets the |result| output parameter
// and signals |got_result|.
void ExecuteJavascript(const std::string& script_utf8,
@@ -308,6 +311,9 @@
// Simple flag used for basic error checking.
bool is_running_;
+ // Whether or not a render tree has been produced but not yet rasterized.
+ base::CVal<bool, base::CValPublic> is_render_tree_rasterization_pending_;
+
// Object that provides renderer resources like images and fonts.
render_tree::ResourceProvider* resource_provider_;
// The type id of resource provider being used by the WebModule. Whenever this
@@ -421,6 +427,9 @@
base::Closure on_before_unload_fired_but_not_handled_;
bool should_retain_remote_typeface_cache_on_suspend_;
+
+ scoped_refptr<cobalt::dom::captions::SystemCaptionSettings>
+ system_caption_settings_;
};
class WebModule::Impl::DocumentLoadedObserver : public dom::DocumentObserver {
@@ -445,6 +454,9 @@
WebModule::Impl::Impl(const ConstructionData& data)
: name_(data.options.name),
is_running_(false),
+ is_render_tree_rasterization_pending_(
+ StringPrintf("%s.IsRenderTreeRasterizationPending", name_.c_str()),
+ false, "True when a render tree is produced but not yet rasterized."),
resource_provider_(data.resource_provider),
resource_provider_type_id_(data.resource_provider->GetTypeId()) {
// Currently we rely on a platform to explicitly specify that it supports
@@ -463,7 +475,9 @@
// testing whether it parses or not via the CSS.supports() Web API.
css_parser::Parser::SupportsMapToMeshFlag supports_map_to_mesh =
#if defined(ENABLE_MAP_TO_MESH)
- css_parser::Parser::kSupportsMapToMesh;
+ data.options.enable_map_to_mesh_rectangular
+ ? css_parser::Parser::kSupportsMapToMeshRectangular
+ : css_parser::Parser::kSupportsMapToMesh;
#else
css_parser::Parser::kDoesNotSupportMapToMesh;
#endif
@@ -565,6 +579,9 @@
media_session_client_ = media_session::MediaSessionClient::Create();
+ system_caption_settings_ =
+ new cobalt::dom::captions::SystemCaptionSettings();
+
dom::Window::CacheCallback splash_screen_cache_callback =
CacheUrlContentCallback(data.options.splash_screen_cache);
@@ -603,7 +620,8 @@
#else
dom::Window::kClockTypeSystemTime,
#endif
- splash_screen_cache_callback);
+ splash_screen_cache_callback,
+ system_caption_settings_);
DCHECK(window_);
window_weak_ = base::AsWeakPtr(window_.get());
@@ -842,19 +860,13 @@
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(is_running_);
- LayoutResults layout_results_with_callback(layout_results.render_tree,
- layout_results.layout_time);
-
- // Notify the stat tracker that a render tree has been produced.
+ is_render_tree_rasterization_pending_ = true;
web_module_stat_tracker_->OnRenderTreeProduced();
- // If the stat tracker is expecting to be notified of the rasterization time
- // of the next render tree, then set a callback for this layout.
- if (web_module_stat_tracker_->IsRenderTreeRasterizationPending()) {
- layout_results_with_callback.on_rasterized_callback =
- base::Bind(&WebModule::Impl::OnRenderTreeRasterized,
- base::Unretained(this), base::MessageLoopProxy::current());
- }
+ LayoutResults layout_results_with_callback(
+ layout_results.render_tree, layout_results.layout_time,
+ base::Bind(&WebModule::Impl::OnRenderTreeRasterized,
+ base::Unretained(this), base::MessageLoopProxy::current()));
#if defined(ENABLE_DEBUG_CONSOLE)
debug_overlay_->OnRenderTreeProduced(layout_results_with_callback);
@@ -874,6 +886,7 @@
const base::TimeTicks& on_rasterize_time) {
DCHECK(thread_checker_.CalledOnValidThread());
web_module_stat_tracker_->OnRenderTreeRasterized(on_rasterize_time);
+ is_render_tree_rasterization_pending_ = false;
}
#if defined(ENABLE_PARTIAL_LAYOUT_CONTROL)
@@ -1139,6 +1152,11 @@
}
}
+void WebModule::Impl::InjectCaptionSettingsChangedEvent() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ system_caption_settings_->OnCaptionSettingsChanged();
+}
+
void WebModule::Impl::PurgeResourceCaches(
bool should_retain_remote_typeface_cache) {
image_cache_->Purge();
@@ -1188,6 +1206,7 @@
image_cache_capacity(32 * 1024 * 1024),
remote_typeface_cache_capacity(4 * 1024 * 1024),
mesh_cache_capacity(COBALT_MESH_CACHE_SIZE_IN_BYTES),
+ enable_map_to_mesh_rectangular(false),
csp_enforcement_mode(dom::kCspEnforcementEnable),
csp_insecure_allowed_token(0),
track_event_stats(false),
@@ -1390,6 +1409,16 @@
base::Unretained(impl_.get())));
}
+void WebModule::InjectCaptionSettingsChangedEvent() {
+ TRACE_EVENT0("cobalt::browser",
+ "WebModule::InjectCaptionSettingsChangedEvent()");
+ DCHECK(message_loop());
+ DCHECK(impl_);
+ message_loop()->PostTask(FROM_HERE,
+ base::Bind(&WebModule::Impl::InjectCaptionSettingsChangedEvent,
+ base::Unretained(impl_.get())));
+}
+
std::string WebModule::ExecuteJavascript(
const std::string& script_utf8, const base::SourceLocation& script_location,
bool* out_succeeded) {
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index c0b94b1..8b712db 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -137,6 +137,9 @@
// Mesh cache capacity in bytes.
int mesh_cache_capacity;
+ // Whether map-to-mesh for rectangular videos is enabled.
+ bool enable_map_to_mesh_rectangular;
+
// Content Security Policy enforcement mode for this web module.
dom::CspEnforcementType csp_enforcement_mode;
@@ -263,6 +266,8 @@
// will be called.
void InjectBeforeUnloadEvent();
+ void InjectCaptionSettingsChangedEvent();
+
// Executes Javascript code in this web module. The calling thread will
// block until the JavaScript has executed and the output results are
// available.
diff --git a/src/cobalt/browser/web_module_stat_tracker.cc b/src/cobalt/browser/web_module_stat_tracker.cc
index 55b4142..601cc5b 100644
--- a/src/cobalt/browser/web_module_stat_tracker.cc
+++ b/src/cobalt/browser/web_module_stat_tracker.cc
@@ -124,7 +124,6 @@
void WebModuleStatTracker::OnRenderTreeRasterized(
const base::TimeTicks& on_rasterize_time) {
- DCHECK(should_track_event_stats_);
for (const auto& event_stats : event_stats_list_) {
if (event_stats->is_render_tree_rasterization_pending) {
event_stats->is_render_tree_rasterization_pending = false;
@@ -134,17 +133,6 @@
}
}
-bool WebModuleStatTracker::IsRenderTreeRasterizationPending() const {
- if (should_track_event_stats_) {
- for (const auto& event_stats : event_stats_list_) {
- if (event_stats->is_render_tree_rasterization_pending) {
- return true;
- }
- }
- }
- return false;
-}
-
WebModuleStatTracker::EventStats::EventStats(const std::string& name)
: produced_render_tree(
StringPrintf("Event.%s.ProducedRenderTree", name.c_str()), false,
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 411e4df..04ded3e 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-136005
\ No newline at end of file
+140175
\ No newline at end of file
diff --git a/src/cobalt/build/cobalt_configuration.gypi b/src/cobalt/build/cobalt_configuration.gypi
index 83cbb0f..950aad0 100644
--- a/src/cobalt/build/cobalt_configuration.gypi
+++ b/src/cobalt/build/cobalt_configuration.gypi
@@ -69,27 +69,17 @@
# 'standard' -- The default package. It includes all sans-serif, serif,
# and FCC fonts, non-CJK fallback fonts in both 'normal' and
# 'bold' weights, 'normal' weight CJK ('bold' weight CJK is
- # synthesized from it), and historic script fonts. This
- # package is ~31.4MB.
- # 'limited_with_jp' -- A significantly smaller package than 'standard'.
- # This package removes all but 'normal' and 'bold' weighted
+ # synthesized from it), historic script fonts, and color
+ # emojis. This package is ~38.3MB.
+ # 'limited' -- A significantly smaller package than 'standard'. This
+ # package removes all but 'normal' and 'bold' weighted
# sans-serif and serif, removes the FCC fonts (which must be
# provided by the system or downloaded from the web),
- # removes the 'bold' weighted non-CJK fallback fonts (the
- # 'normal' weight is still included and is used to
- # synthesize bold), and replaces standard CJK with low
- # quality CJK. However, higher quality Japanese is still
- # included. Because low quality CJK cannot synthesize bold,
- # bold glyphs are unavailable in Chinese and Korean.
- # Historic script fonts are not included. This package is
- # ~11.5MB.
- # 'limited' -- A smaller package than 'limited_with_jp'. The two packages
- # are identical with the exception that 'limited' does not
- # include the higher quality Japanese font; instead it
- # relies on low quality CJK for all CJK characters. Because
- # low quality CJK cannot synthesize bold, bold glyphs are
- # unavailable in Chinese, Japanese, and Korean. This package
- # is ~8.3MB.
+ # replaces standard CJK with low quality CJK, removes
+ # historic script fonts, and replaces colored emojis with
+ # uncolored ones. Because low quality CJK cannot synthesize
+ # bold, bold glyphs are unavailable in Chinese, Japanese and
+ # Korean. This package is ~8.3MB.
# 'minimal' -- The smallest possible font package. It only includes
# Roboto's Basic Latin characters. Everything else must be
# provided by the system or downloaded from the web. This
@@ -126,7 +116,6 @@
'cobalt_font_package_override_fallback_lang_non_cjk%': -1,
'cobalt_font_package_override_fallback_lang_cjk%': -1,
'cobalt_font_package_override_fallback_lang_cjk_low_quality%': -1,
- 'cobalt_font_package_override_fallback_lang_jp%': -1,
'cobalt_font_package_override_fallback_historic%': -1,
'cobalt_font_package_override_fallback_color_emoji%': -1,
'cobalt_font_package_override_fallback_emoji%': -1,
@@ -473,6 +462,7 @@
'COBALT_BOX_DUMP_ENABLED',
'COBALT_BUILD_TYPE_DEBUG',
'COBALT_ENABLE_JAVASCRIPT_ERROR_LOGGING',
+ 'COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS',
'COBALT_SECURITY_SCREEN_CLEAR_TO_UGLY_COLOR',
'ENABLE_DEBUG_COMMAND_LINE_SWITCHES',
'ENABLE_DEBUG_C_VAL',
@@ -492,6 +482,7 @@
'ALLOCATOR_STATS_TRACKING',
'COBALT_BUILD_TYPE_DEVEL',
'COBALT_ENABLE_JAVASCRIPT_ERROR_LOGGING',
+ 'COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS',
'COBALT_SECURITY_SCREEN_CLEAR_TO_UGLY_COLOR',
'ENABLE_DEBUG_COMMAND_LINE_SWITCHES',
'ENABLE_DEBUG_C_VAL',
diff --git a/src/cobalt/build/config/base.gni b/src/cobalt/build/config/base.gni
index 5e55fd2..d695cc9 100644
--- a/src/cobalt/build/config/base.gni
+++ b/src/cobalt/build/config/base.gni
@@ -44,24 +44,16 @@
# "standard" -- The default package. It includes all sans-serif, serif, and
# FCC fonts, non-CJK fallback fonts in both 'normal' and 'bold'
# weights, 'normal' weight CJK ('bold' weight CJK is synthesized
-# from it), and historic script fonts. This package is ~31.4MB.
-# "limited_with_jp" -- A significantly smaller package than 'standard'. This
-# package removes all but 'normal' and 'bold' weighted
-# sans-serif and serif, removes the FCC fonts (which must be
-# provided by the system or downloaded from the web), removes
-# the 'bold' weighted non-CJK fallback fonts (the 'normal'
-# weight is still included and is used to synthesize bold), and
-# replaces standard CJK with low quality CJK. However, higher
-# quality Japanese is still included. Because low quality CJK
-# cannot synthesize bold, bold glyphs are unavailable in Chinese
-# and Korean. Historic script fonts are not included. This
-# package is ~11.5MB.
-# "limited" -- A smaller package than 'limited_with_jp'. The two packages are
-# identical with the exception that 'limited' does not include
-# the higher quality Japanese font; instead it relies on low
-# quality CJK for all CJK characters. Because low quality CJK
+# from it), historic script fonts, and color emojis. This
+# package is ~38.3MB.
+# 'limited' -- A significantly smaller package than 'standard'. This package
+# removes all but 'normal' and 'bold' weighted sans-serif and
+# serif, removes the FCC fonts (which must be provided by the
+# system or downloaded from the web), replaces standard CJK with
+# low quality CJK, removes historic script fonts, and replaces
+# colored emojis with uncolored ones. Because low quality CJK
# cannot synthesize bold, bold glyphs are unavailable in
-# Chinese, Japanese, and Korean. This package is ~8.3MB.
+# Chinese, Japanese and Korean. This package is ~8.3MB.
# "minimal" -- The smallest possible font package. It only includes Roboto's
# Basic Latin characters. Everything else must be provided by
# the system or downloaded from the web. This package is
@@ -112,9 +104,6 @@
if (!defined(cobalt_font_package_override_fallback_lang_cjk_low_quality)) {
cobalt_font_package_override_fallback_lang_cjk_low_quality = -1
}
-if (!defined(cobalt_font_package_override_fallback_lang_jp)) {
- cobalt_font_package_override_fallback_lang_jp = -1
-}
if (!defined(cobalt_font_package_override_fallback_historic)) {
cobalt_font_package_override_fallback_historic = -1
}
diff --git a/src/cobalt/content/fonts/README.md b/src/cobalt/content/fonts/README.md
index 7ce8582..749c1bc 100644
--- a/src/cobalt/content/fonts/README.md
+++ b/src/cobalt/content/fonts/README.md
@@ -54,43 +54,19 @@
'package_fallback_lang_non_cjk': 2,
'package_fallback_lang_cjk': 1,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_historic': 1,
'package_fallback_color_emoji': 1,
'package_fallback_emoji': 0,
'package_fallback_symbols': 1,
-* 'limited_with_jp' -- A significantly smaller package than 'standard'. This
- package removes all but 'normal' and 'bold' weighted sans-serif
- and serif, removes the FCC fonts (which must be provided by the
- system or downloaded from the web), removes the 'bold' weighted
- non-CJK fallback fonts (the 'normal' weight is still included
- and is used to synthesize bold), and replaces standard CJK with
- low quality CJK. However, higher quality Japanese is still
- included. Because low quality CJK cannot synthesize bold, bold
- glyphs are unavailable in Chinese and Korean. Historic script
- fonts are not included. Uncolored emojis are used in place of
- the colored ones. This package is ~11.5MB.
-
- Package category values:
- 'package_named_sans_serif': 2,
- 'package_named_serif': 0,
- 'package_named_fcc_fonts': 0,
- 'package_fallback_lang_non_cjk': 1,
- 'package_fallback_lang_cjk': 0,
- 'package_fallback_lang_cjk_low_quality': 1,
- 'package_fallback_lang_jp': 1,
- 'package_fallback_historic': 0,
- 'package_fallback_color_emoji': 0,
- 'package_fallback_emoji': 1,
- 'package_fallback_symbols': 1,
-
-* 'limited' -- A smaller package than 'limited_with_jp'. The two packages are
- identical with the exception that 'limited' does not include
- the higher quality Japanese font; instead it relies on low
- quality CJK for all CJK characters. Because low quality CJK
+* 'limited' -- A significantly smaller package than 'standard'. This package
+ removes all but 'normal' and 'bold' weighted sans-serif and
+ serif, removes the FCC fonts (which must be provided by the
+ system or downloaded from the web), replaces standard CJK with
+ low quality CJK, removes historic script fonts, and replaces
+ colored emojis with uncolored ones. Because low quality CJK
cannot synthesize bold, bold glyphs are unavailable in Chinese,
- Japanese, and Korean. This package is ~8.3MB.
+ Japanese and Korean. This package is ~8.3MB.
Package category values:
'package_named_sans_serif': 2,
@@ -99,7 +75,6 @@
'package_fallback_lang_non_cjk': 1,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 1,
- 'package_fallback_lang_jp': 0,
'package_fallback_historic': 0,
'package_fallback_color_emoji': 0,
'package_fallback_emoji': 1,
@@ -116,7 +91,6 @@
'package_fallback_lang_non_cjk': 0,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_historic': 0,
'package_fallback_color_emoji': 0,
'package_fallback_emoji': 0,
@@ -153,10 +127,6 @@
included when 'package_fallback_lang_cjk' has a value of '0'. This is the
only category of fonts that is not synthetically boldable.
- * 'package_fallback_lang_jp':
- Higher quality Japanese language-specific fallback fonts. These should
- only be included when 'package_fallback_lang_cjk' has a value of '0'.
-
* 'package_fallback_historic':
Historic script fallback fonts.
@@ -218,8 +188,6 @@
'package_fallback_lang_cjk'
* 'cobalt_font_package_override_fallback_lang_cjk_low_quality' ==>
'package_fallback_lang_cjk_low_quality'
- * 'cobalt_font_package_override_fallback_lang_jp' ==>
- 'package_fallback_lang_jp'
* 'cobalt_font_package_override_fallback_color_emoji' ==>
'package_fallback_color_emoji'
* 'cobalt_font_package_override_fallback_emoji' ==>
diff --git a/src/cobalt/content/fonts/config/common/fonts.xml b/src/cobalt/content/fonts/config/common/fonts.xml
index 3bfaefd..bfa0cdf 100644
--- a/src/cobalt/content/fonts/config/common/fonts.xml
+++ b/src/cobalt/content/fonts/config/common/fonts.xml
@@ -437,9 +437,6 @@
<family lang="ko" pages="0-4,17,30,32-39,41,43,46-159,169,172-215,249-251,254-255,497-498,512-658,660-682,685,687,689,691-696,698-702,704-718,760-761">
<font weight="400" style="normal" index="1">NotoSansCJK-Regular.ttc</font>
</family>
- <family lang="ja" pages="0,32,34-35,46-159,249-250,254-255,498,512-523,525-527,530-538,540-543,545-547,550,552,554-559,561,563-568,570,572-573,575-579,582-584,586-594,596-608,610-612,614-618,620,622-625,627-628,630-631,633-638,640,642-646,649-655,658,660-664,666,669-678,681,695-696,760-761">
- <font weight="400" style="normal">NotoSansJP-Regular.otf</font>
- </family>
<family pages="0,32-33,35-39,41,43,48,50,496-502,505,3584,4068,4072">
<font weight="400" style="normal">NotoColorEmoji.ttf</font>
</family>
diff --git a/src/cobalt/content/fonts/font_files/NotoSansJP-Regular.otf b/src/cobalt/content/fonts/font_files/NotoSansJP-Regular.otf
deleted file mode 100644
index 40b064a..0000000
--- a/src/cobalt/content/fonts/font_files/NotoSansJP-Regular.otf
+++ /dev/null
Binary files differ
diff --git a/src/cobalt/css_parser/grammar.y b/src/cobalt/css_parser/grammar.y
index 47f3bc5..f1d197e 100644
--- a/src/cobalt/css_parser/grammar.y
+++ b/src/cobalt/css_parser/grammar.y
@@ -242,6 +242,7 @@
%token kPreLineToken // pre-line
%token kPreWrapToken // pre-wrap
%token kPurpleToken // purple
+%token kRectangularToken // rectangular
%token kRedToken // red
%token kRepeatToken // repeat
%token kRepeatXToken // repeat-x
@@ -6790,6 +6791,21 @@
stereo_mode);
}
}
+ // map-to-mesh filter with the rectangular built-in mesh. Does not take FOV
+ // or transforms.
+ | cobalt_mtm_function_name maybe_whitespace kRectangularToken comma
+ kNoneToken comma kNoneToken maybe_cobalt_mtm_stereo_mode
+ ')' maybe_whitespace {
+ scoped_refptr<cssom::KeywordValue> stereo_mode =
+ MakeScopedRefPtrAndRelease($8);
+
+ if (!parser_impl->supports_map_to_mesh_rectangular()) {
+ YYERROR;
+ } else {
+ $$ = new cssom::MapToMeshFunction(cssom::MapToMeshFunction::kRectangular,
+ stereo_mode);
+ }
+ }
;
cobalt_map_to_mesh_spec:
diff --git a/src/cobalt/css_parser/parser.cc b/src/cobalt/css_parser/parser.cc
index 5397d14..fad2b67 100644
--- a/src/cobalt/css_parser/parser.cc
+++ b/src/cobalt/css_parser/parser.cc
@@ -176,6 +176,9 @@
}
bool supports_map_to_mesh() const { return supports_map_to_mesh_; }
+ bool supports_map_to_mesh_rectangular() const {
+ return supports_map_to_mesh_rectangular_;
+ }
private:
bool Parse();
@@ -218,6 +221,9 @@
// Whether or not we support parsing "filter: map-to-mesh(...)".
bool supports_map_to_mesh_;
+ // Whether or not we also support parsing
+ // "filter: map-to-mesh(rectangular, ...)".
+ bool supports_map_to_mesh_rectangular_;
static void IncludeInputWithMessage(const std::string& input,
const Parser::OnMessageCallback& callback,
@@ -257,8 +263,10 @@
css_parser_(css_parser),
scanner_(input_.c_str(), &string_pool_),
into_declaration_data_(NULL),
- supports_map_to_mesh_(supports_map_to_mesh ==
- Parser::kSupportsMapToMesh) {}
+ supports_map_to_mesh_(supports_map_to_mesh !=
+ Parser::kDoesNotSupportMapToMesh),
+ supports_map_to_mesh_rectangular_(
+ supports_map_to_mesh == Parser::kSupportsMapToMeshRectangular) {}
scoped_refptr<cssom::CSSStyleSheet> ParserImpl::ParseStyleSheet() {
TRACK_MEMORY_SCOPE("CSS");
diff --git a/src/cobalt/css_parser/parser.h b/src/cobalt/css_parser/parser.h
index f556672..35ee0e9 100644
--- a/src/cobalt/css_parser/parser.h
+++ b/src/cobalt/css_parser/parser.h
@@ -27,6 +27,8 @@
public:
enum SupportsMapToMeshFlag {
kSupportsMapToMesh,
+ // Additionally supports map-to-mesh on rectangular video.
+ kSupportsMapToMeshRectangular,
kDoesNotSupportMapToMesh,
};
diff --git a/src/cobalt/css_parser/scanner.cc b/src/cobalt/css_parser/scanner.cc
index 06f6eaa..9ad950b 100644
--- a/src/cobalt/css_parser/scanner.cc
+++ b/src/cobalt/css_parser/scanner.cc
@@ -2276,6 +2276,10 @@
*property_value_token = kTransparentToken;
return true;
}
+ if (IsEqualToCssIdentifier(name.begin, cssom::kRectangularKeywordName)) {
+ *property_value_token = kRectangularToken;
+ return true;
+ }
return false;
case 12:
diff --git a/src/cobalt/cssom/compound_selector.h b/src/cobalt/cssom/compound_selector.h
index a9cbf44..90ea872 100644
--- a/src/cobalt/cssom/compound_selector.h
+++ b/src/cobalt/cssom/compound_selector.h
@@ -51,7 +51,7 @@
// Rest of public methods.
void AppendSelector(scoped_ptr<SimpleSelector> selector);
- const SimpleSelectors& simple_selectors() { return simple_selectors_; }
+ const SimpleSelectors& simple_selectors() const { return simple_selectors_; }
PseudoElement* pseudo_element() {
if (has_pseudo_element_) {
for (SimpleSelectors::iterator iter = simple_selectors_.begin();
diff --git a/src/cobalt/cssom/keyword_names.cc b/src/cobalt/cssom/keyword_names.cc
index 6ef873c..98f8ac3 100644
--- a/src/cobalt/cssom/keyword_names.cc
+++ b/src/cobalt/cssom/keyword_names.cc
@@ -85,6 +85,7 @@
const char kPreLineKeywordName[] = "pre-line";
const char kPreWrapKeywordName[] = "pre-wrap";
const char kPurpleKeywordName[] = "purple";
+const char kRectangularKeywordName[] = "rectangular";
const char kRedKeywordName[] = "red";
const char kRelativeKeywordName[] = "relative";
const char kRepeatKeywordName[] = "repeat";
diff --git a/src/cobalt/cssom/keyword_names.h b/src/cobalt/cssom/keyword_names.h
index a0956f6..57a0b46 100644
--- a/src/cobalt/cssom/keyword_names.h
+++ b/src/cobalt/cssom/keyword_names.h
@@ -87,6 +87,7 @@
extern const char kPreLineKeywordName[];
extern const char kPreWrapKeywordName[];
extern const char kPurpleKeywordName[];
+extern const char kRectangularKeywordName[];
extern const char kRedKeywordName[];
extern const char kRelativeKeywordName[];
extern const char kRepeatKeywordName[];
diff --git a/src/cobalt/cssom/map_to_mesh_function.cc b/src/cobalt/cssom/map_to_mesh_function.cc
index 800ffa6..6e408f0 100644
--- a/src/cobalt/cssom/map_to_mesh_function.cc
+++ b/src/cobalt/cssom/map_to_mesh_function.cc
@@ -29,6 +29,8 @@
if (mesh_spec().mesh_type() == kEquirectangular) {
result.append("equirectangular");
+ } else if (mesh_spec().mesh_type() == kRectangular) {
+ result.append("rectangular");
} else if (mesh_spec().mesh_type() == kUrls) {
result.append(mesh_spec().mesh_url()->ToString());
@@ -44,20 +46,26 @@
}
}
- result.append(base::StringPrintf(", %.7grad", horizontal_fov_in_radians()));
- result.append(base::StringPrintf(" %.7grad, ", vertical_fov_in_radians()));
+ if (mesh_spec().mesh_type() == kRectangular) {
+ // Rectangular filters carry neither FOV nor transforms.
+ result.append(", none, none, ");
+ } else {
+ result.append(base::StringPrintf(", %.7grad", horizontal_fov_in_radians()));
+ result.append(base::StringPrintf(" %.7grad, ", vertical_fov_in_radians()));
- result.append("matrix3d(");
- for (int col = 0; col <= 3; ++col) {
- for (int row = 0; row <= 3; ++row) {
- if (col > 0 || row > 0) {
- result.append(", ");
+ result.append("matrix3d(");
+ for (int col = 0; col <= 3; ++col) {
+ for (int row = 0; row <= 3; ++row) {
+ if (col > 0 || row > 0) {
+ result.append(", ");
+ }
+ result.append(base::StringPrintf("%.7g", transform()[col][row]));
}
- result.append(base::StringPrintf("%.7g", transform()[col][row]));
}
+
+ result.append("), ");
}
- result.append("), ");
result.append(stereo_mode()->ToString());
result.append(")");
diff --git a/src/cobalt/cssom/map_to_mesh_function.h b/src/cobalt/cssom/map_to_mesh_function.h
index 3b61145..e6f7d4e 100644
--- a/src/cobalt/cssom/map_to_mesh_function.h
+++ b/src/cobalt/cssom/map_to_mesh_function.h
@@ -55,6 +55,8 @@
// Type of the source of the mesh: either a built-in mesh type or a custom
// mesh.
enum MeshSpecType {
+ // Built-in rectangular mesh.
+ kRectangular,
// Built-in equirectangular mesh.
kEquirectangular,
// List of custom binary mesh URLs.
@@ -67,7 +69,7 @@
public:
explicit MeshSpec(MeshSpecType mesh_type) : mesh_type_(mesh_type) {
// Check that this is a built-in mesh type.
- DCHECK_EQ(mesh_type, kEquirectangular);
+ DCHECK(mesh_type == kRectangular || mesh_type == kEquirectangular);
}
MeshSpec(MeshSpecType mesh_type,
@@ -108,6 +110,7 @@
transform_(transform),
stereo_mode_(stereo_mode) {
DCHECK(mesh_spec_);
+ DCHECK_NE(mesh_spec_->mesh_type(), kRectangular);
DCHECK(stereo_mode_);
}
@@ -135,6 +138,19 @@
vertical_fov_in_radians_(vertical_fov_in_radians),
transform_(transform),
stereo_mode_(stereo_mode) {
+ DCHECK_NE(spec_type, kRectangular);
+ DCHECK(stereo_mode_);
+ }
+
+ // Alternate constructor for built-in meshes without FOV or transforms.
+ MapToMeshFunction(MeshSpecType spec_type,
+ const scoped_refptr<KeywordValue>& stereo_mode)
+ : mesh_spec_(new MeshSpec(spec_type)),
+ horizontal_fov_in_radians_(0.0f),
+ vertical_fov_in_radians_(0.0f),
+ transform_(glm::mat4()),
+ stereo_mode_(stereo_mode) {
+ DCHECK_EQ(spec_type, kRectangular);
DCHECK(stereo_mode_);
}
diff --git a/src/cobalt/cssom/selector_tree.cc b/src/cobalt/cssom/selector_tree.cc
index 9e520f4..011032f 100644
--- a/src/cobalt/cssom/selector_tree.cc
+++ b/src/cobalt/cssom/selector_tree.cc
@@ -14,6 +14,11 @@
#include "cobalt/cssom/selector_tree.h"
+#include <set>
+
+#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+#include "cobalt/base/version_compatibility.h"
+#endif // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
#include "cobalt/cssom/complex_selector.h"
#include "cobalt/cssom/compound_selector.h"
#include "cobalt/cssom/css_style_rule.h"
@@ -71,6 +76,110 @@
return owned_nodes_map_[std::make_pair(node, combinator)];
}
+#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+namespace {
+
+// This uses the old CompoundSelector compare logic that had a bug where 'not'
+// pseudo classes with the same prefix would be treated as matching, regardless
+// of their arguments.
+struct PreVersion16CompoundSelectorLessThan {
+ bool operator()(const CompoundSelector* lhs,
+ const CompoundSelector* rhs) const {
+ const CompoundSelector::SimpleSelectors& lhs_simple_selectors =
+ lhs->simple_selectors();
+ const CompoundSelector::SimpleSelectors& rhs_simple_selectors =
+ rhs->simple_selectors();
+ if (lhs_simple_selectors.size() < rhs_simple_selectors.size()) {
+ return true;
+ }
+ if (lhs_simple_selectors.size() > rhs_simple_selectors.size()) {
+ return false;
+ }
+
+ for (size_t i = 0; i < lhs_simple_selectors.size(); ++i) {
+ if (lhs_simple_selectors[i]->type() < rhs_simple_selectors[i]->type()) {
+ return true;
+ }
+ if (lhs_simple_selectors[i]->type() > rhs_simple_selectors[i]->type()) {
+ return false;
+ }
+ if (lhs_simple_selectors[i]->prefix() <
+ rhs_simple_selectors[i]->prefix()) {
+ return true;
+ }
+ if (lhs_simple_selectors[i]->prefix() >
+ rhs_simple_selectors[i]->prefix()) {
+ return false;
+ }
+ if (lhs_simple_selectors[i]->text() < rhs_simple_selectors[i]->text()) {
+ return true;
+ }
+ if (lhs_simple_selectors[i]->text() > rhs_simple_selectors[i]->text()) {
+ return false;
+ }
+ }
+
+ return false;
+ }
+};
+
+bool HasNotPseudoClassCompatibilityViolations(
+ const SelectorTree::OwnedNodesMap& owned_nodes_map) {
+ constexpr int kNotPseudoClassCobaltVersionFix = 16;
+ if (base::VersionCompatibility::GetInstance()->GetMinimumVersion() >=
+ kNotPseudoClassCobaltVersionFix) {
+ return false;
+ }
+
+ typedef std::set<CompoundSelector*, PreVersion16CompoundSelectorLessThan>
+ PreVersion16CompoundSelectorLessThanSet;
+
+ // Walk all of the owned nodes looking for multiple compound selectors within
+ // them that are treated as duplicates using the pre-version 16 compound
+ // selector less than logic.
+ PreVersion16CompoundSelectorLessThanSet unsupported_usage_set;
+ for (const auto& owned_nodes_iterator : owned_nodes_map) {
+ PreVersion16CompoundSelectorLessThanSet encountered_set;
+ for (const auto& node_info : owned_nodes_iterator.second) {
+ if (!encountered_set.insert(node_info.first).second) {
+ unsupported_usage_set.insert(node_info.first);
+ }
+ }
+ }
+
+ // Log the cases of unsupported usage.
+ for (const auto& unsupported_usage_iterator : unsupported_usage_set) {
+ const std::string kUnsupportedNotUsageString =
+ "Unsupported :not() pseudo class usage found. Multiple negation pseudo "
+ "classes with the same prefix but different arguments are not "
+ "supported in versions of Cobalt <= 15. Offending selectors: '";
+
+ std::string selectors_string;
+ const CompoundSelector::SimpleSelectors& simple_selectors =
+ unsupported_usage_iterator->simple_selectors();
+ for (const auto& simple_selector : simple_selectors) {
+ selectors_string += simple_selector->prefix().c_str();
+ if (simple_selector->type() == kPseudoClass &&
+ simple_selector->GetContainedCompoundSelector() != NULL) {
+ selectors_string += "not(...)";
+ } else {
+ selectors_string += simple_selector->text().c_str();
+ }
+ }
+
+ base::VersionCompatibility::GetInstance()->ReportViolation(
+ kUnsupportedNotUsageString + selectors_string);
+ }
+ return !unsupported_usage_set.empty();
+}
+
+} // namespace
+
+bool SelectorTree::ValidateVersionCompatibility() const {
+ return !HasNotPseudoClassCompatibilityViolations(owned_nodes_map_);
+}
+#endif // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+
SelectorTree::Node* SelectorTree::GetOrCreateNodeForComplexSelector(
ComplexSelector* complex_selector) {
CompoundSelector* selector = complex_selector->first_selector();
diff --git a/src/cobalt/cssom/selector_tree.h b/src/cobalt/cssom/selector_tree.h
index 1192d3b..10f1545 100644
--- a/src/cobalt/cssom/selector_tree.h
+++ b/src/cobalt/cssom/selector_tree.h
@@ -140,6 +140,9 @@
}
};
+ typedef std::map<std::pair<const Node*, CombinatorType>, OwnedNodes>
+ OwnedNodesMap;
+
struct PseudoClassNode {
PseudoClassType pseudo_class_type;
CombinatorType combinator_type;
@@ -265,6 +268,12 @@
// Used by unit tests only.
const OwnedNodes& children(const Node* node, CombinatorType combinator);
+#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+ // Validates the selector tree's compatibility against pre-selected versions
+ // of Cobalt. Returns true if there are no version compatibility violations.
+ bool ValidateVersionCompatibility() const;
+#endif // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+
private:
// Gets or creates node for complex selector, starting from root.
Node* GetOrCreateNodeForComplexSelector(ComplexSelector* selector);
@@ -283,7 +292,7 @@
// type. It is only used when modifying the SelectorTree and is not used
// during rule matching. So we store it externally to the Node to minimize
// the size of Node structure.
- std::map<std::pair<const Node*, CombinatorType>, OwnedNodes> owned_nodes_map_;
+ OwnedNodesMap owned_nodes_map_;
bool has_sibling_combinators_;
diff --git a/src/cobalt/cssom/selector_tree_test.cc b/src/cobalt/cssom/selector_tree_test.cc
index 2e909ce..304f5c9 100644
--- a/src/cobalt/cssom/selector_tree_test.cc
+++ b/src/cobalt/cssom/selector_tree_test.cc
@@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "cobalt/cssom/selector_tree.h"
+
+#include "cobalt/base/version_compatibility.h"
#include "cobalt/css_parser/parser.h"
#include "cobalt/cssom/css_style_rule.h"
-#include "cobalt/cssom/selector_tree.h"
#include "cobalt/cssom/specificity.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -48,6 +50,12 @@
"[object SelectorTreeTest]", 1, 1))
->AsCSSStyleRule();
selector_tree.AppendRule(css_style_rule_1);
+
+ // Verify that ValidateVersionCompatibility does not report a usage error
+ // when the minimum compatibility version is 1.
+ base::VersionCompatibility::GetInstance()->SetMinimumVersion(1);
+ EXPECT_TRUE(selector_tree.ValidateVersionCompatibility());
+
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(1,
@@ -88,6 +96,12 @@
->AsCSSStyleRule();
selector_tree.AppendRule(css_style_rule_1);
selector_tree.AppendRule(css_style_rule_2);
+
+ // Verify that ValidateVersionCompatibility does not report a usage error
+ // when the minimum compatibility version is 1.
+ base::VersionCompatibility::GetInstance()->SetMinimumVersion(1);
+ EXPECT_TRUE(selector_tree.ValidateVersionCompatibility());
+
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(1,
@@ -119,6 +133,11 @@
selector_tree.AppendRule(css_style_rule_1);
selector_tree.AppendRule(css_style_rule_2);
+ // Verify that ValidateVersionCompatibility does not report a usage error
+ // when the minimum compatibility version is 1.
+ base::VersionCompatibility::GetInstance()->SetMinimumVersion(1);
+ EXPECT_TRUE(selector_tree.ValidateVersionCompatibility());
+
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(1,
@@ -160,6 +179,11 @@
selector_tree.AppendRule(css_style_rule_1);
selector_tree.AppendRule(css_style_rule_2);
+ // Verify that ValidateVersionCompatibility does not report a usage error
+ // when the minimum compatibility version is 1.
+ base::VersionCompatibility::GetInstance()->SetMinimumVersion(1);
+ EXPECT_TRUE(selector_tree.ValidateVersionCompatibility());
+
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(1,
@@ -212,6 +236,16 @@
selector_tree.AppendRule(css_style_rule_1);
selector_tree.AppendRule(css_style_rule_2);
+ // Verify that ValidateVersionCompatibility does not report a usage error
+ // when the minimum compatibility version is 16.
+ base::VersionCompatibility::GetInstance()->SetMinimumVersion(16);
+ EXPECT_TRUE(selector_tree.ValidateVersionCompatibility());
+
+ // Verify that ValidateVersionCompatibility reports a usage error when the
+ // minimum compatibility version is 1.
+ base::VersionCompatibility::GetInstance()->SetMinimumVersion(1);
+ EXPECT_FALSE(selector_tree.ValidateVersionCompatibility());
+
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(2,
@@ -258,6 +292,11 @@
selector_tree.AppendRule(css_style_rule_1);
selector_tree.AppendRule(css_style_rule_2);
+ // Verify that ValidateVersionCompatibility does not report a usage error
+ // when the minimum compatibility version is 1.
+ base::VersionCompatibility::GetInstance()->SetMinimumVersion(1);
+ EXPECT_TRUE(selector_tree.ValidateVersionCompatibility());
+
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(2,
@@ -303,6 +342,11 @@
selector_tree.AppendRule(css_style_rule_1);
selector_tree.AppendRule(css_style_rule_2);
+ // Verify that ValidateVersionCompatibility does not report a usage error
+ // when the minimum compatibility version is 1.
+ base::VersionCompatibility::GetInstance()->SetMinimumVersion(1);
+ EXPECT_TRUE(selector_tree.ValidateVersionCompatibility());
+
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(1,
diff --git a/src/cobalt/debug/javascript_debugger_component.h b/src/cobalt/debug/javascript_debugger_component.h
index 6d14fc1..5b3b1a6 100644
--- a/src/cobalt/debug/javascript_debugger_component.h
+++ b/src/cobalt/debug/javascript_debugger_component.h
@@ -65,7 +65,7 @@
// Script location, corresponding to physical breakpoint, etc.
struct ScriptLocation {
- ScriptLocation(const std::string script_id, int line_number,
+ ScriptLocation(const std::string& script_id, int line_number,
int column_number)
: script_id(script_id),
line_number(line_number),
diff --git a/src/cobalt/dom/captions/system_caption_settings.cc b/src/cobalt/dom/captions/system_caption_settings.cc
index 850e4ca..2535fa9 100644
--- a/src/cobalt/dom/captions/system_caption_settings.cc
+++ b/src/cobalt/dom/captions/system_caption_settings.cc
@@ -17,6 +17,8 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "cobalt/base/accessibility_caption_settings_changed_event.h"
+#include "cobalt/base/event_dispatcher.h"
#include "cobalt/dom/captions/caption_character_edge_style.h"
#include "cobalt/dom/captions/caption_color.h"
#include "cobalt/dom/captions/caption_font_family.h"
@@ -179,7 +181,10 @@
#endif // SB_HAS(CAPTIONS)
-SystemCaptionSettings::SystemCaptionSettings() {}
+void SystemCaptionSettings::OnCaptionSettingsChanged() {
+ DispatchEventAndRunCallback(base::Tokens::change(),
+ base::Closure(base::Bind(base::DoNothing)));
+}
base::optional<std::string> SystemCaptionSettings::background_color() {
#if SB_HAS(CAPTIONS)
diff --git a/src/cobalt/dom/captions/system_caption_settings.h b/src/cobalt/dom/captions/system_caption_settings.h
index 71c9753..2fe541d 100644
--- a/src/cobalt/dom/captions/system_caption_settings.h
+++ b/src/cobalt/dom/captions/system_caption_settings.h
@@ -18,6 +18,8 @@
#include <string>
+#include "cobalt/base/event.h"
+#include "cobalt/base/event_dispatcher.h"
#include "cobalt/dom/captions/caption_character_edge_style.h"
#include "cobalt/dom/captions/caption_color.h"
#include "cobalt/dom/captions/caption_font_family.h"
@@ -32,7 +34,7 @@
class SystemCaptionSettings : public EventTarget {
public:
- SystemCaptionSettings();
+ SystemCaptionSettings() {}
base::optional<std::string> background_color();
CaptionState background_color_state();
@@ -74,6 +76,8 @@
const EventListenerScriptValue* onchanged() const;
void set_onchanged(const EventListenerScriptValue& event_listener);
+ void OnCaptionSettingsChanged();
+
private:
// TODO: Delete these functions and their implementations if nullable
// enums work with our IDL generation code. Make the implementations of our
diff --git a/src/cobalt/dom/csp_delegate.cc b/src/cobalt/dom/csp_delegate.cc
index b9afec6..743b0ae 100644
--- a/src/cobalt/dom/csp_delegate.cc
+++ b/src/cobalt/dom/csp_delegate.cc
@@ -113,6 +113,10 @@
bool CspDelegateSecure::AllowInline(ResourceType type,
const base::SourceLocation& location,
const std::string& content) const {
+ // If CSP is not provided, allow inline script.
+ if (!was_header_received_) {
+ return true;
+ }
bool can_load = false;
if (type == kScript) {
can_load = csp_->AllowInlineScript(location.file_path, location.line_number,
@@ -128,6 +132,8 @@
bool CspDelegateSecure::AllowEval(std::string* eval_disabled_message) const {
bool allow_eval =
+ // If CSP is not provided, allow eval() function.
+ !was_header_received_ ||
csp_->AllowEval(csp::ContentSecurityPolicy::kSuppressReport);
if (!allow_eval && eval_disabled_message) {
*eval_disabled_message = csp_->disable_eval_error_message();
@@ -140,21 +146,21 @@
}
bool CspDelegateSecure::OnReceiveHeaders(const csp::ResponseHeaders& headers) {
- if (headers.content_security_policy().empty()) {
+ was_header_received_ = !headers.content_security_policy().empty();
+ if (was_header_received_) {
+ csp_->OnReceiveHeaders(headers);
+ } else {
// Didn't find Content-Security-Policy header.
if (!headers.content_security_policy_report_only().empty()) {
DLOG(INFO)
<< "Content-Security-Policy-Report-Only headers were "
"received, but Content-Security-Policy headers are required.";
}
- return false;
}
- csp_->OnReceiveHeaders(headers);
- was_header_received_ = true;
if (!policy_changed_callback_.is_null()) {
policy_changed_callback_.Run();
}
- return true;
+ return was_header_received_;
}
void CspDelegateSecure::OnReceiveHeader(const std::string& header,
diff --git a/src/cobalt/dom/document.cc b/src/cobalt/dom/document.cc
index 26bfaff..545505f 100644
--- a/src/cobalt/dom/document.cc
+++ b/src/cobalt/dom/document.cc
@@ -898,6 +898,12 @@
AppendRulesFromCSSStyleSheetToSelectorTree(css_style_sheet,
selector_tree_.get());
}
+#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+ // Now that the selector tree is fully updated, validate its version
+ // compatibility.
+ selector_tree_->ValidateVersionCompatibility();
+#endif // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
+
scoped_refptr<HTMLHtmlElement> current_html = html();
if (current_html) {
current_html->InvalidateMatchingRulesRecursively();
diff --git a/src/cobalt/dom/html_video_element.cc b/src/cobalt/dom/html_video_element.cc
index 8b63f37..dad9259 100644
--- a/src/cobalt/dom/html_video_element.cc
+++ b/src/cobalt/dom/html_video_element.cc
@@ -22,10 +22,10 @@
namespace dom {
#if defined(COBALT_MEDIA_SOURCE_2016)
-using media::ShellVideoFrameProvider;
+using media::VideoFrameProvider;
using media::WebMediaPlayer;
#else // defined(COBALT_MEDIA_SOURCE_2016)
-using ::media::ShellVideoFrameProvider;
+using VideoFrameProvider = ::media::ShellVideoFrameProvider;
using ::media::WebMediaPlayer;
#endif // defined(COBALT_MEDIA_SOURCE_2016)
@@ -87,8 +87,7 @@
0.); // total_frame_delay
}
-scoped_refptr<ShellVideoFrameProvider>
-HTMLVideoElement::GetVideoFrameProvider() {
+scoped_refptr<VideoFrameProvider> HTMLVideoElement::GetVideoFrameProvider() {
DCHECK(thread_checker_.CalledOnValidThread());
return player() ? player()->GetVideoFrameProvider() : NULL;
}
diff --git a/src/cobalt/dom/html_video_element.h b/src/cobalt/dom/html_video_element.h
index 6e86996..fbfb27e 100644
--- a/src/cobalt/dom/html_video_element.h
+++ b/src/cobalt/dom/html_video_element.h
@@ -33,9 +33,9 @@
class HTMLVideoElement : public HTMLMediaElement {
public:
#if defined(COBALT_MEDIA_SOURCE_2016)
- typedef media::ShellVideoFrameProvider ShellVideoFrameProvider;
+ typedef media::VideoFrameProvider VideoFrameProvider;
#else // defined(COBALT_MEDIA_SOURCE_2016)
- typedef ::media::ShellVideoFrameProvider ShellVideoFrameProvider;
+ typedef ::media::ShellVideoFrameProvider VideoFrameProvider;
#endif // defined(WebMediaPlayerDelegate)
static const char kTagName[];
@@ -57,10 +57,7 @@
// From HTMLElement
scoped_refptr<HTMLVideoElement> AsHTMLVideoElement() override { return this; }
- // TODO: ShellVideoFrameProvider is guaranteed to be long live and
- // thread safe. However, it is actually a singleton internally. We should find
- // a better way to support concurrent video playbacks.
- scoped_refptr<ShellVideoFrameProvider> GetVideoFrameProvider();
+ scoped_refptr<VideoFrameProvider> GetVideoFrameProvider();
WebMediaPlayer::SetBoundsCB GetSetBoundsCB();
diff --git a/src/cobalt/dom/navigator.cc b/src/cobalt/dom/navigator.cc
index 29ebdb4..49b810f 100644
--- a/src/cobalt/dom/navigator.cc
+++ b/src/cobalt/dom/navigator.cc
@@ -31,15 +31,16 @@
namespace dom {
Navigator::Navigator(const std::string& user_agent, const std::string& language,
- scoped_refptr<MediaSession> media_session,
- script::ScriptValueFactory* script_value_factory)
+ scoped_refptr<MediaSession> media_session,
+ scoped_refptr<cobalt::dom::captions::SystemCaptionSettings> captions,
+ script::ScriptValueFactory* script_value_factory)
: user_agent_(user_agent),
language_(language),
mime_types_(new MimeTypeArray()),
plugins_(new PluginArray()),
media_session_(media_session),
media_devices_(new media_capture::MediaDevices(script_value_factory)),
- system_caption_settings_(new captions::SystemCaptionSettings()),
+ system_caption_settings_(captions),
script_value_factory_(script_value_factory) {}
const std::string& Navigator::language() const { return language_; }
diff --git a/src/cobalt/dom/navigator.h b/src/cobalt/dom/navigator.h
index ffdec86..f09f26f 100644
--- a/src/cobalt/dom/navigator.h
+++ b/src/cobalt/dom/navigator.h
@@ -40,8 +40,9 @@
class Navigator : public script::Wrappable {
public:
Navigator(const std::string& user_agent, const std::string& language,
- scoped_refptr<cobalt::media_session::MediaSession> media_session,
- script::ScriptValueFactory* script_value_factory);
+ scoped_refptr<cobalt::media_session::MediaSession> media_session,
+ scoped_refptr<cobalt::dom::captions::SystemCaptionSettings> captions,
+ script::ScriptValueFactory* script_value_factory);
// Web API: NavigatorID
const std::string& user_agent() const;
diff --git a/src/cobalt/dom/on_screen_keyboard.cc b/src/cobalt/dom/on_screen_keyboard.cc
index 0e33eca..aa20b06 100644
--- a/src/cobalt/dom/on_screen_keyboard.cc
+++ b/src/cobalt/dom/on_screen_keyboard.cc
@@ -21,6 +21,7 @@
namespace cobalt {
namespace dom {
+
OnScreenKeyboard::OnScreenKeyboard(
OnScreenKeyboardBridge* bridge,
script::ScriptValueFactory* script_value_factory)
@@ -33,12 +34,11 @@
scoped_ptr<OnScreenKeyboard::VoidPromiseValue> OnScreenKeyboard::Show() {
scoped_ptr<VoidPromiseValue> promise =
script_value_factory_->CreateBasicPromise<void>();
- VoidPromiseValue::StrongReference promise_reference(*promise);
int ticket = next_ticket_++;
bool is_emplaced =
ticket_to_show_promise_map_
- .emplace(ticket, std::unique_ptr<VoidPromiseValue::StrongReference>(
- new VoidPromiseValue::StrongReference(*promise)))
+ .emplace(ticket, std::unique_ptr<VoidPromiseValue::TracedReference>(
+ new VoidPromiseValue::TracedReference(*promise)))
.second;
DCHECK(is_emplaced);
bridge_->Show(data_.c_str(), ticket);
@@ -48,12 +48,11 @@
scoped_ptr<OnScreenKeyboard::VoidPromiseValue> OnScreenKeyboard::Hide() {
scoped_ptr<VoidPromiseValue> promise =
script_value_factory_->CreateBasicPromise<void>();
- VoidPromiseValue::StrongReference promise_reference(*promise);
int ticket = next_ticket_++;
bool is_emplaced =
ticket_to_hide_promise_map_
- .emplace(ticket, std::unique_ptr<VoidPromiseValue::StrongReference>(
- new VoidPromiseValue::StrongReference(*promise)))
+ .emplace(ticket, std::unique_ptr<VoidPromiseValue::TracedReference>(
+ new VoidPromiseValue::TracedReference(*promise)))
.second;
DCHECK(is_emplaced);
bridge_->Hide(ticket);
@@ -63,12 +62,11 @@
scoped_ptr<OnScreenKeyboard::VoidPromiseValue> OnScreenKeyboard::Focus() {
scoped_ptr<VoidPromiseValue> promise =
script_value_factory_->CreateBasicPromise<void>();
- VoidPromiseValue::StrongReference promise_reference(*promise);
int ticket = next_ticket_++;
bool is_emplaced =
ticket_to_focus_promise_map_
- .emplace(ticket, std::unique_ptr<VoidPromiseValue::StrongReference>(
- new VoidPromiseValue::StrongReference(*promise)))
+ .emplace(ticket, std::unique_ptr<VoidPromiseValue::TracedReference>(
+ new VoidPromiseValue::TracedReference(*promise)))
.second;
DCHECK(is_emplaced);
bridge_->Focus(ticket);
@@ -78,12 +76,11 @@
scoped_ptr<OnScreenKeyboard::VoidPromiseValue> OnScreenKeyboard::Blur() {
scoped_ptr<VoidPromiseValue> promise =
script_value_factory_->CreateBasicPromise<void>();
- VoidPromiseValue::StrongReference promise_reference(*promise);
int ticket = next_ticket_++;
bool is_emplaced =
ticket_to_blur_promise_map_
- .emplace(ticket, std::unique_ptr<VoidPromiseValue::StrongReference>(
- new VoidPromiseValue::StrongReference(*promise)))
+ .emplace(ticket, std::unique_ptr<VoidPromiseValue::TracedReference>(
+ new VoidPromiseValue::TracedReference(*promise)))
.second;
DCHECK(is_emplaced);
bridge_->Blur(ticket);
@@ -198,5 +195,14 @@
DispatchEvent(new dom::Event(base::Tokens::blur()));
}
+void OnScreenKeyboard::TraceMembers(script::Tracer* tracer) {
+ EventTarget::TraceMembers(tracer);
+
+ tracer->TraceValues(ticket_to_hide_promise_map_);
+ tracer->TraceValues(ticket_to_show_promise_map_);
+ tracer->TraceValues(ticket_to_focus_promise_map_);
+ tracer->TraceValues(ticket_to_blur_promise_map_);
+}
+
} // namespace dom
} // namespace cobalt
diff --git a/src/cobalt/dom/on_screen_keyboard.h b/src/cobalt/dom/on_screen_keyboard.h
index 2f436f9..4159a4a 100644
--- a/src/cobalt/dom/on_screen_keyboard.h
+++ b/src/cobalt/dom/on_screen_keyboard.h
@@ -38,7 +38,7 @@
typedef script::ScriptValue<script::Promise<void>> VoidPromiseValue;
typedef std::unordered_map<int,
- std::unique_ptr<VoidPromiseValue::StrongReference>>
+ std::unique_ptr<VoidPromiseValue::TracedReference>>
TicketToPromiseMap;
OnScreenKeyboard(OnScreenKeyboardBridge* bridge,
@@ -87,6 +87,7 @@
void DispatchBlurEvent(int ticket);
DEFINE_WRAPPABLE_TYPE(OnScreenKeyboard);
+ void TraceMembers(script::Tracer* tracer) override;
private:
~OnScreenKeyboard() override {}
diff --git a/src/cobalt/dom/rule_matching.cc b/src/cobalt/dom/rule_matching.cc
index 7e8f67b..f764718 100644
--- a/src/cobalt/dom/rule_matching.cc
+++ b/src/cobalt/dom/rule_matching.cc
@@ -434,7 +434,7 @@
void ForEachChildOnNodes(
const NodeSet& node_set, cssom::CombinatorType combinator_type,
HTMLElement* element,
- base::Callback<void(HTMLElement* element, const SelectorTree::Node*)>
+ const base::Callback<void(HTMLElement* element, const SelectorTree::Node*)>&
callback) {
// Gathering Phase: Generate candidate nodes from the node set.
SelectorTree::NodeSet<kRuleMatchingNodeSetSize> candidate_nodes;
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index 0a5f9ce..8da7ca4 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -119,7 +119,8 @@
const scoped_refptr<MediaSession>& media_session,
int csp_insecure_allowed_token, int dom_max_element_depth,
float video_playback_rate_multiplier, ClockType clock_type,
- const CacheCallback& splash_screen_cache_callback)
+ const CacheCallback& splash_screen_cache_callback,
+ const scoped_refptr<captions::SystemCaptionSettings>& captions)
: width_(width),
height_(height),
device_pixel_ratio_(device_pixel_ratio),
@@ -159,7 +160,7 @@
document_loader_(NULL),
history_(new History()),
navigator_(new Navigator(user_agent, language, media_session,
- script_value_factory)),
+ captions, script_value_factory)),
ALLOW_THIS_IN_INITIALIZER_LIST(
relay_on_load_event_(new RelayLoadEvent(this))),
console_(new Console(execution_state)),
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h
index 0f3079f..1afd941 100644
--- a/src/cobalt/dom/window.h
+++ b/src/cobalt/dom/window.h
@@ -27,6 +27,7 @@
#include "cobalt/cssom/css_parser.h"
#include "cobalt/cssom/css_style_declaration.h"
#include "cobalt/dom/animation_frame_request_callback_list.h"
+#include "cobalt/dom/captions/system_caption_settings.h"
#include "cobalt/dom/crypto.h"
#include "cobalt/dom/csp_delegate_type.h"
#include "cobalt/dom/dom_stat_tracker.h"
@@ -155,7 +156,8 @@
int csp_insecure_allowed_token = 0, int dom_max_element_depth = 0,
float video_playback_rate_multiplier = 1.f,
ClockType clock_type = kClockTypeSystemTime,
- const CacheCallback& splash_screen_cache_callback = CacheCallback());
+ const CacheCallback& splash_screen_cache_callback = CacheCallback(),
+ const scoped_refptr<captions::SystemCaptionSettings>& captions = nullptr);
// Web API: Window
//
diff --git a/src/cobalt/layout/box_generator.cc b/src/cobalt/layout/box_generator.cc
index 8502790..7fe2d0e 100644
--- a/src/cobalt/layout/box_generator.cc
+++ b/src/cobalt/layout/box_generator.cc
@@ -43,7 +43,7 @@
#include "cobalt/render_tree/image.h"
#include "cobalt/web_animations/keyframe_effect_read_only.h"
#if defined(COBALT_MEDIA_SOURCE_2016)
-#include "cobalt/media/base/shell_video_frame_provider.h"
+#include "cobalt/media/base/video_frame_provider.h"
#else // defined(COBALT_MEDIA_SOURCE_2016)
#include "media/base/shell_video_frame_provider.h"
#endif // defined(COBALT_MEDIA_SOURCE_2016)
@@ -53,17 +53,16 @@
namespace layout {
#if defined(COBALT_MEDIA_SOURCE_2016)
-using media::ShellVideoFrameProvider;
-using media::VideoFrame;
+using media::VideoFrameProvider;
#else // defined(COBALT_MEDIA_SOURCE_2016)
-using ::media::ShellVideoFrameProvider;
+using VideoFrameProvider = ::media::ShellVideoFrameProvider;
using ::media::VideoFrame;
#endif // defined(COBALT_MEDIA_SOURCE_2016)
namespace {
scoped_refptr<render_tree::Image> GetVideoFrame(
- const scoped_refptr<ShellVideoFrameProvider>& frame_provider,
+ const scoped_refptr<VideoFrameProvider>& frame_provider,
render_tree::ResourceProvider* resource_provider) {
TRACE_EVENT0("cobalt::layout", "GetVideoFrame()");
SbDecodeTarget decode_target = frame_provider->GetCurrentSbDecodeTarget();
@@ -76,13 +75,14 @@
#endif // SB_HAS(GRAPHICS)
} else {
DCHECK(frame_provider);
+#if !defined(COBALT_MEDIA_SOURCE_2016)
scoped_refptr<VideoFrame> video_frame = frame_provider->GetCurrentFrame();
if (video_frame && video_frame->texture_id()) {
scoped_refptr<render_tree::Image> image =
reinterpret_cast<render_tree::Image*>(video_frame->texture_id());
return image;
}
-
+#endif // !defined(COBALT_MEDIA_SOURCE_2016)
return NULL;
}
}
@@ -316,8 +316,8 @@
// https://www.w3.org/TR/CSS21/visuren.html#propdef-unicode-bidi
// https://www.w3.org/TR/css3-text/#line-break-details
int32 text_position =
- (*paragraph_)->AppendCodePoint(
- Paragraph::kObjectReplacementCharacterCodePoint);
+ (*paragraph_)
+ ->AppendCodePoint(Paragraph::kObjectReplacementCharacterCodePoint);
render_tree::ResourceProvider* resource_provider =
*video_element->node_document()
@@ -328,11 +328,10 @@
// or not.
base::optional<bool> is_punch_out;
if (video_element->GetVideoFrameProvider()) {
- ShellVideoFrameProvider::OutputMode output_mode =
+ VideoFrameProvider::OutputMode output_mode =
video_element->GetVideoFrameProvider()->GetOutputMode();
- if (output_mode != ShellVideoFrameProvider::kOutputModeInvalid) {
- is_punch_out =
- output_mode == ShellVideoFrameProvider::kOutputModePunchOut;
+ if (output_mode != VideoFrameProvider::kOutputModeInvalid) {
+ is_punch_out = output_mode == VideoFrameProvider::kOutputModePunchOut;
}
}
@@ -543,8 +542,9 @@
// https://www.w3.org/TR/CSS21/visuren.html#propdef-unicode-bidi
// https://www.w3.org/TR/css3-text/#line-break-details
int32 text_position =
- (*paragraph_)->AppendCodePoint(
- Paragraph::kObjectReplacementCharacterCodePoint);
+ (*paragraph_)
+ ->AppendCodePoint(
+ Paragraph::kObjectReplacementCharacterCodePoint);
scoped_refptr<Paragraph> prior_paragraph = *paragraph_;
// The inline block creates a new paragraph, which the old paragraph
diff --git a/src/cobalt/layout/replaced_box.cc b/src/cobalt/layout/replaced_box.cc
index 0af0b8e..0e3f920 100644
--- a/src/cobalt/layout/replaced_box.cc
+++ b/src/cobalt/layout/replaced_box.cc
@@ -207,18 +207,6 @@
}
namespace {
-void AddLetterboxFillRects(const LetterboxDimensions& dimensions,
- CompositionNode::Builder* composition_node_builder) {
- const render_tree::ColorRGBA kSolidBlack(0, 0, 0, 1);
-
- for (uint32 i = 0; i < dimensions.fill_rects.size(); ++i) {
- const math::RectF& fill_rect = dimensions.fill_rects[i];
- composition_node_builder->AddChild(new RectNode(
- fill_rect,
- scoped_ptr<render_tree::Brush>(new SolidColorBrush(kSolidBlack))));
- }
-}
-
void AddLetterboxedImageToRenderTree(
const LetterboxDimensions& dimensions,
const scoped_refptr<render_tree::Image>& image,
@@ -227,8 +215,6 @@
ImageNode::Builder image_builder(image, *dimensions.image_rect);
composition_node_builder->AddChild(new ImageNode(image_builder));
}
-
- AddLetterboxFillRects(dimensions, composition_node_builder);
}
void AddLetterboxedPunchThroughVideoNodeToRenderTree(
@@ -240,7 +226,6 @@
set_bounds_cb);
border_node_builder->AddChild(new PunchThroughVideoNode(builder));
}
- AddLetterboxFillRects(dimensions, border_node_builder);
}
void AnimateVideoImage(const ReplacedBox::ReplaceImageCB& replace_image_cb,
@@ -255,9 +240,9 @@
}
}
-// Animates an image, and additionally adds letterbox rectangles as well
-// according to the aspect ratio of the resulting animated image versus the
-// aspect ratio of the destination box size.
+// Animates an image, and letterboxes the image as well according to the aspect
+// ratio of the resulting animated image versus the aspect ratio of the
+// destination box size.
void AnimateVideoWithLetterboxing(
const ReplacedBox::ReplaceImageCB& replace_image_cb,
math::SizeF destination_size,
@@ -324,7 +309,8 @@
cssom::MapToMeshFunction::ExtractFromFilterList(
computed_style()->filter());
- if (mtm_filter_function) {
+ if (mtm_filter_function && mtm_filter_function->mesh_spec().mesh_type() !=
+ cssom::MapToMeshFunction::kRectangular) {
DCHECK(!*is_video_punched_out_)
<< "We currently do not support punched out video with map-to-mesh "
"filters.";
@@ -338,11 +324,18 @@
animate_node_builder.Add(
image_node, base::Bind(&AnimateVideoImage, replace_image_cb_));
+ render_tree::StereoMode stereo_mode = render_tree::kMono;
+
+ if (mtm_filter_function) {
+ // For rectangular stereo.
+ stereo_mode = ReadStereoMode(mtm_filter_function->stereo_mode());
+ }
+
// Attach an empty map to mesh filter node to signal the need for an
// external mesh.
- border_node_builder->AddChild(
- new FilterNode(MapToMeshFilter(render_tree::kMono),
- new AnimateNode(animate_node_builder, image_node)));
+ border_node_builder->AddChild(new FilterNode(
+ MapToMeshFilter(stereo_mode, render_tree::kRectangular),
+ new AnimateNode(animate_node_builder, image_node)));
return;
}
#endif
@@ -611,6 +604,7 @@
render_tree::StereoMode stereo_mode =
ReadStereoMode(stereo_mode_keyword_value);
+ scoped_refptr<render_tree::Node> filter_node;
// Fetch either the embedded equirectangular mesh or a custom one depending
// on the spec.
MapToMeshFilter::Builder builder;
@@ -685,10 +679,10 @@
loader::mesh::MeshProjection::kLeftEyeOrMonoCollection),
mesh_projection->GetMesh(
loader::mesh::MeshProjection::kRightEyeCollection));
- }
- scoped_refptr<render_tree::Node> filter_node =
- new FilterNode(MapToMeshFilter(stereo_mode, builder), animate_node);
+ filter_node =
+ new FilterNode(MapToMeshFilter(stereo_mode, builder), animate_node);
+ }
#if !SB_HAS(VIRTUAL_REALITY)
// Attach a 3D camera to the map-to-mesh node, so the rendering of its
diff --git a/src/cobalt/loader/cors_preflight_cache.cc b/src/cobalt/loader/cors_preflight_cache.cc
index 860ba27..32d53b3 100644
--- a/src/cobalt/loader/cors_preflight_cache.cc
+++ b/src/cobalt/loader/cors_preflight_cache.cc
@@ -61,7 +61,7 @@
if (methods_vec.size() == 1 && methods_vec.at(0) == "*") {
new_entry->allow_all_methods = true;
} else {
- for (auto method : methods_vec) {
+ for (const auto& method : methods_vec) {
net::URLFetcher::RequestType request_type;
if (MethodNameToRequestType(method, &request_type)) {
new_entry->methods.insert(request_type);
@@ -74,7 +74,7 @@
}
// TODO: Consider change this function to use std::copy with std::inserter.
// Currently compilers on some machines do not support it.
- for (auto headername : headernames_vec) {
+ for (const auto& headername : headernames_vec) {
new_entry->headernames.insert(headername);
}
@@ -124,7 +124,7 @@
// name("Authentication") and last preflight allowed * headers.
if (entry_ptr->allow_all_headers_except_non_wildcard) {
bool has_auth_header = false;
- for (auto header : unsafe_headernames) {
+ for (const auto& header : unsafe_headernames) {
if (SbStringCompareNoCase(header.c_str(), kAuthorization)) {
has_auth_header = true;
break;
@@ -137,7 +137,7 @@
}
// If last preflight does not allow arbitrary header, then match each header
// with allowed headers.
- for (auto unsafe_headername : unsafe_headernames) {
+ for (const auto& unsafe_headername : unsafe_headernames) {
if (entry_ptr->headernames.find(unsafe_headername) ==
entry_ptr->headernames.end()) {
return false;
diff --git a/src/cobalt/media/base/pipeline.h b/src/cobalt/media/base/pipeline.h
index 927b03d..4dd622f 100644
--- a/src/cobalt/media/base/pipeline.h
+++ b/src/cobalt/media/base/pipeline.h
@@ -26,6 +26,7 @@
#include "cobalt/media/base/media_export.h"
#include "cobalt/media/base/pipeline_status.h"
#include "cobalt/media/base/ranges.h"
+#include "cobalt/media/base/video_frame_provider.h"
#include "starboard/drm.h"
#include "starboard/window.h"
#include "ui/gfx/rect.h"
@@ -75,7 +76,7 @@
static scoped_refptr<Pipeline> Create(
PipelineWindow window,
const scoped_refptr<base::MessageLoopProxy>& message_loop,
- MediaLog* media_log);
+ MediaLog* media_log, VideoFrameProvider* video_frame_provider);
virtual ~Pipeline() {}
diff --git a/src/cobalt/media/base/sbplayer_pipeline.cc b/src/cobalt/media/base/sbplayer_pipeline.cc
index afd247a..85fbc6b 100644
--- a/src/cobalt/media/base/sbplayer_pipeline.cc
+++ b/src/cobalt/media/base/sbplayer_pipeline.cc
@@ -77,7 +77,8 @@
// Constructs a media pipeline that will execute on |message_loop|.
SbPlayerPipeline(PipelineWindow window,
const scoped_refptr<base::MessageLoopProxy>& message_loop,
- MediaLog* media_log);
+ MediaLog* media_log,
+ VideoFrameProvider* video_frame_provider);
~SbPlayerPipeline() override;
void Suspend() override;
@@ -242,13 +243,15 @@
bool stopped_;
bool ended_;
+ VideoFrameProvider* video_frame_provider_;
+
DISALLOW_COPY_AND_ASSIGN(SbPlayerPipeline);
};
SbPlayerPipeline::SbPlayerPipeline(
PipelineWindow window,
const scoped_refptr<base::MessageLoopProxy>& message_loop,
- MediaLog* media_log)
+ MediaLog* media_log, VideoFrameProvider* video_frame_provider)
: window_(window),
message_loop_(message_loop),
natural_size_(0, 0),
@@ -262,7 +265,8 @@
set_bounds_helper_(new SbPlayerSetBoundsHelper),
suspended_(false),
stopped_(false),
- ended_(false) {}
+ ended_(false),
+ video_frame_provider_(video_frame_provider) {}
SbPlayerPipeline::~SbPlayerPipeline() { DCHECK(!player_); }
@@ -745,7 +749,7 @@
player_.reset(new StarboardPlayer(
message_loop_, source_url, window_, this, set_bounds_helper_.get(),
*decode_to_texture_output_mode_,
- on_encrypted_media_init_data_encountered_cb_));
+ on_encrypted_media_init_data_encountered_cb_, video_frame_provider_));
SetPlaybackRateTask(playback_rate_);
SetVolumeTask(volume_);
}
@@ -819,7 +823,8 @@
base::AutoLock auto_lock(lock_);
player_.reset(new StarboardPlayer(
message_loop_, audio_config, video_config, window_, drm_system, this,
- set_bounds_helper_.get(), *decode_to_texture_output_mode_));
+ set_bounds_helper_.get(), *decode_to_texture_output_mode_,
+ video_frame_provider_));
SetPlaybackRateTask(playback_rate_);
SetVolumeTask(volume_);
}
@@ -880,6 +885,15 @@
DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
+
+#if SB_API_VERSION < SB_AUDIOLESS_VIDEO_API_VERSION
+ if (audio_stream == NULL) {
+ LOG(INFO) << "The video has to contain an audio track.";
+ ResetAndRunIfNotNull(&error_cb_, DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
+ return;
+ }
+#endif // SB_API_VERSION < SB_AUDIOLESS_VIDEO_API_VERSION
+
if (video_stream == NULL) {
LOG(INFO) << "The video has to contain a video track.";
ResetAndRunIfNotNull(&error_cb_, DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
@@ -1156,8 +1170,9 @@
scoped_refptr<Pipeline> Pipeline::Create(
PipelineWindow window,
const scoped_refptr<base::MessageLoopProxy>& message_loop,
- MediaLog* media_log) {
- return new SbPlayerPipeline(window, message_loop, media_log);
+ MediaLog* media_log, VideoFrameProvider* video_frame_provider) {
+ return new SbPlayerPipeline(window, message_loop, media_log,
+ video_frame_provider);
}
} // namespace media
diff --git a/src/cobalt/media/base/shell_audio_bus.cc b/src/cobalt/media/base/shell_audio_bus.cc
index aea8fb0..aa13966 100644
--- a/src/cobalt/media/base/shell_audio_bus.cc
+++ b/src/cobalt/media/base/shell_audio_bus.cc
@@ -53,6 +53,29 @@
}
}
+void Sum(const float* source, float* destination, size_t size) {
+ for (int i = 0; i < size; ++i) {
+ *destination += *source;
+ ++source;
+ ++destination;
+ }
+}
+
+void Sum(const int16* source, int16* destination, size_t size) {
+ for (int i = 0; i < size; ++i) {
+ int sample_in_int32 = *destination + static_cast<int>(*source);
+ if (sample_in_int32 > std::numeric_limits<int16>::max()) {
+ *destination = std::numeric_limits<int16>::max();
+ } else if (sample_in_int32 < std::numeric_limits<int16>::min()) {
+ *destination = std::numeric_limits<int16>::min();
+ } else {
+ *destination = static_cast<int16>(sample_in_int32);
+ }
+ ++source;
+ ++destination;
+ }
+}
+
} // namespace
ShellAudioBus::ShellAudioBus(size_t channels, size_t frames,
@@ -148,6 +171,17 @@
return channel_data_[channel];
}
+uint8* ShellAudioBus::interleaved_data() {
+ DCHECK_EQ(storage_type_, kInterleaved);
+ return channel_data_[0];
+}
+
+uint8* ShellAudioBus::planar_data(size_t channel) {
+ DCHECK_LT(channel, channels_);
+ DCHECK_EQ(storage_type_, kPlanar);
+ return channel_data_[channel];
+}
+
void ShellAudioBus::ZeroFrames(size_t start_frame, size_t end_frame) {
DCHECK_LE(start_frame, end_frame);
DCHECK_LE(end_frame, frames_);
@@ -223,84 +257,103 @@
}
}
-template <typename SourceSampleType, typename DestSampleType,
- StorageType SourceStorageType, StorageType DestStorageType>
-void ShellAudioBus::MixForTypes(const ShellAudioBus& source) {
+template <StorageType SourceStorageType, StorageType DestStorageType>
+void ShellAudioBus::MixFloatSamples(const ShellAudioBus& source) {
const size_t frames = std::min(frames_, source.frames_);
+ if (SourceStorageType == DestStorageType) {
+ if (SourceStorageType == kInterleaved) {
+ Sum(reinterpret_cast<const float*>(source.interleaved_data()),
+ reinterpret_cast<float*>(interleaved_data()), frames * channels_);
+ return;
+ }
+ for (size_t channel = 0; channel < channels_; ++channel) {
+ Sum(reinterpret_cast<const float*>(source.planar_data(channel)),
+ reinterpret_cast<float*>(planar_data(channel)), frames);
+ }
+ return;
+ }
+
for (size_t channel = 0; channel < channels_; ++channel) {
for (size_t frame = 0; frame < frames; ++frame) {
- *reinterpret_cast<DestSampleType*>(
- GetSamplePtrForType<DestSampleType, DestStorageType>(channel,
- frame)) +=
- source.GetSampleForType<SourceSampleType, SourceStorageType>(channel,
- frame);
+ *reinterpret_cast<float*>(
+ GetSamplePtrForType<float, DestStorageType>(channel, frame)) +=
+ source.GetSampleForType<float, SourceStorageType>(channel, frame);
+ }
+ }
+}
+
+template <StorageType SourceStorageType, StorageType DestStorageType>
+void ShellAudioBus::MixInt16Samples(const ShellAudioBus& source) {
+ const size_t frames = std::min(frames_, source.frames_);
+
+ if (SourceStorageType == DestStorageType) {
+ if (SourceStorageType == kInterleaved) {
+ Sum(reinterpret_cast<const int16*>(source.interleaved_data()),
+ reinterpret_cast<int16*>(interleaved_data()), frames * channels_);
+ return;
+ }
+ for (size_t channel = 0; channel < channels_; ++channel) {
+ Sum(reinterpret_cast<const int16*>(source.planar_data(channel)),
+ reinterpret_cast<int16*>(planar_data(channel)), frames);
+ }
+ return;
+ }
+
+ for (size_t channel = 0; channel < channels_; ++channel) {
+ for (size_t frame = 0; frame < frames; ++frame) {
+ auto& dest_sample = *reinterpret_cast<int16*>(
+ GetSamplePtrForType<int16, DestStorageType>(channel, frame));
+ int source_sample =
+ source.GetSampleForType<int16, SourceStorageType>(channel, frame);
+ if (dest_sample + source_sample > std::numeric_limits<int16>::max()) {
+ dest_sample = std::numeric_limits<int16>::max();
+ } else if (dest_sample + source_sample <
+ std::numeric_limits<int16>::min()) {
+ dest_sample = std::numeric_limits<int16>::min();
+ } else {
+ dest_sample += source_sample;
+ }
}
}
}
void ShellAudioBus::Mix(const ShellAudioBus& source) {
DCHECK_EQ(channels_, source.channels_);
+ DCHECK_EQ(sample_type_, source.sample_type_);
- if (channels_ != source.channels_) {
+ if (channels_ != source.channels_ || sample_type_ != source.sample_type_) {
ZeroAllFrames();
return;
}
// Profiling has identified this area of code as hot, so instead of calling
- // GetSamplePtr, which branches each time it is called, we branch once
- // before we loop and inline the branch of the function we want.
- if (source.sample_type_ == kInt16 && sample_type_ == kInt16 &&
- source.storage_type_ == kInterleaved && storage_type_ == kInterleaved) {
- MixForTypes<int16, int16, kInterleaved, kInterleaved>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kInt16 &&
- source.storage_type_ == kInterleaved && storage_type_ == kPlanar) {
- MixForTypes<int16, int16, kInterleaved, kPlanar>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kInt16 &&
- source.storage_type_ == kPlanar && storage_type_ == kInterleaved) {
- MixForTypes<int16, int16, kPlanar, kInterleaved>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kInt16 &&
- source.storage_type_ == kPlanar && storage_type_ == kPlanar) {
- MixForTypes<int16, int16, kPlanar, kPlanar>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kFloat32 &&
- source.storage_type_ == kInterleaved &&
+ // GetSamplePtr, which branches each time it is called, we branch once before
+ // we loop and inline the branch of the function we want.
+ if (source.sample_type_ == kInt16 && source.storage_type_ == kInterleaved &&
+ storage_type_ == kInterleaved) {
+ MixInt16Samples<kInterleaved, kInterleaved>(source);
+ } else if (sample_type_ == kInt16 && source.storage_type_ == kInterleaved &&
+ storage_type_ == kPlanar) {
+ MixInt16Samples<kInterleaved, kPlanar>(source);
+ } else if (sample_type_ == kInt16 && source.storage_type_ == kPlanar &&
storage_type_ == kInterleaved) {
- MixForTypes<int16, float, kInterleaved, kInterleaved>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kFloat32 &&
- source.storage_type_ == kInterleaved && storage_type_ == kPlanar) {
- MixForTypes<int16, float, kInterleaved, kPlanar>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kFloat32 &&
- source.storage_type_ == kPlanar && storage_type_ == kInterleaved) {
- MixForTypes<int16, float, kPlanar, kInterleaved>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kFloat32 &&
- source.storage_type_ == kPlanar && storage_type_ == kPlanar) {
- MixForTypes<int16, float, kPlanar, kPlanar>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kInt16 &&
- source.storage_type_ == kInterleaved &&
+ MixInt16Samples<kPlanar, kInterleaved>(source);
+ } else if (sample_type_ == kInt16 && source.storage_type_ == kPlanar &&
+ storage_type_ == kPlanar) {
+ MixInt16Samples<kPlanar, kPlanar>(source);
+ } else if (sample_type_ == kFloat32 && source.storage_type_ == kInterleaved &&
storage_type_ == kInterleaved) {
- MixForTypes<float, int16, kInterleaved, kInterleaved>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kInt16 &&
- source.storage_type_ == kInterleaved && storage_type_ == kPlanar) {
- MixForTypes<float, int16, kInterleaved, kPlanar>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kInt16 &&
- source.storage_type_ == kPlanar && storage_type_ == kInterleaved) {
- MixForTypes<float, int16, kPlanar, kInterleaved>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kInt16 &&
- source.storage_type_ == kPlanar && storage_type_ == kPlanar) {
- MixForTypes<float, int16, kPlanar, kPlanar>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kFloat32 &&
- source.storage_type_ == kInterleaved &&
+ MixFloatSamples<kInterleaved, kInterleaved>(source);
+ } else if (sample_type_ == kFloat32 && source.storage_type_ == kInterleaved &&
+ storage_type_ == kPlanar) {
+ MixFloatSamples<kInterleaved, kPlanar>(source);
+ } else if (sample_type_ == kFloat32 && source.storage_type_ == kPlanar &&
storage_type_ == kInterleaved) {
- MixForTypes<float, float, kInterleaved, kInterleaved>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kFloat32 &&
- source.storage_type_ == kInterleaved && storage_type_ == kPlanar) {
- MixForTypes<float, float, kInterleaved, kPlanar>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kFloat32 &&
- source.storage_type_ == kPlanar && storage_type_ == kInterleaved) {
- MixForTypes<float, float, kPlanar, kInterleaved>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kFloat32 &&
- source.storage_type_ == kPlanar && storage_type_ == kPlanar) {
- MixForTypes<float, float, kPlanar, kPlanar>(source);
+ MixFloatSamples<kPlanar, kInterleaved>(source);
+ } else if (sample_type_ == kFloat32 && source.storage_type_ == kPlanar &&
+ storage_type_ == kPlanar) {
+ MixFloatSamples<kPlanar, kPlanar>(source);
} else {
NOTREACHED();
}
diff --git a/src/cobalt/media/base/shell_audio_bus.h b/src/cobalt/media/base/shell_audio_bus.h
index c9ef550..833d2dc 100644
--- a/src/cobalt/media/base/shell_audio_bus.h
+++ b/src/cobalt/media/base/shell_audio_bus.h
@@ -63,6 +63,8 @@
size_t GetSampleSizeInBytes() const;
const uint8* interleaved_data() const;
const uint8* planar_data(size_t channel) const;
+ uint8* interleaved_data();
+ uint8* planar_data(size_t channel);
int16 GetInt16Sample(size_t channel, size_t frame) const {
DCHECK_EQ(sample_type_, kInt16);
@@ -130,9 +132,11 @@
GetSamplePtrForType<SampleTypeName, T>(channel, frame));
}
- template <typename SourceSampleType, typename DestSampleType,
- StorageType SourceStorageType, StorageType DestStorageType>
- void MixForTypes(const ShellAudioBus& source);
+ template <StorageType SourceStorageType, StorageType DestStorageType>
+ void MixFloatSamples(const ShellAudioBus& source);
+
+ template <StorageType SourceStorageType, StorageType DestStorageType>
+ void MixInt16Samples(const ShellAudioBus& source);
private:
void SetFloat32Sample(size_t channel, size_t frame, float sample) {
diff --git a/src/cobalt/media/base/shell_media_platform.h b/src/cobalt/media/base/shell_media_platform.h
index 1e6c711..30f502f 100644
--- a/src/cobalt/media/base/shell_media_platform.h
+++ b/src/cobalt/media/base/shell_media_platform.h
@@ -21,7 +21,6 @@
#include "cobalt/media/base/decoder_buffer.h"
#include "cobalt/media/base/limits.h"
#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/shell_video_frame_provider.h"
#include "cobalt/render_tree/resource_provider.h"
#include "starboard/decode_target.h"
@@ -59,10 +58,6 @@
virtual size_t GetSourceBufferStreamAudioMemoryLimit() const = 0;
virtual size_t GetSourceBufferStreamVideoMemoryLimit() const = 0;
- virtual scoped_refptr<ShellVideoFrameProvider> GetVideoFrameProvider() {
- return NULL;
- }
-
virtual SbDecodeTargetGraphicsContextProvider*
GetSbDecodeTargetGraphicsContextProvider() {
return NULL;
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc
index f85526a..5bed9c5 100644
--- a/src/cobalt/media/base/starboard_player.cc
+++ b/src/cobalt/media/base/starboard_player.cc
@@ -76,7 +76,8 @@
const std::string& url, SbWindow window, Host* host,
SbPlayerSetBoundsHelper* set_bounds_helper, bool prefer_decode_to_texture,
const OnEncryptedMediaInitDataEncounteredCB&
- on_encrypted_media_init_data_encountered_cb)
+ on_encrypted_media_init_data_encountered_cb,
+ VideoFrameProvider* const video_frame_provider)
: url_(url),
message_loop_(message_loop),
callback_helper_(
@@ -93,7 +94,8 @@
seek_pending_(false),
state_(kPlaying),
on_encrypted_media_init_data_encountered_cb_(
- on_encrypted_media_init_data_encountered_cb) {
+ on_encrypted_media_init_data_encountered_cb),
+ video_frame_provider_(video_frame_provider) {
DCHECK(host_);
DCHECK(set_bounds_helper_);
@@ -113,7 +115,8 @@
const AudioDecoderConfig& audio_config,
const VideoDecoderConfig& video_config, SbWindow window,
SbDrmSystem drm_system, Host* host,
- SbPlayerSetBoundsHelper* set_bounds_helper, bool prefer_decode_to_texture)
+ SbPlayerSetBoundsHelper* set_bounds_helper, bool prefer_decode_to_texture,
+ VideoFrameProvider* const video_frame_provider)
: message_loop_(message_loop),
callback_helper_(
new CallbackHelper(ALLOW_THIS_IN_INITIALIZER_LIST(this))),
@@ -129,10 +132,12 @@
volume_(1.0),
playback_rate_(0.0),
seek_pending_(false),
- state_(kPlaying) {
+ state_(kPlaying),
+ video_frame_provider_(video_frame_provider) {
DCHECK(video_config.IsValidConfig());
DCHECK(host_);
DCHECK(set_bounds_helper_);
+ DCHECK(video_frame_provider_);
output_mode_ = ComputeSbPlayerOutputMode(
MediaVideoCodecToSbMediaVideoCodec(video_config.codec()), drm_system,
@@ -153,11 +158,8 @@
callback_helper_->ResetPlayer();
set_bounds_helper_->SetPlayer(NULL);
- ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
- ShellVideoFrameProvider::kOutputModeInvalid);
- ShellMediaPlatform::Instance()
- ->GetVideoFrameProvider()
- ->ResetGetCurrentSbDecodeTargetFunction();
+ video_frame_provider_->SetOutputMode(VideoFrameProvider::kOutputModeInvalid);
+ video_frame_provider_->ResetGetCurrentSbDecodeTargetFunction();
if (SbPlayerIsValid(player_)) {
SbPlayerDestroy(player_);
@@ -423,11 +425,8 @@
preroll_timestamp_ = SbMediaTimeToTimeDelta(info.current_media_pts);
set_bounds_helper_->SetPlayer(NULL);
- ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
- ShellVideoFrameProvider::kOutputModeInvalid);
- ShellMediaPlatform::Instance()
- ->GetVideoFrameProvider()
- ->ResetGetCurrentSbDecodeTargetFunction();
+ video_frame_provider_->SetOutputMode(VideoFrameProvider::kOutputModeInvalid);
+ video_frame_provider_->ResetGetCurrentSbDecodeTargetFunction();
SbPlayerDestroy(player_);
@@ -459,19 +458,19 @@
}
namespace {
-ShellVideoFrameProvider::OutputMode ToVideoFrameProviderOutputMode(
+VideoFrameProvider::OutputMode ToVideoFrameProviderOutputMode(
SbPlayerOutputMode output_mode) {
switch (output_mode) {
case kSbPlayerOutputModeDecodeToTexture:
- return ShellVideoFrameProvider::kOutputModeDecodeToTexture;
+ return VideoFrameProvider::kOutputModeDecodeToTexture;
case kSbPlayerOutputModePunchOut:
- return ShellVideoFrameProvider::kOutputModePunchOut;
+ return VideoFrameProvider::kOutputModePunchOut;
case kSbPlayerOutputModeInvalid:
- return ShellVideoFrameProvider::kOutputModeInvalid;
+ return VideoFrameProvider::kOutputModeInvalid;
}
NOTREACHED();
- return ShellVideoFrameProvider::kOutputModeInvalid;
+ return VideoFrameProvider::kOutputModeInvalid;
}
} // namespace
@@ -503,13 +502,10 @@
if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
// If the player is setup to decode to texture, then provide Cobalt with
// a method of querying that texture.
- ShellMediaPlatform::Instance()
- ->GetVideoFrameProvider()
- ->SetGetCurrentSbDecodeTargetFunction(
- base::Bind(&StarboardPlayer::GetCurrentSbDecodeTarget,
- base::Unretained(this)));
+ video_frame_provider_->SetGetCurrentSbDecodeTargetFunction(base::Bind(
+ &StarboardPlayer::GetCurrentSbDecodeTarget, base::Unretained(this)));
}
- ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
+ video_frame_provider_->SetOutputMode(
ToVideoFrameProviderOutputMode(output_mode_));
set_bounds_helper_->SetPlayer(this);
@@ -552,13 +548,10 @@
if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
// If the player is setup to decode to texture, then provide Cobalt with
// a method of querying that texture.
- ShellMediaPlatform::Instance()
- ->GetVideoFrameProvider()
- ->SetGetCurrentSbDecodeTargetFunction(
- base::Bind(&StarboardPlayer::GetCurrentSbDecodeTarget,
- base::Unretained(this)));
+ video_frame_provider_->SetGetCurrentSbDecodeTargetFunction(base::Bind(
+ &StarboardPlayer::GetCurrentSbDecodeTarget, base::Unretained(this)));
}
- ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
+ video_frame_provider_->SetOutputMode(
ToVideoFrameProviderOutputMode(output_mode_));
set_bounds_helper_->SetPlayer(this);
diff --git a/src/cobalt/media/base/starboard_player.h b/src/cobalt/media/base/starboard_player.h
index d1708f3..43522a4 100644
--- a/src/cobalt/media/base/starboard_player.h
+++ b/src/cobalt/media/base/starboard_player.h
@@ -29,6 +29,7 @@
#include "cobalt/media/base/demuxer_stream.h"
#include "cobalt/media/base/sbplayer_set_bounds_helper.h"
#include "cobalt/media/base/video_decoder_config.h"
+#include "cobalt/media/base/video_frame_provider.h"
#include "starboard/media.h"
#include "starboard/player.h"
@@ -58,14 +59,16 @@
SbPlayerSetBoundsHelper* set_bounds_helper,
bool prefer_decode_to_texture,
const OnEncryptedMediaInitDataEncounteredCB&
- encrypted_media_init_data_encountered_cb);
+ encrypted_media_init_data_encountered_cb,
+ VideoFrameProvider* const video_frame_provider);
#else // SB_HAS(PLAYER_WITH_URL)
StarboardPlayer(const scoped_refptr<base::MessageLoopProxy>& message_loop,
const AudioDecoderConfig& audio_config,
const VideoDecoderConfig& video_config, SbWindow window,
SbDrmSystem drm_system, Host* host,
SbPlayerSetBoundsHelper* set_bounds_helper,
- bool prefer_decode_to_texture);
+ bool prefer_decode_to_texture,
+ VideoFrameProvider* const video_frame_provider);
#endif // SB_HAS(PLAYER_WITH_URL)
~StarboardPlayer();
@@ -220,6 +223,8 @@
// Keep track of the output mode we are supposed to output to.
SbPlayerOutputMode output_mode_;
+
+ VideoFrameProvider* const video_frame_provider_;
};
} // namespace media
diff --git a/src/cobalt/media/base/shell_video_frame_provider.h b/src/cobalt/media/base/video_frame_provider.h
similarity index 67%
rename from src/cobalt/media/base/shell_video_frame_provider.h
rename to src/cobalt/media/base/video_frame_provider.h
index e2b1569..e2581b0 100644
--- a/src/cobalt/media/base/shell_video_frame_provider.h
+++ b/src/cobalt/media/base/video_frame_provider.h
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2018 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_BASE_SHELL_VIDEO_FRAME_PROVIDER_H_
-#define COBALT_MEDIA_BASE_SHELL_VIDEO_FRAME_PROVIDER_H_
+#ifndef COBALT_MEDIA_BASE_VIDEO_FRAME_PROVIDER_H_
+#define COBALT_MEDIA_BASE_VIDEO_FRAME_PROVIDER_H_
#include "base/callback.h"
#include "base/memory/ref_counted.h"
@@ -24,22 +24,13 @@
namespace cobalt {
namespace media {
-// TODO: The following class is tentative to make the new media stack work.
-// We should consider remove VideoFrame as it is no longer useful.
-class VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
- public:
- uintptr_t texture_id() const { return 0; }
- base::TimeDelta GetTimestamp() const { return base::TimeDelta(); }
-};
-
-// TODO: Remove Shell prefix.
-// The ShellVideoFrameProvider manages the backlog for video frames. It has the
+// The VideoFrameProvider manages the backlog for video frames. It has the
// following functionalities:
// 1. It caches the video frames ready to be displayed.
// 2. It decides which frame to be displayed at the current time.
// 3. It removes frames that will no longer be displayed.
-class ShellVideoFrameProvider
- : public base::RefCountedThreadSafe<ShellVideoFrameProvider> {
+class VideoFrameProvider
+ : public base::RefCountedThreadSafe<VideoFrameProvider> {
public:
enum OutputMode {
kOutputModePunchOut,
@@ -47,26 +38,24 @@
kOutputModeInvalid,
};
- ShellVideoFrameProvider() : output_mode_(kOutputModeInvalid) {}
+ VideoFrameProvider() : output_mode_(kOutputModeInvalid) {}
typedef base::Callback<SbDecodeTarget()> GetCurrentSbDecodeTargetFunction;
- scoped_refptr<VideoFrame> GetCurrentFrame() { return NULL; }
-
void SetOutputMode(OutputMode output_mode) {
base::AutoLock auto_lock(lock_);
output_mode_ = output_mode;
}
- ShellVideoFrameProvider::OutputMode GetOutputMode() const {
+ VideoFrameProvider::OutputMode GetOutputMode() const {
base::AutoLock auto_lock(lock_);
return output_mode_;
}
// For Starboard platforms that have a decode-to-texture player, we enable
- // this ShellVideoFrameProvider to act as a bridge for Cobalt code to query
+ // this VideoFrameProvider to act as a bridge for Cobalt code to query
// for the current SbDecodeTarget. In effect, we bypass all of
- // ShellVideoFrameProvider's logic in this case, instead relying on the
+ // VideoFrameProvider's logic in this case, instead relying on the
// Starboard implementation to provide us with the current video frame when
// needed.
void SetGetCurrentSbDecodeTargetFunction(
@@ -95,10 +84,10 @@
OutputMode output_mode_;
GetCurrentSbDecodeTargetFunction get_current_sb_decode_target_function_;
- DISALLOW_COPY_AND_ASSIGN(ShellVideoFrameProvider);
+ DISALLOW_COPY_AND_ASSIGN(VideoFrameProvider);
};
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_BASE_SHELL_VIDEO_FRAME_PROVIDER_H_
+#endif // COBALT_MEDIA_BASE_VIDEO_FRAME_PROVIDER_H_
diff --git a/src/cobalt/media/media2.gyp b/src/cobalt/media/media2.gyp
index 82cf946..8a5e99d 100644
--- a/src/cobalt/media/media2.gyp
+++ b/src/cobalt/media/media2.gyp
@@ -106,6 +106,7 @@
'base/video_codecs.h',
'base/video_decoder_config.cc',
'base/video_decoder_config.h',
+ 'base/video_frame_provider.h',
'base/video_util.cc',
'base/video_util.h',
'filters/chunk_demuxer.cc',
diff --git a/src/cobalt/media/media_module_starboard.cc b/src/cobalt/media/media_module_starboard.cc
index ddaf1fb..d0c01cd 100644
--- a/src/cobalt/media/media_module_starboard.cc
+++ b/src/cobalt/media/media_module_starboard.cc
@@ -81,8 +81,7 @@
window = system_window_->GetSbWindow();
}
return make_scoped_ptr<WebMediaPlayer>(new media::WebMediaPlayerImpl(
- window, client, this, &decoder_buffer_allocator_,
- media_platform_.GetVideoFrameProvider(), new media::MediaLog));
+ window, client, this, &decoder_buffer_allocator_, new media::MediaLog));
#else // defined(COBALT_MEDIA_SOURCE_2016)
scoped_ptr<MessageLoopFactory> message_loop_factory(new MessageLoopFactory);
scoped_refptr<base::MessageLoopProxy> pipeline_message_loop =
diff --git a/src/cobalt/media/player/web_media_player.h b/src/cobalt/media/player/web_media_player.h
index fbe7df1..1c4055c 100644
--- a/src/cobalt/media/player/web_media_player.h
+++ b/src/cobalt/media/player/web_media_player.h
@@ -19,7 +19,7 @@
#include "base/memory/weak_ptr.h"
#include "base/time.h"
#include "cobalt/media/base/ranges.h"
-#include "cobalt/media/base/shell_video_frame_provider.h"
+#include "cobalt/media/base/video_frame_provider.h"
#include "cobalt/media/filters/chunk_demuxer.h"
#include "cobalt/media/player/buffered_data_source.h"
#include "googleurl/src/gurl.h"
@@ -145,7 +145,7 @@
virtual unsigned GetAudioDecodedByteCount() const = 0;
virtual unsigned GetVideoDecodedByteCount() const = 0;
- virtual scoped_refptr<ShellVideoFrameProvider> GetVideoFrameProvider() {
+ virtual scoped_refptr<VideoFrameProvider> GetVideoFrameProvider() {
return NULL;
}
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc
index aa4e26b..cd232c7 100644
--- a/src/cobalt/media/player/web_media_player_impl.cc
+++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -107,7 +107,6 @@
PipelineWindow window, WebMediaPlayerClient* client,
WebMediaPlayerDelegate* delegate,
DecoderBuffer::Allocator* buffer_allocator,
- const scoped_refptr<ShellVideoFrameProvider>& video_frame_provider,
const scoped_refptr<MediaLog>& media_log)
: pipeline_thread_("media_pipeline"),
network_state_(WebMediaPlayer::kNetworkStateEmpty),
@@ -116,7 +115,6 @@
client_(client),
delegate_(delegate),
buffer_allocator_(buffer_allocator),
- video_frame_provider_(video_frame_provider),
proxy_(new WebMediaPlayerProxy(main_loop_->message_loop_proxy(), this)),
media_log_(media_log),
incremented_externally_allocated_memory_(false),
@@ -126,6 +124,8 @@
drm_system_(NULL) {
TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::WebMediaPlayerImpl");
+ video_frame_provider_ = new VideoFrameProvider();
+
DLOG_IF(ERROR, s_instance)
<< "More than one WebMediaPlayerImpl has been created.";
s_instance = this;
@@ -136,7 +136,7 @@
pipeline_thread_.Start();
pipeline_ = Pipeline::Create(window, pipeline_thread_.message_loop_proxy(),
- media_log_);
+ media_log_, video_frame_provider_);
// Also we want to be notified of |main_loop_| destruction.
main_loop_->AddDestructionObserver(this);
@@ -561,8 +561,7 @@
return stats.video_bytes_decoded;
}
-scoped_refptr<ShellVideoFrameProvider>
-WebMediaPlayerImpl::GetVideoFrameProvider() {
+scoped_refptr<VideoFrameProvider> WebMediaPlayerImpl::GetVideoFrameProvider() {
return video_frame_provider_;
}
diff --git a/src/cobalt/media/player/web_media_player_impl.h b/src/cobalt/media/player/web_media_player_impl.h
index 0876e89..f9e62c1 100644
--- a/src/cobalt/media/player/web_media_player_impl.h
+++ b/src/cobalt/media/player/web_media_player_impl.h
@@ -63,6 +63,7 @@
#include "cobalt/media/base/eme_constants.h"
#include "cobalt/media/base/pipeline.h"
#include "cobalt/media/base/ranges.h"
+#include "cobalt/media/base/video_frame_provider.h"
#include "cobalt/media/player/web_media_player.h"
#include "cobalt/media/player/web_media_player_delegate.h"
#include "googleurl/src/gurl.h"
@@ -108,7 +109,6 @@
PipelineWindow window, WebMediaPlayerClient* client,
WebMediaPlayerDelegate* delegate,
DecoderBuffer::Allocator* buffer_allocator,
- const scoped_refptr<ShellVideoFrameProvider>& video_frame_provider,
const scoped_refptr<MediaLog>& media_log);
~WebMediaPlayerImpl() override;
@@ -175,7 +175,7 @@
unsigned GetAudioDecodedByteCount() const override;
unsigned GetVideoDecodedByteCount() const override;
- scoped_refptr<ShellVideoFrameProvider> GetVideoFrameProvider() override;
+ scoped_refptr<VideoFrameProvider> GetVideoFrameProvider() override;
SetBoundsCB GetSetBoundsCB() override;
@@ -296,7 +296,7 @@
WebMediaPlayerClient* client_;
WebMediaPlayerDelegate* delegate_;
DecoderBuffer::Allocator* buffer_allocator_;
- scoped_refptr<ShellVideoFrameProvider> video_frame_provider_;
+ scoped_refptr<VideoFrameProvider> video_frame_provider_;
scoped_refptr<WebMediaPlayerProxy> proxy_;
diff --git a/src/cobalt/media/sandbox/web_media_player_helper.cc b/src/cobalt/media/sandbox/web_media_player_helper.cc
index cc31daa..d017bb4 100644
--- a/src/cobalt/media/sandbox/web_media_player_helper.cc
+++ b/src/cobalt/media/sandbox/web_media_player_helper.cc
@@ -99,9 +99,11 @@
delete client_;
}
+#if !defined(COBALT_MEDIA_SOURCE_2016)
scoped_refptr<VideoFrame> WebMediaPlayerHelper::GetCurrentFrame() const {
return player_->GetVideoFrameProvider()->GetCurrentFrame();
}
+#endif // !defined(COBALT_MEDIA_SOURCE_2016)
SbDecodeTarget WebMediaPlayerHelper::GetCurrentDecodeTarget() const {
return player_->GetVideoFrameProvider()->GetCurrentSbDecodeTarget();
diff --git a/src/cobalt/media/sandbox/web_media_player_helper.h b/src/cobalt/media/sandbox/web_media_player_helper.h
index 297ac94..ab5e3f1 100644
--- a/src/cobalt/media/sandbox/web_media_player_helper.h
+++ b/src/cobalt/media/sandbox/web_media_player_helper.h
@@ -23,7 +23,7 @@
#include "cobalt/media/media_module.h"
#include "googleurl/src/gurl.h"
#if defined(COBALT_MEDIA_SOURCE_2016)
-#include "cobalt/media/base/shell_video_frame_provider.h"
+#include "cobalt/media/base/video_frame_provider.h"
#include "cobalt/media/player/web_media_player.h"
#else // defined(COBALT_MEDIA_SOURCE_2016)
#include "media/base/video_frame.h"
@@ -57,7 +57,9 @@
const GURL& video_url);
~WebMediaPlayerHelper();
+#if !defined(COBALT_MEDIA_SOURCE_2016)
scoped_refptr<VideoFrame> GetCurrentFrame() const;
+#endif // !defined(COBALT_MEDIA_SOURCE_2016)
SbDecodeTarget GetCurrentDecodeTarget() const;
bool IsPlaybackFinished() const;
diff --git a/src/cobalt/media/sandbox/web_media_player_sandbox.cc b/src/cobalt/media/sandbox/web_media_player_sandbox.cc
index 6c4be8a..b6e63b2 100644
--- a/src/cobalt/media/sandbox/web_media_player_sandbox.cc
+++ b/src/cobalt/media/sandbox/web_media_player_sandbox.cc
@@ -28,11 +28,9 @@
#include "cobalt/media/sandbox/media_sandbox.h"
#include "cobalt/media/sandbox/web_media_player_helper.h"
#include "cobalt/render_tree/image.h"
-#if defined(COBALT_MEDIA_SOURCE_2016)
-#include "cobalt/media/base/shell_video_frame_provider.h"
-#else // defined(COBALT_MEDIA_SOURCE_2016)
+#if !defined(COBALT_MEDIA_SOURCE_2016)
#include "media/base/video_frame.h"
-#endif // defined(COBALT_MEDIA_SOURCE_2016)
+#endif // !defined(COBALT_MEDIA_SOURCE_2016)
#include "net/base/net_util.h"
#include "starboard/event.h"
#include "starboard/file.h"
@@ -339,9 +337,12 @@
return media_sandbox_.resource_provider()->CreateImageFromSbDecodeTarget(
decode_target);
}
-
+#if !defined(COBALT_MEDIA_SOURCE_2016)
scoped_refptr<VideoFrame> frame = player_helper_->GetCurrentFrame();
return frame ? reinterpret_cast<Image*>(frame->texture_id()) : NULL;
+#else // !defined(COBALT_MEDIA_SOURCE_2016)
+ return NULL;
+#endif // !defined(COBALT_MEDIA_SOURCE_2016)
#else // SB_HAS(GRAPHICS)
return NULL;
#endif // SB_HAS(GRAPHICS)
diff --git a/src/cobalt/media/shell_media_platform_starboard.h b/src/cobalt/media/shell_media_platform_starboard.h
index 6c9a807..9229fee 100644
--- a/src/cobalt/media/shell_media_platform_starboard.h
+++ b/src/cobalt/media/shell_media_platform_starboard.h
@@ -30,8 +30,7 @@
public:
explicit ShellMediaPlatformStarboard(
cobalt::render_tree::ResourceProvider* resource_provider)
- : resource_provider_(resource_provider),
- video_frame_provider_(new ShellVideoFrameProvider) {
+ : resource_provider_(resource_provider) {
SetInstance(this);
}
@@ -40,10 +39,6 @@
SetInstance(NULL);
}
- scoped_refptr<ShellVideoFrameProvider> GetVideoFrameProvider() override {
- return video_frame_provider_;
- }
-
SbDecodeTargetGraphicsContextProvider*
GetSbDecodeTargetGraphicsContextProvider() override {
#if SB_HAS(GRAPHICS)
@@ -78,7 +73,6 @@
}
cobalt::render_tree::ResourceProvider* resource_provider_;
- scoped_refptr<ShellVideoFrameProvider> video_frame_provider_;
};
} // namespace media
@@ -91,7 +85,6 @@
#include "base/memory/aligned_memory.h"
#include "base/memory/scoped_ptr.h"
#include "cobalt/media/shell_video_data_allocator_common.h"
-#include "media/base/shell_video_frame_provider.h"
#include "nb/memory_pool.h"
#include "starboard/common/locked_ptr.h"
@@ -111,9 +104,6 @@
size_t GetSourceBufferStreamVideoMemoryLimit() const override {
return SB_MEDIA_SOURCE_BUFFER_STREAM_VIDEO_MEMORY_LIMIT;
}
- scoped_refptr<ShellVideoFrameProvider> GetVideoFrameProvider() override {
- return video_frame_provider_;
- }
int GetMaxVideoPrerollFrames() const override {
return SB_MEDIA_MAXIMUM_VIDEO_PREROLL_FRAMES;
}
@@ -152,7 +142,6 @@
starboard::LockedPtr<nb::MemoryPool> main_memory_pool_;
ShellVideoDataAllocatorCommon video_data_allocator_;
- scoped_refptr<ShellVideoFrameProvider> video_frame_provider_;
DISALLOW_COPY_AND_ASSIGN(ShellMediaPlatformStarboard);
};
diff --git a/src/cobalt/network/lib/exported/user_agent.h b/src/cobalt/network/lib/exported/user_agent.h
index 06af638..0b72f83 100644
--- a/src/cobalt/network/lib/exported/user_agent.h
+++ b/src/cobalt/network/lib/exported/user_agent.h
@@ -19,6 +19,7 @@
#define COBALT_NETWORK_LIB_EXPORTED_USER_AGENT_H_
#include "starboard/export.h"
+#include "starboard/system.h"
#ifdef __cplusplus
extern "C" {
@@ -31,6 +32,19 @@
// UA string.
SB_EXPORT_PLATFORM bool CbLibUserAgentSetPlatformNameSuffix(const char* suffix);
+// Sets the device type reported in the UA string. If |type| is not a
+// valid device type, the default value for this platform (as per starboard) is
+// kept and the function returns false.
+SB_EXPORT_PLATFORM bool CbLibUserAgentSetDeviceTypeOverride(
+ SbSystemDeviceType type);
+
+// Set the reported device brand and model names. The maximum length of
+// |value| is 512 bytes including null terminator (which is required). If
+// |value| is null, the property is reset to its default value for this
+// platform. Returns true if the value was set or reset successfully.
+SB_EXPORT_PLATFORM bool CbLibUserAgentSetBrandNameOverride(const char* value);
+SB_EXPORT_PLATFORM bool CbLibUserAgentSetModelNameOverride(const char* value);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc b/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc
index 010ec6b..3c65fc7 100644
--- a/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc
+++ b/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc
@@ -43,9 +43,9 @@
case kSbSystemDeviceTypeSetTopBox:
case kSbSystemDeviceTypeTV:
case kSbSystemDeviceTypeAndroidTV:
+ case kSbSystemDeviceTypeUnknown:
return true;
case kSbSystemDeviceTypeDesktopPC:
- case kSbSystemDeviceTypeUnknown:
default:
return false;
}
@@ -90,29 +90,8 @@
#endif // SB_API_VERSION >= 5
// Device Type
- switch (device_type) {
- case kSbSystemDeviceTypeBlueRayDiskPlayer:
- platform_info_->device_type = PlatformInfo::kBlueRayDiskPlayer;
- break;
- case kSbSystemDeviceTypeGameConsole:
- platform_info_->device_type = PlatformInfo::kGameConsole;
- break;
- case kSbSystemDeviceTypeOverTheTopBox:
- platform_info_->device_type = PlatformInfo::kOverTheTopBox;
- break;
- case kSbSystemDeviceTypeSetTopBox:
- platform_info_->device_type = PlatformInfo::kSetTopBox;
- break;
- case kSbSystemDeviceTypeTV:
- platform_info_->device_type = PlatformInfo::kTV;
- break;
- case kSbSystemDeviceTypeAndroidTV:
- platform_info_->device_type = PlatformInfo::kAndroidTV;
- break;
- case kSbSystemDeviceTypeDesktopPC:
- default:
- platform_info_->device_type = PlatformInfo::kInvalidDeviceType;
- }
+ platform_info_->device_type =
+ StarboardToPlatformInfoDeviceType(device_type);
// Chipset model number
result = SbSystemGetProperty(kSbSystemPropertyChipsetModelNumber, value,
diff --git a/src/cobalt/network/user_agent_string_factory.cc b/src/cobalt/network/user_agent_string_factory.cc
index e1c03fa..576b6e2 100644
--- a/src/cobalt/network/user_agent_string_factory.cc
+++ b/src/cobalt/network/user_agent_string_factory.cc
@@ -25,13 +25,39 @@
#include "cobalt_build_id.h" // NOLINT(build/include)
-#if defined(COBALT_ENABLE_LIB)
namespace {
+
// Max length including null terminator.
-const size_t kUserAgentPlatformMaxSuffixLength = 128;
-char g_user_agent_platform_suffix[kUserAgentPlatformMaxSuffixLength] = {0};
+const size_t kUserAgentPlatformSuffixMaxLength = 128;
+char g_user_agent_platform_suffix[kUserAgentPlatformSuffixMaxLength] = {0};
+
+bool g_device_type_override_set = false;
+SbSystemDeviceType g_device_type_override = kSbSystemDeviceTypeUnknown;
+
+// Max length including null terminator.
+const size_t kPropertyMaxLength = 512;
+bool g_brand_name_override_set = false;
+char g_brand_name_override[kPropertyMaxLength] = {0};
+bool g_model_name_override_set = false;
+char g_model_name_override[kPropertyMaxLength] = {0};
+
+bool ShouldOverrideDevice() {
+ return g_device_type_override_set || g_brand_name_override_set ||
+ g_model_name_override_set;
+}
+
+#if defined(COBALT_ENABLE_LIB)
+bool CopyStringAndTestIfSuccess(char* out_value,
+ size_t value_length,
+ const char* from_value) {
+ if (strlen(from_value) + 1 > value_length)
+ return false;
+ base::strlcpy(out_value, from_value, value_length);
+ return true;
+}
+#endif
+
} // namespace
-#endif // defined(COBALT_ENABLE_LIB)
namespace cobalt {
namespace network {
@@ -103,9 +129,20 @@
CreateDeviceTypeString().c_str(),
Sanitize(platform_info_->chipset_model_number.value_or("")).c_str(),
Sanitize(platform_info_->firmware_version.value_or("")).c_str(),
- Sanitize(platform_info_->brand).c_str(),
- Sanitize(platform_info_->model).c_str(),
+ Sanitize(g_brand_name_override_set ?
+ std::string(g_brand_name_override) : platform_info_->brand).c_str(),
+ Sanitize(g_model_name_override_set ?
+ std::string(g_model_name_override) : platform_info_->model).c_str(),
CreateConnectionTypeString().c_str());
+ } else if (ShouldOverrideDevice()) {
+ // When Starboard does not report platform info but we are overriding the
+ // device.
+ base::StringAppendF(&user_agent, ", _%s_ (%s, %s)",
+ CreateDeviceTypeString().c_str(),
+ Sanitize(g_brand_name_override_set ?
+ g_brand_name_override : "").c_str(),
+ Sanitize(g_model_name_override_set ?
+ g_model_name_override : "").c_str());
}
if (!aux_field_.empty()) {
@@ -130,19 +167,22 @@
platform += "; ";
platform += architecture_tokens_;
}
-
-#if defined(COBALT_ENABLE_LIB)
if (g_user_agent_platform_suffix[0] != '\0') {
platform += "; ";
platform += g_user_agent_platform_suffix;
}
-#endif // defined(COBALT_ENABLE_LIB)
return platform;
}
std::string UserAgentStringFactory::CreateDeviceTypeString() {
- switch (platform_info_->device_type) {
+ auto reported_device_type =
+ g_device_type_override_set ?
+ StarboardToPlatformInfoDeviceType(g_device_type_override) :
+ platform_info_ ? platform_info_->device_type :
+ PlatformInfo::kInvalidDeviceType;
+
+ switch (reported_device_type) {
case PlatformInfo::kBlueRayDiskPlayer:
return "BDP";
case PlatformInfo::kGameConsole:
@@ -155,6 +195,8 @@
return "TV";
case PlatformInfo::kAndroidTV:
return "ATV";
+ case PlatformInfo::kUnknown:
+ return "UNKNOWN";
case PlatformInfo::kInvalidDeviceType:
default:
NOTREACHED();
@@ -177,15 +219,45 @@
return "";
}
+UserAgentStringFactory::PlatformInfo::DeviceType
+UserAgentStringFactory::StarboardToPlatformInfoDeviceType(
+ SbSystemDeviceType device_type) {
+ switch (device_type) {
+ case kSbSystemDeviceTypeBlueRayDiskPlayer:
+ return PlatformInfo::kBlueRayDiskPlayer;
+ break;
+ case kSbSystemDeviceTypeGameConsole:
+ return PlatformInfo::kGameConsole;
+ break;
+ case kSbSystemDeviceTypeOverTheTopBox:
+ return PlatformInfo::kOverTheTopBox;
+ break;
+ case kSbSystemDeviceTypeSetTopBox:
+ return PlatformInfo::kSetTopBox;
+ break;
+ case kSbSystemDeviceTypeTV:
+ return PlatformInfo::kTV;
+ break;
+ case kSbSystemDeviceTypeAndroidTV:
+ return PlatformInfo::kAndroidTV;
+ break;
+ case kSbSystemDeviceTypeUnknown:
+ return PlatformInfo::kUnknown;
+ break;
+ case kSbSystemDeviceTypeDesktopPC:
+ default:
+ return PlatformInfo::kInvalidDeviceType;
+ }
+}
+
} // namespace network
} // namespace cobalt
#if defined(COBALT_ENABLE_LIB)
// Allow host app to append a suffix to the reported platform name.
bool CbLibUserAgentSetPlatformNameSuffix(const char* suffix) {
- size_t suffix_length = base::strlcpy(g_user_agent_platform_suffix, suffix,
- kUserAgentPlatformMaxSuffixLength);
- if (suffix_length >= kUserAgentPlatformMaxSuffixLength) {
+ if (!CopyStringAndTestIfSuccess(g_user_agent_platform_suffix,
+ kPropertyMaxLength, suffix)) {
// If the suffix is too large then nothing is appended to the platform.
g_user_agent_platform_suffix[0] = '\0';
return false;
@@ -193,4 +265,55 @@
return true;
}
+
+bool CbLibUserAgentSetBrandNameOverride(const char* value) {
+ if (!value) {
+ g_brand_name_override_set = false;
+ return true;
+ }
+
+ if (CopyStringAndTestIfSuccess(g_brand_name_override,
+ kPropertyMaxLength, value)) {
+ g_brand_name_override_set = true;
+ return true;
+ }
+
+ // Failed to reset/set value.
+ return false;
+}
+
+bool CbLibUserAgentSetModelNameOverride(const char* value) {
+ if (!value) {
+ g_model_name_override_set = false;
+ return true;
+ }
+
+ if (CopyStringAndTestIfSuccess(g_model_name_override,
+ kPropertyMaxLength, value)) {
+ g_model_name_override_set = true;
+ return true;
+ }
+
+ // Failed to reset/set value.
+ return false;
+}
+
+bool CbLibUserAgentSetDeviceTypeOverride(SbSystemDeviceType device_type) {
+ switch (device_type) {
+ case kSbSystemDeviceTypeBlueRayDiskPlayer:
+ case kSbSystemDeviceTypeGameConsole:
+ case kSbSystemDeviceTypeOverTheTopBox:
+ case kSbSystemDeviceTypeSetTopBox:
+ case kSbSystemDeviceTypeTV:
+ case kSbSystemDeviceTypeDesktopPC:
+ case kSbSystemDeviceTypeAndroidTV:
+ case kSbSystemDeviceTypeUnknown:
+ g_device_type_override_set = true;
+ g_device_type_override = device_type;
+ return true;
+ default:
+ g_device_type_override_set = false;
+ return false;
+ }
+}
#endif // defined(COBALT_ENABLE_LIB)
diff --git a/src/cobalt/network/user_agent_string_factory.h b/src/cobalt/network/user_agent_string_factory.h
index 45fbc75..f51ea1b 100644
--- a/src/cobalt/network/user_agent_string_factory.h
+++ b/src/cobalt/network/user_agent_string_factory.h
@@ -19,6 +19,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/optional.h"
+#include "starboard/system.h"
namespace cobalt {
namespace network {
@@ -53,6 +54,7 @@
kOverTheTopBox,
kSetTopBox,
kTV,
+ kUnknown
};
enum ConnectionType {
@@ -70,6 +72,10 @@
std::string model;
base::optional<ConnectionType> connection_type;
};
+
+ static PlatformInfo::DeviceType StarboardToPlatformInfoDeviceType(
+ SbSystemDeviceType device_type);
+
base::optional<PlatformInfo> platform_info_;
private:
diff --git a/src/cobalt/render_tree/map_to_mesh_filter.h b/src/cobalt/render_tree/map_to_mesh_filter.h
index a5c248f..d633a48 100644
--- a/src/cobalt/render_tree/map_to_mesh_filter.h
+++ b/src/cobalt/render_tree/map_to_mesh_filter.h
@@ -29,18 +29,31 @@
enum StereoMode {
kMono = 0,
- // Stereoscopic modes where each half of the video represents the view of
+ // Stereoscopic modes where each half of the content represents the view of
// one eye, and where the texture coordinates of the meshes need to be
// scaled and offset to the appropriate half. The same mesh may be used for
// both eyes, or there may be one for each eye.
kLeftRight = 1,
kTopBottom = 2,
// Like kLeftRight, but where the texture coordinates already refer to the
- // corresponding half of the video and need no adjustment. This can only
+ // corresponding half of the content and need no adjustment. This can only
// happen when there are distinct meshes for each eye.
kLeftRightUnadjustedTextureCoords = 3
};
+// The shape of the mesh that this filter applies.
+enum MeshType {
+ // Rectangular content: some rasterizers render rectangular video separately
+ // from the rest of the document (for example, for stereo content). Does not
+ // specify a custom mesh, since a rectangle with the content's aspect ratio
+ // can be assumed (accounting for whether it needs to be halved in one
+ // dimension for stereo). Not enabled on all rasterizers/platforms.
+ kRectangular = 0,
+ // Mesh that is centered around the camera; examples include 360 and 180
+ // content. Needs to be specified, since the shape is arbitrary.
+ kCustomMesh = 1
+};
+
// A MapToMeshFilter can be used to map source content onto a 3D mesh, within a
// specified well-defined viewport.
class MapToMeshFilter {
@@ -104,7 +117,7 @@
};
MapToMeshFilter(StereoMode stereo_mode, const Builder& builder)
- : stereo_mode_(stereo_mode), data_(builder) {
+ : stereo_mode_(stereo_mode), mesh_type_(kCustomMesh), data_(builder) {
DCHECK(left_eye_mesh());
if (stereo_mode == kLeftRightUnadjustedTextureCoords) {
// This stereo mode implies there are two meshes.
@@ -114,8 +127,9 @@
// A filter without a an explicit mesh, to represent mesh-mapped content whose
// mesh will be supplied externally.
- explicit MapToMeshFilter(StereoMode stereo_mode)
- : stereo_mode_(stereo_mode), data_() {
+ MapToMeshFilter(StereoMode stereo_mode, MeshType mesh_type)
+ : stereo_mode_(stereo_mode), mesh_type_(mesh_type), data_() {
+ DCHECK(mesh_type != kCustomMesh);
DCHECK(stereo_mode != kLeftRightUnadjustedTextureCoords);
}
@@ -125,6 +139,8 @@
StereoMode stereo_mode() const { return stereo_mode_; }
+ MeshType mesh_type() const { return mesh_type_; }
+
// The omission of the |resolution| parameter will yield the default
// meshes in each of the following functions (by failing to match the
// invalid resolution).
@@ -146,6 +162,7 @@
private:
static math::Size InvalidSize() { return math::Size(-1, -1); }
StereoMode stereo_mode_;
+ MeshType mesh_type_;
Builder data_;
};
diff --git a/src/cobalt/renderer/copy_font_data.gypi b/src/cobalt/renderer/copy_font_data.gypi
index ae1cc92..4617aea 100644
--- a/src/cobalt/renderer/copy_font_data.gypi
+++ b/src/cobalt/renderer/copy_font_data.gypi
@@ -32,15 +32,14 @@
'package_fallback_lang_non_cjk': 2,
'package_fallback_lang_cjk': 1,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_historic': 1,
'package_fallback_color_emoji': 1,
'package_fallback_emoji': 0,
'package_fallback_symbols': 1,
}],
- # '10megabytes' is deprecated but is mapped to 'limited_with_jp'
- [ 'cobalt_font_package == "limited_with_jp" or cobalt_font_package == "10megabytes"', {
+ # '10megabytes' and 'limited_with_jp' are deprecated but map to 'limited'
+ [ 'cobalt_font_package == "limited" or cobalt_font_package == "limited_with_jp" or cobalt_font_package == "10megabytes"', {
'source_font_config_dir': '<(static_contents_source_dir)/fonts/config/common',
'package_named_sans_serif': 2,
@@ -49,23 +48,6 @@
'package_fallback_lang_non_cjk': 1,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 1,
- 'package_fallback_lang_jp': 1,
- 'package_fallback_historic': 0,
- 'package_fallback_color_emoji': 0,
- 'package_fallback_emoji': 1,
- 'package_fallback_symbols': 1,
- }],
-
- [ 'cobalt_font_package == "limited"', {
- 'source_font_config_dir': '<(static_contents_source_dir)/fonts/config/common',
-
- 'package_named_sans_serif': 2,
- 'package_named_serif': 0,
- 'package_named_fcc_fonts': 0,
- 'package_fallback_lang_non_cjk': 1,
- 'package_fallback_lang_cjk': 0,
- 'package_fallback_lang_cjk_low_quality': 1,
- 'package_fallback_lang_jp': 0,
'package_fallback_historic': 0,
'package_fallback_color_emoji': 0,
'package_fallback_emoji': 1,
@@ -81,7 +63,6 @@
'package_fallback_lang_non_cjk': 0,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_historic': 0,
'package_fallback_color_emoji': 0,
'package_fallback_emoji': 0,
@@ -100,7 +81,6 @@
'package_fallback_lang_non_cjk': 0,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_historic': 0,
'package_fallback_color_emoji': 0,
'package_fallback_emoji': 0,
@@ -125,9 +105,6 @@
[ 'cobalt_font_package_override_fallback_lang_cjk_low_quality >= 0', {
'package_fallback_lang_cjk_low_quality': '<(cobalt_font_package_override_fallback_lang_cjk_low_quality)',
}],
- [ 'cobalt_font_package_override_fallback_lang_jp >= 0', {
- 'package_fallback_lang_jp': '<(cobalt_font_package_override_fallback_lang_jp)',
- }],
[ 'cobalt_font_package_override_fallback_historic >= 0', {
'package_fallback_historic': '<(cobalt_font_package_override_fallback_historic)',
}],
@@ -318,11 +295,6 @@
'<(source_font_files_dir)/DroidSansFallback.ttf',
],
}],
- [ 'package_fallback_lang_jp >= 1', {
- 'files+': [
- '<(source_font_files_dir)/NotoSansJP-Regular.otf',
- ],
- }],
[ 'package_fallback_historic >= 1', {
'files+': [
'<(source_font_files_dir)/NotoSansAvestan-Regular.ttf',
diff --git a/src/cobalt/renderer/fps_overlay.cc b/src/cobalt/renderer/fps_overlay.cc
index 50f29b2..3bd4510 100644
--- a/src/cobalt/renderer/fps_overlay.cc
+++ b/src/cobalt/renderer/fps_overlay.cc
@@ -49,7 +49,7 @@
// together.
float y_offset = kTextMarginInPixels;
render_tree::CompositionNode::Builder text_builder;
- for (auto line : lines) {
+ for (const auto& line : lines) {
scoped_refptr<render_tree::GlyphBuffer> glyph_buffer =
resource_provider->CreateGlyphBuffer(line, font);
math::RectF bounds(glyph_buffer->GetBounds());
diff --git a/src/cobalt/renderer/rasterizer/blitter/image.cc b/src/cobalt/renderer/rasterizer/blitter/image.cc
index c33b7b8..e57d83d 100644
--- a/src/cobalt/renderer/rasterizer/blitter/image.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/image.cc
@@ -123,7 +123,12 @@
size_.width(), size_.height(), kN32_SkColorType, kPremul_SkAlphaType);
SkBitmap bitmap;
- bitmap.allocPixels(image_info);
+ bool allocation_successful = bitmap.tryAllocPixels(image_info);
+ if (!allocation_successful) {
+ LOG(WARNING) << "Unable to allocate pixels of size " << size_.width()
+ << "x" << size_.height();
+ return image_;
+ }
bool result = SbBlitterDownloadSurfacePixels(
surface_, SkiaToBlitterPixelFormat(image_info.colorType()),
bitmap.rowBytes(), bitmap.getPixels());
diff --git a/src/cobalt/renderer/rasterizer/egl/rect_allocator.cc b/src/cobalt/renderer/rasterizer/egl/rect_allocator.cc
index 90d8d44..bf4a197 100644
--- a/src/cobalt/renderer/rasterizer/egl/rect_allocator.cc
+++ b/src/cobalt/renderer/rasterizer/egl/rect_allocator.cc
@@ -50,6 +50,10 @@
}
math::Rect RectAllocator::Allocate(const math::Size& alloc_size) {
+ if ((alloc_size.width() < 0) || (alloc_size.height() < 0)) {
+ // Invalid allocation was requested.
+ return math::Rect(0, 0, 0, 0);
+ }
math::Rect allocation(0, 0, alloc_size.width(), alloc_size.height());
// Find the first block that is too small for the requested allocation.
diff --git a/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc b/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc
index 3042396..b8df300 100644
--- a/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc
@@ -321,11 +321,14 @@
map_to_mesh_search.found_node->data().map_to_mesh_filter;
CbLibVideoProjectionType new_projection_type;
- if (!filter->left_eye_mesh()) {
- // Video is rectangular. Mesh is provided externally (by host).
- new_projection_type = kCbLibVideoProjectionTypeRectangular;
- } else {
- new_projection_type = kCbLibVideoProjectionTypeMesh;
+ switch (filter->mesh_type()) {
+ case render_tree::kRectangular:
+ // Video is rectangular. Mesh is provided externally (by host).
+ new_projection_type = kCbLibVideoProjectionTypeRectangular;
+ break;
+ case render_tree::kCustomMesh:
+ new_projection_type = kCbLibVideoProjectionTypeMesh;
+ break;
}
if (video_projection_type_ != new_projection_type ||
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
index b725a77..a8cf645 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
@@ -473,6 +473,11 @@
const render_tree::ImageNode* image_node,
const render_tree::MapToMeshFilter& mesh_filter,
RenderTreeNodeVisitorDrawState* draw_state) {
+ if (mesh_filter.mesh_type() == render_tree::kRectangular) {
+ NOTREACHED() << "This rasterizer does not support rectangular meshes on "
+ "the map-to-mesh filter.";
+ return;
+ }
Image* image =
base::polymorphic_downcast<Image*>(image_node->data().source.get());
if (!image) {
@@ -552,14 +557,15 @@
GrContext::Create(kOpenGL_GrBackend, NULL, context_options));
DCHECK(gr_context_);
- // The GrContext manages a resource cache internally using GrResourceCache
- // which by default caches 96MB of resources. This is used for helping with
- // rendering shadow effects, gradient effects, and software rendered paths.
- // As we have our own cache for most resources, set it to a much smaller value
- // so Skia doesn't use too much GPU memory.
+ // The GrContext manages a budget for GPU resources. Setting the budget equal
+ // to |skia_cache_size_in_bytes| + glyph cache's size will let Skia use
+ // additional |skia_cache_size_in_bytes| for GPU resources like textures,
+ // vertex buffers, etc.
const int kSkiaCacheMaxResources = 128;
- gr_context_->setResourceCacheLimits(kSkiaCacheMaxResources,
- skia_cache_size_in_bytes);
+ gr_context_->setResourceCacheLimits(
+ kSkiaCacheMaxResources,
+ skia_cache_size_in_bytes +
+ context_options.fGlyphCacheTextureMaximumBytes);
base::Callback<sk_sp<SkSurface>(const math::Size&)>
create_sk_surface_function = base::Bind(
@@ -705,7 +711,9 @@
"width", size.width(), "height", size.height());
SkImageInfo image_info =
SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType);
- return SkSurface::MakeRenderTarget(gr_context_.get(), SkBudgeted::kYes,
+ // Do not count the resources for this surface towards the budget since
+ // the budget is currently only meant for Skia managed resources.
+ return SkSurface::MakeRenderTarget(gr_context_.get(), SkBudgeted::kNo,
image_info);
}
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
index 4c843ac..d19e7b8 100644
--- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
@@ -388,6 +388,7 @@
if (!source) {
return;
}
+
// WIP TODO: pass in the mesh in the filter here.
if (TryRenderMapToRect(source, *filter_node->data().map_to_mesh_filter,
render_image_with_mesh_function_, &draw_state_)) {
@@ -1311,7 +1312,13 @@
SkImageInfo image_info =
SkImageInfo::MakeN32(rect.width(), rect.height(), kPremul_SkAlphaType);
SkBitmap bitmap;
- bitmap.allocPixels(image_info);
+
+ bool allocation_successful = bitmap.tryAllocPixels(image_info);
+ if (!allocation_successful) {
+ LOG(WARNING) << "Unable to allocate pixels of size " << rect.width() << "x"
+ << rect.height();
+ return;
+ }
SkCanvas canvas(bitmap);
canvas.clear(SkColorSetARGB(0, 0, 0, 0));
diff --git a/src/cobalt/renderer/render_tree_pixel_tester.cc b/src/cobalt/renderer/render_tree_pixel_tester.cc
index ff33071..cfe8807 100644
--- a/src/cobalt/renderer/render_tree_pixel_tester.cc
+++ b/src/cobalt/renderer/render_tree_pixel_tester.cc
@@ -108,15 +108,19 @@
// We need to convert our image to premultiplied alpha and N32 color
// before proceeding to blur them, as Skia is designed to primarily deal
// only with images in this format.
- SkImageInfo premul_alpha_image_info = SkImageInfo::Make(
- bitmap.width(), bitmap.height(), kN32_SkColorType, kPremul_SkAlphaType);
- premul_alpha_bitmap.allocPixels(premul_alpha_image_info);
+ SkImageInfo premul_alpha_image_info =
+ SkImageInfo::MakeN32Premul(bitmap.width(), bitmap.height());
+ bool allocation_successful =
+ premul_alpha_bitmap.tryAllocPixels(premul_alpha_image_info);
+ // Since this is a test, just crash.
+ DCHECK(allocation_successful);
bitmap.readPixels(premul_alpha_image_info, premul_alpha_bitmap.getPixels(),
premul_alpha_bitmap.rowBytes(), 0, 0);
}
SkBitmap blurred_bitmap;
- blurred_bitmap.allocPixels(SkImageInfo::Make(
- bitmap.width(), bitmap.height(), kN32_SkColorType, kPremul_SkAlphaType));
+ bool blurred_bitmap_allocated =
+ blurred_bitmap.tryAllocN32Pixels(bitmap.width(), bitmap.height());
+ DCHECK(blurred_bitmap_allocated);
SkPaint paint;
sk_sp<SkImageFilter> blur_filter(
diff --git a/src/cobalt/script/mozjs-45/mozjs-45.gyp b/src/cobalt/script/mozjs-45/mozjs-45.gyp
index 0b9e06b..8eddeb6 100644
--- a/src/cobalt/script/mozjs-45/mozjs-45.gyp
+++ b/src/cobalt/script/mozjs-45/mozjs-45.gyp
@@ -81,7 +81,6 @@
# SpiderMonkey bindings implements indexed deleters.
'ENGINE_SUPPORTS_INDEXED_DELETERS',
'ENGINE_SUPPORTS_INT64',
- 'ENGINE_SUPPORTS_STACK_TRACE_COLUMNS',
# TODO: Remove this when exact rooting and generational GC is enabled.
'ENGINE_USES_CONSERVATIVE_ROOTING',
],
diff --git a/src/cobalt/script/mozjs-45/mozjs_callback_function.h b/src/cobalt/script/mozjs-45/mozjs_callback_function.h
index 6b05688..1a60269 100644
--- a/src/cobalt/script/mozjs-45/mozjs_callback_function.h
+++ b/src/cobalt/script/mozjs-45/mozjs_callback_function.h
@@ -95,6 +95,7 @@
JSObject* handle() const { return weak_function_.GetObject(); }
const JS::Value& value() const { return weak_function_.GetValue(); }
bool WasCollected() const { return weak_function_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { weak_function_.Trace(js_tracer); }
private:
JSContext* context_;
@@ -155,6 +156,7 @@
JSObject* handle() const { return weak_function_.GetObject(); }
const JS::Value& value() const { return weak_function_.GetValue(); }
bool WasCollected() const { return weak_function_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { weak_function_.Trace(js_tracer); }
private:
JSContext* context_;
@@ -217,6 +219,7 @@
JSObject* handle() const { return weak_function_.GetObject(); }
const JS::Value& value() const { return weak_function_.GetValue(); }
bool WasCollected() const { return weak_function_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { weak_function_.Trace(js_tracer); }
private:
JSContext* context_;
@@ -281,6 +284,7 @@
JSObject* handle() const { return weak_function_.GetObject(); }
const JS::Value& value() const { return weak_function_.GetValue(); }
bool WasCollected() const { return weak_function_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { weak_function_.Trace(js_tracer); }
private:
JSContext* context_;
@@ -347,6 +351,7 @@
JSObject* handle() const { return weak_function_.GetObject(); }
const JS::Value& value() const { return weak_function_.GetValue(); }
bool WasCollected() const { return weak_function_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { weak_function_.Trace(js_tracer); }
private:
JSContext* context_;
@@ -416,6 +421,7 @@
JSObject* handle() const { return weak_function_.GetObject(); }
const JS::Value& value() const { return weak_function_.GetValue(); }
bool WasCollected() const { return weak_function_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { weak_function_.Trace(js_tracer); }
private:
JSContext* context_;
@@ -487,6 +493,7 @@
JSObject* handle() const { return weak_function_.GetObject(); }
const JS::Value& value() const { return weak_function_.GetValue(); }
bool WasCollected() const { return weak_function_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { weak_function_.Trace(js_tracer); }
private:
JSContext* context_;
@@ -560,6 +567,7 @@
JSObject* handle() const { return weak_function_.GetObject(); }
const JS::Value& value() const { return weak_function_.GetValue(); }
bool WasCollected() const { return weak_function_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { weak_function_.Trace(js_tracer); }
private:
JSContext* context_;
diff --git a/src/cobalt/script/mozjs-45/mozjs_callback_function.h.pump b/src/cobalt/script/mozjs-45/mozjs_callback_function.h.pump
index c4d7009..f0d1b24 100644
--- a/src/cobalt/script/mozjs-45/mozjs_callback_function.h.pump
+++ b/src/cobalt/script/mozjs-45/mozjs_callback_function.h.pump
@@ -123,6 +123,7 @@
JSObject* handle() const { return weak_function_.GetObject(); }
const JS::Value& value() const { return weak_function_.GetValue(); }
bool WasCollected() const { return weak_function_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { weak_function_.Trace(js_tracer); }
private:
JSContext* context_;
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.h b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
index 924c5e3..d4c64c3 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.h
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
@@ -91,9 +91,6 @@
ScriptValueFactory* script_value_factory() override;
- // Evaluates any automatically included Javascript for the environment.
- void EvaluateAutomatics();
-
JSContext* context() const { return context_; }
JSObject* global_object_proxy() const { return global_object_proxy_; }
@@ -159,6 +156,9 @@
int count;
};
+ // Evaluates any automatically included Javascript for the environment.
+ void EvaluateAutomatics();
+
bool EvaluateScriptInternal(const scoped_refptr<SourceCode>& source_code,
bool mute_errors,
JS::MutableHandleValue out_result);
diff --git a/src/cobalt/script/mozjs-45/mozjs_tracer.cc b/src/cobalt/script/mozjs-45/mozjs_tracer.cc
index 0a07f3a..99f4f5f 100644
--- a/src/cobalt/script/mozjs-45/mozjs_tracer.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_tracer.cc
@@ -32,7 +32,7 @@
// rather than a |JSContext|. Fortunately, Cobalt will only create one
// global environment per runtime, so we can still safely get back to our
// context, and thus our global environment.
- JSContext* context = NULL;
+ JSContext* context = nullptr;
JS_ContextIterator(js_tracer_->runtime(), &context);
DCHECK(context);
MozjsGlobalEnvironment* global_environment =
@@ -74,10 +74,10 @@
DCHECK(wrapper_private->context_ == context);
DCHECK(wrapper_private->wrapper_proxy_);
JS_CallObjectTracer(js_tracer_, &wrapper_private->wrapper_proxy_,
- "WrapperPrivate::TraceWrappable");
+ "MozjsTracer::Trace");
}
- DCHECK(JS_ContextIterator(js_tracer_->runtime(), &context) == NULL);
+ DCHECK(JS_ContextIterator(js_tracer_->runtime(), &context) == nullptr);
}
void MozjsTracer::TraceFrom(Wrappable* wrappable) {
diff --git a/src/cobalt/script/mozjs-45/mozjs_tracer.h b/src/cobalt/script/mozjs-45/mozjs_tracer.h
index a426ae7..22180b1 100644
--- a/src/cobalt/script/mozjs-45/mozjs_tracer.h
+++ b/src/cobalt/script/mozjs-45/mozjs_tracer.h
@@ -36,12 +36,21 @@
class MozjsTracer : public ::cobalt::script::Tracer {
public:
explicit MozjsTracer(JSTracer* js_tracer) : js_tracer_(js_tracer) {}
+
void Trace(Traceable* traceable) override;
+ // Traverse the embedder heap and JavaScript heap, starting from
+ // |wrappable|. For any reachable |Traceable|s that have corresponding
+ // wrappers, feed those wrappers to the SpiderMonkey-side tracer. In the
+ // case that they don't, add them to |frontier_|, and trace them ourselves.
void TraceFrom(Wrappable* wrappable);
+ // This is primarly exposed for |MozjsUserObjectHolder|'s implementation of
+ // |TraceMembers|.
+ JSTracer* js_tracer() const { return js_tracer_; }
+
private:
- JSTracer* js_tracer_;
+ JSTracer* const js_tracer_;
// Pending |Traceable|s that we must traverse ourselves, since they did not
// have a |WrapperPrivate|, or were not a wrapper.
std::vector<Traceable*> frontier_;
diff --git a/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h b/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h
index 8db589d..a33ff7a 100644
--- a/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h
+++ b/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h
@@ -57,6 +57,31 @@
DCHECK(!persistent_root_);
}
+ bool EqualTo(const BaseClass& other) const override {
+ const MozjsUserObjectHolder* mozjs_other =
+ base::polymorphic_downcast<const MozjsUserObjectHolder*>(&other);
+ if (!handle_) {
+ return !mozjs_other->handle_;
+ } else if (!mozjs_other->handle_) {
+ return false;
+ }
+
+ DCHECK(handle_);
+ DCHECK(mozjs_other->handle_);
+
+ JS::RootedValue value1(context_, js_value());
+ JS::RootedValue value2(context_, mozjs_other->js_value());
+ return util::IsSameGcThing(context_, value1, value2);
+ }
+
+ void TraceMembers(Tracer* tracer) override {
+ if (handle_) {
+ MozjsTracer* mozjs_tracer =
+ base::polymorphic_downcast<MozjsTracer*>(tracer);
+ handle_->Trace(mozjs_tracer->js_tracer());
+ }
+ }
+
void RegisterOwner(Wrappable* owner) override {
JSAutoRequest auto_request(context_);
JS::RootedValue owned_value(context_, js_value());
@@ -66,9 +91,8 @@
if (!owned_value.isNullOrUndefined() && owned_value.isGCThing()) {
MozjsGlobalEnvironment* global_environment =
MozjsGlobalEnvironment::GetFromContext(context_);
- intptr_t key = ReferencedObjectMap::GetKeyForWrappable(owner);
global_environment->referenced_objects()->AddReferencedObject(
- key, owned_value);
+ owner, owned_value);
}
}
@@ -80,9 +104,8 @@
if (!owned_value.isNullOrUndefined() && owned_value.isGCThing()) {
MozjsGlobalEnvironment* global_environment =
MozjsGlobalEnvironment::GetFromContext(context_);
- intptr_t key = ReferencedObjectMap::GetKeyForWrappable(owner);
global_environment->referenced_objects()->RemoveReferencedObject(
- key, owned_value);
+ owner, owned_value);
}
}
@@ -114,23 +137,6 @@
new MozjsUserObjectHolder(context_, rooted_value));
}
- bool EqualTo(const BaseClass& other) const override {
- const MozjsUserObjectHolder* mozjs_other =
- base::polymorphic_downcast<const MozjsUserObjectHolder*>(&other);
- if (!handle_) {
- return !mozjs_other->handle_;
- } else if (!mozjs_other->handle_) {
- return false;
- }
-
- DCHECK(handle_);
- DCHECK(mozjs_other->handle_);
-
- JS::RootedValue value1(context_, js_value());
- JS::RootedValue value2(context_, mozjs_other->js_value());
- return util::IsSameGcThing(context_, value1, value2);
- }
-
const JS::Value& js_value() const {
DCHECK(handle_);
return handle_->value();
@@ -142,9 +148,6 @@
}
private:
- typedef base::hash_map<const Wrappable*, base::WeakPtr<WrapperPrivate> >
- WrappableAndPrivateHashMap;
-
JSContext* context_;
base::optional<MozjsUserObjectType> handle_;
int prevent_garbage_collection_count_;
diff --git a/src/cobalt/script/mozjs-45/mozjs_value_handle.h b/src/cobalt/script/mozjs-45/mozjs_value_handle.h
index 0a30572..3b35952 100644
--- a/src/cobalt/script/mozjs-45/mozjs_value_handle.h
+++ b/src/cobalt/script/mozjs-45/mozjs_value_handle.h
@@ -34,9 +34,11 @@
class MozjsValueHandle : public ValueHandle {
public:
typedef ValueHandle BaseType;
+
JSObject* handle() const { return handle_.GetObject(); }
const JS::Value& value() const { return handle_.GetValue(); }
bool WasCollected() const { return handle_.WasCollected(); }
+ void Trace(JSTracer* js_tracer) { handle_.Trace(js_tracer); }
private:
MozjsValueHandle(JSContext* context, JS::HandleValue value)
diff --git a/src/cobalt/script/mozjs-45/native_promise.h b/src/cobalt/script/mozjs-45/native_promise.h
index 803e412..f5f09d6 100644
--- a/src/cobalt/script/mozjs-45/native_promise.h
+++ b/src/cobalt/script/mozjs-45/native_promise.h
@@ -69,6 +69,7 @@
JSObject* handle() const { return promise_resolver_->get().GetObject(); }
const JS::Value& value() const { return promise_resolver_->get().GetValue(); }
bool WasCollected() const { return promise_resolver_->get().WasCollected(); }
+ void Trace(JSTracer* js_tracer) { promise_resolver_->get().Trace(js_tracer); }
// The Promise JS object (not the resolver).
JSObject* promise() const { return promise_resolver_->GetPromise(); }
diff --git a/src/cobalt/script/mozjs-45/promise_wrapper.h b/src/cobalt/script/mozjs-45/promise_wrapper.h
index 1f5420d..cd34140 100644
--- a/src/cobalt/script/mozjs-45/promise_wrapper.h
+++ b/src/cobalt/script/mozjs-45/promise_wrapper.h
@@ -34,6 +34,7 @@
PromiseWrapper(JSContext* context, JS::HandleValue promise_wrapper);
+ WeakHeapObject& get() { return weak_promise_wrapper_; }
const WeakHeapObject& get() const { return weak_promise_wrapper_; }
JSObject* GetPromise() const;
void Resolve(JS::HandleValue value) const;
diff --git a/src/cobalt/script/mozjs-45/referenced_object_map.cc b/src/cobalt/script/mozjs-45/referenced_object_map.cc
index 4bac38f..38312fe 100644
--- a/src/cobalt/script/mozjs-45/referenced_object_map.cc
+++ b/src/cobalt/script/mozjs-45/referenced_object_map.cc
@@ -28,24 +28,21 @@
: context_(context) {}
// Add/Remove a reference from a WrapperPrivate to a JSValue.
-void ReferencedObjectMap::AddReferencedObject(intptr_t key,
+void ReferencedObjectMap::AddReferencedObject(const Wrappable* wrappable,
JS::HandleValue referee) {
TRACK_MEMORY_SCOPE("Javascript");
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!referee.isNullOrUndefined());
DCHECK(referee.isGCThing());
referenced_objects_.insert(
- std::make_pair(key, WeakHeapObject(context_, referee)));
+ std::make_pair(wrappable, WeakHeapObject(context_, referee)));
}
-void ReferencedObjectMap::RemoveReferencedObject(intptr_t key,
+void ReferencedObjectMap::RemoveReferencedObject(const Wrappable* wrappable,
JS::HandleValue referee) {
DCHECK(thread_checker_.CalledOnValidThread());
- std::pair<ReferencedObjectMultiMap::iterator,
- ReferencedObjectMultiMap::iterator> pair_range =
- referenced_objects_.equal_range(key);
- for (ReferencedObjectMultiMap::iterator it = pair_range.first;
- it != pair_range.second; ++it) {
+ auto pair_range = referenced_objects_.equal_range(wrappable);
+ for (auto it = pair_range.first; it != pair_range.second; ++it) {
JS::RootedValue element(context_, it->second.GetValue());
if (util::IsSameGcThing(context_, referee, element)) {
// There may be multiple mappings between a specific owner and a JS
@@ -58,24 +55,20 @@
}
void ReferencedObjectMap::TraceReferencedObjects(JSTracer* trace,
- intptr_t key) {
+ const Wrappable* wrappable) {
DCHECK(thread_checker_.CalledOnValidThread());
- std::pair<ReferencedObjectMultiMap::iterator,
- ReferencedObjectMultiMap::iterator> pair_range =
- referenced_objects_.equal_range(key);
- for (ReferencedObjectMultiMap::iterator it = pair_range.first;
- it != pair_range.second; ++it) {
+ auto pair_range = referenced_objects_.equal_range(wrappable);
+ for (auto it = pair_range.first; it != pair_range.second; ++it) {
it->second.Trace(trace);
}
}
void ReferencedObjectMap::RemoveNullReferences() {
DCHECK(thread_checker_.CalledOnValidThread());
- for (ReferencedObjectMultiMap::iterator it = referenced_objects_.begin();
- it != referenced_objects_.end();
+ for (auto it = referenced_objects_.begin(); it != referenced_objects_.end();
/*Incremented in the loop */) {
if (it->second.WasCollected()) {
- ReferencedObjectMultiMap::iterator erase_iterator = it++;
+ auto erase_iterator = it++;
referenced_objects_.erase(erase_iterator);
} else {
DCHECK(it->second.IsGcThing());
diff --git a/src/cobalt/script/mozjs-45/referenced_object_map.h b/src/cobalt/script/mozjs-45/referenced_object_map.h
index 134a221..7ae3281 100644
--- a/src/cobalt/script/mozjs-45/referenced_object_map.h
+++ b/src/cobalt/script/mozjs-45/referenced_object_map.h
@@ -25,28 +25,20 @@
namespace script {
namespace mozjs {
-// Maintains a set of JSObjects that are reachable from a given object. This
-// relationship is registered by mapping a key to a JSObject. The calling code
-// should ensure that a key uniquely identifies the entity that holds a
-// reference to the JSObjects.
-// During garbage collection, supply a key to TraceReferencedObjects to trace
-// all objects that are registered as being reachable from the object
-// represented by that key.
+// Maintains a set of |JSObject|s that are reachable from a given object. This
+// relationship is registered by mapping a |Wrappable| to a |JSObject|. During
+// garbage collection, supply a |Wrappable| to |TraceReferencedObjects| to
+// trace all objects that are registered as being reachable from the object.
class ReferencedObjectMap {
public:
explicit ReferencedObjectMap(JSContext* context);
- // Reinterpret the pointer as an integer to be used as a key for tracking
- // referenced objects.
- static intptr_t GetKeyForWrappable(const Wrappable* wrappable) {
- return reinterpret_cast<intptr_t>(wrappable);
- }
+ void AddReferencedObject(const Wrappable* wrappable, JS::HandleValue referee);
+ void RemoveReferencedObject(const Wrappable* wrappable,
+ JS::HandleValue referee);
- void AddReferencedObject(intptr_t key, JS::HandleValue referee);
- void RemoveReferencedObject(intptr_t key, JS::HandleValue referee);
-
- // Trace all objects referenced from this WrapperPrivate*.
- void TraceReferencedObjects(JSTracer* trace, intptr_t key);
+ // Trace all objects referenced from this |wrappable|.
+ void TraceReferencedObjects(JSTracer* trace, const Wrappable* wrappable);
// Remove any referenced objects that are NULL. It may be the case that a
// weak reference to an object was garbage collected, so remove it from the
@@ -54,11 +46,11 @@
void RemoveNullReferences();
private:
- typedef base::hash_multimap<intptr_t, WeakHeapObject>
+ typedef base::hash_multimap<const Wrappable*, WeakHeapObject>
ReferencedObjectMultiMap;
base::ThreadChecker thread_checker_;
- JSContext* context_;
+ JSContext* const context_;
ReferencedObjectMultiMap referenced_objects_;
};
diff --git a/src/cobalt/script/mozjs-45/union_type_conversion_impl.h.pump b/src/cobalt/script/mozjs-45/union_type_conversion_impl.h.pump
index 05f2238..6b5dab9 100644
--- a/src/cobalt/script/mozjs-45/union_type_conversion_impl.h.pump
+++ b/src/cobalt/script/mozjs-45/union_type_conversion_impl.h.pump
@@ -27,8 +27,8 @@
#include "cobalt/base/type_id.h"
#include "cobalt/script/mozjs-45/mozjs_exception_state.h"
#include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_value_handle.h"
#include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs-45/mozjs_value_handle.h"
#include "cobalt/script/mozjs-45/type_traits.h"
#include "cobalt/script/union_type.h"
diff --git a/src/cobalt/script/mozjs-45/util/exception_helpers.cc b/src/cobalt/script/mozjs-45/util/exception_helpers.cc
index a9523f5..d650dd6 100644
--- a/src/cobalt/script/mozjs-45/util/exception_helpers.cc
+++ b/src/cobalt/script/mozjs-45/util/exception_helpers.cc
@@ -79,7 +79,7 @@
sf.line_number = static_cast<int>(line);
sf.column_number = static_cast<int>(column);
- sf.function_name = "global code";
+ sf.function_name = "";
if (name) {
JS::RootedValue rooted_value(context);
rooted_value.setString(name);
@@ -125,10 +125,10 @@
auto* chars = atom->latin1Chars(nogc);
sf.function_name = std::string(chars, chars + atom->length());
} else {
- sf.function_name = "(anonymous function)";
+ sf.function_name = "<anonymous>";
}
} else {
- sf.function_name = "global code";
+ sf.function_name = "";
}
output->push_back(sf);
diff --git a/src/cobalt/script/mozjs-45/weak_heap_object.cc b/src/cobalt/script/mozjs-45/weak_heap_object.cc
index d6d8ddb..3d26ad6 100644
--- a/src/cobalt/script/mozjs-45/weak_heap_object.cc
+++ b/src/cobalt/script/mozjs-45/weak_heap_object.cc
@@ -40,9 +40,16 @@
return *this;
}
-void WeakHeapObject::Trace(JSTracer* trace) {
+WeakHeapObject::~WeakHeapObject() {
+ // It's safe to call StopTracking even if StartTracking wasn't called. the
+ // WeakObjectManager handles the case where it's not currently tracking the
+ // WeakHeapObject.
+ weak_object_manager_->StopTracking(this);
+}
+
+void WeakHeapObject::Trace(JSTracer* js_tracer) {
if (!value_.isNullOrUndefined()) {
- JS_CallValueTracer(trace, &value_, "WeakHeapObject::Trace");
+ JS_CallValueTracer(js_tracer, &value_, "WeakHeapObject::Trace");
}
}
@@ -56,13 +63,6 @@
return (was_collected_ && value_.isNullOrUndefined());
}
-WeakHeapObject::~WeakHeapObject() {
- // It's safe to call StopTracking even if StartTracking wasn't called. the
- // WeakObjectManager handles the case where it's not currently tracking the
- // WeakHeapObject.
- weak_object_manager_->StopTracking(this);
-}
-
void WeakHeapObject::Initialize(WeakHeapObjectManager* weak_heap_object_manager,
const JS::Value& value) {
weak_object_manager_ = weak_heap_object_manager;
diff --git a/src/cobalt/script/mozjs-45/weak_heap_object.h b/src/cobalt/script/mozjs-45/weak_heap_object.h
index 1240e98..ea252c1 100644
--- a/src/cobalt/script/mozjs-45/weak_heap_object.h
+++ b/src/cobalt/script/mozjs-45/weak_heap_object.h
@@ -29,22 +29,22 @@
public:
WeakHeapObject(JSContext* context, JS::HandleValue value);
WeakHeapObject(const WeakHeapObject& other);
-
WeakHeapObject& operator=(const WeakHeapObject& rhs);
+
+ ~WeakHeapObject();
+
const JS::Value& GetValue() const { return value_.get(); }
JSObject* GetObject() const {
return value_.toObjectOrNull();
}
- void Trace(JSTracer* trace);
+ void Trace(JSTracer* js_tracer);
bool IsObject() const;
bool IsGcThing() const;
// Whether the value was a GC Thing and has been actually GC'd.
bool WasCollected() const;
- ~WeakHeapObject();
-
private:
void Initialize(WeakHeapObjectManager* weak_heap_object_manager,
const JS::Value& value);
diff --git a/src/cobalt/script/mozjs-45/wrapper_private.cc b/src/cobalt/script/mozjs-45/wrapper_private.cc
index 24b2e2a..e7aa1a6 100644
--- a/src/cobalt/script/mozjs-45/wrapper_private.cc
+++ b/src/cobalt/script/mozjs-45/wrapper_private.cc
@@ -125,10 +125,8 @@
MozjsGlobalEnvironment* global_environment =
MozjsGlobalEnvironment::GetFromContext(wrapper_private->context_);
- intptr_t key = ReferencedObjectMap::GetKeyForWrappable(
- wrapper_private->wrappable_.get());
- global_environment->referenced_objects()->TraceReferencedObjects(trace,
- key);
+ global_environment->referenced_objects()->TraceReferencedObjects(
+ trace, wrapper_private->wrappable_);
MozjsTracer mozjs_tracer(trace);
mozjs_tracer.TraceFrom(wrapper_private->wrappable_);
}
diff --git a/src/cobalt/script/script_value.h b/src/cobalt/script/script_value.h
index fcca2c4..09bd016 100644
--- a/src/cobalt/script/script_value.h
+++ b/src/cobalt/script/script_value.h
@@ -18,6 +18,7 @@
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "cobalt/script/tracer.h"
namespace cobalt {
namespace script {
@@ -41,8 +42,44 @@
// detached from the rest of the graph of JavaScript GC things, and can safely
// be garbage collected.
template <class T>
-class ScriptValue {
+class ScriptValue : public Traceable {
public:
+ // A reference type for when a |Traceable| owns a |ScriptValue|, and only
+ // wants to keep it alive if the owning object continues to get traced. This
+ // is the preferred reference type in that if you can use it, you should (as
+ // opposed to legacy types |Reference| or |StrongReference|, which predate
+ // the TraceMembers system).
+ class TracedReference : public Traceable {
+ public:
+ explicit TracedReference(scoped_ptr<ScriptValue> script_value)
+ : referenced_value_(script_value.Pass()) {
+ DCHECK(referenced_value_);
+ }
+
+ explicit TracedReference(const ScriptValue& script_value)
+ : referenced_value_(script_value.MakeCopy()) {
+ DCHECK(referenced_value_);
+ }
+
+ const T& value() const { return *(referenced_value_->GetScriptValue()); }
+
+ // Return the referenced ScriptValue. This ScriptValue can
+ // be passed back into the JavaScript bindings layer where the referenced
+ // JavaScript object can be extracted from the ScriptValue.
+ const ScriptValue<T>& referenced_value() const {
+ return *(referenced_value_.get());
+ }
+
+ void TraceMembers(Tracer* tracer) override {
+ tracer->Trace(referenced_value_.get());
+ }
+
+ private:
+ scoped_ptr<ScriptValue> referenced_value_;
+
+ DISALLOW_COPY_AND_ASSIGN(TracedReference);
+ };
+
// The Reference class maintains the ownership relationship between a
// Wrappable and the JavaScript value wrapped by a ScriptValue. This is an
// RAII object in that creation of a Reference instance will mark the
diff --git a/src/cobalt/script/testing/fake_script_value.h b/src/cobalt/script/testing/fake_script_value.h
index 1982740..9ecf42e 100644
--- a/src/cobalt/script/testing/fake_script_value.h
+++ b/src/cobalt/script/testing/fake_script_value.h
@@ -26,24 +26,27 @@
class FakeScriptValue : public cobalt::script::ScriptValue<T> {
public:
typedef cobalt::script::ScriptValue<T> BaseClass;
+
explicit FakeScriptValue(const T* listener)
: value_(listener) {}
- void RegisterOwner(script::Wrappable*) override {}
- void DeregisterOwner(script::Wrappable*) override {}
- void PreventGarbageCollection() override {}
- void AllowGarbageCollection() override {}
- const T* GetScriptValue(void) const override { return value_; }
- scoped_ptr<BaseClass> MakeCopy() const override {
- return make_scoped_ptr<BaseClass>(new FakeScriptValue(value_));
- }
-
bool EqualTo(const BaseClass& other) const override {
const FakeScriptValue* other_script_object =
base::polymorphic_downcast<const FakeScriptValue*>(&other);
return value_ == other_script_object->value_;
}
+ void TraceMembers(Tracer*) override {};
+
+ void RegisterOwner(script::Wrappable*) override {}
+ void DeregisterOwner(script::Wrappable*) override {}
+ void PreventGarbageCollection() override {}
+ void AllowGarbageCollection() override {}
+ const T* GetScriptValue() const override { return value_; }
+ scoped_ptr<BaseClass> MakeCopy() const override {
+ return make_scoped_ptr<BaseClass>(new FakeScriptValue(value_));
+ }
+
private:
const T* value_;
};
diff --git a/src/cobalt/script/tracer.h b/src/cobalt/script/tracer.h
index c7ffdbe..3e7f771 100644
--- a/src/cobalt/script/tracer.h
+++ b/src/cobalt/script/tracer.h
@@ -15,7 +15,10 @@
#ifndef COBALT_SCRIPT_TRACER_H_
#define COBALT_SCRIPT_TRACER_H_
+#include <memory>
+
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "cobalt/script/sequence.h"
@@ -23,6 +26,7 @@
namespace script {
class Tracer;
+
class Traceable {
public:
// Trace all native |Traceable|s accessible by the |Traceable|. Any class
@@ -56,6 +60,16 @@
Trace(const_cast<Traceable*>(&traceable));
}
+ template <typename T>
+ void Trace(const scoped_ptr<T>& ptr) {
+ Trace(ptr.get());
+ }
+
+ template <typename T>
+ void Trace(const std::unique_ptr<T>& ptr) {
+ Trace(ptr.get());
+ }
+
// Trace the items of a container of |Traceable|s, such as |std::vector|.
template <typename T>
void TraceItems(const T& items) {
diff --git a/src/cobalt/script/v8c/conversion_helpers.h b/src/cobalt/script/v8c/conversion_helpers.h
index 00d8d2f..0dea922 100644
--- a/src/cobalt/script/v8c/conversion_helpers.h
+++ b/src/cobalt/script/v8c/conversion_helpers.h
@@ -496,7 +496,7 @@
V8cGlobalEnvironment* global_environment =
V8cGlobalEnvironment::GetFromIsolate(isolate);
WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
- v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
+ v8::Local<v8::Object> object = value.As<v8::Object>();
// Note that |DoesObjectImplementInterface| handles the case in which
// |object| has no |WrapperPrivate|.
diff --git a/src/cobalt/script/v8c/interface_data.h b/src/cobalt/script/v8c/interface_data.h
deleted file mode 100644
index afd5a4d..0000000
--- a/src/cobalt/script/v8c/interface_data.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef COBALT_SCRIPT_V8C_INTERFACE_DATA_H_
-#define COBALT_SCRIPT_V8C_INTERFACE_DATA_H_
-
-#include "v8/include/v8.h"
-
-namespace cobalt {
-namespace script {
-namespace v8c {
-
-// Data that is cached on a per-interface basis.
-struct InterfaceData {
- v8::Eternal<v8::FunctionTemplate> function_template;
- v8::Eternal<v8::Object> interface_object;
-};
-
-} // namespace v8c
-} // namespace script
-} // namespace cobalt
-
-#endif // COBALT_SCRIPT_V8C_INTERFACE_DATA_H_
diff --git a/src/cobalt/script/v8c/union_type_conversion_impl.h b/src/cobalt/script/v8c/union_type_conversion_impl.h
index af42037..8446e0a 100644
--- a/src/cobalt/script/v8c/union_type_conversion_impl.h
+++ b/src/cobalt/script/v8c/union_type_conversion_impl.h
@@ -92,8 +92,7 @@
// case. Just choose the first interface in the flattened members that
// matches.
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- v8::Local<v8::Object> object = value->ToObject(context).ToLocalChecked();
+ v8::Local<v8::Object> object = value.As<v8::Object>();
V8cGlobalEnvironment* global_environment =
V8cGlobalEnvironment::GetFromIsolate(isolate);
@@ -285,8 +284,7 @@
// case. Just choose the first interface in the flattened members that
// matches.
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- v8::Local<v8::Object> object = value->ToObject(context).ToLocalChecked();
+ v8::Local<v8::Object> object = value.As<v8::Object>();
V8cGlobalEnvironment* global_environment =
V8cGlobalEnvironment::GetFromIsolate(isolate);
@@ -528,8 +526,7 @@
// case. Just choose the first interface in the flattened members that
// matches.
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- v8::Local<v8::Object> object = value->ToObject(context).ToLocalChecked();
+ v8::Local<v8::Object> object = value.As<v8::Object>();
V8cGlobalEnvironment* global_environment =
V8cGlobalEnvironment::GetFromIsolate(isolate);
diff --git a/src/cobalt/script/v8c/union_type_conversion_impl.h.pump b/src/cobalt/script/v8c/union_type_conversion_impl.h.pump
index 00bd006..71b0ffd 100644
--- a/src/cobalt/script/v8c/union_type_conversion_impl.h.pump
+++ b/src/cobalt/script/v8c/union_type_conversion_impl.h.pump
@@ -110,8 +110,7 @@
// case. Just choose the first interface in the flattened members that
// matches.
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- v8::Local<v8::Object> object = value->ToObject(context).ToLocalChecked();
+ v8::Local<v8::Object> object = value.As<v8::Object>();
V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
const WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
diff --git a/src/cobalt/script/v8c/v8c.gyp b/src/cobalt/script/v8c/v8c.gyp
index 075815a..ab51b262 100644
--- a/src/cobalt/script/v8c/v8c.gyp
+++ b/src/cobalt/script/v8c/v8c.gyp
@@ -69,7 +69,6 @@
'defines': [
'ENGINE_SUPPORTS_INDEXED_DELETERS',
'ENGINE_SUPPORTS_INT64',
- 'ENGINE_SUPPORTS_STACK_TRACE_COLUMNS',
# TODO: Remove this when exact rooting and generational GC is enabled.
'ENGINE_USES_CONSERVATIVE_ROOTING',
],
diff --git a/src/cobalt/script/v8c/v8c_callback_interface.cc b/src/cobalt/script/v8c/v8c_callback_interface.cc
index 9369a2a..ee89329 100644
--- a/src/cobalt/script/v8c/v8c_callback_interface.cc
+++ b/src/cobalt/script/v8c/v8c_callback_interface.cc
@@ -23,36 +23,27 @@
// Helper class to get the actual callable object from a v8::Object
// implementing a callback interface.
// Returns true if a callable was found, and false if not.
-v8::MaybeLocal<v8::Object> GetCallableForCallbackInterface(
+v8::MaybeLocal<v8::Function> GetCallableForCallbackInterface(
v8::Isolate* isolate, v8::Local<v8::Object> implementing_object,
- const char* property_name) {
+ v8::Local<v8::String> key) {
DCHECK(!implementing_object.IsEmpty());
- DCHECK(property_name);
- if (implementing_object->IsCallable()) {
- return implementing_object;
+ if (implementing_object->IsFunction()) {
+ return implementing_object.As<v8::Function>();
}
- v8::MaybeLocal<v8::Value> maybe_property_value = implementing_object->Get(
- isolate->GetCurrentContext(),
- v8::String::NewFromUtf8(isolate, property_name,
- v8::NewStringType::kNormal)
- .ToLocalChecked());
+ v8::MaybeLocal<v8::Value> maybe_property_value =
+ implementing_object->Get(isolate->GetCurrentContext(), key);
v8::Local<v8::Value> property_value;
if (!maybe_property_value.ToLocal(&property_value)) {
return {};
}
- if (!property_value->IsObject()) {
- return {};
- }
- v8::Local<v8::Object> property_object =
- v8::Local<v8::Object>::Cast(property_value);
- if (!property_object->IsCallable()) {
+ if (!property_value->IsFunction()) {
return {};
}
- return property_object;
+ return property_value.As<v8::Function>();
}
} // namespace v8c
diff --git a/src/cobalt/script/v8c/v8c_callback_interface.h b/src/cobalt/script/v8c/v8c_callback_interface.h
index f446d2c..f95ce67 100644
--- a/src/cobalt/script/v8c/v8c_callback_interface.h
+++ b/src/cobalt/script/v8c/v8c_callback_interface.h
@@ -26,9 +26,9 @@
// Helper class to get the actual callable object from a v8::Object
// implementing a callback interface.
// Returns true if a callable was found, and false if not.
-v8::MaybeLocal<v8::Object> GetCallableForCallbackInterface(
+v8::MaybeLocal<v8::Function> GetCallableForCallbackInterface(
v8::Isolate* isolate, v8::Local<v8::Object> implementing_object,
- const char* property_name);
+ v8::Local<v8::String> key);
} // namespace v8c
} // namespace script
diff --git a/src/cobalt/script/v8c/v8c_engine.h b/src/cobalt/script/v8c/v8c_engine.h
index 9192415..8b36a35 100644
--- a/src/cobalt/script/v8c/v8c_engine.h
+++ b/src/cobalt/script/v8c/v8c_engine.h
@@ -32,6 +32,12 @@
class V8cEngine : public JavaScriptEngine {
public:
+ // Helper function to allow others to retrieve us (a |V8cEngine|) from our
+ // |v8::Isolate|.
+ static V8cEngine* GetFromIsolate(v8::Isolate* isolate) {
+ return static_cast<V8cEngine*>(isolate->GetData(kIsolateDataIndex));
+ }
+
explicit V8cEngine(const Options& options);
~V8cEngine() override;
@@ -42,8 +48,11 @@
void SetGcThreshold(int64_t bytes) override;
v8::Isolate* isolate() const { return isolate_; }
+ V8cHeapTracer* heap_tracer() const { return v8c_heap_tracer_.get(); }
private:
+ // Where we store ourselves as embedder private data in our corresponding
+ // |v8::Isolate|.
static const int kIsolateDataIndex = 0;
base::ThreadChecker thread_checker_;
diff --git a/src/cobalt/script/v8c/v8c_global_environment.cc b/src/cobalt/script/v8c/v8c_global_environment.cc
index 0eed92b..a5eaa7d 100644
--- a/src/cobalt/script/v8c/v8c_global_environment.cc
+++ b/src/cobalt/script/v8c/v8c_global_environment.cc
@@ -17,6 +17,7 @@
#include <algorithm>
#include <utility>
+#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "base/stringprintf.h"
#include "cobalt/base/polymorphic_downcast.h"
@@ -61,6 +62,8 @@
eval_enabled_(false),
isolate_(isolate) {
TRACK_MEMORY_SCOPE("Javascript");
+ TRACE_EVENT0("cobalt::script",
+ "V8cGlobalEnvironment::V8cGlobalEnvironment()");
wrapper_factory_.reset(new WrapperFactory(isolate));
isolate_->SetData(kIsolateDataIndex, this);
DCHECK(isolate_->GetData(kIsolateDataIndex) == this);
@@ -70,6 +73,8 @@
}
V8cGlobalEnvironment::~V8cGlobalEnvironment() {
+ TRACE_EVENT0("cobalt::script",
+ "V8cGlobalEnvironment::~V8cGlobalEnvironment()");
DCHECK(thread_checker_.CalledOnValidThread());
// TODO: Change type of this member to scoped_ptr
@@ -83,6 +88,7 @@
}
void V8cGlobalEnvironment::CreateGlobalObject() {
+ TRACE_EVENT0("cobalt::script", "V8cGlobalEnvironment::CreateGlobalObject()");
TRACK_MEMORY_SCOPE("Javascript");
DCHECK(thread_checker_.CalledOnValidThread());
@@ -100,41 +106,19 @@
const scoped_refptr<SourceCode>& source_code, bool mute_errors,
std::string* out_result_utf8) {
TRACK_MEMORY_SCOPE("Javascript");
+ TRACE_EVENT0("cobalt::script", "V8cGlobalEnvironment::EvaluateScript()");
DCHECK(thread_checker_.CalledOnValidThread());
EntryScope entry_scope(isolate_);
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
-
- V8cSourceCode* v8c_source_code =
- base::polymorphic_downcast<V8cSourceCode*>(source_code.get());
- const base::SourceLocation& source_location = v8c_source_code->location();
-
v8::TryCatch try_catch(isolate_);
- v8::ScriptOrigin script_origin(
- v8::String::NewFromUtf8(isolate_, source_location.file_path.c_str(),
- v8::NewStringType::kNormal)
- .ToLocalChecked(),
- v8::Integer::New(isolate_, source_location.line_number),
- v8::Integer::New(isolate_, source_location.column_number),
- v8::Boolean::New(isolate_, !mute_errors));
- v8::Local<v8::String> source =
- v8::String::NewFromUtf8(isolate_, v8c_source_code->source_utf8().c_str(),
- v8::NewStringType::kNormal)
- .ToLocalChecked();
- v8::MaybeLocal<v8::Script> maybe_script =
- v8::Script::Compile(context, source, &script_origin);
- v8::Local<v8::Script> script;
- if (!maybe_script.ToLocal(&script)) {
- if (out_result_utf8) {
- *out_result_utf8 = ExceptionToString(try_catch);
- }
- return false;
- }
-
- v8::MaybeLocal<v8::Value> maybe_result = script->Run(context);
v8::Local<v8::Value> result;
- if (!maybe_result.ToLocal(&result)) {
+ if (!EvaluateScriptInternal(source_code, mute_errors).ToLocal(&result)) {
+ if (!try_catch.HasCaught()) {
+ LOG(WARNING) << "Script evaluation failed with no JavaScript exception.";
+ return false;
+ }
if (out_result_utf8) {
*out_result_utf8 = ExceptionToString(try_catch);
}
@@ -153,38 +137,18 @@
const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
base::optional<ValueHandleHolder::Reference>* out_value_handle) {
TRACK_MEMORY_SCOPE("Javascript");
+ TRACE_EVENT0("cobalt::script", "V8cGlobalEnvironment::EvaluateScript()");
DCHECK(thread_checker_.CalledOnValidThread());
EntryScope entry_scope(isolate_);
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
-
- V8cSourceCode* v8c_source_code =
- base::polymorphic_downcast<V8cSourceCode*>(source_code.get());
- const base::SourceLocation& source_location = v8c_source_code->location();
-
v8::TryCatch try_catch(isolate_);
- v8::ScriptOrigin script_origin(
- v8::String::NewFromUtf8(isolate_, source_location.file_path.c_str(),
- v8::NewStringType::kNormal)
- .ToLocalChecked(),
- v8::Integer::New(isolate_, source_location.line_number),
- v8::Integer::New(isolate_, source_location.column_number),
- v8::Boolean::New(isolate_, !mute_errors));
- v8::Local<v8::String> source =
- v8::String::NewFromUtf8(isolate_, v8c_source_code->source_utf8().c_str(),
- v8::NewStringType::kNormal)
- .ToLocalChecked();
- v8::MaybeLocal<v8::Script> maybe_script =
- v8::Script::Compile(context, source, &script_origin);
- v8::Local<v8::Script> script;
- if (!maybe_script.ToLocal(&script)) {
- return false;
- }
-
- v8::MaybeLocal<v8::Value> maybe_result = script->Run(context);
v8::Local<v8::Value> result;
- if (!maybe_result.ToLocal(&result)) {
+ if (!EvaluateScriptInternal(source_code, mute_errors).ToLocal(&result)) {
+ if (!try_catch.HasCaught()) {
+ LOG(WARNING) << "Script evaluation failed with no JavaScript exception.";
+ }
return false;
}
@@ -197,11 +161,20 @@
}
std::vector<StackFrame> V8cGlobalEnvironment::GetStackTrace(int max_frames) {
+ TRACE_EVENT0("cobalt::script", "V8cGlobalEnvironment::GetStackTrace()");
DCHECK(thread_checker_.CalledOnValidThread());
+
+ // cobalt::script treats |max_frames| being set to 0 as "the entire stack",
+ // while V8 interprets the frame count being set to 0 as "give me 0 frames",
+ // so we have to translate between the two.
+ const int kV8CallMaxFrameAmount = 4096;
+ int v8_max_frames = (max_frames == 0) ? kV8CallMaxFrameAmount : max_frames;
+
v8::HandleScope handle_scope(isolate_);
- std::vector<StackFrame> result;
v8::Local<v8::StackTrace> stack_trace =
- v8::StackTrace::CurrentStackTrace(isolate_, max_frames);
+ v8::StackTrace::CurrentStackTrace(isolate_, v8_max_frames);
+
+ std::vector<StackFrame> result;
for (int i = 0; i < stack_trace->GetFrameCount(); i++) {
v8::Local<v8::StackFrame> stack_frame = stack_trace->GetFrame(i);
result.emplace_back(
@@ -209,6 +182,7 @@
*v8::String::Utf8Value(isolate_, stack_frame->GetFunctionName()),
*v8::String::Utf8Value(isolate_, stack_frame->GetScriptName()));
}
+
return result;
}
@@ -277,6 +251,7 @@
void V8cGlobalEnvironment::Bind(const std::string& identifier,
const scoped_refptr<Wrappable>& impl) {
+ TRACE_EVENT0("cobalt::script", "V8cGlobalEnvironment::Bind()");
TRACK_MEMORY_SCOPE("Javascript");
DCHECK(impl);
@@ -300,12 +275,94 @@
return script_value_factory_;
}
+v8::MaybeLocal<v8::Value> V8cGlobalEnvironment::EvaluateScriptInternal(
+ const scoped_refptr<SourceCode>& source_code, bool mute_errors) {
+ TRACK_MEMORY_SCOPE("Javascript");
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Note that we expect an |EntryScope| and |v8::TryCatch| to have been set
+ // up by our caller.
+ V8cSourceCode* v8c_source_code =
+ base::polymorphic_downcast<V8cSourceCode*>(source_code.get());
+ const base::SourceLocation& source_location = v8c_source_code->location();
+
+ v8::Local<v8::String> resource_name;
+ if (!v8::String::NewFromUtf8(isolate_, source_location.file_path.c_str(),
+ v8::NewStringType::kNormal)
+ .ToLocal(&resource_name)) {
+ // Technically possible, but whoa man should this never happen.
+ LOG(WARNING) << "Failed to convert source location file path \""
+ << source_location.file_path << "\" to a V8 UTF-8 string.";
+ return {};
+ }
+
+ // Note that |v8::ScriptOrigin| offsets are 0-based, whereas
+ // |SourceLocation| line/column numbers are 1-based, so subtract 1 to
+ // translate between the two.
+ v8::ScriptOrigin script_origin(
+ /*resource_name=*/resource_name,
+ /*resource_line_offset=*/
+ v8::Integer::New(isolate_, source_location.line_number - 1),
+ /*resource_column_offset=*/
+ v8::Integer::New(isolate_, source_location.column_number - 1),
+ /*resource_is_shared_cross_origin=*/
+ v8::Boolean::New(isolate_, !mute_errors));
+
+ v8::Local<v8::String> source;
+ if (!v8::String::NewFromUtf8(isolate_, v8c_source_code->source_utf8().c_str(),
+ v8::NewStringType::kNormal)
+ .ToLocal(&source)) {
+ LOG(WARNING) << "Failed to convert source code to V8 UTF-8 string.";
+ return {};
+ }
+
+ v8::Local<v8::Context> context = isolate_->GetCurrentContext();
+ v8::Local<v8::Script> script;
+ if (!v8::Script::Compile(context, source, &script_origin).ToLocal(&script)) {
+ LOG(WARNING) << "Failed to compile script.";
+ return {};
+ }
+
+ v8::Local<v8::Value> result;
+ if (!script->Run(context).ToLocal(&result)) {
+ LOG(WARNING) << "Failed to run script.";
+ return {};
+ }
+
+ return result;
+}
+
void V8cGlobalEnvironment::EvaluateAutomatics() {
+ TRACE_EVENT0("cobalt::script", "V8cGlobalEnvironment::EvaluateAutomatics()");
// TODO: Maybe add fetch and stream polyfills. Investigate what V8 has to
// natively offer first.
NOTIMPLEMENTED();
}
+bool V8cGlobalEnvironment::HasInterfaceData(int key) const {
+ DCHECK_GE(key, 0);
+ if (key >= cached_interface_data_.size()) {
+ return false;
+ }
+ return !cached_interface_data_[key].IsEmpty();
+}
+
+v8::Local<v8::FunctionTemplate> V8cGlobalEnvironment::GetInterfaceData(
+ int key) const {
+ DCHECK(HasInterfaceData(key));
+ return cached_interface_data_[key].Get(isolate_);
+}
+
+void V8cGlobalEnvironment::AddInterfaceData(
+ int key, v8::Local<v8::FunctionTemplate> function_template) {
+ DCHECK(!HasInterfaceData(key));
+ if (key >= cached_interface_data_.size()) {
+ cached_interface_data_.resize(key + 1);
+ }
+ DCHECK(!HasInterfaceData(key));
+ cached_interface_data_[key].Set(isolate_, function_template);
+}
+
} // namespace v8c
} // namespace script
} // namespace cobalt
diff --git a/src/cobalt/script/v8c/v8c_global_environment.h b/src/cobalt/script/v8c/v8c_global_environment.h
index 0f12324..6428f79 100644
--- a/src/cobalt/script/v8c/v8c_global_environment.h
+++ b/src/cobalt/script/v8c/v8c_global_environment.h
@@ -27,7 +27,6 @@
#include "base/threading/thread_checker.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/javascript_engine.h"
-#include "cobalt/script/v8c/interface_data.h"
#include "cobalt/script/v8c/v8c_heap_tracer.h"
#include "cobalt/script/v8c/wrapper_factory.h"
#include "v8/include/libplatform/libplatform.h"
@@ -94,21 +93,23 @@
ScriptValueFactory* script_value_factory() override;
- // Evaluates any automatically included Javascript for the environment.
- void EvaluateAutomatics();
-
v8::Isolate* isolate() const { return isolate_; }
v8::Local<v8::Context> context() const {
return v8::Local<v8::Context>::New(isolate_, context_);
}
- InterfaceData* GetInterfaceData(int key) {
- DCHECK_GE(key, 0);
- if (key >= cached_interface_data_.size()) {
- cached_interface_data_.resize(key + 1);
- }
- return &cached_interface_data_[key];
- }
+ // Check whether we have interface data loaded for interface key |key|.
+ bool HasInterfaceData(int key) const;
+
+ // Get interface data for |key|. Attempting to get interface data for a key
+ // that does not have any is a usage error. Check |HasInterfaceData| first.
+ v8::Local<v8::FunctionTemplate> GetInterfaceData(int key) const;
+
+ // Register interface data (which is just |function_template|) for key
+ // |key|. Attempting to add interface data for a key that already has
+ // interface data is a usage error.
+ void AddInterfaceData(int key,
+ v8::Local<v8::FunctionTemplate> function_template);
WrapperFactory* wrapper_factory() { return wrapper_factory_.get(); }
@@ -143,6 +144,12 @@
int count;
};
+ v8::MaybeLocal<v8::Value> EvaluateScriptInternal(
+ const scoped_refptr<SourceCode>& source_code, bool mute_errors);
+
+ // Evaluates any automatically included Javascript for the environment.
+ void EvaluateAutomatics();
+
// Where we store ourselves as embedder private data in our corresponding
// |v8::Isolate|.
static const int kIsolateDataIndex = 1;
@@ -155,7 +162,10 @@
v8::Global<v8::Object> global_object_;
scoped_ptr<WrapperFactory> wrapper_factory_;
- std::vector<InterfaceData> cached_interface_data_;
+ // Data that is cached on a per-interface basis. Note that we can get to
+ // everything (the function instance, the prototype template, and the
+ // instance template) from just the function template.
+ std::vector<v8::Eternal<v8::FunctionTemplate>> cached_interface_data_;
// TODO: Should be scoped_ptr, fix headers/sources template mess.
V8cScriptValueFactory* script_value_factory_;
diff --git a/src/cobalt/script/v8c/v8c_heap_tracer.cc b/src/cobalt/script/v8c/v8c_heap_tracer.cc
index 8bf7f91..0c19377 100644
--- a/src/cobalt/script/v8c/v8c_heap_tracer.cc
+++ b/src/cobalt/script/v8c/v8c_heap_tracer.cc
@@ -28,9 +28,11 @@
WrapperPrivate* wrapper_private =
static_cast<WrapperPrivate*>(embedder_field.first);
wrapper_private->Mark();
+
Wrappable* wrappable = wrapper_private->raw_wrappable();
- frontier_.push_back(wrappable);
- visited_.insert(wrappable);
+ if (visited_.insert(wrappable).second) {
+ frontier_.push_back(wrappable);
+ }
// We expect this field to always be null, since we only have it as a
// workaround for V8. See "wrapper_private.h" for details.
diff --git a/src/cobalt/script/v8c/v8c_heap_tracer.h b/src/cobalt/script/v8c/v8c_heap_tracer.h
index 0fc1a41..e081277 100644
--- a/src/cobalt/script/v8c/v8c_heap_tracer.h
+++ b/src/cobalt/script/v8c/v8c_heap_tracer.h
@@ -57,7 +57,7 @@
private:
v8::Isolate* const isolate_;
- v8::Platform* platform_ = GetPlatform();
+ v8::Platform* const platform_ = GetPlatform();
std::vector<Traceable*> frontier_;
std::unordered_set<Traceable*> visited_;
};
diff --git a/src/cobalt/script/v8c/v8c_user_object_holder.h b/src/cobalt/script/v8c/v8c_user_object_holder.h
index 8e54923..29d6e33 100644
--- a/src/cobalt/script/v8c/v8c_user_object_holder.h
+++ b/src/cobalt/script/v8c/v8c_user_object_holder.h
@@ -38,22 +38,53 @@
public:
typedef ScriptValue<typename V8cUserObjectType::BaseType> BaseClass;
- V8cUserObjectHolder()
- : isolate_(nullptr), prevent_garbage_collection_count_(0) {}
-
+ V8cUserObjectHolder() = default;
V8cUserObjectHolder(v8::Isolate* isolate, v8::Local<v8::Value> value)
: isolate_(isolate),
handle_(isolate, value),
prevent_garbage_collection_count_(0) {
handle_.SetWeak();
}
-
- V8cUserObjectHolder& operator=(const V8cUserObjectHolder& other) {
+ V8cUserObjectHolder(const V8cUserObjectHolder&) = delete;
+ V8cUserObjectHolder& operator=(const V8cUserObjectHolder&) = delete;
+ V8cUserObjectHolder(V8cUserObjectHolder&& other)
+ : isolate_(other.isolate_),
+ handle_(other.isolate_, other.v8_value()),
+ prevent_garbage_collection_count_(
+ other.prevent_garbage_collection_count_) {
+ if (prevent_garbage_collection_count_ == 0) {
+ handle_.SetWeak();
+ }
+ other.isolate_ = nullptr;
+ other.handle_.Clear();
+ other.prevent_garbage_collection_count_ = 0;
+ }
+ V8cUserObjectHolder& operator=(V8cUserObjectHolder&& other) {
isolate_ = other.isolate_;
handle_.Set(isolate_, other.v8_value());
+ prevent_garbage_collection_count_ = other.prevent_garbage_collection_count_;
+ if (prevent_garbage_collection_count_ == 0) {
+ handle_.SetWeak();
+ }
+ other.isolate_ = nullptr;
+ other.handle_.Clear();
+ other.prevent_garbage_collection_count_ = 0;
return *this;
}
+ bool EqualTo(const BaseClass& other) const override {
+ v8::HandleScope handle_scope(isolate_);
+ const V8cUserObjectHolder* v8c_other =
+ base::polymorphic_downcast<const V8cUserObjectHolder*>(&other);
+ return v8_value() == v8c_other->v8_value();
+ }
+
+ void TraceMembers(Tracer* tracer) override {
+ if (!handle_.IsEmpty()) {
+ handle_.Get().RegisterExternalReference(isolate_);
+ }
+ }
+
void RegisterOwner(Wrappable* owner) override {
V8cGlobalEnvironment* global_environment =
V8cGlobalEnvironment::GetFromIsolate(isolate_);
@@ -90,29 +121,22 @@
}
}
+ const typename V8cUserObjectType::BaseType* GetScriptValue() const override {
+ return handle_.IsEmpty() ? nullptr : &handle_;
+ }
+
scoped_ptr<BaseClass> MakeCopy() const override {
v8::HandleScope handle_scope(isolate_);
return make_scoped_ptr<BaseClass>(
new V8cUserObjectHolder(isolate_, v8_value()));
}
- bool EqualTo(const BaseClass& other) const override {
- v8::HandleScope handle_scope(isolate_);
- const V8cUserObjectHolder* v8c_other =
- base::polymorphic_downcast<const V8cUserObjectHolder*>(&other);
- return v8_value() == v8c_other->v8_value();
- }
-
- const typename V8cUserObjectType::BaseType* GetScriptValue() const override {
- return handle_.IsEmpty() ? nullptr : &handle_;
- }
-
v8::Local<v8::Value> v8_value() const { return handle_.NewLocal(isolate_); }
private:
- v8::Isolate* isolate_;
- V8cUserObjectType handle_;
- int prevent_garbage_collection_count_;
+ v8::Isolate* isolate_ = nullptr;
+ V8cUserObjectType handle_{};
+ int prevent_garbage_collection_count_ = 0;
};
} // namespace v8c
diff --git a/src/cobalt/script/v8c/wrapper_factory.cc b/src/cobalt/script/v8c/wrapper_factory.cc
index 3af19cf..45e7de6 100644
--- a/src/cobalt/script/v8c/wrapper_factory.cc
+++ b/src/cobalt/script/v8c/wrapper_factory.cc
@@ -29,12 +29,11 @@
void WrapperFactory::RegisterWrappableType(
base::TypeId wrappable_type, const CreateWrapperFunction& create_function,
- const PrototypeClassFunction& class_function) {
- std::pair<WrappableTypeFunctionsHashMap::iterator, bool> pib =
- wrappable_type_functions_.insert(std::make_pair(
- wrappable_type,
- WrappableTypeFunctions(create_function, class_function)));
- DCHECK(pib.second)
+ const GetFunctionTemplate& get_function_template) {
+ auto insert_pair = wrappable_type_functions_.insert(std::make_pair(
+ wrappable_type,
+ WrappableTypeFunctions(create_function, get_function_template)));
+ DCHECK(insert_pair.second)
<< "RegisterWrappableType registered for type more than once.";
}
@@ -61,8 +60,7 @@
scoped_ptr<Wrappable::WeakWrapperHandle> WrapperFactory::CreateWrapper(
const scoped_refptr<Wrappable>& wrappable) const {
- WrappableTypeFunctionsHashMap::const_iterator it =
- wrappable_type_functions_.find(wrappable->GetWrappableType());
+ auto it = wrappable_type_functions_.find(wrappable->GetWrappableType());
if (it == wrappable_type_functions_.end()) {
NOTREACHED();
return scoped_ptr<Wrappable::WeakWrapperHandle>();
@@ -78,7 +76,7 @@
bool WrapperFactory::DoesObjectImplementInterface(v8::Local<v8::Object> object,
base::TypeId type_id) const {
- // If the object doesn't have a wrapper private which means it is not a
+ // If the object doesn't have a wrapper private, then that means it is not a
// platform object, so the object doesn't implement the interface.
if (!WrapperPrivate::HasWrapperPrivate(object)) {
return false;
@@ -88,7 +86,7 @@
DCHECK(it != wrappable_type_functions_.end());
v8::Local<v8::FunctionTemplate> function_template =
- it->second.prototype_class.Run(isolate_);
+ it->second.get_function_template.Run(isolate_);
return function_template->HasInstance(object);
}
diff --git a/src/cobalt/script/v8c/wrapper_factory.h b/src/cobalt/script/v8c/wrapper_factory.h
index 7991b05..4910bbc 100644
--- a/src/cobalt/script/v8c/wrapper_factory.h
+++ b/src/cobalt/script/v8c/wrapper_factory.h
@@ -35,15 +35,15 @@
const scoped_refptr<Wrappable>&)>
CreateWrapperFunction;
- // Callback to get v8::FunctionTemplate of prototype.
+ // Callback to get v8::FunctionTemplate of an interface.
typedef base::Callback<v8::Local<v8::FunctionTemplate>(v8::Isolate*)>
- PrototypeClassFunction;
+ GetFunctionTemplate;
explicit WrapperFactory(v8::Isolate* isolate) : isolate_(isolate) {}
void RegisterWrappableType(base::TypeId wrappable_type,
const CreateWrapperFunction& create_function,
- const PrototypeClassFunction& class_function);
+ const GetFunctionTemplate& class_function);
v8::Local<v8::Object> GetWrapper(const scoped_refptr<Wrappable>& wrappable);
@@ -57,10 +57,11 @@
private:
struct WrappableTypeFunctions {
CreateWrapperFunction create_wrapper;
- PrototypeClassFunction prototype_class;
+ GetFunctionTemplate get_function_template;
WrappableTypeFunctions(const CreateWrapperFunction& create_wrapper,
- const PrototypeClassFunction& prototype_class)
- : create_wrapper(create_wrapper), prototype_class(prototype_class) {}
+ const GetFunctionTemplate& get_function_template)
+ : create_wrapper(create_wrapper),
+ get_function_template(get_function_template) {}
};
scoped_ptr<Wrappable::WeakWrapperHandle> CreateWrapper(
diff --git a/src/cobalt/script/v8c/wrapper_private.h b/src/cobalt/script/v8c/wrapper_private.h
index f7203b0..646213c 100644
--- a/src/cobalt/script/v8c/wrapper_private.h
+++ b/src/cobalt/script/v8c/wrapper_private.h
@@ -33,7 +33,6 @@
// The callback that V8 will run when the |v8::Object| that we live inside
// of dies.
static void Callback(const v8::WeakCallbackInfo<WrapperPrivate>& data) {
- data.GetParameter()->wrapper_.Reset();
delete data.GetParameter();
}
@@ -50,6 +49,9 @@
return object->InternalFieldCount() == kInternalFieldCount;
}
+ // The total amount of internal fields in |wrapper_| we use. See
+ // |kInternalFieldDataIndex| and |kInternalFieldDummyIndex| below for
+ // further information.
static const int kInternalFieldCount = 2;
WrapperPrivate() = delete;
@@ -63,6 +65,11 @@
wrapper_.SetWeak(this, &WrapperPrivate::Callback,
v8::WeakCallbackType::kParameter);
}
+ ~WrapperPrivate() {
+ DCHECK(wrapper_.IsNearDeath());
+ wrapper_.ClearWeak();
+ wrapper_.Reset();
+ }
// Mark |wrapper_| as reachable from other |Traceable|s. This will be
// called by |V8cHeapTracer| during tracing.
diff --git a/src/cobalt/tools/automated_testing/c_val_names.py b/src/cobalt/tools/automated_testing/c_val_names.py
index 2400cfd..226ee9a 100644
--- a/src/cobalt/tools/automated_testing/c_val_names.py
+++ b/src/cobalt/tools/automated_testing/c_val_names.py
@@ -49,6 +49,10 @@
return 'Count.Renderer.Rasterize.NewRenderTree'
+def count_version_compatibility_violation():
+ return 'Count.VersionCompatibilityViolation'
+
+
def event_duration_dom_video_start_delay():
return 'Event.Duration.MainWebModule.DOM.VideoStartDelay'
@@ -67,10 +71,14 @@
return 'Event.MainWebModule.{}.ValueDictionary'.format(event_type)
-def layout_is_render_tree_pending():
+def is_render_tree_generation_pending():
return 'MainWebModule.Layout.IsRenderTreePending'
+def is_render_tree_rasterization_pending():
+ return 'MainWebModule.IsRenderTreeRasterizationPending'
+
+
def memory_font_cache_resource_loaded():
return 'Memory.MainWebModule.RemoteTypefaceCache.Resource.Loaded'
diff --git a/src/cobalt/tools/automated_testing/cobalt_test.py b/src/cobalt/tools/automated_testing/cobalt_test.py
index e573d54..f135f30 100644
--- a/src/cobalt/tools/automated_testing/cobalt_test.py
+++ b/src/cobalt/tools/automated_testing/cobalt_test.py
@@ -227,7 +227,8 @@
def is_processing(self, check_animations):
"""Checks to see if Cobalt is currently processing."""
return (self.get_cval(c_val_names.count_dom_active_java_script_events()) or
- self.get_cval(c_val_names.layout_is_render_tree_pending()) or
+ self.get_cval(c_val_names.is_render_tree_generation_pending()) or
+ self.get_cval(c_val_names.is_render_tree_rasterization_pending()) or
(check_animations and
self.get_cval(c_val_names.renderer_has_active_animations())) or
self.get_cval(c_val_names.count_image_cache_resource_loading()))
diff --git a/src/cobalt/trace_event/scoped_trace_to_file.h b/src/cobalt/trace_event/scoped_trace_to_file.h
index 8c2b2f5..32ba2ce 100644
--- a/src/cobalt/trace_event/scoped_trace_to_file.h
+++ b/src/cobalt/trace_event/scoped_trace_to_file.h
@@ -33,6 +33,8 @@
explicit ScopedTraceToFile(const FilePath& output_path_relative_to_logs);
~ScopedTraceToFile();
+ const FilePath& absolute_output_path() const { return absolute_output_path_; }
+
private:
FilePath absolute_output_path_;
};
diff --git a/src/starboard/CHANGELOG.md b/src/starboard/CHANGELOG.md
index 6baf5a2..d30a2c0 100644
--- a/src/starboard/CHANGELOG.md
+++ b/src/starboard/CHANGELOG.md
@@ -8,6 +8,13 @@
**NOTE: Starboard versions 3 and below are no longer supported.**
+## Version 10
+
+### Moved `tizen` to `contrib/tizen`.
+
+Please see [contrib/README.md](contrib/README.md) for description of
+expectations for contents in this directory.
+
## Version 9
### Add string label to `SbMicrophoneInfo`.
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index 9e5f2d6..3b3da18 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -71,6 +71,9 @@
// Minimum API version for supporting system-level closed caption settings.
#define SB_ACCESSIBILITY_CAPTIONS_API_VERSION SB_EXPERIMENTAL_API_VERSION
+// Minimum API version for supporting audioless video playback.
+#define SB_AUDIOLESS_VIDEO_API_VERSION SB_EXPERIMENTAL_API_VERSION
+
// --- Release Candidate Feature Defines -------------------------------------
// --- Common Detected Features ----------------------------------------------
diff --git a/src/starboard/contrib/README.md b/src/starboard/contrib/README.md
new file mode 100644
index 0000000..fe405cc
--- /dev/null
+++ b/src/starboard/contrib/README.md
@@ -0,0 +1,10 @@
+# The starboard/contrib directroy
+
+Contents of this directory have been contributed by the community, but
+have not been fully integrated into the Google-managed internal continuous
+integration system.
+
+Therefore, while ports in this directory have compiled and worked correctly
+in the past, they may require some maintenence to work with the current
+release of Cobalt.
+
diff --git a/src/starboard/contrib/__init__.py b/src/starboard/contrib/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/starboard/contrib/__init__.py
@@ -0,0 +1 @@
+
diff --git a/src/starboard/contrib/_env.py b/src/starboard/contrib/_env.py
new file mode 100644
index 0000000..f697920
--- /dev/null
+++ b/src/starboard/contrib/_env.py
@@ -0,0 +1,26 @@
+#
+# Copyright 2018 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Ask the parent directory to load the project environment."""
+
+from imp import load_source
+from os import path
+import sys
+
+_ENV = path.abspath(path.join(path.dirname(__file__), path.pardir, '_env.py'))
+if not path.exists(_ENV):
+ print '%s: Can\'t find repo root.\nMissing parent: %s' % (__file__, _ENV)
+ sys.exit(1)
+load_source('', _ENV)
diff --git a/src/starboard/creator/README.md b/src/starboard/contrib/creator/README.md
similarity index 100%
rename from src/starboard/creator/README.md
rename to src/starboard/contrib/creator/README.md
diff --git a/src/starboard/creator/__init__.py b/src/starboard/contrib/creator/__init__.py
similarity index 100%
rename from src/starboard/creator/__init__.py
rename to src/starboard/contrib/creator/__init__.py
diff --git a/src/starboard/contrib/creator/_env.py b/src/starboard/contrib/creator/_env.py
new file mode 100644
index 0000000..6188bb7
--- /dev/null
+++ b/src/starboard/contrib/creator/_env.py
@@ -0,0 +1,26 @@
+#
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Ask the parent directory to load the project environment."""
+
+from imp import load_source
+from os import path
+import sys
+
+_ENV = path.abspath(path.join(path.dirname(__file__), path.pardir, '_env.py'))
+if not path.exists(_ENV):
+ print '%s: Can\'t find repo root.\nMissing parent: %s' % (__file__, _ENV)
+ sys.exit(1)
+load_source('', _ENV)
diff --git a/src/starboard/creator/__init__.py b/src/starboard/contrib/creator/ci20x11/__init__.py
similarity index 100%
copy from src/starboard/creator/__init__.py
copy to src/starboard/contrib/creator/ci20x11/__init__.py
diff --git a/src/starboard/contrib/creator/ci20x11/_env.py b/src/starboard/contrib/creator/ci20x11/_env.py
new file mode 100644
index 0000000..6188bb7
--- /dev/null
+++ b/src/starboard/contrib/creator/ci20x11/_env.py
@@ -0,0 +1,26 @@
+#
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Ask the parent directory to load the project environment."""
+
+from imp import load_source
+from os import path
+import sys
+
+_ENV = path.abspath(path.join(path.dirname(__file__), path.pardir, '_env.py'))
+if not path.exists(_ENV):
+ print '%s: Can\'t find repo root.\nMissing parent: %s' % (__file__, _ENV)
+ sys.exit(1)
+load_source('', _ENV)
diff --git a/src/starboard/creator/ci20x11/gcc/4.9/atomic_public.h b/src/starboard/contrib/creator/ci20x11/atomic_public.h
similarity index 78%
rename from src/starboard/creator/ci20x11/gcc/4.9/atomic_public.h
rename to src/starboard/contrib/creator/ci20x11/atomic_public.h
index 547cf9a..db75dc1 100644
--- a/src/starboard/creator/ci20x11/gcc/4.9/atomic_public.h
+++ b/src/starboard/contrib/creator/ci20x11/atomic_public.h
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_CREATOR_CI20X11_GCC_4_9_ATOMIC_PUBLIC_H_
-#define STARBOARD_CREATOR_CI20X11_GCC_4_9_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_CONTRIB_CREATOR_CI20X11_ATOMIC_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_CI20X11_ATOMIC_PUBLIC_H_
#include "starboard/linux/shared/atomic_public.h"
-#endif // STARBOARD_CREATOR_CI20X11_GCC_4_9_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_CONTRIB_CREATOR_CI20X11_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/creator/ci20x11/gcc/4.9/configuration_public.h b/src/starboard/contrib/creator/ci20x11/configuration_public.h
similarity index 70%
rename from src/starboard/creator/ci20x11/gcc/4.9/configuration_public.h
rename to src/starboard/contrib/creator/ci20x11/configuration_public.h
index e47392a..d5b6080 100644
--- a/src/starboard/creator/ci20x11/gcc/4.9/configuration_public.h
+++ b/src/starboard/contrib/creator/ci20x11/configuration_public.h
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_CREATOR_CI20X11_GCC_4_9_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_CREATOR_CI20X11_GCC_4_9_CONFIGURATION_PUBLIC_H_
+#ifndef STARBOARD_CONTRIB_CREATOR_CI20X11_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_CI20X11_CONFIGURATION_PUBLIC_H_
-#include "starboard/creator/shared/configuration_public.h"
+#include "starboard/contrib/creator/shared/configuration_public.h"
-#endif // STARBOARD_CREATOR_CI20X11_GCC_4_9_CONFIGURATION_PUBLIC_H_
+#endif // STARBOARD_CONTRIB_CREATOR_CI20X11_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/creator/ci20x11/gcc/4.9/atomic_public.h b/src/starboard/contrib/creator/ci20x11/gcc/4.9/atomic_public.h
similarity index 76%
copy from src/starboard/creator/ci20x11/gcc/4.9/atomic_public.h
copy to src/starboard/contrib/creator/ci20x11/gcc/4.9/atomic_public.h
index 547cf9a..05a42e8 100644
--- a/src/starboard/creator/ci20x11/gcc/4.9/atomic_public.h
+++ b/src/starboard/contrib/creator/ci20x11/gcc/4.9/atomic_public.h
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_CREATOR_CI20X11_GCC_4_9_ATOMIC_PUBLIC_H_
-#define STARBOARD_CREATOR_CI20X11_GCC_4_9_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_CONTRIB_CREATOR_CI20X11_GCC_4_9_ATOMIC_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_CI20X11_GCC_4_9_ATOMIC_PUBLIC_H_
#include "starboard/linux/shared/atomic_public.h"
-#endif // STARBOARD_CREATOR_CI20X11_GCC_4_9_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_CONTRIB_CREATOR_CI20X11_GCC_4_9_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/creator/ci20x11/gcc/4.9/compiler_flags.gypi b/src/starboard/contrib/creator/ci20x11/gcc/4.9/compiler_flags.gypi
similarity index 100%
rename from src/starboard/creator/ci20x11/gcc/4.9/compiler_flags.gypi
rename to src/starboard/contrib/creator/ci20x11/gcc/4.9/compiler_flags.gypi
diff --git a/src/starboard/creator/ci20x11/thread_types_public.h b/src/starboard/contrib/creator/ci20x11/gcc/4.9/configuration_public.h
similarity index 67%
copy from src/starboard/creator/ci20x11/thread_types_public.h
copy to src/starboard/contrib/creator/ci20x11/gcc/4.9/configuration_public.h
index 7437a70..e9d4416 100644
--- a/src/starboard/creator/ci20x11/thread_types_public.h
+++ b/src/starboard/contrib/creator/ci20x11/gcc/4.9/configuration_public.h
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
+#ifndef STARBOARD_CONTRIB_CREATOR_CI20X11_GCC_4_9_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_CI20X11_GCC_4_9_CONFIGURATION_PUBLIC_H_
-#include "starboard/linux/shared/thread_types_public.h"
+#include "starboard/contrib/creator/shared/configuration_public.h"
-#endif // STARBOARD_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
+#endif // STARBOARD_CONTRIB_CREATOR_CI20X11_GCC_4_9_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/creator/ci20x11/gcc/4.9/gyp_configuration.gypi b/src/starboard/contrib/creator/ci20x11/gcc/4.9/gyp_configuration.gypi
similarity index 100%
rename from src/starboard/creator/ci20x11/gcc/4.9/gyp_configuration.gypi
rename to src/starboard/contrib/creator/ci20x11/gcc/4.9/gyp_configuration.gypi
diff --git a/src/starboard/creator/ci20x11/gcc/4.9/gyp_configuration.py b/src/starboard/contrib/creator/ci20x11/gcc/4.9/gyp_configuration.py
similarity index 98%
rename from src/starboard/creator/ci20x11/gcc/4.9/gyp_configuration.py
rename to src/starboard/contrib/creator/ci20x11/gcc/4.9/gyp_configuration.py
index f180c32..e20b9f7 100644
--- a/src/starboard/creator/ci20x11/gcc/4.9/gyp_configuration.py
+++ b/src/starboard/contrib/creator/ci20x11/gcc/4.9/gyp_configuration.py
@@ -20,7 +20,7 @@
# pylint: disable=import-self,g-import-not-at-top
import gyp_utils
# Import the shared Linux platform configuration.
-from starboard.creator.shared import gyp_configuration
+from starboard.contrib.creator.shared import gyp_configuration
from starboard.tools.testing import test_filter
class PlatformConfig(gyp_configuration.PlatformConfig):
diff --git a/src/starboard/creator/ci20x11/gcc/4.9/starboard_platform.gyp b/src/starboard/contrib/creator/ci20x11/gcc/4.9/starboard_platform.gyp
similarity index 100%
rename from src/starboard/creator/ci20x11/gcc/4.9/starboard_platform.gyp
rename to src/starboard/contrib/creator/ci20x11/gcc/4.9/starboard_platform.gyp
diff --git a/src/starboard/creator/ci20x11/gcc/4.9/thread_types_public.h b/src/starboard/contrib/creator/ci20x11/gcc/4.9/thread_types_public.h
similarity index 75%
rename from src/starboard/creator/ci20x11/gcc/4.9/thread_types_public.h
rename to src/starboard/contrib/creator/ci20x11/gcc/4.9/thread_types_public.h
index 34bd624..b442fe0 100644
--- a/src/starboard/creator/ci20x11/gcc/4.9/thread_types_public.h
+++ b/src/starboard/contrib/creator/ci20x11/gcc/4.9/thread_types_public.h
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_CREATOR_CI20X11_GCC_4_9_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_CREATOR_CI20X11_GCC_4_9_THREAD_TYPES_PUBLIC_H_
+#ifndef STARBOARD_CONTRIB_CREATOR_CI20X11_GCC_4_9_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_CI20X11_GCC_4_9_THREAD_TYPES_PUBLIC_H_
#include "starboard/linux/shared/thread_types_public.h"
-#endif // STARBOARD_CREATOR_CI20X11_GCC_4_9_THREAD_TYPES_PUBLIC_H_
+#endif // STARBOARD_CONTRIB_CREATOR_CI20X11_GCC_4_9_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/creator/ci20x11/gcc/gyp_configuration.gypi b/src/starboard/contrib/creator/ci20x11/gcc/gyp_configuration.gypi
similarity index 100%
rename from src/starboard/creator/ci20x11/gcc/gyp_configuration.gypi
rename to src/starboard/contrib/creator/ci20x11/gcc/gyp_configuration.gypi
diff --git a/src/starboard/creator/ci20x11/gcc/starboard_platform.gyp b/src/starboard/contrib/creator/ci20x11/gcc/starboard_platform.gyp
similarity index 100%
rename from src/starboard/creator/ci20x11/gcc/starboard_platform.gyp
rename to src/starboard/contrib/creator/ci20x11/gcc/starboard_platform.gyp
diff --git a/src/starboard/creator/ci20x11/gyp_configuration.gypi b/src/starboard/contrib/creator/ci20x11/gyp_configuration.gypi
similarity index 100%
rename from src/starboard/creator/ci20x11/gyp_configuration.gypi
rename to src/starboard/contrib/creator/ci20x11/gyp_configuration.gypi
diff --git a/src/starboard/creator/ci20x11/gyp_configuration.py b/src/starboard/contrib/creator/ci20x11/gyp_configuration.py
similarity index 96%
rename from src/starboard/creator/ci20x11/gyp_configuration.py
rename to src/starboard/contrib/creator/ci20x11/gyp_configuration.py
index 3d62ed8..09351b4 100644
--- a/src/starboard/creator/ci20x11/gyp_configuration.py
+++ b/src/starboard/contrib/creator/ci20x11/gyp_configuration.py
@@ -17,8 +17,9 @@
import os
import sys
+import _env # pylint: disable=unused-import
# Import the shared Creator platform configuration.
-from starboard.creator.shared import gyp_configuration
+from starboard.contrib.creator.shared import gyp_configuration
from starboard.tools.testing import test_filter
class PlatformConfig(gyp_configuration.PlatformConfig):
diff --git a/src/starboard/creator/ci20x11/libraries.gypi b/src/starboard/contrib/creator/ci20x11/libraries.gypi
similarity index 100%
rename from src/starboard/creator/ci20x11/libraries.gypi
rename to src/starboard/contrib/creator/ci20x11/libraries.gypi
diff --git a/src/starboard/creator/ci20x11/main.cc b/src/starboard/contrib/creator/ci20x11/main.cc
similarity index 100%
rename from src/starboard/creator/ci20x11/main.cc
rename to src/starboard/contrib/creator/ci20x11/main.cc
diff --git a/src/starboard/creator/ci20x11/starboard_platform.gyp b/src/starboard/contrib/creator/ci20x11/starboard_platform.gyp
similarity index 98%
rename from src/starboard/creator/ci20x11/starboard_platform.gyp
rename to src/starboard/contrib/creator/ci20x11/starboard_platform.gyp
index c1e7eb0..3ae1a09 100644
--- a/src/starboard/creator/ci20x11/starboard_platform.gyp
+++ b/src/starboard/contrib/creator/ci20x11/starboard_platform.gyp
@@ -25,11 +25,11 @@
'target_name': 'starboard_platform',
'type': 'static_library',
'sources': [
- '<(DEPTH)/starboard/creator/ci20x11/atomic_public.h',
- '<(DEPTH)/starboard/creator/ci20x11/configuration_public.h',
- '<(DEPTH)/starboard/creator/ci20x11/main.cc',
- '<(DEPTH)/starboard/creator/ci20x11/system_get_property.cc',
- '<(DEPTH)/starboard/creator/shared/player_components_impl.cc',
+ '<(DEPTH)/starboard/contrib/creator/ci20x11/atomic_public.h',
+ '<(DEPTH)/starboard/contrib/creator/ci20x11/configuration_public.h',
+ '<(DEPTH)/starboard/contrib/creator/ci20x11/main.cc',
+ '<(DEPTH)/starboard/contrib/creator/ci20x11/system_get_property.cc',
+ '<(DEPTH)/starboard/contrib/creator/shared/player_components_impl.cc',
'<(DEPTH)/starboard/linux/shared/atomic_public.h',
'<(DEPTH)/starboard/linux/shared/decode_target_internal.h',
'<(DEPTH)/starboard/linux/shared/decode_target_internal.cc',
diff --git a/src/starboard/creator/ci20x11/system_get_property.cc b/src/starboard/contrib/creator/ci20x11/system_get_property.cc
similarity index 100%
rename from src/starboard/creator/ci20x11/system_get_property.cc
rename to src/starboard/contrib/creator/ci20x11/system_get_property.cc
diff --git a/src/starboard/creator/ci20x11/thread_types_public.h b/src/starboard/contrib/creator/ci20x11/thread_types_public.h
similarity index 77%
rename from src/starboard/creator/ci20x11/thread_types_public.h
rename to src/starboard/contrib/creator/ci20x11/thread_types_public.h
index 7437a70..4a0e470 100644
--- a/src/starboard/creator/ci20x11/thread_types_public.h
+++ b/src/starboard/contrib/creator/ci20x11/thread_types_public.h
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
+#ifndef STARBOARD_CONTRIB_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
#include "starboard/linux/shared/thread_types_public.h"
-#endif // STARBOARD_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
+#endif // STARBOARD_CONTRIB_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/creator/shared/__init__.py b/src/starboard/contrib/creator/shared/__init__.py
similarity index 100%
rename from src/starboard/creator/shared/__init__.py
rename to src/starboard/contrib/creator/shared/__init__.py
diff --git a/src/starboard/contrib/creator/shared/_env.py b/src/starboard/contrib/creator/shared/_env.py
new file mode 100644
index 0000000..6188bb7
--- /dev/null
+++ b/src/starboard/contrib/creator/shared/_env.py
@@ -0,0 +1,26 @@
+#
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Ask the parent directory to load the project environment."""
+
+from imp import load_source
+from os import path
+import sys
+
+_ENV = path.abspath(path.join(path.dirname(__file__), path.pardir, '_env.py'))
+if not path.exists(_ENV):
+ print '%s: Can\'t find repo root.\nMissing parent: %s' % (__file__, _ENV)
+ sys.exit(1)
+load_source('', _ENV)
diff --git a/src/starboard/creator/shared/configuration_public.h b/src/starboard/contrib/creator/shared/configuration_public.h
similarity index 98%
rename from src/starboard/creator/shared/configuration_public.h
rename to src/starboard/contrib/creator/shared/configuration_public.h
index 9172529..1ea3bed 100644
--- a/src/starboard/creator/shared/configuration_public.h
+++ b/src/starboard/contrib/creator/shared/configuration_public.h
@@ -14,8 +14,8 @@
// The shared Starboard configuration for Creator devices.
-#ifndef STARBOARD_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_
+#ifndef STARBOARD_CONTRIB_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_
// --- Architecture Configuration --------------------------------------------
@@ -444,4 +444,4 @@
#error "CREATOR_SHARED builds need a GCC-like compiler (for the moment)."
#endif
-#endif // STARBOARD_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_
+#endif // STARBOARD_CONTRIB_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/creator/shared/gyp_configuration.gypi b/src/starboard/contrib/creator/shared/gyp_configuration.gypi
similarity index 100%
rename from src/starboard/creator/shared/gyp_configuration.gypi
rename to src/starboard/contrib/creator/shared/gyp_configuration.gypi
diff --git a/src/starboard/creator/shared/gyp_configuration.py b/src/starboard/contrib/creator/shared/gyp_configuration.py
similarity index 98%
rename from src/starboard/creator/shared/gyp_configuration.py
rename to src/starboard/contrib/creator/shared/gyp_configuration.py
index b5f75cb..cbee9c8 100644
--- a/src/starboard/creator/shared/gyp_configuration.py
+++ b/src/starboard/contrib/creator/shared/gyp_configuration.py
@@ -20,6 +20,8 @@
import config.base
import gyp_utils
+
+import _env # pylint: disable=unused-import
from starboard.tools.testing import test_filter
diff --git a/src/starboard/creator/shared/player_components_impl.cc b/src/starboard/contrib/creator/shared/player_components_impl.cc
similarity index 100%
rename from src/starboard/creator/shared/player_components_impl.cc
rename to src/starboard/contrib/creator/shared/player_components_impl.cc
diff --git a/src/starboard/tizen/armv7l/atomic_public.h b/src/starboard/contrib/tizen/armv7l/atomic_public.h
similarity index 73%
rename from src/starboard/tizen/armv7l/atomic_public.h
rename to src/starboard/contrib/tizen/armv7l/atomic_public.h
index d42b571..b1adbbe 100644
--- a/src/starboard/tizen/armv7l/atomic_public.h
+++ b/src/starboard/contrib/tizen/armv7l/atomic_public.h
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef STARBOARD_TIZEN_ARMV7L_ATOMIC_PUBLIC_H_
-#define STARBOARD_TIZEN_ARMV7L_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_CONTRIB_TIZEN_ARMV7L_ATOMIC_PUBLIC_H_
+#define STARBOARD_CONTRIB_TIZEN_ARMV7L_ATOMIC_PUBLIC_H_
-#include "starboard/tizen/shared/atomic_public.h"
+#include "starboard/contrib/tizen/shared/atomic_public.h"
-#endif // STARBOARD_TIZEN_ARMV7L_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_CONTRIB_TIZEN_ARMV7L_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/tizen/armv7l/configuration_public.h b/src/starboard/contrib/tizen/armv7l/configuration_public.h
similarity index 95%
rename from src/starboard/tizen/armv7l/configuration_public.h
rename to src/starboard/contrib/tizen/armv7l/configuration_public.h
index b5b8830..3b9e99b 100644
--- a/src/starboard/tizen/armv7l/configuration_public.h
+++ b/src/starboard/contrib/tizen/armv7l/configuration_public.h
@@ -19,8 +19,8 @@
// Other source files should never include this header directly, but should
// include the generic "starboard/configuration.h" instead.
-#ifndef STARBOARD_TIZEN_ARMV7L_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_TIZEN_ARMV7L_CONFIGURATION_PUBLIC_H_
+#ifndef STARBOARD_CONTRIB_TIZEN_ARMV7L_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_CONTRIB_TIZEN_ARMV7L_CONFIGURATION_PUBLIC_H_
// The API version implemented by this platform.
#define SB_API_VERSION 4
@@ -152,7 +152,7 @@
// --- Common Configuration ---------------------------------------------------
// Include the Tizen configuration that's common between all Tizen.
-#include "starboard/tizen/shared/configuration_public.h"
+#include "starboard/contrib/tizen/shared/configuration_public.h"
// --- User Configuration ----------------------------------------------------
@@ -165,4 +165,4 @@
// has spent in the executing state.
#define SB_HAS_TIME_THREAD_NOW 1
-#endif // STARBOARD_TIZEN_ARMV7L_CONFIGURATION_PUBLIC_H_
+#endif // STARBOARD_CONTRIB_TIZEN_ARMV7L_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/tizen/armv7l/gyp_configuration.gypi b/src/starboard/contrib/tizen/armv7l/gyp_configuration.gypi
similarity index 100%
rename from src/starboard/tizen/armv7l/gyp_configuration.gypi
rename to src/starboard/contrib/tizen/armv7l/gyp_configuration.gypi
diff --git a/src/starboard/tizen/armv7l/gyp_configuration.py b/src/starboard/contrib/tizen/armv7l/gyp_configuration.py
similarity index 100%
rename from src/starboard/tizen/armv7l/gyp_configuration.py
rename to src/starboard/contrib/tizen/armv7l/gyp_configuration.py
diff --git a/src/starboard/tizen/armv7l/starboard_common.gyp b/src/starboard/contrib/tizen/armv7l/starboard_common.gyp
similarity index 92%
rename from src/starboard/tizen/armv7l/starboard_common.gyp
rename to src/starboard/contrib/tizen/armv7l/starboard_common.gyp
index 86c0acf..d627fbd 100644
--- a/src/starboard/tizen/armv7l/starboard_common.gyp
+++ b/src/starboard/contrib/tizen/armv7l/starboard_common.gyp
@@ -219,13 +219,13 @@
'<(DEPTH)/starboard/shared/wayland/window_get_platform_handle.cc',
'<(DEPTH)/starboard/shared/wayland/window_get_size.cc',
'<(DEPTH)/starboard/shared/wayland/window_internal.cc',
- '<(DEPTH)/starboard/tizen/shared/system_get_device_type.cc',
- '<(DEPTH)/starboard/tizen/shared/thread_create.cc',
- '<(DEPTH)/starboard/tizen/shared/audio/audio_sink_adaptor.cc',
- '<(DEPTH)/starboard/tizen/shared/audio/audio_sink_private.cc',
- '<(DEPTH)/starboard/tizen/shared/log/log.cc',
- '<(DEPTH)/starboard/tizen/shared/get_home_directory.cc',
- '<(DEPTH)/starboard/tizen/shared/memory_flush.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system_get_device_type.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/thread_create.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/audio/audio_sink_adaptor.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/audio/audio_sink_private.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/log/log.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/get_home_directory.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/memory_flush.cc',
],
'defines': [
# This must be defined when building Starboard, and must not when
@@ -234,14 +234,14 @@
],
'dependencies': [
'<(DEPTH)/starboard/common/common.gyp:common',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:capi-appfw-application',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:capi-media-audio-io',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:edbus',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:elementary',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:evas',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:gles20',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:tizen-extension-client',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:wayland-egl',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:capi-appfw-application',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:capi-media-audio-io',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:edbus',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:elementary',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:evas',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:gles20',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:tizen-extension-client',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:wayland-egl',
'<(DEPTH)/third_party/libevent/libevent.gyp:libevent',
'starboard_base_symbolize',
],
diff --git a/src/starboard/tizen/armv7l/starboard_platform.gyp b/src/starboard/contrib/tizen/armv7l/starboard_platform.gyp
similarity index 90%
rename from src/starboard/tizen/armv7l/starboard_platform.gyp
rename to src/starboard/contrib/tizen/armv7l/starboard_platform.gyp
index 37371df..ac9a851 100644
--- a/src/starboard/tizen/armv7l/starboard_platform.gyp
+++ b/src/starboard/contrib/tizen/armv7l/starboard_platform.gyp
@@ -105,17 +105,17 @@
'<(DEPTH)/starboard/shared/stub/media_is_supported.cc',
'<(DEPTH)/starboard/shared/stub/media_is_transfer_characteristics_supported.cc',
'<(DEPTH)/starboard/shared/wayland/application_wayland.cc',
- '<(DEPTH)/starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.cc',
- '<(DEPTH)/starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h',
+ '<(DEPTH)/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h',
'<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_audio_resampler.cc',
'<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_audio_resampler.h',
- '<(DEPTH)/starboard/tizen/shared/ffmpeg/ffmpeg_common.cc',
- '<(DEPTH)/starboard/tizen/shared/ffmpeg/ffmpeg_common.h',
- '<(DEPTH)/starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.cc',
- '<(DEPTH)/starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.h',
- '<(DEPTH)/starboard/tizen/shared/main.cc',
- '<(DEPTH)/starboard/tizen/shared/player/filter/ffmpeg_player_components_impl.cc',
- '<(DEPTH)/starboard/tizen/shared/system_get_path.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.h',
+ '<(DEPTH)/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.h',
+ '<(DEPTH)/starboard/contrib/tizen/shared/main.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/player/filter/ffmpeg_player_components_impl.cc',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system_get_path.cc',
'atomic_public.h',
'configuration_public.h',
'system_get_property.cc',
@@ -127,8 +127,8 @@
],
'dependencies': [
'<(DEPTH)/starboard/common/common.gyp:common',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:aul',
- '<(DEPTH)/starboard/tizen/shared/system.gyp:elementary',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:aul',
+ '<(DEPTH)/starboard/contrib/tizen/shared/system.gyp:elementary',
'<(DEPTH)/third_party/dlmalloc/dlmalloc.gyp:dlmalloc',
'starboard_common.gyp:starboard_common',
],
diff --git a/src/starboard/tizen/armv7l/system_get_property.cc b/src/starboard/contrib/tizen/armv7l/system_get_property.cc
similarity index 100%
rename from src/starboard/tizen/armv7l/system_get_property.cc
rename to src/starboard/contrib/tizen/armv7l/system_get_property.cc
diff --git a/src/starboard/tizen/armv7l/thread_types_public.h b/src/starboard/contrib/tizen/armv7l/thread_types_public.h
similarity index 100%
rename from src/starboard/tizen/armv7l/thread_types_public.h
rename to src/starboard/contrib/tizen/armv7l/thread_types_public.h
diff --git a/src/starboard/tizen/packaging/README.md b/src/starboard/contrib/tizen/packaging/README.md
similarity index 70%
rename from src/starboard/tizen/packaging/README.md
rename to src/starboard/contrib/tizen/packaging/README.md
index dc3c3a9..0049ea3 100644
--- a/src/starboard/tizen/packaging/README.md
+++ b/src/starboard/contrib/tizen/packaging/README.md
@@ -1,7 +1,7 @@
## Introduction
cobalt tizen is a Cobalt engine port to tizen platform. The port
-implements starboard/tizen platform APIs.
+implements starboard/contrib/tizen platform APIs.
## Precondition
@@ -17,10 +17,10 @@
1. Build commands:
- Need to add packaging-dir option
- --packaging-dir src/starboard/tizen/packaging/
+ --packaging-dir src/starboard/contrib/tizen/packaging/
- armv7l
$ gbs -c packaging/gbs.conf -v build -A armv7l -P profile.cobalt [options]
Detail option see "gbs --help" and "gbs -v build --help"
- ex) gbs -c src/starboard/tizen/packaging/gbs.conf -v build -A armv7l -P profile.cobalt --packaging-dir src/starboard/tizen/packaging/
+ ex) gbs -c src/starboard/contrib/tizen/packaging/gbs.conf -v build -A armv7l -P profile.cobalt --packaging-dir src/starboard/contrib/tizen/packaging/
cobalt tizen code uses the BSD license, see our `LICENSE` file.
diff --git a/src/starboard/tizen/packaging/com.youtube.cobalt.manifest b/src/starboard/contrib/tizen/packaging/com.youtube.cobalt.manifest
similarity index 100%
rename from src/starboard/tizen/packaging/com.youtube.cobalt.manifest
rename to src/starboard/contrib/tizen/packaging/com.youtube.cobalt.manifest
diff --git a/src/starboard/tizen/packaging/com.youtube.cobalt.spec b/src/starboard/contrib/tizen/packaging/com.youtube.cobalt.spec
similarity index 96%
rename from src/starboard/tizen/packaging/com.youtube.cobalt.spec
rename to src/starboard/contrib/tizen/packaging/com.youtube.cobalt.spec
index c42faff..1b4a636 100644
--- a/src/starboard/tizen/packaging/com.youtube.cobalt.spec
+++ b/src/starboard/contrib/tizen/packaging/com.youtube.cobalt.spec
@@ -150,7 +150,7 @@
cp -rd %{_outdir}/content/dir_source_root %{buildroot}%{_contentdir}/
%endif
-cp src/starboard/tizen/packaging/%{_pkgname}.xml %{buildroot}%{_manifestdir}
+cp src/starboard/contrib/tizen/packaging/%{_pkgname}.xml %{buildroot}%{_manifestdir}
%post
@@ -160,7 +160,7 @@
# rpm files
#####################
%files
-%manifest src/starboard/tizen/packaging/%{_pkgname}.manifest
+%manifest src/starboard/contrib/tizen/packaging/%{_pkgname}.manifest
%defattr(-,root,root,-)
%if "%{_name}" == "all"
%{_bindir}/*
diff --git a/src/starboard/tizen/packaging/com.youtube.cobalt.xml b/src/starboard/contrib/tizen/packaging/com.youtube.cobalt.xml
similarity index 100%
rename from src/starboard/tizen/packaging/com.youtube.cobalt.xml
rename to src/starboard/contrib/tizen/packaging/com.youtube.cobalt.xml
diff --git a/src/starboard/tizen/packaging/gbs.conf b/src/starboard/contrib/tizen/packaging/gbs.conf
similarity index 100%
rename from src/starboard/tizen/packaging/gbs.conf
rename to src/starboard/contrib/tizen/packaging/gbs.conf
diff --git a/src/starboard/tizen/shared/atomic_public.h b/src/starboard/contrib/tizen/shared/atomic_public.h
similarity index 100%
rename from src/starboard/tizen/shared/atomic_public.h
rename to src/starboard/contrib/tizen/shared/atomic_public.h
diff --git a/src/starboard/tizen/shared/audio/audio_sink_adaptor.cc b/src/starboard/contrib/tizen/shared/audio/audio_sink_adaptor.cc
similarity index 97%
rename from src/starboard/tizen/shared/audio/audio_sink_adaptor.cc
rename to src/starboard/contrib/tizen/shared/audio/audio_sink_adaptor.cc
index 5e06b2f..6e26abe 100644
--- a/src/starboard/tizen/shared/audio/audio_sink_adaptor.cc
+++ b/src/starboard/contrib/tizen/shared/audio/audio_sink_adaptor.cc
@@ -14,7 +14,7 @@
#include "starboard/audio_sink.h"
#include "starboard/log.h"
-#include "starboard/tizen/shared/audio/audio_sink_private.h"
+#include "starboard/contrib/tizen/shared/audio/audio_sink_private.h"
bool SbAudioSinkIsValid(SbAudioSink audio_sink) {
if (audio_sink == kSbAudioSinkInvalid) {
diff --git a/src/starboard/tizen/shared/audio/audio_sink_private.cc b/src/starboard/contrib/tizen/shared/audio/audio_sink_private.cc
similarity index 98%
rename from src/starboard/tizen/shared/audio/audio_sink_private.cc
rename to src/starboard/contrib/tizen/shared/audio/audio_sink_private.cc
index 52c3b95..aac2939 100644
--- a/src/starboard/tizen/shared/audio/audio_sink_private.cc
+++ b/src/starboard/contrib/tizen/shared/audio/audio_sink_private.cc
@@ -15,7 +15,7 @@
#include "starboard/audio_sink.h"
#include "starboard/log.h"
#include "starboard/mutex.h"
-#include "starboard/tizen/shared/audio/audio_sink_private.h"
+#include "starboard/contrib/tizen/shared/audio/audio_sink_private.h"
#define CHECK_CAPI_AUDIO_ERROR(func) \
if (capi_ret != AUDIO_IO_ERROR_NONE) { \
diff --git a/src/starboard/tizen/shared/audio/audio_sink_private.h b/src/starboard/contrib/tizen/shared/audio/audio_sink_private.h
similarity index 100%
rename from src/starboard/tizen/shared/audio/audio_sink_private.h
rename to src/starboard/contrib/tizen/shared/audio/audio_sink_private.h
diff --git a/src/starboard/tizen/shared/configuration_public.h b/src/starboard/contrib/tizen/shared/configuration_public.h
similarity index 100%
rename from src/starboard/tizen/shared/configuration_public.h
rename to src/starboard/contrib/tizen/shared/configuration_public.h
diff --git a/src/starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.cc b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.cc
similarity index 98%
rename from src/starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.cc
rename to src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.cc
index ebe970b..7092f7b 100644
--- a/src/starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.cc
+++ b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h"
+#include "starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h"
#include "starboard/audio_sink.h"
#include "starboard/log.h"
diff --git a/src/starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h
similarity index 88%
rename from src/starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h
rename to src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h
index 3271d88..42e20a7 100644
--- a/src/starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h
+++ b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_TIZEN_SHARED_FFMPEG_FFMPEG_AUDIO_DECODER_H_
-#define STARBOARD_TIZEN_SHARED_FFMPEG_FFMPEG_AUDIO_DECODER_H_
+#ifndef STARBOARD_CONTRIB_TIZEN_SHARED_FFMPEG_FFMPEG_AUDIO_DECODER_H_
+#define STARBOARD_CONTRIB_TIZEN_SHARED_FFMPEG_FFMPEG_AUDIO_DECODER_H_
#include <queue>
@@ -21,7 +21,7 @@
#include "starboard/shared/internal_only.h"
#include "starboard/shared/starboard/player/decoded_audio_internal.h"
#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
-#include "starboard/tizen/shared/ffmpeg/ffmpeg_common.h"
+#include "starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.h"
namespace starboard {
namespace shared {
@@ -68,4 +68,4 @@
} // namespace shared
} // namespace starboard
-#endif // STARBOARD_TIZEN_SHARED_FFMPEG_FFMPEG_AUDIO_DECODER_H_
+#endif // STARBOARD_CONTRIB_TIZEN_SHARED_FFMPEG_FFMPEG_AUDIO_DECODER_H_
diff --git a/src/starboard/tizen/shared/ffmpeg/ffmpeg_common.cc b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.cc
similarity index 95%
rename from src/starboard/tizen/shared/ffmpeg/ffmpeg_common.cc
rename to src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.cc
index 7dc091c..cc7e83a 100644
--- a/src/starboard/tizen/shared/ffmpeg/ffmpeg_common.cc
+++ b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/tizen/shared/ffmpeg/ffmpeg_common.h"
+#include "starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.h"
#include "starboard/log.h"
#include "starboard/mutex.h"
diff --git a/src/starboard/tizen/shared/ffmpeg/ffmpeg_common.h b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.h
similarity index 100%
rename from src/starboard/tizen/shared/ffmpeg/ffmpeg_common.h
rename to src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.h
diff --git a/src/starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.cc b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.cc
similarity index 98%
rename from src/starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.cc
rename to src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.cc
index c898592..f0fe7be 100644
--- a/src/starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.cc
+++ b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.h"
+#include "starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.h"
#include "starboard/memory.h"
diff --git a/src/starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.h b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.h
similarity index 90%
rename from src/starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.h
rename to src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.h
index ea4e33b..5d257ac 100644
--- a/src/starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.h
+++ b/src/starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_TIZEN_SHARED_FFMPEG_FFMPEG_VIDEO_DECODER_H_
-#define STARBOARD_TIZEN_SHARED_FFMPEG_FFMPEG_VIDEO_DECODER_H_
+#ifndef STARBOARD_CONTRIB_TIZEN_SHARED_FFMPEG_FFMPEG_VIDEO_DECODER_H_
+#define STARBOARD_CONTRIB_TIZEN_SHARED_FFMPEG_FFMPEG_VIDEO_DECODER_H_
#include "starboard/log.h"
#include "starboard/media.h"
@@ -23,7 +23,7 @@
#include "starboard/shared/starboard/player/input_buffer_internal.h"
#include "starboard/shared/starboard/player/video_frame_internal.h"
#include "starboard/thread.h"
-#include "starboard/tizen/shared/ffmpeg/ffmpeg_common.h"
+#include "starboard/contrib/tizen/shared/ffmpeg/ffmpeg_common.h"
namespace starboard {
namespace shared {
@@ -95,4 +95,4 @@
} // namespace shared
} // namespace starboard
-#endif // STARBOARD_TIZEN_SHARED_FFMPEG_FFMPEG_VIDEO_DECODER_H_
+#endif // STARBOARD_CONTRIB_TIZEN_SHARED_FFMPEG_FFMPEG_VIDEO_DECODER_H_
diff --git a/src/starboard/tizen/shared/get_home_directory.cc b/src/starboard/contrib/tizen/shared/get_home_directory.cc
similarity index 100%
rename from src/starboard/tizen/shared/get_home_directory.cc
rename to src/starboard/contrib/tizen/shared/get_home_directory.cc
diff --git a/src/starboard/tizen/shared/gyp_configuration.gypi b/src/starboard/contrib/tizen/shared/gyp_configuration.gypi
similarity index 100%
rename from src/starboard/tizen/shared/gyp_configuration.gypi
rename to src/starboard/contrib/tizen/shared/gyp_configuration.gypi
diff --git a/src/starboard/tizen/shared/log/log.cc b/src/starboard/contrib/tizen/shared/log/log.cc
similarity index 100%
rename from src/starboard/tizen/shared/log/log.cc
rename to src/starboard/contrib/tizen/shared/log/log.cc
diff --git a/src/starboard/tizen/shared/main.cc b/src/starboard/contrib/tizen/shared/main.cc
similarity index 100%
rename from src/starboard/tizen/shared/main.cc
rename to src/starboard/contrib/tizen/shared/main.cc
diff --git a/src/starboard/tizen/shared/memory_flush.cc b/src/starboard/contrib/tizen/shared/memory_flush.cc
similarity index 100%
rename from src/starboard/tizen/shared/memory_flush.cc
rename to src/starboard/contrib/tizen/shared/memory_flush.cc
diff --git a/src/starboard/tizen/shared/player/filter/ffmpeg_player_components_impl.cc b/src/starboard/contrib/tizen/shared/player/filter/ffmpeg_player_components_impl.cc
similarity index 93%
rename from src/starboard/tizen/shared/player/filter/ffmpeg_player_components_impl.cc
rename to src/starboard/contrib/tizen/shared/player/filter/ffmpeg_player_components_impl.cc
index 1081d37..84ddd6a 100644
--- a/src/starboard/tizen/shared/player/filter/ffmpeg_player_components_impl.cc
+++ b/src/starboard/contrib/tizen/shared/player/filter/ffmpeg_player_components_impl.cc
@@ -16,8 +16,8 @@
#include "starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h"
#include "starboard/shared/starboard/player/filter/video_renderer_impl_internal.h"
-#include "starboard/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h"
-#include "starboard/tizen/shared/ffmpeg/ffmpeg_video_decoder.h"
+#include "starboard/contrib/tizen/shared/ffmpeg/ffmpeg_audio_decoder.h"
+#include "starboard/contrib/tizen/shared/ffmpeg/ffmpeg_video_decoder.h"
namespace starboard {
namespace shared {
diff --git a/src/starboard/tizen/shared/system.gyp b/src/starboard/contrib/tizen/shared/system.gyp
similarity index 100%
rename from src/starboard/tizen/shared/system.gyp
rename to src/starboard/contrib/tizen/shared/system.gyp
diff --git a/src/starboard/tizen/shared/system_get_device_type.cc b/src/starboard/contrib/tizen/shared/system_get_device_type.cc
similarity index 100%
rename from src/starboard/tizen/shared/system_get_device_type.cc
rename to src/starboard/contrib/tizen/shared/system_get_device_type.cc
diff --git a/src/starboard/tizen/shared/system_get_path.cc b/src/starboard/contrib/tizen/shared/system_get_path.cc
similarity index 100%
rename from src/starboard/tizen/shared/system_get_path.cc
rename to src/starboard/contrib/tizen/shared/system_get_path.cc
diff --git a/src/starboard/tizen/shared/thread_create.cc b/src/starboard/contrib/tizen/shared/thread_create.cc
similarity index 100%
rename from src/starboard/tizen/shared/thread_create.cc
rename to src/starboard/contrib/tizen/shared/thread_create.cc
diff --git a/src/starboard/creator/ci20x11/atomic_public.h b/src/starboard/creator/ci20x11/atomic_public.h
deleted file mode 100644
index 932fe9d..0000000
--- a/src/starboard/creator/ci20x11/atomic_public.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STARBOARD_CREATOR_CI20X11_ATOMIC_PUBLIC_H_
-#define STARBOARD_CREATOR_CI20X11_ATOMIC_PUBLIC_H_
-
-#include "starboard/linux/shared/atomic_public.h"
-
-#endif // STARBOARD_CREATOR_CI20X11_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/creator/ci20x11/configuration_public.h b/src/starboard/creator/ci20x11/configuration_public.h
deleted file mode 100644
index 4c00bad..0000000
--- a/src/starboard/creator/ci20x11/configuration_public.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STARBOARD_CREATOR_CI20X11_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_CREATOR_CI20X11_CONFIGURATION_PUBLIC_H_
-
-#include "starboard/creator/shared/configuration_public.h"
-
-#endif // STARBOARD_CREATOR_CI20X11_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/event.h b/src/starboard/event.h
index cda0d09..a693ae9 100644
--- a/src/starboard/event.h
+++ b/src/starboard/event.h
@@ -203,7 +203,8 @@
// The platform's accessibility settings have changed. The application should
// query the accessibility settings using the appropriate APIs to get the
- // new settings.
+ // new settings. Note this excludes captions settings changes, which
+ // causes kSbEventTypeAccessibilityCaptionSettingsChanged to fire.
kSbEventTypeAccessiblitySettingsChanged,
#if SB_API_VERSION >= 6
@@ -258,6 +259,11 @@
kSbEventTypeOnScreenKeyboardBlurred,
#endif // SB_HAS(ON_SCREEN_KEYBOARD)
+#if SB_HAS(CAPTIONS)
+ // One or more of the fields returned by SbAccessibilityGetCaptionSettings
+ // has changed.
+ kSbEventTypeAccessibilityCaptionSettingsChanged,
+#endif // SB_HAS(CAPTIONS)
} SbEventType;
// Structure representing a Starboard event and its data.
diff --git a/src/starboard/linux/x64x11/starboard_platform_tests.gyp b/src/starboard/linux/x64x11/starboard_platform_tests.gyp
index d714153..1a4a493 100644
--- a/src/starboard/linux/x64x11/starboard_platform_tests.gyp
+++ b/src/starboard/linux/x64x11/starboard_platform_tests.gyp
@@ -13,7 +13,7 @@
# limitations under the License.
{
'includes': [
- '<(DEPTH)/starboard/shared/starboard/player/filter/filter_tests.gypi',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/filter_tests.gypi',
],
'targets': [
{
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index e84264e..d48b409 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -23,6 +23,8 @@
'type': '<(gtest_target_type)',
'sources': [
'<(DEPTH)/starboard/common/test_main.cc',
+ '<(DEPTH)/starboard/testing/fake_graphics_context_provider.cc',
+ '<(DEPTH)/starboard/testing/fake_graphics_context_provider.h',
'accessibility_get_setting_test.cc',
'align_test.cc',
'atomic_test.cc',
diff --git a/src/starboard/nplb/player_create_test.cc b/src/starboard/nplb/player_create_test.cc
index c5a5410..971950d 100644
--- a/src/starboard/nplb/player_create_test.cc
+++ b/src/starboard/nplb/player_create_test.cc
@@ -15,6 +15,7 @@
#include "starboard/blitter.h"
#include "starboard/decode_target.h"
#include "starboard/player.h"
+#include "starboard/testing/fake_graphics_context_provider.h"
#include "starboard/window.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,28 +25,26 @@
#if SB_HAS(PLAYER_WITH_URL)
// This test does not apply. See player_create_with_url_test.cc instead.
-#else
+#else // SB_HAS(PLAYER_WITH_URL)
-#if SB_HAS(GLES2)
-void GlesContextRunner(
- SbDecodeTargetGraphicsContextProvider* graphics_context_provider,
- SbDecodeTargetGlesContextRunnerTarget target_function,
- void* target_function_context) {
- SB_UNREFERENCED_PARAMETER(graphics_context_provider);
+using ::starboard::testing::FakeGraphicsContextProvider;
- // Just call the function directly in case the player implementation relies
- // on this function call being made.
- (*target_function)(target_function_context);
-}
-#endif // SB_HAS(GLES2)
+class SbPlayerTest : public ::testing::Test {
+ protected:
+ void SetUp() {
+ SbWindowOptions window_options;
+ SbWindowSetDefaultOptions(&window_options);
-TEST(SbPlayerTest, SunnyDay) {
- SbWindowOptions window_options;
- SbWindowSetDefaultOptions(&window_options);
+ window_ = SbWindowCreate(&window_options);
+ EXPECT_TRUE(SbWindowIsValid(window_));
+ }
+ void TearDown() { SbWindowDestroy(window_); }
- SbWindow window = SbWindowCreate(&window_options);
- EXPECT_TRUE(SbWindowIsValid(window));
+ SbWindow window_;
+ FakeGraphicsContextProvider fake_graphics_context_provider_;
+};
+TEST_F(SbPlayerTest, SunnyDay) {
SbMediaAudioHeader audio_header;
audio_header.format_tag = 0xff;
@@ -54,9 +53,6 @@
audio_header.block_alignment = 4;
audio_header.bits_per_sample = 32;
audio_header.audio_specific_config_size = 0;
-#if SB_API_VERSION >= 6
- audio_header.audio_specific_config = NULL;
-#endif // SB_API_VERSION >= 6
audio_header.average_bytes_per_second = audio_header.samples_per_second *
audio_header.number_of_channels *
audio_header.bits_per_sample / 8;
@@ -73,22 +69,11 @@
continue;
}
- SbDecodeTargetGraphicsContextProvider
- decode_target_graphics_context_provider;
-#if SB_HAS(BLITTER)
- decode_target_graphics_context_provider.device = kSbBlitterInvalidDevice;
-#elif SB_HAS(GLES2)
- decode_target_graphics_context_provider.egl_display = NULL;
- decode_target_graphics_context_provider.egl_context = NULL;
- decode_target_graphics_context_provider.gles_context_runner =
- &GlesContextRunner;
- decode_target_graphics_context_provider.gles_context_runner_context = NULL;
-#endif // SB_HAS(BLITTER)
-
SbPlayer player = SbPlayerCreate(
- window, kSbMediaVideoCodecH264, kSbMediaAudioCodecAac,
+ window_, kSbMediaVideoCodecH264, kSbMediaAudioCodecAac,
SB_PLAYER_NO_DURATION, kSbDrmSystemInvalid, &audio_header, NULL, NULL,
- NULL, NULL, output_mode, &decode_target_graphics_context_provider);
+ NULL, NULL, output_mode,
+ fake_graphics_context_provider_.decoder_target_provider());
EXPECT_TRUE(SbPlayerIsValid(player));
if (output_mode == kSbPlayerOutputModeDecodeToTexture) {
@@ -97,10 +82,38 @@
SbPlayerDestroy(player);
}
-
- SbWindowDestroy(window);
}
+#if SB_API_VERSION >= SB_AUDIOLESS_VIDEO_API_VERSION
+TEST_F(SbPlayerTest, Audioless) {
+ SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
+ SbDrmSystem kDrmSystem = kSbDrmSystemInvalid;
+
+ SbPlayerOutputMode output_modes[] = {kSbPlayerOutputModeDecodeToTexture,
+ kSbPlayerOutputModePunchOut};
+
+ for (int i = 0; i < SB_ARRAY_SIZE_INT(output_modes); ++i) {
+ SbPlayerOutputMode output_mode = output_modes[i];
+ if (!SbPlayerOutputModeSupported(output_mode, kVideoCodec, kDrmSystem)) {
+ continue;
+ }
+
+ SbPlayer player = SbPlayerCreate(
+ window_, kSbMediaVideoCodecH264, kSbMediaAudioCodecNone,
+ SB_PLAYER_NO_DURATION, kSbDrmSystemInvalid, NULL, NULL, NULL, NULL,
+ NULL, output_mode,
+ fake_graphics_context_provider_.decoder_target_provider());
+ EXPECT_TRUE(SbPlayerIsValid(player));
+
+ if (output_mode == kSbPlayerOutputModeDecodeToTexture) {
+ SbDecodeTarget current_frame = SbPlayerGetCurrentFrame(player);
+ }
+
+ SbPlayerDestroy(player);
+ }
+}
+#endif // SB_API_VERSION >= SB_AUDIOLESS_VIDEO_API_VERSION
+
#endif // SB_HAS(PLAYER_WITH_URL)
} // namespace
diff --git a/src/starboard/nplb/socket_resolve_test.cc b/src/starboard/nplb/socket_resolve_test.cc
index ebca117..3c2b9bd 100644
--- a/src/starboard/nplb/socket_resolve_test.cc
+++ b/src/starboard/nplb/socket_resolve_test.cc
@@ -37,7 +37,8 @@
const void* kNull = NULL;
// A random host name to use to test DNS resolution.
-const char* kTestHostName = "www.yahoo.com";
+const char kTestHostName[] = "www.yahoo.com";
+const char kLocalhost[] = "localhost";
#define LOG_ADDRESS(i) "In returned address #" << (i)
@@ -57,6 +58,24 @@
SbSocketFreeResolution(resolution);
}
+TEST_P(SbSocketResolveTest, Localhost) {
+ SbSocketResolution* resolution =
+ SbSocketResolve(kLocalhost, GetResolveFilter());
+ ASSERT_NE(kNull, resolution);
+ EXPECT_LT(0, resolution->address_count);
+ EXPECT_NE(kNull, resolution->addresses);
+ for (int i = 0; i < resolution->address_count; ++i) {
+ const SbSocketAddress& address = resolution->addresses[i];
+ EXPECT_TRUE(address.type == kSbSocketAddressTypeIpv4 ||
+ address.type == kSbSocketAddressTypeIpv6)
+ << LOG_ADDRESS(i);
+ EXPECT_TRUE(IsLocalhost(&address)) << LOG_ADDRESS(i);
+ EXPECT_FALSE(IsUnspecified(&address)) << LOG_ADDRESS(i);
+ }
+
+ SbSocketFreeResolution(resolution);
+}
+
TEST_P(SbSocketResolveTest, SunnyDayFiltered) {
SbSocketResolution* resolution =
SbSocketResolve(kTestHostName, GetResolveFilter());
diff --git a/src/starboard/player.h b/src/starboard/player.h
index 95aa665..6de176c 100644
--- a/src/starboard/player.h
+++ b/src/starboard/player.h
@@ -301,6 +301,10 @@
// |audio_codec|: The audio codec used for the player. The value should never
// be |kSbMediaAudioCodecNone|. In addition, the caller must provide a
// populated |audio_header| if the audio codec is |kSbMediaAudioCodecAac|.
+#if SB_API_VERSION >= SB_AUDIOLESS_VIDEO_API_VERSION
+// This can be set to |kSbMediaAudioCodecNone| to play a video without any
+// audio track. In such case |audio_header| must be NULL.
+#endif // SB_API_VERSION >= SB_AUDIOLESS_VIDEO_API_VERSION
//
// |duration_pts|: The expected media duration in 90KHz ticks (PTS). It may be
// set to |SB_PLAYER_NO_DURATION| for live streams.
@@ -318,6 +322,9 @@
// is no longer valid after this function returns. The implementation has to
// make a copy of the content if it is needed after the function returns.
#endif // SB_API_VERSION >= 6
+#if SB_API_VERSION >= SB_AUDIOLESS_VIDEO_API_VERSION
+// When |audio_codec| is |kSbMediaAudioCodecNone|, this must be set to NULL.
+#endif // SB_API_VERSION >= SB_AUDIOLESS_VIDEO_API_VERSION
//
// |sample_deallocator_func|: If not |NULL|, the player calls this function
// on an internal thread to free the sample buffers passed into
diff --git a/src/starboard/raspi/shared/gyp_configuration.py b/src/starboard/raspi/shared/gyp_configuration.py
index aba2888..f6c72be 100644
--- a/src/starboard/raspi/shared/gyp_configuration.py
+++ b/src/starboard/raspi/shared/gyp_configuration.py
@@ -59,9 +59,10 @@
clang.GetClangSpecification())
raspi_home = self._GetRasPiHome()
- toolchain = os.path.realpath(os.path.join(
- raspi_home,
- 'tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64'))
+ toolchain = os.path.realpath(
+ os.path.join(
+ raspi_home,
+ 'tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64'))
toolchain_bin_dir = os.path.join(toolchain, 'bin')
env_variables.update({
'CC': os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-gcc'),
@@ -69,6 +70,10 @@
})
return env_variables
+ def GetLauncherPath(self):
+ """Gets the path to the launcher module for this platform."""
+ return os.path.dirname(__file__)
+
def GetTestFilters(self):
filters = super(RaspiPlatformConfig, self).GetTestFilters()
filters.extend([
@@ -76,14 +81,13 @@
# disable the related tests.
test_filter.TestFilter(
'nplb', 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.'
- 'SunnyDayDestination/1'),
+ 'SunnyDayDestination/1'),
test_filter.TestFilter(
'nplb', 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.'
- 'SunnyDaySourceForDestination/1'),
+ 'SunnyDaySourceForDestination/1'),
test_filter.TestFilter(
'nplb', 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.'
- 'SunnyDaySourceNotLoopback/1'),
-
+ 'SunnyDaySourceNotLoopback/1'),
test_filter.TestFilter('starboard_platform_tests',
test_filter.FILTER_ALL),
test_filter.TestFilter('nplb_blitter_pixel_tests',
diff --git a/src/starboard/raspi/shared/launcher.py b/src/starboard/raspi/shared/launcher.py
new file mode 100644
index 0000000..ebf20ed
--- /dev/null
+++ b/src/starboard/raspi/shared/launcher.py
@@ -0,0 +1,248 @@
+#
+# Copyright 2018 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Raspi implementation of Starboard launcher abstraction."""
+
+import functools
+import logging
+import os
+import re
+import signal
+import sys
+import threading
+import time
+
+import _env # pylint: disable=unused-import
+import pexpect
+from starboard.tools import abstract_launcher
+
+
+# pylint: disable=unused-argument
+def _SigIntOrSigTermHandler(signum, frame):
+ """Clean up and exit with status |signum|.
+
+ Args:
+ signum: Signal number that triggered this callback. Passed in when the
+ signal handler is called by python runtime.
+ frame: Current stack frame. Passed in when the signal handler is called
+ by python runtime.
+ """
+ sys.exit(signum)
+
+
+class Launcher(abstract_launcher.AbstractLauncher):
+ """Class for launching Cobalt/tools on Raspi."""
+
+ _STARTUP_TIMEOUT_SECONDS = 900
+
+ _RASPI_USERNAME = 'pi'
+ _RASPI_PASSWORD = 'raspberry'
+
+ # pexpect times out each second to allow Kill to quickly stop a test run
+ _PEXPECT_TIMEOUT = 1
+
+ # Wait up to 30 seconds for the password prompt from the raspi
+ _PEXPECT_PASSWORD_TIMEOUT_MAX_RETRIES = 30
+ # Wait up to 900 seconds for new output from the raspi
+ _PEXPECT_READLINE_TIMEOUT_MAX_RETRIES = 900
+
+ # This is used to strip ansi color codes from pexpect output.
+ _PEXPECT_SANITIZE_LINE_RE = re.compile(r'\x1b[^m]*m')
+
+ def __init__(self, platform, target_name, config, device_id, **kwargs):
+ super(Launcher, self).__init__(platform, target_name, config, device_id,
+ **kwargs)
+ env = os.environ.copy()
+ env.update(self.env_variables)
+ self.full_env = env
+
+ if not self.device_id:
+ self.device_id = self.full_env.get('RASPI_ADDR')
+ if not self.device_id:
+ raise ValueError(
+ 'Unable to determine target, please pass it in, or set RASPI_ADDR '
+ 'environment variable.')
+
+ self.startup_timeout_seconds = Launcher._STARTUP_TIMEOUT_SECONDS
+
+ self.pexpect_process = None
+ self._InitPexpectCommands()
+
+ self.run_inactive = threading.Event()
+ self.run_inactive.set()
+
+ self.shutdown_initiated = threading.Event()
+
+ signal.signal(signal.SIGINT, functools.partial(_SigIntOrSigTermHandler))
+ signal.signal(signal.SIGTERM, functools.partial(_SigIntOrSigTermHandler))
+
+ def _InitPexpectCommands(self):
+ """Initializes all of the pexpect commands needed for running the test."""
+
+ test_path = self.GetTargetPath()
+ if not os.path.isfile(test_path):
+ raise ValueError('TargetPath ({}) must be a file.'.format(test_path))
+
+ test_dir_path, test_file = os.path.split(test_path)
+ test_base_dir = os.path.basename(os.path.normpath(test_dir_path))
+
+ raspi_user_hostname = Launcher._RASPI_USERNAME + '@' + self.device_id
+ raspi_test_path = os.path.join(test_base_dir, test_file)
+
+ # rsync command setup
+ options = '-avzh --exclude obj*'
+ source = test_dir_path
+ destination = raspi_user_hostname + ':~/'
+ self.rsync_command = 'rsync ' + options + ' ' + source + ' ' + destination
+
+ # ssh command setup
+ self.ssh_command = 'ssh ' + raspi_user_hostname
+
+ # escape command line metacharacters in the flags
+ flags = ' '.join(self.target_command_line_params)
+ meta_chars = '()[]{}%!^"<>&|'
+ meta_re = re.compile('(' + '|'.join(
+ re.escape(char) for char in list(meta_chars)) + ')')
+ escaped_flags = re.subn(meta_re, r'\\\1', flags)[0]
+
+ # test output tags
+ self.test_complete_tag = 'TEST-{time}'.format(time=time.time())
+ self.test_success_tag = 'succeeded'
+ self.test_failure_tag = 'failed'
+
+ # test command setup
+ test_base_command = raspi_test_path + ' ' + escaped_flags
+ test_success_output = ' && echo {} {}'.format(self.test_complete_tag,
+ self.test_success_tag)
+ test_failure_output = ' || echo {} {}'.format(self.test_complete_tag,
+ self.test_failure_tag)
+ self.test_command = '{} {} {}'.format(
+ test_base_command, test_success_output, test_failure_output)
+
+ def _PexpectSpawnAndConnect(self, command):
+ """Spawns a process with pexpect and connect to the raspi.
+
+ Args:
+ command: The command to use when spawning the pexpect process.
+ """
+
+ self.pexpect_process = pexpect.spawn(
+ command, timeout=Launcher._PEXPECT_TIMEOUT)
+ retry_count = 0
+ while True:
+ try:
+ self.pexpect_process.expect(r'\S+ password:')
+ break
+ except pexpect.TIMEOUT:
+ if self.shutdown_initiated.is_set():
+ return
+ retry_count += 1
+ # Check if the max retry count has been exceeded. If it has, then
+ # re-raise the timeout exception.
+ if retry_count > Launcher._PEXPECT_PASSWORD_TIMEOUT_MAX_RETRIES:
+ exc_info = sys.exc_info()
+ raise exc_info[0], exc_info[1], exc_info[2]
+ self.pexpect_process.sendline(Launcher._RASPI_PASSWORD)
+
+ def _PexpectReadLines(self):
+ """Reads all lines from the pexpect process."""
+
+ retry_count = 0
+ while True:
+ try:
+ # Sanitize the line to remove ansi color codes.
+ line = Launcher._PEXPECT_SANITIZE_LINE_RE.sub(
+ '', self.pexpect_process.readline())
+ if not line:
+ break
+ self.output_file.write(line)
+ self.output_file.flush()
+ # Check for the test complete tag. It will be followed by either a
+ # success or failure tag.
+ if line.startswith(self.test_complete_tag):
+ if line.find(self.test_success_tag) != -1:
+ self.return_value = 0
+ break
+ # A line was successfully read without timing out; reset the retry
+ # count before attempting to read the next line.
+ retry_count = 0
+ except pexpect.TIMEOUT:
+ if self.shutdown_initiated.is_set():
+ return
+ retry_count += 1
+ # Check if the max retry count has been exceeded. If it has, then
+ # re-raise the timeout exception.
+ if retry_count > Launcher._PEXPECT_READLINE_TIMEOUT_MAX_RETRIES:
+ exc_info = sys.exc_info()
+ raise exc_info[0], exc_info[1], exc_info[2]
+
+ def _CleanupPexpectProcess(self):
+ """Closes current pexpect process."""
+
+ if self.pexpect_process is not None and self.pexpect_process.isalive():
+ # Send ctrl-c to the raspi and close the process.
+ self.pexpect_process.sendline(chr(3))
+ self.pexpect_process.close()
+
+ def Run(self):
+ """Runs launcher's executable on the target raspi.
+
+ Returns:
+ Whether or not the run finished successfully.
+ """
+
+ self.return_value = 1
+
+ try:
+ # Notify other threads that the run is now active
+ self.run_inactive.clear()
+
+ # rsync the test files to the raspi
+ if not self.shutdown_initiated.is_set():
+ self._PexpectSpawnAndConnect(self.rsync_command)
+ if not self.shutdown_initiated.is_set():
+ self._PexpectReadLines()
+
+ # ssh into the raspi and run the test
+ if not self.shutdown_initiated.is_set():
+ self._PexpectSpawnAndConnect(self.ssh_command)
+ if not self.shutdown_initiated.is_set():
+ self.pexpect_process.sendline(self.test_command)
+ self._PexpectReadLines()
+
+ except pexpect.EOF:
+ logging.exception('pexpect encountered EOF while reading line.')
+ except pexpect.TIMEOUT:
+ logging.exception('pexpect timed out while reading line.')
+ # pylint: disable=W0703
+ except Exception:
+ logging.exception('Error occured while running test.')
+ finally:
+ self._CleanupPexpectProcess()
+
+ # Notify other threads that the run is no longer active
+ self.run_inactive.set()
+
+ return self.return_value
+
+ def Kill(self):
+ """Stops the run so that the launcher can be killed."""
+
+ sys.stderr.write('\n***Killing Launcher***\n')
+ if self.run_inactive.is_set():
+ return
+ # Initiate the shutdown. This causes the run to abort within one second.
+ self.shutdown_initiated.set()
+ # Wait up to three seconds for the run to be set to inactive.
+ self.run_inactive.wait(3)
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
index e04395e..3def412 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
@@ -42,7 +42,6 @@
#if LIBAVUTIL_VERSION_MAJOR > 52
void ReleaseBuffer(void* opaque, uint8_t* data) {
- SbMemorySet(data, 0, sizeof(data));
SbMemoryDeallocate(data);
}
diff --git a/src/starboard/shared/posix/memory_flush.cc b/src/starboard/shared/posix/memory_flush.cc
index 202b081..61dadd9 100644
--- a/src/starboard/shared/posix/memory_flush.cc
+++ b/src/starboard/shared/posix/memory_flush.cc
@@ -18,10 +18,6 @@
#include <iomanip>
-#if SB_IS(ARCH_MIPS)
-#include <sys/cachectl.h>
-#endif
-
#include "starboard/log.h"
#if !SB_CAN(MAP_EXECUTABLE_MEMORY)
@@ -37,11 +33,6 @@
<< std::dec << result << "d)";
#endif
-#if SB_IS(ARCH_MIPS)
- _flush_cache(reinterpret_cast<char*>(memory), (size_t)size_bytes, BCACHE);
- return;
-#endif
-
#if !defined(__has_builtin)
#define __has_builtin(a) (0)
#endif
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
index 87ee74b..b2a5220 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -140,8 +140,11 @@
::starboard::ScopedLock lock(video_renderer_existence_mutex_);
- video_renderer_ = player_components->CreateVideoRenderer(
- video_parameters, GetMediaTimeProvider());
+ auto media_time_provider = GetMediaTimeProvider();
+ SB_DCHECK(media_time_provider);
+
+ video_renderer_ = player_components->CreateVideoRenderer(video_parameters,
+ media_time_provider);
video_renderer_->Initialize(
std::bind(&FilterBasedPlayerWorkerHandler::OnError, this));
@@ -418,7 +421,6 @@
if (audio_renderer_) {
return audio_renderer_.get();
}
- SB_DCHECK(media_time_provider_impl_);
return media_time_provider_impl_.get();
}
diff --git a/src/starboard/shared/starboard/player/filter/audio_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
similarity index 97%
rename from src/starboard/shared/starboard/player/filter/audio_decoder_test.cc
rename to src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
index 1f854cb..6bf38cf 100644
--- a/src/starboard/shared/starboard/player/filter/audio_decoder_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
@@ -167,7 +167,7 @@
--number_of_inputs_to_write;
while (number_of_inputs_to_write > 0) {
- Event event;
+ Event event = kError;
ASSERT_NO_FATAL_FAILURE(WaitForNextEvent(&event));
if (event == kConsumed) {
ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index));
@@ -189,7 +189,7 @@
}
for (;;) {
- Event event;
+ Event event = kError;
ASSERT_NO_FATAL_FAILURE(WaitForNextEvent(&event));
if (event == kError) {
if (error_occurred) {
@@ -245,12 +245,13 @@
last_input_buffer_ = dmp_reader_.GetAudioInputBuffer(0);
std::vector<uint8_t> content(last_input_buffer_->size(), 0xab);
// Replace the content with invalid data.
- last_input_buffer_->SetDecryptedContent(content.data(), content.size());
+ last_input_buffer_->SetDecryptedContent(content.data(),
+ static_cast<int>(content.size()));
audio_decoder_->Decode(last_input_buffer_, consumed_cb());
audio_decoder_->WriteEndOfStream();
- bool error_occurred;
+ bool error_occurred = false;
ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred));
// The decoder is allowed to either signal an error or return dummy audio
// data but not both.
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
similarity index 98%
rename from src/starboard/shared/starboard/player/filter/audio_renderer_internal_test.cc
rename to src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
index 30cdab6..babf1f1 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
@@ -233,6 +233,7 @@
static void DeallocateSampleCB(SbPlayer player,
void* context,
const void* sample_buffer) {
+ SB_UNREFERENCED_PARAMETER(player);
AudioRendererTest* test = static_cast<AudioRendererTest*>(context);
EXPECT_TRUE(test != NULL);
test->OnDeallocateSample(sample_buffer);
@@ -264,7 +265,7 @@
Seek(0);
- int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
+ FillRendererWithDecodedAudioAndWriteEOS();
bool is_playing = true;
bool is_eos_played = true;
@@ -342,7 +343,7 @@
Seek(0);
- int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
+ FillRendererWithDecodedAudioAndWriteEOS();
bool is_playing = false;
bool is_eos_played = true;
@@ -406,7 +407,7 @@
audio_renderer_->Play();
- int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
+ FillRendererWithDecodedAudioAndWriteEOS();
SendDecoderOutput(new DecodedAudio);
diff --git a/src/starboard/shared/starboard/player/filter/filter_tests.gypi b/src/starboard/shared/starboard/player/filter/testing/filter_tests.gypi
similarity index 74%
rename from src/starboard/shared/starboard/player/filter/filter_tests.gypi
rename to src/starboard/shared/starboard/player/filter/testing/filter_tests.gypi
index 5babcbf..c635d56 100644
--- a/src/starboard/shared/starboard/player/filter/filter_tests.gypi
+++ b/src/starboard/shared/starboard/player/filter/testing/filter_tests.gypi
@@ -19,16 +19,16 @@
'type': '<(gtest_target_type)',
'sources': [
'<(DEPTH)/starboard/common/test_main.cc',
- '<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_test.cc',
- '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal_test.cc',
- '<(DEPTH)/starboard/shared/starboard/player/filter/fake_graphics_context_provider.cc',
- '<(DEPTH)/starboard/shared/starboard/player/filter/fake_graphics_context_provider.h',
- '<(DEPTH)/starboard/shared/starboard/player/filter/media_time_provider_impl_test.cc',
- '<(DEPTH)/starboard/shared/starboard/player/filter/video_decoder_test.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/media_time_provider_impl_test.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc',
'<(DEPTH)/starboard/shared/starboard/player/video_dmp_common.cc',
'<(DEPTH)/starboard/shared/starboard/player/video_dmp_common.h',
'<(DEPTH)/starboard/shared/starboard/player/video_dmp_reader.cc',
'<(DEPTH)/starboard/shared/starboard/player/video_dmp_reader.h',
+ '<(DEPTH)/starboard/testing/fake_graphics_context_provider.cc',
+ '<(DEPTH)/starboard/testing/fake_graphics_context_provider.h',
],
'defines': [
# This allows the tests to include internal only header files.
@@ -49,7 +49,7 @@
],
'output_dir': '/starboard/shared/starboard/player',
},
- 'includes': ['../../../../build/copy_test_data.gypi'],
+ 'includes': ['../../../../../build/copy_test_data.gypi'],
}
],
},
@@ -62,7 +62,7 @@
'variables': {
'executable_name': 'filter_tests',
},
- 'includes': [ '../../../../build/deploy.gypi' ],
+ 'includes': [ '../../../../../build/deploy.gypi' ],
},
],
}
diff --git a/src/starboard/shared/starboard/player/filter/media_time_provider_impl_test.cc b/src/starboard/shared/starboard/player/filter/testing/media_time_provider_impl_test.cc
similarity index 100%
rename from src/starboard/shared/starboard/player/filter/media_time_provider_impl_test.cc
rename to src/starboard/shared/starboard/player/filter/testing/media_time_provider_impl_test.cc
diff --git a/src/starboard/shared/starboard/player/filter/video_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
similarity index 97%
rename from src/starboard/shared/starboard/player/filter/video_decoder_test.cc
rename to src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
index 3e4d819..e7e452f 100644
--- a/src/starboard/shared/starboard/player/filter/video_decoder_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
@@ -27,11 +27,11 @@
#include "starboard/mutex.h"
#include "starboard/shared/starboard/media/media_support_internal.h"
#include "starboard/shared/starboard/media/media_util.h"
-#include "starboard/shared/starboard/player/filter/fake_graphics_context_provider.h"
#include "starboard/shared/starboard/player/filter/player_components.h"
#include "starboard/shared/starboard/player/job_queue.h"
#include "starboard/shared/starboard/player/video_dmp_reader.h"
#include "starboard/string.h"
+#include "starboard/testing/fake_graphics_context_provider.h"
#include "starboard/thread.h"
#include "starboard/time.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -48,6 +48,7 @@
namespace testing {
namespace {
+using ::starboard::testing::FakeGraphicsContextProvider;
using ::std::placeholders::_1;
using ::std::placeholders::_2;
using ::testing::ValuesIn;
@@ -374,7 +375,7 @@
WriteSingleInput(0);
WriteEndOfStream();
- bool error_occurred;
+ bool error_occurred = false;
ASSERT_NO_FATAL_FAILURE(DrainOutputs(
&error_occurred, [=](const Event& event, bool* continue_process) {
if (event.frame) {
@@ -391,12 +392,13 @@
outstanding_inputs_.insert(input_buffer->pts());
std::vector<uint8_t> content(input_buffer->size(), 0xab);
// Replace the content with invalid data.
- input_buffer->SetDecryptedContent(content.data(), content.size());
+ input_buffer->SetDecryptedContent(content.data(),
+ static_cast<int>(content.size()));
video_decoder_->WriteInputBuffer(input_buffer);
WriteEndOfStream();
- bool error_occurred;
+ bool error_occurred = true;
ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred));
if (error_occurred) {
ASSERT_TRUE(decoded_frames_.empty());
@@ -442,6 +444,7 @@
ASSERT_NO_FATAL_FAILURE(WriteMultipleInputs(
0, dmp_reader_.number_of_video_buffers(),
[&](const Event& event, bool* continue_process) {
+ SB_UNREFERENCED_PARAMETER(event);
frames_decoded += decoded_frames_.size();
decoded_frames_.clear();
*continue_process = frames_decoded < number_of_expected_decoded_frames;
@@ -458,6 +461,7 @@
ASSERT_NO_FATAL_FAILURE(WriteMultipleInputs(
0, dmp_reader_.number_of_video_buffers(),
[=](const Event& event, bool* continue_process) {
+ SB_UNREFERENCED_PARAMETER(event);
if (decoded_frames_.size() >= video_decoder_->GetPrerollFrameCount()) {
*continue_process = false;
return;
@@ -477,12 +481,14 @@
ASSERT_NO_FATAL_FAILURE(WriteMultipleInputs(
0, dmp_reader_.number_of_video_buffers(),
[=](const Event& event, bool* continue_process) {
+ SB_UNREFERENCED_PARAMETER(event);
*continue_process = decoded_frames_.size() < kMaxCachedFrames;
}));
WriteEndOfStream();
bool error_occurred = false;
ASSERT_NO_FATAL_FAILURE(DrainOutputs(
&error_occurred, [=](const Event& event, bool* continue_process) {
+ SB_UNREFERENCED_PARAMETER(event);
*continue_process = decoded_frames_.size() < kMaxCachedFrames;
}));
ASSERT_FALSE(error_occurred);
@@ -501,6 +507,7 @@
ASSERT_NO_FATAL_FAILURE(WriteMultipleInputs(
0, gop_size, [=](const Event& event, bool* continue_process) {
+ SB_UNREFERENCED_PARAMETER(event);
while (decoded_frames_.size() >
video_decoder_->GetPrerollFrameCount()) {
decoded_frames_.pop_front();
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
index 5186d7e..8d4fd20 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
@@ -105,8 +105,8 @@
return;
}
end_of_stream_written_ = true;
- decoder_->WriteEndOfStream();
first_input_written_ = true;
+ decoder_->WriteEndOfStream();
}
void VideoRenderer::Seek(SbMediaTime seek_to_pts) {
diff --git a/src/starboard/shared/starboard/player/video_dmp_common.cc b/src/starboard/shared/starboard/player/video_dmp_common.cc
index 4f7d166..c729bd1 100644
--- a/src/starboard/shared/starboard/player/video_dmp_common.cc
+++ b/src/starboard/shared/starboard/player/video_dmp_common.cc
@@ -28,8 +28,8 @@
int32_t int32_value; \
Read(read_cb, &int32_value, sizeof(int32_value)); \
if (reverse_byte_order) { \
- std::reverse(reinterpret_cast<uint8_t*>(int32_value), \
- reinterpret_cast<uint8_t*>(int32_value + 1)); \
+ std::reverse(reinterpret_cast<uint8_t*>(&int32_value), \
+ reinterpret_cast<uint8_t*>(&int32_value + 1)); \
} \
*value = static_cast<Type>(int32_value); \
}
@@ -40,8 +40,8 @@
uint32_t uint32_value; \
Read(read_cb, &uint32_value, sizeof(uint32_value)); \
if (reverse_byte_order) { \
- std::reverse(reinterpret_cast<uint8_t*>(uint32_value), \
- reinterpret_cast<uint8_t*>(uint32_value + 1)); \
+ std::reverse(reinterpret_cast<uint8_t*>(&uint32_value), \
+ reinterpret_cast<uint8_t*>(&uint32_value + 1)); \
} \
*value = static_cast<Type>(uint32_value); \
}
diff --git a/src/starboard/shared/starboard/player/video_dmp_reader.cc b/src/starboard/shared/starboard/player/video_dmp_reader.cc
index 98c8c91..882c6e1 100644
--- a/src/starboard/shared/starboard/player/video_dmp_reader.cc
+++ b/src/starboard/shared/starboard/player/video_dmp_reader.cc
@@ -50,7 +50,11 @@
static void DeallocateSampleFunc(SbPlayer player,
void* context,
- const void* sample_buffer) {}
+ const void* sample_buffer) {
+ SB_UNREFERENCED_PARAMETER(player);
+ SB_UNREFERENCED_PARAMETER(context);
+ SB_UNREFERENCED_PARAMETER(sample_buffer);
+}
} // namespace
@@ -76,8 +80,8 @@
SB_DCHECK(index < audio_access_units_.size());
const AudioAccessUnit& au = audio_access_units_[index];
return new InputBuffer(kSbMediaTypeAudio, DeallocateSampleFunc, NULL, NULL,
- au.data().data(), au.data().size(), au.timestamp(),
- NULL, NULL);
+ au.data().data(), static_cast<int>(au.data().size()),
+ au.timestamp(), NULL, NULL);
}
scoped_refptr<InputBuffer> VideoDmpReader::GetVideoInputBuffer(
@@ -85,8 +89,8 @@
SB_DCHECK(index < video_access_units_.size());
const VideoAccessUnit& au = video_access_units_[index];
return new InputBuffer(kSbMediaTypeVideo, DeallocateSampleFunc, NULL, NULL,
- au.data().data(), au.data().size(), au.timestamp(),
- &au.video_sample_info(), NULL);
+ au.data().data(), static_cast<int>(au.data().size()),
+ au.timestamp(), &au.video_sample_info(), NULL);
}
void VideoDmpReader::Parse() {
@@ -110,8 +114,8 @@
break;
}
if (reverse_byte_order_) {
- std::reverse(reinterpret_cast<uint8_t*>(type),
- reinterpret_cast<uint8_t*>(type + 1));
+ std::reverse(reinterpret_cast<uint8_t*>(&type),
+ reinterpret_cast<uint8_t*>(&type + 1));
}
switch (type) {
case kRecordTypeAudioConfig:
diff --git a/src/starboard/shared/uwp/sso.cc b/src/starboard/shared/uwp/sso.cc
index 7c5c67f..1378c78 100644
--- a/src/starboard/shared/uwp/sso.cc
+++ b/src/starboard/shared/uwp/sso.cc
@@ -56,7 +56,20 @@
namespace uwp {
concurrency::task<WebTokenRequestResult^> TryToFetchSsoToken(
+ const std::string& url, bool prompt);
+
+concurrency::task<WebTokenRequestResult^> TryToFetchSsoToken(
const std::string& url) {
+ return TryToFetchSsoToken(url, false);
+}
+
+concurrency::task<WebTokenRequestResult^> TryToFetchSsoTokenAndPrompt(
+ const std::string& url) {
+ return TryToFetchSsoToken(url, true);
+}
+
+concurrency::task<WebTokenRequestResult^> TryToFetchSsoToken(
+ const std::string& url, bool prompt) {
if (SbFileExists(GetSsoRejectionFilePath().c_str())) {
concurrency::task_completion_event<WebTokenRequestResult^> result;
result.set(nullptr);
@@ -65,7 +78,7 @@
return concurrency::create_task(
WebAuthenticationCoreManager::FindAccountProviderAsync(
sbwin32::stringToPlatformString(kXboxLiveAccountProviderId)))
- .then([url](concurrency::task<WebAccountProvider^> previous_task) {
+ .then([url, prompt](concurrency::task<WebAccountProvider^> previous_task) {
WebAccountProvider^ xbox_provider = nullptr;
try {
xbox_provider = previous_task.get();
@@ -83,7 +96,7 @@
bool main_thread = sbuwp::GetDispatcher()->HasThreadAccess;
- if (main_thread) {
+ if (main_thread && prompt) {
return concurrency::create_task(
WebAuthenticationCoreManager::RequestTokenAsync(request));
} else {
@@ -118,10 +131,10 @@
case WebTokenRequestStatus::UserInteractionRequired: {
concurrency::task_completion_event<WebTokenRequestResult^> completion;
RunInMainThreadAsync([url, completion]() {
- // When we run TryToFetchSsoToken in the main thread,
+ // When we run TryToFetchSsoTokenAndPrompt in the main thread,
// we'll always ask for user input via RequestTokenAsync, which
// never returns this case.
- TryToFetchSsoToken(url)
+ TryToFetchSsoTokenAndPrompt(url)
.then([completion](concurrency::task<WebTokenRequestResult^> result) {
try {
completion.set(result.get());
diff --git a/src/starboard/shared/win32/audio_decoder.cc b/src/starboard/shared/win32/audio_decoder.cc
index b9440e8..d851857 100644
--- a/src/starboard/shared/win32/audio_decoder.cc
+++ b/src/starboard/shared/win32/audio_decoder.cc
@@ -64,11 +64,6 @@
sample_type_(kSbMediaAudioSampleTypeFloat32),
stream_ended_(false) {
SB_DCHECK(audio_codec == kSbMediaAudioCodecAac);
- decoder_impl_ = AbstractWin32AudioDecoder::Create(
- audio_codec_, GetStorageType(), GetSampleType(), audio_header_,
- drm_system_);
- decoder_thread_.reset(new AudioDecoderThread(decoder_impl_.get(), this));
- callback_scheduler_.reset(new CallbackScheduler());
}
AudioDecoder::~AudioDecoder() {
@@ -87,6 +82,11 @@
SB_DCHECK(output_cb);
SB_DCHECK(!output_cb_);
output_cb_ = output_cb;
+ decoder_impl_ = AbstractWin32AudioDecoder::Create(
+ audio_codec_, GetStorageType(), GetSampleType(), audio_header_,
+ drm_system_);
+ decoder_thread_.reset(new AudioDecoderThread(decoder_impl_.get(), this));
+ callback_scheduler_.reset(new CallbackScheduler());
}
void AudioDecoder::Decode(const scoped_refptr<InputBuffer>& input_buffer,
diff --git a/src/starboard/shared/win32/decrypting_decoder.cc b/src/starboard/shared/win32/decrypting_decoder.cc
index b713f25..c02670e 100644
--- a/src/starboard/shared/win32/decrypting_decoder.cc
+++ b/src/starboard/shared/win32/decrypting_decoder.cc
@@ -203,7 +203,11 @@
drm_system_->GetLicense(key_id, key_id_size);
if (license && license->usable()) {
decryptor_.reset(new MediaTransform(license->decryptor()));
- ActivateDecryptor();
+ bool success = ActivateDecryptor();
+ if (!success) {
+ decryptor_.reset();
+ return false;
+ }
}
}
if (!decryptor_) {
@@ -257,7 +261,7 @@
}
}
-void DecryptingDecoder::ActivateDecryptor() {
+bool DecryptingDecoder::ActivateDecryptor() {
SB_DCHECK(decryptor_);
ComPtr<IMFMediaType> decoder_output_type = decoder_->GetCurrentOutputType();
@@ -290,7 +294,7 @@
std::min(decoder_protection_version, decryption_protection_version);
if (protection_version < SAMPLE_PROTECTION_VERSION_RC4) {
SB_NOTREACHED();
- return;
+ return true;
}
BYTE* cert_data = NULL;
@@ -305,6 +309,11 @@
hr = decryption_sample_protection->InitOutputProtection(
protection_version, 0, cert_data, cert_data_size, &crypt_seed,
&crypt_seed_size);
+ if (FAILED(hr)) {
+ // This can happen if we call InitOutputProtection while procesing
+ // a UWP resume event or shortly after.
+ return false;
+ }
CheckResult(hr);
hr = decoder_sample_protection->InitInputProtection(
@@ -331,9 +340,10 @@
output_type->GetGUID(MF_MT_SUBTYPE, &sub_type);
if (IsEqualGUID(sub_type, original_sub_type)) {
decoder_->SetOutputType(output_type);
- return;
+ return true;
}
}
+ return true;
}
void DecryptingDecoder::Reset() {
diff --git a/src/starboard/shared/win32/decrypting_decoder.h b/src/starboard/shared/win32/decrypting_decoder.h
index c12bda4..225d612 100644
--- a/src/starboard/shared/win32/decrypting_decoder.h
+++ b/src/starboard/shared/win32/decrypting_decoder.h
@@ -63,7 +63,7 @@
void Reset();
private:
- void ActivateDecryptor();
+ bool ActivateDecryptor();
// TODO: Clarify the thread pattern of this class.
const std::string type_; // For debugging purpose.
diff --git a/src/starboard/shared/win32/video_decoder.cc b/src/starboard/shared/win32/video_decoder.cc
index 5b531ec..f3136b2 100644
--- a/src/starboard/shared/win32/video_decoder.cc
+++ b/src/starboard/shared/win32/video_decoder.cc
@@ -169,8 +169,6 @@
ComPtr<ID3D11DeviceContext> d3d_context;
d3d_device_->GetImmediateContext(d3d_context.GetAddressOf());
CheckResult(d3d_context.As(&video_context_));
-
- InitializeCodec();
}
VideoDecoder::~VideoDecoder() {
@@ -199,6 +197,7 @@
SB_DCHECK(error_cb);
decoder_status_cb_ = decoder_status_cb;
error_cb_ = error_cb;
+ InitializeCodec();
}
void VideoDecoder::WriteInputBuffer(
diff --git a/src/starboard/shared/starboard/player/filter/fake_graphics_context_provider.cc b/src/starboard/testing/fake_graphics_context_provider.cc
similarity index 69%
rename from src/starboard/shared/starboard/player/filter/fake_graphics_context_provider.cc
rename to src/starboard/testing/fake_graphics_context_provider.cc
index be3549a..69f52e8 100644
--- a/src/starboard/shared/starboard/player/filter/fake_graphics_context_provider.cc
+++ b/src/starboard/testing/fake_graphics_context_provider.cc
@@ -12,34 +12,66 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/shared/starboard/player/filter/fake_graphics_context_provider.h"
+#include "starboard/testing/fake_graphics_context_provider.h"
-#include <functional>
+#include "starboard/configuration.h"
namespace starboard {
-namespace shared {
-namespace starboard {
-namespace player {
-namespace filter {
namespace testing {
-FakeGraphicsContextProvider::FakeGraphicsContextProvider()
- : decode_target_context_thread_("dt_context") {
+FakeGraphicsContextProvider::FakeGraphicsContextProvider() {
+#if SB_HAS(BLITTER)
+ decoder_target_provider_.device = kSbBlitterInvalidDevice;
+#elif SB_HAS(GLES2)
+ decoder_target_provider_.egl_display = NULL;
+ decoder_target_provider_.egl_context = NULL;
decoder_target_provider_.gles_context_runner = DecodeTargetGlesContextRunner;
decoder_target_provider_.gles_context_runner_context = this;
+
+ decode_target_context_thread_ = SbThreadCreate(
+ 0, kSbThreadPriorityNormal, kSbThreadNoAffinity, true, "dt_context",
+ &FakeGraphicsContextProvider::ThreadEntryPoint, this);
+#endif // SB_HAS(BLITTER)
}
+FakeGraphicsContextProvider::~FakeGraphicsContextProvider() {
+#if SB_HAS(GLES2)
+ functor_queue_.Wake();
+ SbThreadJoin(decode_target_context_thread_, NULL);
+#endif // SB_HAS(GLES2)
+}
+
+#if SB_HAS(GLES2)
+
void FakeGraphicsContextProvider::ReleaseDecodeTarget(
SbDecodeTarget decode_target) {
Mutex mutex;
ConditionVariable condition_variable(mutex);
ScopedLock scoped_lock(mutex);
- decode_target_context_thread_.job_queue()->Schedule(std::bind(
+
+ functor_queue_.Put(std::bind(
&FakeGraphicsContextProvider::ReleaseDecodeTargetOnGlesContextThread,
this, &mutex, &condition_variable, decode_target));
condition_variable.Wait();
}
+// static
+void* FakeGraphicsContextProvider::ThreadEntryPoint(void* context) {
+ auto provider = static_cast<FakeGraphicsContextProvider*>(context);
+ provider->RunLoop();
+
+ return NULL;
+}
+
+void FakeGraphicsContextProvider::RunLoop() {
+ while (std::function<void()> functor = functor_queue_.Get()) {
+ if (!functor) {
+ break;
+ }
+ functor();
+ }
+}
+
void FakeGraphicsContextProvider::ReleaseDecodeTargetOnGlesContextThread(
Mutex* mutex,
ConditionVariable* condition_variable,
@@ -65,7 +97,8 @@
Mutex mutex;
ConditionVariable condition_variable(mutex);
ScopedLock scoped_lock(mutex);
- decode_target_context_thread_.job_queue()->Schedule(std::bind(
+
+ functor_queue_.Put(std::bind(
&FakeGraphicsContextProvider::RunDecodeTargetFunctionOnGlesContextThread,
this, &mutex, &condition_variable, target_function,
target_function_context));
@@ -84,9 +117,7 @@
target_function_context);
}
+#endif // SB_HAS(GLES2)
+
} // namespace testing
-} // namespace filter
-} // namespace player
-} // namespace starboard
-} // namespace shared
} // namespace starboard
diff --git a/src/starboard/shared/starboard/player/filter/fake_graphics_context_provider.h b/src/starboard/testing/fake_graphics_context_provider.h
similarity index 69%
rename from src/starboard/shared/starboard/player/filter/fake_graphics_context_provider.h
rename to src/starboard/testing/fake_graphics_context_provider.h
index 0c6a3a4..fae6c1d 100644
--- a/src/starboard/shared/starboard/player/filter/fake_graphics_context_provider.h
+++ b/src/starboard/testing/fake_graphics_context_provider.h
@@ -12,36 +12,45 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_FAKE_GRAPHICS_CONTEXT_PROVIDER_H_
-#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_FAKE_GRAPHICS_CONTEXT_PROVIDER_H_
+#ifndef STARBOARD_TESTING_FAKE_GRAPHICS_CONTEXT_PROVIDER_H_
+#define STARBOARD_TESTING_FAKE_GRAPHICS_CONTEXT_PROVIDER_H_
+
+#include <functional>
#include "starboard/condition_variable.h"
#include "starboard/decode_target.h"
#include "starboard/mutex.h"
-#include "starboard/shared/starboard/player/job_queue.h"
-#include "starboard/shared/starboard/player/job_thread.h"
+#include "starboard/queue.h"
+#include "starboard/thread.h"
namespace starboard {
-namespace shared {
-namespace starboard {
-namespace player {
-namespace filter {
namespace testing {
// This class provides a SbDecodeTargetGraphicsContextProvider implementation
-// used by VideoDecoder related tests. It creates a thread and forwards decode
+// used by SbPlayer related tests. It creates a thread and forwards decode
// target creation/destruction to the thread.
class FakeGraphicsContextProvider {
public:
FakeGraphicsContextProvider();
+ ~FakeGraphicsContextProvider();
SbDecodeTargetGraphicsContextProvider* decoder_target_provider() {
+#if SB_HAS(BLITTER) || SB_HAS(GLES2)
return &decoder_target_provider_;
+#else // SB_HAS(BLITTER) || SB_HAS(GLES2)
+ return NULL;
+#endif // SB_HAS(BLITTER) || SB_HAS(GLES2)
}
+#if SB_HAS(BLITTER) || SB_HAS(GLES2)
void ReleaseDecodeTarget(SbDecodeTarget decode_target);
+#endif // SB_HAS(BLITTER) || SB_HAS(GLES2)
private:
+ static void* ThreadEntryPoint(void* context);
+ void RunLoop();
+
+#if SB_HAS(GLES2)
void ReleaseDecodeTargetOnGlesContextThread(
Mutex* mutex,
ConditionVariable* condition_variable,
@@ -60,16 +69,16 @@
SbDecodeTargetGraphicsContextProvider* graphics_context_provider,
SbDecodeTargetGlesContextRunnerTarget target_function,
void* target_function_context);
+#endif // SB_HAS(GLES2)
- JobThread decode_target_context_thread_;
+#if SB_HAS(BLITTER) || SB_HAS(GLES2)
+ Queue<std::function<void()>> functor_queue_;
+ SbThread decode_target_context_thread_;
SbDecodeTargetGraphicsContextProvider decoder_target_provider_;
+#endif // SB_HAS(BLITTER) || SB_HAS(GLES2)
};
} // namespace testing
-} // namespace filter
-} // namespace player
-} // namespace starboard
-} // namespace shared
} // namespace starboard
-#endif // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_FAKE_GRAPHICS_CONTEXT_PROVIDER_H_
+#endif // STARBOARD_TESTING_FAKE_GRAPHICS_CONTEXT_PROVIDER_H_
diff --git a/src/starboard/tools/raspi/run_test.py b/src/starboard/tools/raspi/run_test.py
deleted file mode 100755
index 326b654..0000000
--- a/src/starboard/tools/raspi/run_test.py
+++ /dev/null
@@ -1,234 +0,0 @@
-#!/usr/bin/python2
-#
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the 'License');
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Run a test on Raspi device and print results of test to stdout."""
-
-from __future__ import print_function
-
-import argparse
-import functools
-import logging
-import os
-import re
-import signal
-import sys
-import textwrap
-import time
-
-import pexpect
-
-_COBALT_SRC = os.path.abspath(os.path.join(*([__file__] + 4 * [os.pardir])))
-
-_RASPI_USERNAME = 'pi'
-_RASPI_PASSWORD = 'raspberry'
-
-# Timeouts are in seconds
-_PEXPECT_DEFAULT_TIMEOUT = 600
-_PEXPECT_EXPECT_TIMEOUT = 60
-
-
-def _CleanupProcess(process):
- """Closes current pexpect process.
-
- Args:
- process: Current pexpect process.
- """
- if process is not None and process.isalive():
- # Send ctrl-c to the raspi.
- process.sendline(chr(3))
- process.close()
-
-
-# pylint: disable=unused-argument
-def _SigIntOrSigTermHandler(process, signum, frame):
- """Clean up and exit with status |signum|.
-
- Args:
- process: Current pexpect process.
- signum: Signal number that triggered this callback. Passed in when the
- signal handler is called by python runtime.
- frame: Current stack frame. Passed in when the signal handler is called by
- python runtime.
- """
- _CleanupProcess(process)
- sys.exit(signum)
-
-
-def _RunTest(test_path, raspi_ip, flags):
- """Run a test on a Raspi machine and print relevant stdout.
-
- Args:
- test_path: path to the binary test file to be run
- raspi_ip: the IP address of the Raspi device to run the test on
- flags: list of flags to pass into binary.
-
- Returns:
- Exit status of running the test.
- """
- return_value = 1
-
- try:
- process = None
-
- if not os.path.isfile(test_path):
- raise ValueError('test_path ({}) must be a file.'.format(test_path))
-
- # This is used to strip ansi color codes from output.
- sanitize_line_re = re.compile(r'\x1b[^m]*m')
-
- sys.stdout.write('Process launched, ID={}\n'.format(os.getpid()))
- sys.stdout.flush()
-
- test_dir_path, test_file = os.path.split(test_path)
- test_base_dir = os.path.basename(os.path.normpath(test_dir_path))
-
- raspi_user_hostname = _RASPI_USERNAME + '@' + raspi_ip
- raspi_test_path = os.path.join(test_base_dir, test_file)
-
- # rsync the test files to the raspi
- options = '-avzh --exclude obj*'
- source = test_dir_path
- destination = raspi_user_hostname + ':~/'
- rsync_command = 'rsync ' + options + ' ' + source + ' ' + destination
- process = pexpect.spawn(rsync_command, timeout=_PEXPECT_DEFAULT_TIMEOUT)
-
- signal.signal(signal.SIGINT,
- functools.partial(_SigIntOrSigTermHandler, process))
- signal.signal(signal.SIGTERM,
- functools.partial(_SigIntOrSigTermHandler, process))
-
- process.expect(r'\S+ password:', timeout=_PEXPECT_EXPECT_TIMEOUT)
- process.sendline(_RASPI_PASSWORD)
-
- while True:
- line = sanitize_line_re.sub('', process.readline())
- if line:
- sys.stdout.write(line)
- sys.stdout.flush()
- else:
- break
-
- # ssh into the raspi and run the test
- ssh_command = 'ssh ' + raspi_user_hostname
- process = pexpect.spawn(ssh_command, timeout=_PEXPECT_DEFAULT_TIMEOUT)
-
- signal.signal(signal.SIGINT,
- functools.partial(_SigIntOrSigTermHandler, process))
- signal.signal(signal.SIGTERM,
- functools.partial(_SigIntOrSigTermHandler, process))
-
- process.expect(r'\S+ password:', timeout=_PEXPECT_EXPECT_TIMEOUT)
- process.sendline(_RASPI_PASSWORD)
-
- # Escape command line metacharacters in the flags
- meta_chars = '()[]{}%!^"<>&|'
- meta_re = re.compile('(' + '|'.join(
- re.escape(char) for char in list(meta_chars)) + ')')
- escaped_flags = re.subn(meta_re, r'\\\1', flags)[0]
-
- test_command = raspi_test_path + ' ' + escaped_flags
- test_time_tag = 'TEST-{time}'.format(time=time.time())
- test_success_tag = 'succeeded'
- test_failure_tag = 'failed'
- test_success_output = ' && echo ' + test_time_tag + ' ' + test_success_tag
- test_failure_output = ' || echo ' + test_time_tag + ' ' + test_failure_tag
- process.sendline(test_command + test_success_output + test_failure_output)
-
- while True:
- line = sanitize_line_re.sub('', process.readline())
- if not line:
- break
- sys.stdout.write(line)
- sys.stdout.flush()
- if line.startswith(test_time_tag):
- if line.find(test_success_tag) != -1:
- return_value = 0
- break
-
- except ValueError:
- logging.exception('Test path invalid.')
- except pexpect.EOF:
- logging.exception('pexpect encountered EOF while reading line.')
- except pexpect.TIMEOUT:
- logging.exception('pexpect timed out while reading line.')
- # pylint: disable=W0703
- except Exception:
- logging.exception('Error occured while running test.')
- finally:
- _CleanupProcess(process)
-
- return return_value
-
-
-def _AddTargetFlag(parser):
- """Add target to argument parser."""
- parser.add_argument(
- '-t',
- '--target',
- default=None,
- help=(
- 'IP address of the Raspi device to send package to. If no value is '
- 'specified for this argument then it will default to the '
- 'environment variable `RASPI_ADDR\' if that is set, and '
- 'otherwise exit with status code 1.'),
- nargs='?')
-
-
-def _AddFlagsFlag(parser, default=None):
- """Add flags to argument parser.
-
- Args:
- parser: An ArgumentParser instance.
- default: A string consisting of default value.
- """
- if default is None:
- default = ''
- parser.add_argument(
- '-f',
- '--flags',
- default=default,
- help=('Space separated flags that will be forwarded into Cobalt upon '
- 'launch. Note that there is no way to pass in a flag that has a '
- 'space in it.'),
- nargs='?')
-
-
-def main():
- """Run RunTest using path to binary provided by command line arguments.
-
- Returns:
- exit status
- """
- sys.path.append(os.path.join(_COBALT_SRC, 'cobalt', 'build'))
-
- logging.basicConfig(
- level=logging.INFO,
- format='%(levelname)s|%(filename)s:%(lineno)s|%(message)s')
-
- parser = argparse.ArgumentParser(
- formatter_class=argparse.ArgumentDefaultsHelpFormatter,
- description=textwrap.dedent(__doc__))
-
- _AddFlagsFlag(parser)
- _AddTargetFlag(parser)
- parser.add_argument('test_path', help='Path of test to be run.', type=str)
-
- args = parser.parse_args()
-
- return _RunTest(args.test_path, raspi_ip=args.target, flags=args.flags)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/src/starboard_configuration.py b/src/starboard_configuration.py
index 75bc5ce..cff7294 100644
--- a/src/starboard_configuration.py
+++ b/src/starboard_configuration.py
@@ -18,6 +18,7 @@
# relative to the location of this file.
PORT_ROOTS = [
["starboard"],
+ ["starboard", "contrib"],
["starboard", "port"],
["third_party", "starboard"]
]