blob: e79443d6544381ff663760ab09634838744885b7 [file] [log] [blame]
// Copyright 2019 The Cobalt Authors. 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.
#include "cobalt/script/v8c/common_v8c_bindings_code.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "cobalt/script/wrappable.h"
namespace cobalt {
namespace script {
namespace v8c {
namespace shared_bindings {
// All code here are intended to be used by v8c bindings code.
bool object_implements_interface(
v8::Local<v8::FunctionTemplate> function_template, v8::Isolate* isolate,
v8::Local<v8::Object> object) {
V8cGlobalEnvironment* global_environment =
V8cGlobalEnvironment::GetFromIsolate(isolate);
WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
if (!WrapperPrivate::HasWrapperPrivate(object) ||
!function_template->HasInstance(object)) {
V8cExceptionState exception(isolate);
exception.SetSimpleException(script::kDoesNotImplementInterface);
return false;
}
return true;
}
void set_intrinsic_error_prototype_interface_template(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> function_template) {
// 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);
}
void set_property_for_nonconstructor_attribute(
v8::Isolate* isolate, bool configurable, bool has_setter, bool on_interface,
bool on_instance, v8::Local<v8::FunctionTemplate> function_template,
v8::Local<v8::ObjectTemplate> instance_template,
v8::Local<v8::ObjectTemplate> prototype_template, const char* idl_name,
v8::FunctionCallback IDLGetter, v8::FunctionCallback IDLSetter) {
// The name of the property is the identifier of the attribute.
v8::Local<v8::String> name = NewInternalString(isolate, 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;
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.
v8::Local<v8::FunctionTemplate> getter =
v8::FunctionTemplate::New(isolate, IDLGetter);
v8::Local<v8::FunctionTemplate> setter;
if (has_setter) {
setter = v8::FunctionTemplate::New(isolate, IDLSetter);
}
// The location of the property is determined as follows:
if (on_interface) {
// 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->SetAccessorProperty(name, getter, setter, attributes);
} else if (on_instance) {
// 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->SetAccessorProperty(name, getter, setter, attributes);
} else {
// Otherwise, the property exists solely on the interface's interface
// prototype object.
prototype_template->SetAccessorProperty(name, getter, setter, attributes);
}
}
} // namespace shared_bindings
} // namespace v8c
} // namespace script
} // namespace cobalt