| Index: third_party/WebKit/Source/bindings/core/v8/V8Binding.cpp
|
| diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Binding.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Binding.cpp
|
| index 91a12d24b57bbacdd9b99e5e7160490c90d658d5..8e6594f49de404bfcb9fb9e8f51360db9a4fbfdd 100644
|
| --- a/third_party/WebKit/Source/bindings/core/v8/V8Binding.cpp
|
| +++ b/third_party/WebKit/Source/bindings/core/v8/V8Binding.cpp
|
| @@ -30,841 +30,10 @@
|
|
|
| #include "bindings/core/v8/V8Binding.h"
|
|
|
| -#include "bindings/core/v8/ScriptController.h"
|
| -#include "bindings/core/v8/V8AbstractEventListener.h"
|
| -#include "bindings/core/v8/V8ArrayBufferView.h"
|
| #include "bindings/core/v8/V8BindingMacros.h"
|
| -#include "bindings/core/v8/V8Element.h"
|
| -#include "bindings/core/v8/V8EventTarget.h"
|
| -#include "bindings/core/v8/V8HTMLLinkElement.h"
|
| -#include "bindings/core/v8/V8NodeFilter.h"
|
| -#include "bindings/core/v8/V8NodeFilterCondition.h"
|
| -#include "bindings/core/v8/V8ObjectConstructor.h"
|
| -#include "bindings/core/v8/V8Window.h"
|
| -#include "bindings/core/v8/V8WorkerGlobalScope.h"
|
| -#include "bindings/core/v8/V8WorkletGlobalScope.h"
|
| -#include "bindings/core/v8/V8XPathNSResolver.h"
|
| -#include "bindings/core/v8/WindowProxy.h"
|
| -#include "bindings/core/v8/WorkerOrWorkletScriptController.h"
|
| -#include "bindings/core/v8/custom/V8CustomXPathNSResolver.h"
|
| -#include "core/dom/Document.h"
|
| -#include "core/dom/Element.h"
|
| -#include "core/dom/FlexibleArrayBufferView.h"
|
| -#include "core/dom/NodeFilter.h"
|
| -#include "core/dom/QualifiedName.h"
|
| -#include "core/frame/LocalDOMWindow.h"
|
| -#include "core/frame/LocalFrame.h"
|
| -#include "core/frame/LocalFrameClient.h"
|
| -#include "core/frame/Settings.h"
|
| -#include "core/inspector/InspectorTraceEvents.h"
|
| -#include "core/loader/FrameLoader.h"
|
| -#include "core/workers/WorkerGlobalScope.h"
|
| -#include "core/workers/WorkletGlobalScope.h"
|
| -#include "core/xml/XPathNSResolver.h"
|
| -#include "platform/instrumentation/tracing/TracedValue.h"
|
| -#include "platform/wtf/MathExtras.h"
|
| -#include "platform/wtf/StdLibExtras.h"
|
| -#include "platform/wtf/Threading.h"
|
| -#include "platform/wtf/text/AtomicString.h"
|
| -#include "platform/wtf/text/CString.h"
|
| -#include "platform/wtf/text/CharacterNames.h"
|
| -#include "platform/wtf/text/StringBuffer.h"
|
| -#include "platform/wtf/text/StringHash.h"
|
| -#include "platform/wtf/text/Unicode.h"
|
| -#include "platform/wtf/text/WTFString.h"
|
|
|
| namespace blink {
|
|
|
| -NodeFilter* ToNodeFilter(v8::Local<v8::Value> callback,
|
| - v8::Local<v8::Object> creation_context,
|
| - ScriptState* script_state) {
|
| - if (callback->IsNull())
|
| - return nullptr;
|
| - NodeFilter* filter = NodeFilter::Create();
|
| -
|
| - v8::Local<v8::Value> filter_wrapper =
|
| - ToV8(filter, creation_context, script_state->GetIsolate());
|
| - if (filter_wrapper.IsEmpty())
|
| - return nullptr;
|
| -
|
| - NodeFilterCondition* condition = V8NodeFilterCondition::Create(
|
| - callback, filter_wrapper.As<v8::Object>(), script_state);
|
| - filter->SetCondition(condition);
|
| -
|
| - return filter;
|
| -}
|
| -
|
| -bool ToBooleanSlow(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - ExceptionState& exception_state) {
|
| - DCHECK(!value->IsBoolean());
|
| - v8::TryCatch block(isolate);
|
| - bool result = false;
|
| - if (!V8Call(value->BooleanValue(isolate->GetCurrentContext()), result, block))
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return result;
|
| -}
|
| -
|
| -const int32_t kMaxInt32 = 0x7fffffff;
|
| -const int32_t kMinInt32 = -kMaxInt32 - 1;
|
| -const uint32_t kMaxUInt32 = 0xffffffff;
|
| -const int64_t kJSMaxInteger =
|
| - 0x20000000000000LL -
|
| - 1; // 2^53 - 1, maximum uniquely representable integer in ECMAScript.
|
| -
|
| -static double EnforceRange(double x,
|
| - double minimum,
|
| - double maximum,
|
| - const char* type_name,
|
| - ExceptionState& exception_state) {
|
| - if (std::isnan(x) || std::isinf(x)) {
|
| - exception_state.ThrowTypeError(
|
| - "Value is" + String(std::isinf(x) ? " infinite and" : "") +
|
| - " not of type '" + String(type_name) + "'.");
|
| - return 0;
|
| - }
|
| - x = trunc(x);
|
| - if (x < minimum || x > maximum) {
|
| - exception_state.ThrowTypeError("Value is outside the '" +
|
| - String(type_name) + "' value range.");
|
| - return 0;
|
| - }
|
| - return x;
|
| -}
|
| -
|
| -template <typename T>
|
| -struct IntTypeLimits {};
|
| -
|
| -template <>
|
| -struct IntTypeLimits<int8_t> {
|
| - static const int8_t kMinValue = -128;
|
| - static const int8_t kMaxValue = 127;
|
| - static const unsigned kNumberOfValues = 256; // 2^8
|
| -};
|
| -
|
| -template <>
|
| -struct IntTypeLimits<uint8_t> {
|
| - static const uint8_t kMaxValue = 255;
|
| - static const unsigned kNumberOfValues = 256; // 2^8
|
| -};
|
| -
|
| -template <>
|
| -struct IntTypeLimits<int16_t> {
|
| - static const short kMinValue = -32768;
|
| - static const short kMaxValue = 32767;
|
| - static const unsigned kNumberOfValues = 65536; // 2^16
|
| -};
|
| -
|
| -template <>
|
| -struct IntTypeLimits<uint16_t> {
|
| - static const unsigned short kMaxValue = 65535;
|
| - static const unsigned kNumberOfValues = 65536; // 2^16
|
| -};
|
| -
|
| -template <typename T>
|
| -static inline T ToSmallerInt(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - const char* type_name,
|
| - ExceptionState& exception_state) {
|
| - typedef IntTypeLimits<T> LimitsTrait;
|
| -
|
| - // Fast case. The value is already a 32-bit integer in the right range.
|
| - if (value->IsInt32()) {
|
| - int32_t result = value.As<v8::Int32>()->Value();
|
| - if (result >= LimitsTrait::kMinValue && result <= LimitsTrait::kMaxValue)
|
| - return static_cast<T>(result);
|
| - if (configuration == kEnforceRange) {
|
| - exception_state.ThrowTypeError("Value is outside the '" +
|
| - String(type_name) + "' value range.");
|
| - return 0;
|
| - }
|
| - if (configuration == kClamp)
|
| - return clampTo<T>(result);
|
| - result %= LimitsTrait::kNumberOfValues;
|
| - return static_cast<T>(result > LimitsTrait::kMaxValue
|
| - ? result - LimitsTrait::kNumberOfValues
|
| - : result);
|
| - }
|
| -
|
| - v8::Local<v8::Number> number_object;
|
| - if (value->IsNumber()) {
|
| - number_object = value.As<v8::Number>();
|
| - } else {
|
| - // Can the value be converted to a number?
|
| - v8::TryCatch block(isolate);
|
| - if (!V8Call(value->ToNumber(isolate->GetCurrentContext()), number_object,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return 0;
|
| - }
|
| - }
|
| - DCHECK(!number_object.IsEmpty());
|
| -
|
| - if (configuration == kEnforceRange)
|
| - return EnforceRange(number_object->Value(), LimitsTrait::kMinValue,
|
| - LimitsTrait::kMaxValue, type_name, exception_state);
|
| -
|
| - double number_value = number_object->Value();
|
| - if (std::isnan(number_value) || !number_value)
|
| - return 0;
|
| -
|
| - if (configuration == kClamp)
|
| - return clampTo<T>(number_value);
|
| -
|
| - if (std::isinf(number_value))
|
| - return 0;
|
| -
|
| - number_value =
|
| - number_value < 0 ? -floor(fabs(number_value)) : floor(fabs(number_value));
|
| - number_value = fmod(number_value, LimitsTrait::kNumberOfValues);
|
| -
|
| - return static_cast<T>(number_value > LimitsTrait::kMaxValue
|
| - ? number_value - LimitsTrait::kNumberOfValues
|
| - : number_value);
|
| -}
|
| -
|
| -template <typename T>
|
| -static inline T ToSmallerUInt(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - const char* type_name,
|
| - ExceptionState& exception_state) {
|
| - typedef IntTypeLimits<T> LimitsTrait;
|
| -
|
| - // Fast case. The value is a 32-bit signed integer - possibly positive?
|
| - if (value->IsInt32()) {
|
| - int32_t result = value.As<v8::Int32>()->Value();
|
| - if (result >= 0 && result <= LimitsTrait::kMaxValue)
|
| - return static_cast<T>(result);
|
| - if (configuration == kEnforceRange) {
|
| - exception_state.ThrowTypeError("Value is outside the '" +
|
| - String(type_name) + "' value range.");
|
| - return 0;
|
| - }
|
| - if (configuration == kClamp)
|
| - return clampTo<T>(result);
|
| - return static_cast<T>(result);
|
| - }
|
| -
|
| - v8::Local<v8::Number> number_object;
|
| - if (value->IsNumber()) {
|
| - number_object = value.As<v8::Number>();
|
| - } else {
|
| - // Can the value be converted to a number?
|
| - v8::TryCatch block(isolate);
|
| - if (!V8Call(value->ToNumber(isolate->GetCurrentContext()), number_object,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return 0;
|
| - }
|
| - }
|
| - DCHECK(!number_object.IsEmpty());
|
| -
|
| - if (configuration == kEnforceRange)
|
| - return EnforceRange(number_object->Value(), 0, LimitsTrait::kMaxValue,
|
| - type_name, exception_state);
|
| -
|
| - double number_value = number_object->Value();
|
| -
|
| - if (std::isnan(number_value) || !number_value)
|
| - return 0;
|
| -
|
| - if (configuration == kClamp)
|
| - return clampTo<T>(number_value);
|
| -
|
| - if (std::isinf(number_value))
|
| - return 0;
|
| -
|
| - number_value =
|
| - number_value < 0 ? -floor(fabs(number_value)) : floor(fabs(number_value));
|
| - return static_cast<T>(fmod(number_value, LimitsTrait::kNumberOfValues));
|
| -}
|
| -
|
| -int8_t ToInt8(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - ExceptionState& exception_state) {
|
| - return ToSmallerInt<int8_t>(isolate, value, configuration, "byte",
|
| - exception_state);
|
| -}
|
| -
|
| -uint8_t ToUInt8(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - ExceptionState& exception_state) {
|
| - return ToSmallerUInt<uint8_t>(isolate, value, configuration, "octet",
|
| - exception_state);
|
| -}
|
| -
|
| -int16_t ToInt16(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - ExceptionState& exception_state) {
|
| - return ToSmallerInt<int16_t>(isolate, value, configuration, "short",
|
| - exception_state);
|
| -}
|
| -
|
| -uint16_t ToUInt16(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - ExceptionState& exception_state) {
|
| - return ToSmallerUInt<uint16_t>(isolate, value, configuration,
|
| - "unsigned short", exception_state);
|
| -}
|
| -
|
| -int32_t ToInt32Slow(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - ExceptionState& exception_state) {
|
| - DCHECK(!value->IsInt32());
|
| - // Can the value be converted to a number?
|
| - v8::TryCatch block(isolate);
|
| - v8::Local<v8::Number> number_object;
|
| - if (!V8Call(value->ToNumber(isolate->GetCurrentContext()), number_object,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return 0;
|
| - }
|
| -
|
| - DCHECK(!number_object.IsEmpty());
|
| -
|
| - double number_value = number_object->Value();
|
| - if (configuration == kEnforceRange)
|
| - return EnforceRange(number_value, kMinInt32, kMaxInt32, "long",
|
| - exception_state);
|
| -
|
| - if (std::isnan(number_value))
|
| - return 0;
|
| -
|
| - if (configuration == kClamp)
|
| - return clampTo<int32_t>(number_value);
|
| -
|
| - if (std::isinf(number_value))
|
| - return 0;
|
| -
|
| - int32_t result;
|
| - if (!V8Call(number_object->Int32Value(isolate->GetCurrentContext()), result,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return 0;
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -uint32_t ToUInt32Slow(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - ExceptionState& exception_state) {
|
| - DCHECK(!value->IsUint32());
|
| - if (value->IsInt32()) {
|
| - DCHECK_NE(configuration, kNormalConversion);
|
| - int32_t result = value.As<v8::Int32>()->Value();
|
| - if (result >= 0)
|
| - return result;
|
| - if (configuration == kEnforceRange) {
|
| - exception_state.ThrowTypeError(
|
| - "Value is outside the 'unsigned long' value range.");
|
| - return 0;
|
| - }
|
| - DCHECK_EQ(configuration, kClamp);
|
| - return clampTo<uint32_t>(result);
|
| - }
|
| -
|
| - // Can the value be converted to a number?
|
| - v8::TryCatch block(isolate);
|
| - v8::Local<v8::Number> number_object;
|
| - if (!V8Call(value->ToNumber(isolate->GetCurrentContext()), number_object,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return 0;
|
| - }
|
| - DCHECK(!number_object.IsEmpty());
|
| -
|
| - if (configuration == kEnforceRange)
|
| - return EnforceRange(number_object->Value(), 0, kMaxUInt32, "unsigned long",
|
| - exception_state);
|
| -
|
| - double number_value = number_object->Value();
|
| -
|
| - if (std::isnan(number_value))
|
| - return 0;
|
| -
|
| - if (configuration == kClamp)
|
| - return clampTo<uint32_t>(number_value);
|
| -
|
| - if (std::isinf(number_value))
|
| - return 0;
|
| -
|
| - uint32_t result;
|
| - if (!V8Call(number_object->Uint32Value(isolate->GetCurrentContext()), result,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return 0;
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -int64_t ToInt64Slow(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - ExceptionState& exception_state) {
|
| - DCHECK(!value->IsInt32());
|
| -
|
| - v8::Local<v8::Number> number_object;
|
| - // Can the value be converted to a number?
|
| - v8::TryCatch block(isolate);
|
| - if (!V8Call(value->ToNumber(isolate->GetCurrentContext()), number_object,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return 0;
|
| - }
|
| - DCHECK(!number_object.IsEmpty());
|
| -
|
| - double number_value = number_object->Value();
|
| -
|
| - if (configuration == kEnforceRange)
|
| - return EnforceRange(number_value, -kJSMaxInteger, kJSMaxInteger,
|
| - "long long", exception_state);
|
| -
|
| - if (std::isnan(number_value) || std::isinf(number_value))
|
| - return 0;
|
| -
|
| - // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
|
| - unsigned long long integer;
|
| - doubleToInteger(number_value, integer);
|
| - return integer;
|
| -}
|
| -
|
| -uint64_t ToUInt64Slow(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - IntegerConversionConfiguration configuration,
|
| - ExceptionState& exception_state) {
|
| - DCHECK(!value->IsUint32());
|
| - if (value->IsInt32()) {
|
| - ASSERT(configuration != kNormalConversion);
|
| - int32_t result = value.As<v8::Int32>()->Value();
|
| - if (result >= 0)
|
| - return result;
|
| - if (configuration == kEnforceRange) {
|
| - exception_state.ThrowTypeError(
|
| - "Value is outside the 'unsigned long long' value range.");
|
| - return 0;
|
| - }
|
| - DCHECK_EQ(configuration, kClamp);
|
| - return clampTo<uint64_t>(result);
|
| - }
|
| -
|
| - v8::Local<v8::Number> number_object;
|
| - // Can the value be converted to a number?
|
| - v8::TryCatch block(isolate);
|
| - if (!V8Call(value->ToNumber(isolate->GetCurrentContext()), number_object,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return 0;
|
| - }
|
| - DCHECK(!number_object.IsEmpty());
|
| -
|
| - double number_value = number_object->Value();
|
| -
|
| - if (configuration == kEnforceRange)
|
| - return EnforceRange(number_value, 0, kJSMaxInteger, "unsigned long long",
|
| - exception_state);
|
| -
|
| - if (std::isnan(number_value))
|
| - return 0;
|
| -
|
| - if (configuration == kClamp)
|
| - return clampTo<uint64_t>(number_value);
|
| -
|
| - if (std::isinf(number_value))
|
| - return 0;
|
| -
|
| - // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
|
| - unsigned long long integer;
|
| - doubleToInteger(number_value, integer);
|
| - return integer;
|
| -}
|
| -
|
| -float ToRestrictedFloat(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - ExceptionState& exception_state) {
|
| - float number_value = ToFloat(isolate, value, exception_state);
|
| - if (exception_state.HadException())
|
| - return 0;
|
| - if (!std::isfinite(number_value)) {
|
| - exception_state.ThrowTypeError("The provided float value is non-finite.");
|
| - return 0;
|
| - }
|
| - return number_value;
|
| -}
|
| -
|
| -double ToDoubleSlow(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - ExceptionState& exception_state) {
|
| - DCHECK(!value->IsNumber());
|
| - v8::TryCatch block(isolate);
|
| - v8::Local<v8::Number> number_value;
|
| - if (!value->ToNumber(isolate->GetCurrentContext()).ToLocal(&number_value)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return 0;
|
| - }
|
| - return number_value->Value();
|
| -}
|
| -
|
| -double ToRestrictedDouble(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - ExceptionState& exception_state) {
|
| - double number_value = ToDouble(isolate, value, exception_state);
|
| - if (exception_state.HadException())
|
| - return 0;
|
| - if (!std::isfinite(number_value)) {
|
| - exception_state.ThrowTypeError("The provided double value is non-finite.");
|
| - return 0;
|
| - }
|
| - return number_value;
|
| -}
|
| -
|
| -String ToByteString(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - ExceptionState& exception_state) {
|
| - // Handle null default value.
|
| - if (value.IsEmpty())
|
| - return String();
|
| -
|
| - // From the Web IDL spec: http://heycam.github.io/webidl/#es-ByteString
|
| - if (value.IsEmpty())
|
| - return String();
|
| -
|
| - // 1. Let x be ToString(v)
|
| - v8::Local<v8::String> string_object;
|
| - if (value->IsString()) {
|
| - string_object = value.As<v8::String>();
|
| - } else {
|
| - v8::TryCatch block(isolate);
|
| - if (!V8Call(value->ToString(isolate->GetCurrentContext()), string_object,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return String();
|
| - }
|
| - }
|
| -
|
| - String x = ToCoreString(string_object);
|
| -
|
| - // 2. If the value of any element of x is greater than 255, then throw a
|
| - // TypeError.
|
| - if (!x.ContainsOnlyLatin1()) {
|
| - exception_state.ThrowTypeError("Value is not a valid ByteString.");
|
| - return String();
|
| - }
|
| -
|
| - // 3. Return an IDL ByteString value whose length is the length of x, and
|
| - // where the value of each element is the value of the corresponding
|
| - // element of x.
|
| - // Blink: A ByteString is simply a String with a range constrained per the
|
| - // above, so this is the identity operation.
|
| - return x;
|
| -}
|
| -
|
| -static bool HasUnmatchedSurrogates(const String& string) {
|
| - // By definition, 8-bit strings are confined to the Latin-1 code page and
|
| - // have no surrogates, matched or otherwise.
|
| - if (string.Is8Bit())
|
| - return false;
|
| -
|
| - const UChar* characters = string.Characters16();
|
| - const unsigned length = string.length();
|
| -
|
| - for (unsigned i = 0; i < length; ++i) {
|
| - UChar c = characters[i];
|
| - if (U16_IS_SINGLE(c))
|
| - continue;
|
| - if (U16_IS_TRAIL(c))
|
| - return true;
|
| - ASSERT(U16_IS_LEAD(c));
|
| - if (i == length - 1)
|
| - return true;
|
| - UChar d = characters[i + 1];
|
| - if (!U16_IS_TRAIL(d))
|
| - return true;
|
| - ++i;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -// Replace unmatched surrogates with REPLACEMENT CHARACTER U+FFFD.
|
| -static String ReplaceUnmatchedSurrogates(const String& string) {
|
| - // This roughly implements http://heycam.github.io/webidl/#dfn-obtain-unicode
|
| - // but since Blink strings are 16-bits internally, the output is simply
|
| - // re-encoded to UTF-16.
|
| -
|
| - // The concept of surrogate pairs is explained at:
|
| - // http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G2630
|
| -
|
| - // Blink-specific optimization to avoid making an unnecessary copy.
|
| - if (!HasUnmatchedSurrogates(string))
|
| - return string;
|
| - DCHECK(!string.Is8Bit());
|
| -
|
| - // 1. Let S be the DOMString value.
|
| - const UChar* s = string.Characters16();
|
| -
|
| - // 2. Let n be the length of S.
|
| - const unsigned n = string.length();
|
| -
|
| - // 3. Initialize i to 0.
|
| - unsigned i = 0;
|
| -
|
| - // 4. Initialize U to be an empty sequence of Unicode characters.
|
| - StringBuilder u;
|
| - u.ReserveCapacity(n);
|
| -
|
| - // 5. While i < n:
|
| - while (i < n) {
|
| - // 1. Let c be the code unit in S at index i.
|
| - UChar c = s[i];
|
| - // 2. Depending on the value of c:
|
| - if (U16_IS_SINGLE(c)) {
|
| - // c < 0xD800 or c > 0xDFFF
|
| - // Append to U the Unicode character with code point c.
|
| - u.Append(c);
|
| - } else if (U16_IS_TRAIL(c)) {
|
| - // 0xDC00 <= c <= 0xDFFF
|
| - // Append to U a U+FFFD REPLACEMENT CHARACTER.
|
| - u.Append(kReplacementCharacter);
|
| - } else {
|
| - // 0xD800 <= c <= 0xDBFF
|
| - DCHECK(U16_IS_LEAD(c));
|
| - if (i == n - 1) {
|
| - // 1. If i = n-1, then append to U a U+FFFD REPLACEMENT CHARACTER.
|
| - u.Append(kReplacementCharacter);
|
| - } else {
|
| - // 2. Otherwise, i < n-1:
|
| - DCHECK_LT(i, n - 1);
|
| - // ....1. Let d be the code unit in S at index i+1.
|
| - UChar d = s[i + 1];
|
| - if (U16_IS_TRAIL(d)) {
|
| - // 2. If 0xDC00 <= d <= 0xDFFF, then:
|
| - // ..1. Let a be c & 0x3FF.
|
| - // ..2. Let b be d & 0x3FF.
|
| - // ..3. Append to U the Unicode character with code point
|
| - // 2^16+2^10*a+b.
|
| - u.Append(U16_GET_SUPPLEMENTARY(c, d));
|
| - // Blink: This is equivalent to u.append(c); u.append(d);
|
| - ++i;
|
| - } else {
|
| - // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a U+FFFD
|
| - // REPLACEMENT CHARACTER.
|
| - u.Append(kReplacementCharacter);
|
| - }
|
| - }
|
| - }
|
| - // 3. Set i to i+1.
|
| - ++i;
|
| - }
|
| -
|
| - // 6. Return U.
|
| - DCHECK_EQ(u.length(), string.length());
|
| - return u.ToString();
|
| -}
|
| -
|
| -String ToUSVString(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - ExceptionState& exception_state) {
|
| - // http://heycam.github.io/webidl/#es-USVString
|
| - if (value.IsEmpty())
|
| - return String();
|
| -
|
| - v8::Local<v8::String> string_object;
|
| - if (value->IsString()) {
|
| - string_object = value.As<v8::String>();
|
| - } else {
|
| - v8::TryCatch block(isolate);
|
| - if (!V8Call(value->ToString(isolate->GetCurrentContext()), string_object,
|
| - block)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return String();
|
| - }
|
| - }
|
| -
|
| - // USVString is identical to DOMString except that "convert a
|
| - // DOMString to a sequence of Unicode characters" is used subsequently
|
| - // when converting to an IDL value
|
| - String x = ToCoreString(string_object);
|
| - return ReplaceUnmatchedSurrogates(x);
|
| -}
|
| -
|
| -XPathNSResolver* ToXPathNSResolver(ScriptState* script_state,
|
| - v8::Local<v8::Value> value) {
|
| - XPathNSResolver* resolver = nullptr;
|
| - if (V8XPathNSResolver::hasInstance(value, script_state->GetIsolate()))
|
| - resolver = V8XPathNSResolver::toImpl(v8::Local<v8::Object>::Cast(value));
|
| - else if (value->IsObject())
|
| - resolver =
|
| - V8CustomXPathNSResolver::Create(script_state, value.As<v8::Object>());
|
| - return resolver;
|
| -}
|
| -
|
| -DOMWindow* ToDOMWindow(v8::Isolate* isolate, v8::Local<v8::Value> value) {
|
| - if (value.IsEmpty() || !value->IsObject())
|
| - return 0;
|
| -
|
| - v8::Local<v8::Object> window_wrapper = V8Window::findInstanceInPrototypeChain(
|
| - v8::Local<v8::Object>::Cast(value), isolate);
|
| - if (!window_wrapper.IsEmpty())
|
| - return V8Window::toImpl(window_wrapper);
|
| - return 0;
|
| -}
|
| -
|
| -LocalDOMWindow* ToLocalDOMWindow(v8::Local<v8::Context> context) {
|
| - if (context.IsEmpty())
|
| - return 0;
|
| - return ToLocalDOMWindow(
|
| - ToDOMWindow(context->GetIsolate(), context->Global()));
|
| -}
|
| -
|
| -LocalDOMWindow* EnteredDOMWindow(v8::Isolate* isolate) {
|
| - LocalDOMWindow* window =
|
| - ToLocalDOMWindow(isolate->GetEnteredOrMicrotaskContext());
|
| - DCHECK(window);
|
| - return window;
|
| -}
|
| -
|
| -LocalDOMWindow* CurrentDOMWindow(v8::Isolate* isolate) {
|
| - return ToLocalDOMWindow(isolate->GetCurrentContext());
|
| -}
|
| -
|
| -ExecutionContext* ToExecutionContext(v8::Local<v8::Context> context) {
|
| - if (context.IsEmpty())
|
| - return 0;
|
| - v8::Local<v8::Object> global = context->Global();
|
| - v8::Local<v8::Object> window_wrapper =
|
| - V8Window::findInstanceInPrototypeChain(global, context->GetIsolate());
|
| - if (!window_wrapper.IsEmpty())
|
| - return V8Window::toImpl(window_wrapper)->GetExecutionContext();
|
| - v8::Local<v8::Object> worker_wrapper =
|
| - V8WorkerGlobalScope::findInstanceInPrototypeChain(global,
|
| - context->GetIsolate());
|
| - if (!worker_wrapper.IsEmpty())
|
| - return V8WorkerGlobalScope::toImpl(worker_wrapper)->GetExecutionContext();
|
| - v8::Local<v8::Object> worklet_wrapper =
|
| - V8WorkletGlobalScope::findInstanceInPrototypeChain(global,
|
| - context->GetIsolate());
|
| - if (!worklet_wrapper.IsEmpty())
|
| - return V8WorkletGlobalScope::toImpl(worklet_wrapper);
|
| - // FIXME: Is this line of code reachable?
|
| - return nullptr;
|
| -}
|
| -
|
| -ExecutionContext* CurrentExecutionContext(v8::Isolate* isolate) {
|
| - return ToExecutionContext(isolate->GetCurrentContext());
|
| -}
|
| -
|
| -LocalFrame* ToLocalFrameIfNotDetached(v8::Local<v8::Context> context) {
|
| - LocalDOMWindow* window = ToLocalDOMWindow(context);
|
| - if (window && window->IsCurrentlyDisplayedInFrame())
|
| - return window->GetFrame();
|
| - // We return 0 here because |context| is detached from the Frame. If we
|
| - // did return |frame| we could get in trouble because the frame could be
|
| - // navigated to another security origin.
|
| - return nullptr;
|
| -}
|
| -
|
| -void ToFlexibleArrayBufferView(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - FlexibleArrayBufferView& result,
|
| - void* storage) {
|
| - DCHECK(value->IsArrayBufferView());
|
| - v8::Local<v8::ArrayBufferView> buffer = value.As<v8::ArrayBufferView>();
|
| - if (!storage) {
|
| - result.SetFull(V8ArrayBufferView::toImpl(buffer));
|
| - return;
|
| - }
|
| - size_t length = buffer->ByteLength();
|
| - buffer->CopyContents(storage, length);
|
| - result.SetSmall(storage, length);
|
| -}
|
| -
|
| -static ScriptState* ToScriptStateImpl(LocalFrame* frame,
|
| - DOMWrapperWorld& world) {
|
| - if (!frame)
|
| - return nullptr;
|
| - v8::Local<v8::Context> context = ToV8ContextEvenIfDetached(frame, world);
|
| - if (context.IsEmpty())
|
| - return nullptr;
|
| - ScriptState* script_state = ScriptState::From(context);
|
| - if (!script_state->ContextIsValid())
|
| - return nullptr;
|
| - DCHECK_EQ(frame, ToLocalFrameIfNotDetached(context));
|
| - return script_state;
|
| -}
|
| -
|
| -v8::Local<v8::Context> ToV8Context(ExecutionContext* context,
|
| - DOMWrapperWorld& world) {
|
| - DCHECK(context);
|
| - if (context->IsDocument()) {
|
| - if (LocalFrame* frame = ToDocument(context)->GetFrame())
|
| - return ToV8Context(frame, world);
|
| - } else if (context->IsWorkerGlobalScope()) {
|
| - if (WorkerOrWorkletScriptController* script =
|
| - ToWorkerOrWorkletGlobalScope(context)->ScriptController()) {
|
| - if (script->GetScriptState()->ContextIsValid())
|
| - return script->GetScriptState()->GetContext();
|
| - }
|
| - }
|
| - return v8::Local<v8::Context>();
|
| -}
|
| -
|
| -v8::Local<v8::Context> ToV8Context(LocalFrame* frame, DOMWrapperWorld& world) {
|
| - ScriptState* script_state = ToScriptStateImpl(frame, world);
|
| - if (!script_state)
|
| - return v8::Local<v8::Context>();
|
| - return script_state->GetContext();
|
| -}
|
| -
|
| -v8::Local<v8::Context> ToV8ContextEvenIfDetached(LocalFrame* frame,
|
| - DOMWrapperWorld& world) {
|
| - DCHECK(frame);
|
| - return frame->WindowProxy(world)->ContextIfInitialized();
|
| -}
|
| -
|
| -ScriptState* ToScriptState(LocalFrame* frame, DOMWrapperWorld& world) {
|
| - v8::HandleScope handle_scope(ToIsolate(frame));
|
| - return ToScriptStateImpl(frame, world);
|
| -}
|
| -
|
| -ScriptState* ToScriptStateForMainWorld(LocalFrame* frame) {
|
| - return ToScriptState(frame, DOMWrapperWorld::MainWorld());
|
| -}
|
| -
|
| -bool IsValidEnum(const String& value,
|
| - const char** valid_values,
|
| - size_t length,
|
| - const String& enum_name,
|
| - ExceptionState& exception_state) {
|
| - for (size_t i = 0; i < length; ++i) {
|
| - // Avoid the strlen inside String::operator== (because of the StringView).
|
| - if (WTF::Equal(value.Impl(), valid_values[i]))
|
| - return true;
|
| - }
|
| - exception_state.ThrowTypeError("The provided value '" + value +
|
| - "' is not a valid enum value of type " +
|
| - enum_name + ".");
|
| - return false;
|
| -}
|
| -
|
| -bool IsValidEnum(const Vector<String>& values,
|
| - const char** valid_values,
|
| - size_t length,
|
| - const String& enum_name,
|
| - ExceptionState& exception_state) {
|
| - for (auto value : values) {
|
| - if (!IsValidEnum(value, valid_values, length, enum_name, exception_state))
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| v8::Local<v8::Function> GetBoundFunction(v8::Local<v8::Function> function) {
|
| v8::Local<v8::Value> bound_function = function->GetBoundFunction();
|
| return bound_function->IsFunction()
|
| @@ -872,55 +41,6 @@ v8::Local<v8::Function> GetBoundFunction(v8::Local<v8::Function> function) {
|
| : function;
|
| }
|
|
|
| -v8::Local<v8::Object> GetEsIterator(v8::Isolate* isolate,
|
| - v8::Local<v8::Object> object,
|
| - ExceptionState& exception_state) {
|
| - v8::TryCatch block(isolate);
|
| - v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
| - v8::Local<v8::Value> iterator_getter;
|
| - if (!object->Get(context, v8::Symbol::GetIterator(isolate))
|
| - .ToLocal(&iterator_getter)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return v8::Local<v8::Object>();
|
| - }
|
| - if (!iterator_getter->IsFunction()) {
|
| - exception_state.ThrowTypeError("Iterator getter is not callable.");
|
| - return v8::Local<v8::Object>();
|
| - }
|
| -
|
| - v8::Local<v8::Function> getter_function = iterator_getter.As<v8::Function>();
|
| - v8::Local<v8::Value> iterator;
|
| - if (!V8ScriptRunner::CallFunction(getter_function,
|
| - ToExecutionContext(context), object, 0,
|
| - nullptr, isolate)
|
| - .ToLocal(&iterator)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return v8::Local<v8::Object>();
|
| - }
|
| - if (!iterator->IsObject()) {
|
| - exception_state.ThrowTypeError("Iterator is not an object.");
|
| - return v8::Local<v8::Object>();
|
| - }
|
| - return iterator.As<v8::Object>();
|
| -}
|
| -
|
| -bool HasCallableIteratorSymbol(v8::Isolate* isolate,
|
| - v8::Local<v8::Value> value,
|
| - ExceptionState& exception_state) {
|
| - if (!value->IsObject())
|
| - return false;
|
| - v8::TryCatch block(isolate);
|
| - v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
| - v8::Local<v8::Value> iterator_getter;
|
| - if (!value.As<v8::Object>()
|
| - ->Get(context, v8::Symbol::GetIterator(isolate))
|
| - .ToLocal(&iterator_getter)) {
|
| - exception_state.RethrowV8Exception(block.Exception());
|
| - return false;
|
| - }
|
| - return iterator_getter->IsFunction();
|
| -}
|
| -
|
| bool AddHiddenValueToArray(v8::Isolate* isolate,
|
| v8::Local<v8::Object> object,
|
| v8::Local<v8::Value> value,
|
| @@ -956,38 +76,6 @@ void RemoveHiddenValueFromArray(v8::Isolate* isolate,
|
| }
|
| }
|
|
|
| -void MoveEventListenerToNewWrapper(v8::Isolate* isolate,
|
| - v8::Local<v8::Object> object,
|
| - EventListener* old_value,
|
| - v8::Local<v8::Value> new_value,
|
| - int array_index) {
|
| - if (old_value) {
|
| - V8AbstractEventListener* old_listener =
|
| - V8AbstractEventListener::Cast(old_value);
|
| - if (old_listener) {
|
| - v8::Local<v8::Object> old_listener_object =
|
| - old_listener->GetExistingListenerObject();
|
| - if (!old_listener_object.IsEmpty())
|
| - RemoveHiddenValueFromArray(isolate, object, old_listener_object,
|
| - array_index);
|
| - }
|
| - }
|
| - // Non-callable input is treated as null and ignored
|
| - if (new_value->IsFunction())
|
| - AddHiddenValueToArray(isolate, object, new_value, array_index);
|
| -}
|
| -
|
| -v8::Isolate* ToIsolate(ExecutionContext* context) {
|
| - if (context && context->IsDocument())
|
| - return V8PerIsolateData::MainThreadIsolate();
|
| - return v8::Isolate::GetCurrent();
|
| -}
|
| -
|
| -v8::Isolate* ToIsolate(LocalFrame* frame) {
|
| - DCHECK(frame);
|
| - return frame->GetWindowProxyManager()->GetIsolate();
|
| -}
|
| -
|
| v8::Local<v8::Value> FreezeV8Object(v8::Local<v8::Value> value,
|
| v8::Isolate* isolate) {
|
| value.As<v8::Object>()
|
| @@ -997,18 +85,4 @@ v8::Local<v8::Value> FreezeV8Object(v8::Local<v8::Value> value,
|
| return value;
|
| }
|
|
|
| -v8::Local<v8::Value> FromJSONString(v8::Isolate* isolate,
|
| - const String& stringified_json,
|
| - ExceptionState& exception_state) {
|
| - v8::Local<v8::Value> parsed;
|
| - v8::TryCatch try_catch(isolate);
|
| - if (!V8Call(v8::JSON::Parse(isolate, V8String(isolate, stringified_json)),
|
| - parsed, try_catch)) {
|
| - if (try_catch.HasCaught())
|
| - exception_state.RethrowV8Exception(try_catch.Exception());
|
| - }
|
| -
|
| - return parsed;
|
| -}
|
| -
|
| } // namespace blink
|
|
|