From ff65b7dae1f56ea5f3e1b84e9740f301fdf508a0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 15 Apr 2014 11:04:36 +0800 Subject: [PATCH 001/129] Initial commit. --- LICENSE | 20 + LICENSE.chromium | 27 ++ native_mate/arguments.cc | 48 +++ native_mate/arguments.h | 82 ++++ native_mate/compat.h | 100 +++++ native_mate/converter.cc | 190 ++++++++++ native_mate/converter.h | 193 ++++++++++ native_mate/dictionary.cc | 42 +++ native_mate/dictionary.h | 64 ++++ native_mate/function_template.cc | 35 ++ native_mate/function_template.h | 498 +++++++++++++++++++++++++ native_mate/handle.h | 68 ++++ native_mate/object_template_builder.cc | 39 ++ native_mate/object_template_builder.h | 123 ++++++ native_mate/scoped_persistent.h | 111 ++++++ native_mate/try_catch.cc | 49 +++ native_mate/try_catch.h | 32 ++ native_mate/wrappable.cc | 58 +++ native_mate/wrappable.h | 85 +++++ native_mate_files.gypi | 23 ++ 20 files changed, 1887 insertions(+) create mode 100644 LICENSE create mode 100644 LICENSE.chromium create mode 100644 native_mate/arguments.cc create mode 100644 native_mate/arguments.h create mode 100644 native_mate/compat.h create mode 100644 native_mate/converter.cc create mode 100644 native_mate/converter.h create mode 100644 native_mate/dictionary.cc create mode 100644 native_mate/dictionary.h create mode 100644 native_mate/function_template.cc create mode 100644 native_mate/function_template.h create mode 100644 native_mate/handle.h create mode 100644 native_mate/object_template_builder.cc create mode 100644 native_mate/object_template_builder.h create mode 100644 native_mate/scoped_persistent.h create mode 100644 native_mate/try_catch.cc create mode 100644 native_mate/try_catch.h create mode 100644 native_mate/wrappable.cc create mode 100644 native_mate/wrappable.h create mode 100644 native_mate_files.gypi diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..5f39f8bd955 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2014 Cheng Zhao. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSE.chromium b/LICENSE.chromium new file mode 100644 index 00000000000..972bb2edb09 --- /dev/null +++ b/LICENSE.chromium @@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/native_mate/arguments.cc b/native_mate/arguments.cc new file mode 100644 index 00000000000..70351479a02 --- /dev/null +++ b/native_mate/arguments.cc @@ -0,0 +1,48 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#include "native_mate/arguments.h" + +#include "base/strings/stringprintf.h" +#include "native_mate/converter.h" + +namespace mate { + +Arguments::Arguments() + : isolate_(NULL), + info_(NULL), + next_(0), + insufficient_arguments_(false) { +} + +Arguments::Arguments(const MATE_METHOD_ARGS_TYPE& info) + : isolate_(info.GetIsolate()), + info_(&info), + next_(0), + insufficient_arguments_(false) { +} + +Arguments::~Arguments() { +} + +v8::Handle Arguments::PeekNext() const { + if (next_ >= info_->Length()) + return v8::Handle(); + return (*info_)[next_]; +} + +void Arguments::ThrowError() const { + if (insufficient_arguments_) + return ThrowTypeError("Insufficient number of arguments."); + + ThrowTypeError(base::StringPrintf( + "Error processing argument %d.", next_ - 1)); +} + +void Arguments::ThrowTypeError(const std::string& message) const { + MATE_THROW_EXCEPTION(isolate_, v8::Exception::TypeError( + StringToV8(isolate_, message))); +} + +} // namespace mate diff --git a/native_mate/arguments.h b/native_mate/arguments.h new file mode 100644 index 00000000000..054e03abf84 --- /dev/null +++ b/native_mate/arguments.h @@ -0,0 +1,82 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_ARGUMENTS_H_ +#define NATIVE_MATE_ARGUMENTS_H_ + +#include "base/basictypes.h" +#include "native_mate/compat.h" +#include "native_mate/converter.h" + +namespace mate { + +// Arguments is a wrapper around v8::FunctionCallbackInfo that integrates +// with Converter to make it easier to marshall arguments and return values +// between V8 and C++. +class Arguments { + public: + Arguments(); + explicit Arguments(const MATE_METHOD_ARGS_TYPE& info); + ~Arguments(); + + template + bool GetHolder(T* out) { + return ConvertFromV8(isolate_, info_->Holder(), out); + } + + template + bool GetData(T* out) { + return ConvertFromV8(isolate_, info_->Data(), out); + } + + template + bool GetNext(T* out) { + if (next_ >= info_->Length()) { + insufficient_arguments_ = true; + return false; + } + v8::Handle val = (*info_)[next_++]; + return ConvertFromV8(isolate_, val, out); + } + + template + bool GetRemaining(std::vector* out) { + if (next_ >= info_->Length()) { + insufficient_arguments_ = true; + return false; + } + int remaining = info_->Length() - next_; + out->resize(remaining); + for (int i = 0; i < remaining; ++i) { + v8::Handle val = (*info_)[next_++]; + if (!ConvertFromV8(isolate_, val, &out->at(i))) + return false; + } + return true; + } + +#if NODE_VERSION_AT_LEAST(0, 11, 0) + template + void Return(T val) { + info_->GetReturnValue().Set(ConvertToV8(isolate_, val)); + } +#endif + + v8::Handle PeekNext() const; + + void ThrowError() const; + void ThrowTypeError(const std::string& message) const; + + v8::Isolate* isolate() const { return isolate_; } + + private: + v8::Isolate* isolate_; + const MATE_METHOD_ARGS_TYPE* info_; + int next_; + bool insufficient_arguments_; +}; + +} // namespace mate + +#endif // NATIVE_MATE_ARGUMENTS_H_ diff --git a/native_mate/compat.h b/native_mate/compat.h new file mode 100644 index 00000000000..5641613c42e --- /dev/null +++ b/native_mate/compat.h @@ -0,0 +1,100 @@ +// Copyright 2014 Cheng Zhao. All rights reserved. +// Use of this source code is governed by MIT license that can be found in the +// LICENSE file. + +#ifndef NATIVE_MATE_COMPAT_H_ +#define NATIVE_MATE_COMPAT_H_ + +#include "node_version.h" + +#if (NODE_MODULE_VERSION > 0x000B) // Node 0.11+ + +#define MATE_HANDLE_SCOPE(isolate) v8::HandleScope handle_scope(isolate) + +#define MATE_METHOD_ARGS_TYPE v8::FunctionCallbackInfo +#define MATE_METHOD_RETURN_TYPE void + +#define MATE_METHOD_RETURN_VALUE(value) return info.GetReturnValue().Set(value) +#define MATE_METHOD_RETURN_UNDEFINED() return +#define MATE_METHOD_RETURN_NULL() return info.GetReturnValue().SetNull() +#define MATE_METHOD_RETURN(value) args.Return(value) + +#define MATE_STRING_NEW_FROM_UTF8(isolate, data, length) \ + v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString, length) +#define MATE_STRING_NEW_SYMBOL(isolate, data, length) \ + v8::String::NewFromUtf8(isolate, data, v8::String::kInternalizedString, length) + +#define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ + object->SetAlignedPointerInInternalField(index, value) +#define MATE_GET_INTERNAL_FIELD_POINTER(object, index) \ + object->GetAlignedPointerFromInternalField(index) + +#define MATE_PERSISTENT_INIT(isolate, handle, value) \ + handle(isolate, value) +#define MATE_PERSISTENT_ASSIGN(type, isolate, handle, value) \ + handle.Reset(isolate, value) +#define MATE_PERSISTENT_RESET(handle) \ + handle.Reset() +#define MATE_PERSISTENT_TO_LOCAL(type, isolate, handle) \ + v8::Local::New(isolate, handle) +#define MATE_PERSISTENT_SET_WEAK(handle, parameter, callback) \ + handle.SetWeak(parameter, callback) + +#define MATE_WEAK_CALLBACK(name, v8_type, c_type) \ + void name(const v8::WeakCallbackData& data) +#define MATE_WEAK_CALLBACK_INIT(c_type) \ + c_type* self = data.GetParameter() + +#else // Node 0.8 and 0.10 + +#define MATE_HANDLE_SCOPE(isolate) v8::HandleScope handle_scope + +#define MATE_METHOD_ARGS_TYPE v8::Arguments +#define MATE_METHOD_RETURN_TYPE v8::Handle + +#define MATE_METHOD_RETURN_VALUE(value) return value +#define MATE_METHOD_RETURN_UNDEFINED() return v8::Undefined() +#define MATE_METHOD_RETURN_NULL() return v8::Null() +#define MATE_METHOD_RETURN(value) \ + MATE_METHOD_RETURN_VALUE(ConvertToV8(args.isolate(), value)) + +#define MATE_STRING_NEW_FROM_UTF8(isolate, data, length) \ + v8::String::New(data, length) +#define MATE_STRING_NEW_SYMBOL(isolate, data, length) \ + v8::String::NewSymbol(data, length) + +#define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ + object->SetPointerInInternalField(index, value) +#define MATE_GET_INTERNAL_FIELD_POINTER(object, index) \ + object->GetPointerFromInternalField(index) + +#define MATE_PERSISTENT_INIT(isolate, handle, value) \ + handle(value) +#define MATE_PERSISTENT_ASSIGN(type, isolate, handle, value) \ + handle = v8::Persistent::New(value) +#define MATE_PERSISTENT_RESET(handle) \ + handle.Dispose(); \ + handle.Clear() +#define MATE_PERSISTENT_TO_LOCAL(type, isolate, handle) \ + v8::Local::New(handle) +#define MATE_PERSISTENT_SET_WEAK(handle, parameter, callback) \ + handle.MakeWeak(parameter, callback) + +#define MATE_WEAK_CALLBACK(name, v8_type, c_type) \ + void name(v8::Persistent object, void* parameter) +#define MATE_WEAK_CALLBACK_INIT(c_type) \ + c_type* self = static_cast(parameter) + +#endif // (NODE_MODULE_VERSION > 0x000B) + + +// Generally we should not provide utility macros, but this just makes things +// much more comfortable so we keep it. +#define MATE_METHOD(name) \ + MATE_METHOD_RETURN_TYPE name(const MATE_METHOD_ARGS_TYPE& info) + +// In lastest V8 ThrowException would need to pass isolate, be prepared for it. +#define MATE_THROW_EXCEPTION(isolate, value) \ + v8::ThrowException(value) + +#endif // NATIVE_MATE_COMPAT_H_ diff --git a/native_mate/converter.cc b/native_mate/converter.cc new file mode 100644 index 00000000000..4750e5a30a1 --- /dev/null +++ b/native_mate/converter.cc @@ -0,0 +1,190 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#include "native_mate/converter.h" + +#include "native_mate/compat.h" +#include "v8/include/v8.h" + +using v8::Boolean; +using v8::External; +using v8::Function; +using v8::Handle; +using v8::Integer; +using v8::Isolate; +using v8::Number; +using v8::Object; +using v8::String; +using v8::Value; + +namespace mate { + +Handle Converter::ToV8(Isolate* isolate, bool val) { + return Boolean::New(val); +} + +bool Converter::FromV8(Isolate* isolate, Handle val, bool* out) { + *out = val->BooleanValue(); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, int32_t val) { + return Integer::New(val); +} + +bool Converter::FromV8(Isolate* isolate, Handle val, + int32_t* out) { + if (!val->IsInt32()) + return false; + *out = val->Int32Value(); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, uint32_t val) { + return Integer::NewFromUnsigned(val); +} + +bool Converter::FromV8(Isolate* isolate, Handle val, + uint32_t* out) { + if (!val->IsUint32()) + return false; + *out = val->Uint32Value(); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, int64_t val) { + return Number::New(static_cast(val)); +} + +bool Converter::FromV8(Isolate* isolate, Handle val, + int64_t* out) { + if (!val->IsNumber()) + return false; + // Even though IntegerValue returns int64_t, JavaScript cannot represent + // the full precision of int64_t, which means some rounding might occur. + *out = val->IntegerValue(); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, uint64_t val) { + return Number::New(static_cast(val)); +} + +bool Converter::FromV8(Isolate* isolate, Handle val, + uint64_t* out) { + if (!val->IsNumber()) + return false; + *out = static_cast(val->IntegerValue()); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, float val) { + return Number::New(val); +} + +bool Converter::FromV8(Isolate* isolate, Handle val, + float* out) { + if (!val->IsNumber()) + return false; + *out = static_cast(val->NumberValue()); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, double val) { + return Number::New(val); +} + +bool Converter::FromV8(Isolate* isolate, Handle val, + double* out) { + if (!val->IsNumber()) + return false; + *out = val->NumberValue(); + return true; +} + +Handle Converter::ToV8( + Isolate* isolate, const base::StringPiece& val) { + return MATE_STRING_NEW_FROM_UTF8(isolate, val.data(), + static_cast(val.length())); +} + +Handle Converter::ToV8(Isolate* isolate, + const std::string& val) { + return Converter::ToV8(isolate, val); +} + +bool Converter::FromV8(Isolate* isolate, Handle val, + std::string* out) { + if (!val->IsString()) + return false; + Handle str = Handle::Cast(val); + int length = str->Utf8Length(); + out->resize(length); + str->WriteUtf8(&(*out)[0], length, NULL, String::NO_NULL_TERMINATION); + return true; +} + +bool Converter >::FromV8(Isolate* isolate, Handle val, + Handle* out) { + if (!val->IsFunction()) + return false; + *out = Handle::Cast(val); + return true; +} + +Handle Converter >::ToV8(Isolate* isolate, + Handle val) { + return val; +} + +bool Converter >::FromV8(Isolate* isolate, Handle val, + Handle* out) { + if (!val->IsObject()) + return false; + *out = Handle::Cast(val); + return true; +} + +Handle Converter >::ToV8(Isolate* isolate, + Handle val) { + return val; +} + +bool Converter >::FromV8(Isolate* isolate, + v8::Handle val, + Handle* out) { + if (!val->IsExternal()) + return false; + *out = Handle::Cast(val); + return true; +} + +Handle Converter >::ToV8(Isolate* isolate, + Handle val) { + return val; +} + +bool Converter >::FromV8(Isolate* isolate, Handle val, + Handle* out) { + *out = val; + return true; +} + +v8::Handle StringToSymbol(v8::Isolate* isolate, + const base::StringPiece& val) { + return MATE_STRING_NEW_SYMBOL(isolate, + val.data(), + static_cast(val.length())); +} + +std::string V8ToString(v8::Handle value) { + if (value.IsEmpty()) + return std::string(); + std::string result; + if (!ConvertFromV8(NULL, value, &result)) + return std::string(); + return result; +} + +} // namespace mate diff --git a/native_mate/converter.h b/native_mate/converter.h new file mode 100644 index 00000000000..44b7d4a882b --- /dev/null +++ b/native_mate/converter.h @@ -0,0 +1,193 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_CONVERTER_H_ +#define NATIVE_MATE_CONVERTER_H_ + +#include +#include + +#include "base/strings/string_piece.h" +#include "v8/include/v8.h" + +namespace mate { + +template +struct Converter {}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + bool val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + bool* out); +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + int32_t val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + int32_t* out); +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + uint32_t val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + uint32_t* out); +}; + +template<> +struct Converter { + // Warning: JavaScript cannot represent 64 integers precisely. + static v8::Handle ToV8(v8::Isolate* isolate, + int64_t val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + int64_t* out); +}; + +template<> +struct Converter { + // Warning: JavaScript cannot represent 64 integers precisely. + static v8::Handle ToV8(v8::Isolate* isolate, + uint64_t val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + uint64_t* out); +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + float val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + float* out); +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + double val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + double* out); +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + const base::StringPiece& val); + // No conversion out is possible because StringPiece does not contain storage. +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + const std::string& val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + std::string* out); +}; + +template<> +struct Converter > { + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + v8::Handle* out); +}; + +template<> +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + v8::Handle val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + v8::Handle* out); +}; + +template<> +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + v8::Handle val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + v8::Handle* out); +}; + +template<> +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + v8::Handle val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + v8::Handle* out); +}; + +template +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + const std::vector& val) { + v8::Handle result( + v8::Array::New(static_cast(val.size()))); + for (size_t i = 0; i < val.size(); ++i) { + result->Set(static_cast(i), Converter::ToV8(isolate, val[i])); + } + return result; + } + + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + std::vector* out) { + if (!val->IsArray()) + return false; + + std::vector result; + v8::Handle array(v8::Handle::Cast(val)); + uint32_t length = array->Length(); + for (uint32_t i = 0; i < length; ++i) { + T item; + if (!Converter::FromV8(isolate, array->Get(i), &item)) + return false; + result.push_back(item); + } + + out->swap(result); + return true; + } +}; + +// Convenience functions that deduce T. +template +v8::Handle ConvertToV8(v8::Isolate* isolate, + T input) { + return Converter::ToV8(isolate, input); +} + +inline v8::Handle StringToV8( + v8::Isolate* isolate, + const base::StringPiece& input) { + return ConvertToV8(isolate, input).As(); +} + +v8::Handle StringToSymbol(v8::Isolate* isolate, + const base::StringPiece& val); + +template +bool ConvertFromV8(v8::Isolate* isolate, v8::Handle input, + T* result) { + return Converter::FromV8(isolate, input, result); +} + +std::string V8ToString(v8::Handle value); + +} // namespace mate + +#endif // NATIVE_MATE_CONVERTER_H_ diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc new file mode 100644 index 00000000000..1504f683f0a --- /dev/null +++ b/native_mate/dictionary.cc @@ -0,0 +1,42 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#include "native_mate/dictionary.h" + +namespace mate { + +Dictionary::Dictionary(v8::Isolate* isolate) + : isolate_(isolate) { +} + +Dictionary::Dictionary(v8::Isolate* isolate, + v8::Handle object) + : isolate_(isolate), + object_(object) { +} + +Dictionary::~Dictionary() { +} + +Dictionary Dictionary::CreateEmpty(v8::Isolate* isolate) { + Dictionary dictionary(isolate); + dictionary.object_ = v8::Object::New(); + return dictionary; +} + +v8::Handle Converter::ToV8(v8::Isolate* isolate, + Dictionary val) { + return val.object_; +} + +bool Converter::FromV8(v8::Isolate* isolate, + v8::Handle val, + Dictionary* out) { + if (!val->IsObject()) + return false; + *out = Dictionary(isolate, v8::Handle::Cast(val)); + return true; +} + +} // namespace mate diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h new file mode 100644 index 00000000000..469746653f4 --- /dev/null +++ b/native_mate/dictionary.h @@ -0,0 +1,64 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_DICTIONARY_H_ +#define NATIVE_MATE_DICTIONARY_H_ + +#include "native_mate/converter.h" + +namespace mate { + +// Dictionary is useful when writing bindings for a function that either +// receives an arbitrary JavaScript object as an argument or returns an +// arbitrary JavaScript object as a result. For example, Dictionary is useful +// when you might use the |dictionary| type in WebIDL: +// +// http://heycam.github.io/webidl/#idl-dictionaries +// +// WARNING: You cannot retain a Dictionary object in the heap. The underlying +// storage for Dictionary is tied to the closest enclosing +// v8::HandleScope. Generally speaking, you should store a Dictionary +// on the stack. +// +class Dictionary { + public: + explicit Dictionary(v8::Isolate* isolate); + Dictionary(v8::Isolate* isolate, v8::Handle object); + ~Dictionary(); + + static Dictionary CreateEmpty(v8::Isolate* isolate); + + template + bool Get(const std::string& key, T* out) { + v8::Handle val = object_->Get(StringToV8(isolate_, key)); + return ConvertFromV8(isolate_, val, out); + } + + template + bool Set(const std::string& key, T val) { + return object_->Set(StringToV8(isolate_, key), ConvertToV8(isolate_, val)); + } + + v8::Isolate* isolate() const { return isolate_; } + + private: + friend struct Converter; + + // TODO(aa): Remove this. Instead, get via FromV8(), Set(), and Get(). + v8::Isolate* isolate_; + v8::Handle object_; +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + Dictionary val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + Dictionary* out); +}; + +} // namespace mate + +#endif // NATIVE_MATE_DICTIONARY_H_ diff --git a/native_mate/function_template.cc b/native_mate/function_template.cc new file mode 100644 index 00000000000..711c04150a4 --- /dev/null +++ b/native_mate/function_template.cc @@ -0,0 +1,35 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#include "native_mate/function_template.h" + +namespace mate { + +namespace internal { + +CallbackHolderBase::CallbackHolderBase(v8::Isolate* isolate) + : MATE_PERSISTENT_INIT(isolate, v8_ref_, v8::External::New(isolate)) { + MATE_PERSISTENT_SET_WEAK(v8_ref_, this, &CallbackHolderBase::WeakCallback); +} + +CallbackHolderBase::~CallbackHolderBase() { + DCHECK(v8_ref_.IsEmpty()); +} + +v8::Handle CallbackHolderBase::GetHandle(v8::Isolate* isolate) { + return MATE_PERSISTENT_TO_LOCAL(v8::External, isolate, v8_ref_); +} + +// static +MATE_WEAK_CALLBACK(CallbackHolderBase::WeakCallback, + v8::External, + CallbackHolderBase) { + MATE_WEAK_CALLBACK_INIT(CallbackHolderBase); + MATE_PERSISTENT_RESET(self->v8_ref_); + delete self; +} + +} // namespace internal + +} // namespace mate diff --git a/native_mate/function_template.h b/native_mate/function_template.h new file mode 100644 index 00000000000..2dd5ba5cc4f --- /dev/null +++ b/native_mate/function_template.h @@ -0,0 +1,498 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_FUNCTION_TEMPLATE_H_ +#define NATIVE_MATE_FUNCTION_TEMPLATE_H_ + +#include "base/callback.h" +#include "base/logging.h" +#include "native_mate/arguments.h" +#include "native_mate/converter.h" +#include "v8/include/v8.h" + +namespace mate { + +class PerIsolateData; + +enum CreateFunctionTemplateFlags { + HolderIsFirstArgument = 1 << 0, +}; + +namespace internal { + +template +struct CallbackParamTraits { + typedef T LocalType; +}; +template +struct CallbackParamTraits { + typedef T LocalType; +}; +template +struct CallbackParamTraits { + typedef T* LocalType; +}; + + +// CallbackHolder and CallbackHolderBase are used to pass a base::Callback from +// CreateFunctionTemplate through v8 (via v8::FunctionTemplate) to +// DispatchToCallback, where it is invoked. + +// This simple base class is used so that we can share a single object template +// among every CallbackHolder instance. +class CallbackHolderBase { + public: + v8::Handle GetHandle(v8::Isolate* isolate); + + protected: + explicit CallbackHolderBase(v8::Isolate* isolate); + virtual ~CallbackHolderBase(); + + private: + static MATE_WEAK_CALLBACK(WeakCallback, v8::External, CallbackHolderBase); + + v8::Persistent v8_ref_; + + DISALLOW_COPY_AND_ASSIGN(CallbackHolderBase); +}; + +template +class CallbackHolder : public CallbackHolderBase { + public: + CallbackHolder(v8::Isolate* isolate, + const base::Callback& callback, + int flags) + : CallbackHolderBase(isolate), callback(callback), flags(flags) {} + base::Callback callback; + int flags; + private: + virtual ~CallbackHolder() {} + + DISALLOW_COPY_AND_ASSIGN(CallbackHolder); +}; + + +// This set of templates invokes a base::Callback, converts the return type to a +// JavaScript value, and returns that value to script via the provided +// mate::Arguments object. +// +// In C++, you can declare the function foo(void), but you can't pass a void +// expression to foo. As a result, we must specialize the case of Callbacks that +// have the void return type. +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3, + const P4& a4, + const P5& a5, + const P6& a6) { + MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4, a5, a6)); + } +}; +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3, + const P4& a4, + const P5& a5, + const P6& a6) { + callback.Run(a1, a2, a3, a4, a5, a6); + MATE_METHOD_RETURN_UNDEFINED(); + } +}; + +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3, + const P4& a4, + const P5& a5) { + MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4, a5)); + } +}; +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3, + const P4& a4, + const P5& a5) { + callback.Run(a1, a2, a3, a4, a5); + MATE_METHOD_RETURN_UNDEFINED(); + } +}; + +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3, + const P4& a4) { + MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4)); + } +}; +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3, + const P4& a4) { + callback.Run(a1, a2, a3, a4); + MATE_METHOD_RETURN_UNDEFINED(); + } +}; + +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3) { + MATE_METHOD_RETURN(callback.Run(a1, a2, a3)); + } +}; +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3) { + callback.Run(a1, a2, a3); + MATE_METHOD_RETURN_UNDEFINED(); + } +}; + +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2) { + MATE_METHOD_RETURN(callback.Run(a1, a2)); + } +}; +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2) { + callback.Run(a1, a2); + MATE_METHOD_RETURN_UNDEFINED(); + } +}; + +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1) { + MATE_METHOD_RETURN(callback.Run(a1)); + } +}; +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1) { + MATE_METHOD_RETURN(callback.Run(a1)); + } +}; + +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback) { + MATE_METHOD_RETURN(callback.Run()); + } +}; +template<> +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback) { + callback.Run(); + MATE_METHOD_RETURN_UNDEFINED(); + } +}; + + +template +bool GetNextArgument(Arguments* args, int create_flags, bool is_first, + T* result) { + if (is_first && (create_flags & HolderIsFirstArgument) != 0) { + return args->GetHolder(result); + } else { + return args->GetNext(result); + } +} + +// For advanced use cases, we allow callers to request the unparsed Arguments +// object and poke around in it directly. +inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first, + Arguments* result) { + *result = *args; + return true; +} +inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first, + Arguments** result) { + *result = args; + return true; +} + +// It's common for clients to just need the isolate, so we make that easy. +inline bool GetNextArgument(Arguments* args, int create_flags, + bool is_first, v8::Isolate** result) { + *result = args->isolate(); + return true; +} + + +// DispatchToCallback converts all the JavaScript arguments to C++ types and +// invokes the base::Callback. +template +struct Dispatcher { +}; + +template +struct Dispatcher { + static MATE_METHOD(DispatchToCallback) { + Arguments args(info); + v8::Handle v8_holder; + CHECK(args.GetData(&v8_holder)); + CallbackHolderBase* holder_base = reinterpret_cast( + v8_holder->Value()); + + typedef CallbackHolder HolderT; + HolderT* holder = static_cast(holder_base); + + return Invoker::Go(args, holder->callback); + } +}; + +template +struct Dispatcher { + static MATE_METHOD(DispatchToCallback) { + Arguments args(info); + v8::Handle v8_holder; + CHECK(args.GetData(&v8_holder)); + CallbackHolderBase* holder_base = reinterpret_cast( + v8_holder->Value()); + + typedef CallbackHolder HolderT; + HolderT* holder = static_cast(holder_base); + + typename CallbackParamTraits::LocalType a1; + if (!GetNextArgument(args, holder->flags, true, &a1)) { + args.ThrowError(); + MATE_METHOD_RETURN_UNDEFINED(); + } + + return Invoker::Go(args, holder->callback, a1); + } +}; + +template +struct Dispatcher { + static MATE_METHOD(DispatchToCallback) { + Arguments args(info); + v8::Handle v8_holder; + CHECK(args.GetData(&v8_holder)); + CallbackHolderBase* holder_base = reinterpret_cast( + v8_holder->Value()); + + typedef CallbackHolder HolderT; + HolderT* holder = static_cast(holder_base); + + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + if (!GetNextArgument(args, holder->flags, true, &a1) || + !GetNextArgument(args, holder->flags, false, &a2)) { + args.ThrowError(); + MATE_METHOD_RETURN_UNDEFINED(); + } + + return Invoker::Go(args, holder->callback, a1, a2); + } +}; + +template +struct Dispatcher { + static MATE_METHOD(DispatchToCallback) { + Arguments args(info); + v8::Handle v8_holder; + CHECK(args.GetData(&v8_holder)); + CallbackHolderBase* holder_base = reinterpret_cast( + v8_holder->Value()); + + typedef CallbackHolder HolderT; + HolderT* holder = static_cast(holder_base); + + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + typename CallbackParamTraits::LocalType a3; + if (!GetNextArgument(args, holder->flags, true, &a1) || + !GetNextArgument(args, holder->flags, false, &a2) || + !GetNextArgument(args, holder->flags, false, &a3)) { + args.ThrowError(); + MATE_METHOD_RETURN_UNDEFINED(); + } + + return Invoker::Go(args, holder->callback, a1, a2, a3); + } +}; + +template +struct Dispatcher { + static MATE_METHOD(DispatchToCallback) { + Arguments args(info); + v8::Handle v8_holder; + CHECK(args.GetData(&v8_holder)); + CallbackHolderBase* holder_base = reinterpret_cast( + v8_holder->Value()); + + typedef CallbackHolder HolderT; + HolderT* holder = static_cast(holder_base); + + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + typename CallbackParamTraits::LocalType a3; + typename CallbackParamTraits::LocalType a4; + if (!GetNextArgument(args, holder->flags, true, &a1) || + !GetNextArgument(args, holder->flags, false, &a2) || + !GetNextArgument(args, holder->flags, false, &a3) || + !GetNextArgument(args, holder->flags, false, &a4)) { + args.ThrowError(); + MATE_METHOD_RETURN_UNDEFINED(); + } + + return Invoker::Go(args, holder->callback, a1, a2, a3, + a4); + } +}; + +template +struct Dispatcher { + static MATE_METHOD(DispatchToCallback) { + Arguments args(info); + v8::Handle v8_holder; + CHECK(args.GetData(&v8_holder)); + CallbackHolderBase* holder_base = reinterpret_cast( + v8_holder->Value()); + + typedef CallbackHolder HolderT; + HolderT* holder = static_cast(holder_base); + + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + typename CallbackParamTraits::LocalType a3; + typename CallbackParamTraits::LocalType a4; + typename CallbackParamTraits::LocalType a5; + if (!GetNextArgument(args, holder->flags, true, &a1) || + !GetNextArgument(args, holder->flags, false, &a2) || + !GetNextArgument(args, holder->flags, false, &a3) || + !GetNextArgument(args, holder->flags, false, &a4) || + !GetNextArgument(args, holder->flags, false, &a5)) { + args.ThrowError(); + MATE_METHOD_RETURN_UNDEFINED(); + } + + return Invoker::Go(args, holder->callback, a1, a2, + a3, a4, a5); + } +}; + +template +struct Dispatcher { + static MATE_METHOD(DispatchToCallback) { + Arguments args(info); + v8::Handle v8_holder; + CHECK(args.GetData(&v8_holder)); + CallbackHolderBase* holder_base = reinterpret_cast( + v8_holder->Value()); + + typedef CallbackHolder HolderT; + HolderT* holder = static_cast(holder_base); + + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + typename CallbackParamTraits::LocalType a3; + typename CallbackParamTraits::LocalType a4; + typename CallbackParamTraits::LocalType a5; + typename CallbackParamTraits::LocalType a6; + if (!GetNextArgument(args, holder->flags, true, &a1) || + !GetNextArgument(args, holder->flags, false, &a2) || + !GetNextArgument(args, holder->flags, false, &a3) || + !GetNextArgument(args, holder->flags, false, &a4) || + !GetNextArgument(args, holder->flags, false, &a5) || + !GetNextArgument(args, holder->flags, false, &a6)) { + args.ThrowError(); + MATE_METHOD_RETURN_UNDEFINED(); + } + + return Invoker::Go(args, holder->callback, a1, + a2, a3, a4, a5, a6); + } +}; + +} // namespace internal + + +// CreateFunctionTemplate creates a v8::FunctionTemplate that will create +// JavaScript functions that execute a provided C++ function or base::Callback. +// JavaScript arguments are automatically converted via mate::Converter, as is +// the return value of the C++ function, if any. +template +v8::Local CreateFunctionTemplate( + v8::Isolate* isolate, const base::Callback callback, + int callback_flags = 0) { + typedef internal::CallbackHolder HolderT; + HolderT* holder = new HolderT(isolate, callback, callback_flags); + + return v8::FunctionTemplate::New( + isolate, + &internal::Dispatcher::DispatchToCallback, + ConvertToV8 >(isolate, + holder->GetHandle(isolate))); +} + +} // namespace mate + +#endif // NATIVE_MATE_FUNCTION_TEMPLATE_H_ diff --git a/native_mate/handle.h b/native_mate/handle.h new file mode 100644 index 00000000000..f81b9d12509 --- /dev/null +++ b/native_mate/handle.h @@ -0,0 +1,68 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_HANDLE_H_ +#define NATIVE_MATE_HANDLE_H_ + +#include "native_mate/converter.h" + +namespace mate { + +// You can use mate::Handle on the stack to retain a mate::Wrappable object. +// Currently we don't have a mechanism for retaining a mate::Wrappable object +// in the C++ heap because strong references from C++ to V8 can cause memory +// leaks. +template +class Handle { + public: + Handle() : object_(NULL) {} + + Handle(v8::Handle wrapper, T* object) + : wrapper_(wrapper), + object_(object) { + } + + bool IsEmpty() const { return !object_; } + + void Clear() { + wrapper_.Clear(); + object_ = NULL; + } + + T* operator->() const { return object_; } + v8::Handle ToV8() const { return wrapper_; } + T* get() const { return object_; } + + private: + v8::Handle wrapper_; + T* object_; +}; + +template +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + const mate::Handle& val) { + return val.ToV8(); + } + static bool FromV8(v8::Isolate* isolate, v8::Handle val, + mate::Handle* out) { + T* object = NULL; + if (!Converter::FromV8(isolate, val, &object)) { + return false; + } + *out = mate::Handle(val, object); + return true; + } +}; + +// This function is a convenient way to create a handle from a raw pointer +// without having to write out the type of the object explicitly. +template +mate::Handle CreateHandle(v8::Isolate* isolate, T* object) { + return mate::Handle(object->GetWrapper(isolate), object); +} + +} // namespace mate + +#endif // NATIVE_MATE_HANDLE_H_ diff --git a/native_mate/object_template_builder.cc b/native_mate/object_template_builder.cc new file mode 100644 index 00000000000..a8022158fb6 --- /dev/null +++ b/native_mate/object_template_builder.cc @@ -0,0 +1,39 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#include "native_mate/object_template_builder.h" + +namespace mate { + +ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate) + : isolate_(isolate), template_(v8::ObjectTemplate::New()) { + template_->SetInternalFieldCount(1); +} + +ObjectTemplateBuilder::~ObjectTemplateBuilder() { +} + +ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl( + const base::StringPiece& name, v8::Handle val) { + template_->Set(StringToSymbol(isolate_, name), val); + return *this; +} + +ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl( + const base::StringPiece& name, v8::Handle getter, + v8::Handle setter) { +#if NODE_VERSION_AT_LEAST(0, 11, 0) + template_->SetAccessorProperty(StringToSymbol(isolate_, name), getter, + setter); +#endif + return *this; +} + +v8::Local ObjectTemplateBuilder::Build() { + v8::Local result = template_; + template_.Clear(); + return result; +} + +} // namespace mate diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h new file mode 100644 index 00000000000..a0fad1569b5 --- /dev/null +++ b/native_mate/object_template_builder.h @@ -0,0 +1,123 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_OBJECT_TEMPLATE_BUILDER_H_ +#define NATIVE_MATE_OBJECT_TEMPLATE_BUILDER_H_ + +#include "base/bind.h" +#include "base/callback.h" +#include "base/strings/string_piece.h" +#include "base/template_util.h" +#include "native_mate/converter.h" +#include "native_mate/function_template.h" +#include "v8/include/v8.h" + +namespace mate { + +namespace { + +// Base template - used only for non-member function pointers. Other types +// either go to one of the below specializations, or go here and fail to compile +// because of base::Bind(). +template +struct CallbackTraits { + static v8::Handle CreateTemplate(v8::Isolate* isolate, + T callback) { + return CreateFunctionTemplate(isolate, base::Bind(callback)); + } +}; + +// Specialization for base::Callback. +template +struct CallbackTraits > { + static v8::Handle CreateTemplate( + v8::Isolate* isolate, const base::Callback& callback) { + return CreateFunctionTemplate(isolate, callback); + } +}; + +// Specialization for member function pointers. We need to handle this case +// specially because the first parameter for callbacks to MFP should typically +// come from the the JavaScript "this" object the function was called on, not +// from the first normal parameter. +template +struct CallbackTraits::value>::type> { + static v8::Handle CreateTemplate(v8::Isolate* isolate, + T callback) { + return CreateFunctionTemplate(isolate, base::Bind(callback), + HolderIsFirstArgument); + } +}; + +// This specialization allows people to construct function templates directly if +// they need to do fancier stuff. +template<> +struct CallbackTraits > { + static v8::Handle CreateTemplate( + v8::Handle templ) { + return templ; + } +}; + +} // namespace + + +// ObjectTemplateBuilder provides a handy interface to creating +// v8::ObjectTemplate instances with various sorts of properties. +class ObjectTemplateBuilder { + public: + explicit ObjectTemplateBuilder(v8::Isolate* isolate); + ~ObjectTemplateBuilder(); + + // It's against Google C++ style to return a non-const ref, but we take some + // poetic license here in order that all calls to Set() can be via the '.' + // operator and line up nicely. + template + ObjectTemplateBuilder& SetValue(const base::StringPiece& name, T val) { + return SetImpl(name, ConvertToV8(isolate_, val)); + } + + // In the following methods, T and U can be function pointer, member function + // pointer, base::Callback, or v8::FunctionTemplate. Most clients will want to + // use one of the first two options. Also see mate::CreateFunctionTemplate() + // for creating raw function templates. + template + ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, + const T& callback) { + return SetImpl(name, CallbackTraits::CreateTemplate(isolate_, callback)); + } + template + ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, + const T& getter) { + return SetPropertyImpl(name, + CallbackTraits::CreateTemplate(isolate_, getter), + v8::Local()); + } + template + ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, + const T& getter, const U& setter) { + return SetPropertyImpl(name, + CallbackTraits::CreateTemplate(isolate_, getter), + CallbackTraits::CreateTemplate(isolate_, setter)); + } + + v8::Local Build(); + + private: + ObjectTemplateBuilder& SetImpl(const base::StringPiece& name, + v8::Handle val); + ObjectTemplateBuilder& SetPropertyImpl( + const base::StringPiece& name, v8::Handle getter, + v8::Handle setter); + + v8::Isolate* isolate_; + + // ObjectTemplateBuilder should only be used on the stack. + v8::Local template_; +}; + +} // namespace mate + +#endif // NATIVE_MATE_OBJECT_TEMPLATE_BUILDER_H_ diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h new file mode 100644 index 00000000000..c1705676c28 --- /dev/null +++ b/native_mate/scoped_persistent.h @@ -0,0 +1,111 @@ +// Copyright 2014 Cheng Zhao. All rights reserved. +// Use of this source code is governed by MIT license that can be found in the +// LICENSE file. + +#ifndef NATIVE_MATE_SCOPED_PERSISTENT_H_ +#define NATIVE_MATE_SCOPED_PERSISTENT_H_ + +#include "base/memory/ref_counted.h" +#include "v8/include/v8.h" + +namespace mate { + +// A v8::Persistent handle to a V8 value which destroys and clears the +// underlying handle on destruction. +template +class ScopedPersistent { + public: + ScopedPersistent() { + } + + explicit ScopedPersistent(v8::Handle handle) { + reset(handle); + } + + ~ScopedPersistent() { + reset(); + } + + void reset(v8::Handle handle) { + if (!handle.IsEmpty()) + handle_.Reset(GetIsolate(handle), handle); + else + reset(); + } + + void reset() { + handle_.Reset(); + } + + bool IsEmpty() const { + return handle_.IsEmpty(); + } + + v8::Handle NewHandle() const { + if (handle_.IsEmpty()) + return v8::Local(); + return v8::Local::New(GetIsolate(handle_), handle_); + } + + v8::Handle NewHandle(v8::Isolate* isolate) const { + if (handle_.IsEmpty()) + return v8::Local(); + return v8::Local::New(isolate, handle_); + } + + template + void MakeWeak(P* parameters, + typename v8::WeakReferenceCallbacks::Revivable callback) { + handle_.MakeWeak(parameters, callback); + } + + private: + template + static v8::Isolate* GetIsolate(v8::Handle object_handle) { + // Only works for v8::Object and its subclasses. Add specialisations for + // anything else. + if (!object_handle.IsEmpty()) + return GetIsolate(object_handle->CreationContext()); + return v8::Isolate::GetCurrent(); + } + static v8::Isolate* GetIsolate(v8::Handle context_handle) { + if (!context_handle.IsEmpty()) + return context_handle->GetIsolate(); + return v8::Isolate::GetCurrent(); + } + static v8::Isolate* GetIsolate( + v8::Handle template_handle) { + return v8::Isolate::GetCurrent(); + } + template + static v8::Isolate* GetIsolate(const U& any_handle) { + return v8::Isolate::GetCurrent(); + } + + v8::Persistent handle_; + + DISALLOW_COPY_AND_ASSIGN(ScopedPersistent); +}; + +template +class RefCountedPersistent : public ScopedPersistent, + public base::RefCounted> { + public: + RefCountedPersistent() {} + + explicit RefCountedPersistent(v8::Handle handle) + : ScopedPersistent(handle) { + } + + protected: + friend class base::RefCounted>; + + ~RefCountedPersistent() {} + + private: + DISALLOW_COPY_AND_ASSIGN(RefCountedPersistent); +}; + +} // namespace mate + +#endif // NATIVE_MATE_SCOPED_PERSISTENT_H_ diff --git a/native_mate/try_catch.cc b/native_mate/try_catch.cc new file mode 100644 index 00000000000..c3efd3cddd4 --- /dev/null +++ b/native_mate/try_catch.cc @@ -0,0 +1,49 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#include "native_mate/try_catch.h" + +#include + +#include "native_mate/converter.h" + +namespace mate { + +TryCatch::TryCatch() { +} + +TryCatch::~TryCatch() { +} + +bool TryCatch::HasCaught() { + return try_catch_.HasCaught(); +} + +std::string TryCatch::GetStackTrace() { + if (!HasCaught()) { + return ""; + } + + std::stringstream ss; + v8::Handle message = try_catch_.Message(); + ss << V8ToString(message->Get()) << std::endl + << V8ToString(message->GetSourceLine()) << std::endl; + + v8::Handle trace = message->GetStackTrace(); + if (trace.IsEmpty()) + return ss.str(); + + int len = trace->GetFrameCount(); + for (int i = 0; i < len; ++i) { + v8::Handle frame = trace->GetFrame(i); + ss << V8ToString(frame->GetScriptName()) << ":" + << frame->GetLineNumber() << ":" + << frame->GetColumn() << ": " + << V8ToString(frame->GetFunctionName()) + << std::endl; + } + return ss.str(); +} + +} // namespace mate diff --git a/native_mate/try_catch.h b/native_mate/try_catch.h new file mode 100644 index 00000000000..3b3ece87360 --- /dev/null +++ b/native_mate/try_catch.h @@ -0,0 +1,32 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_TRY_CATCH_H_ +#define NATIVE_MATE_TRY_CATCH_H_ + +#include + +#include "base/basictypes.h" +#include "v8/include/v8.h" + +namespace mate { + +// TryCatch is a convenient wrapper around v8::TryCatch. +class TryCatch { + public: + TryCatch(); + ~TryCatch(); + + bool HasCaught(); + std::string GetStackTrace(); + + private: + v8::TryCatch try_catch_; + + DISALLOW_COPY_AND_ASSIGN(TryCatch); +}; + +} // namespace mate + +#endif // NATIVE_MATE_TRY_CATCH_H_ diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc new file mode 100644 index 00000000000..77bd721ad2f --- /dev/null +++ b/native_mate/wrappable.cc @@ -0,0 +1,58 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#include "native_mate/wrappable.h" + +#include "base/logging.h" +#include "native_mate/object_template_builder.h" + +namespace mate { + +Wrappable::Wrappable() { +} + +Wrappable::~Wrappable() { + MATE_PERSISTENT_RESET(wrapper_); +} + +ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return ObjectTemplateBuilder(isolate); +} + +// static +MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { + MATE_WEAK_CALLBACK_INIT(Wrappable); + MATE_PERSISTENT_RESET(self->wrapper_); + delete self; +} + +v8::Handle Wrappable::GetWrapper(v8::Isolate* isolate) { + if (!wrapper_.IsEmpty()) { + return MATE_PERSISTENT_TO_LOCAL(v8::Object, isolate, wrapper_); + } + + v8::Local templ = + GetObjectTemplateBuilder(isolate).Build(); + CHECK(!templ.IsEmpty()); + CHECK_EQ(1, templ->InternalFieldCount()); + v8::Handle wrapper = templ->NewInstance(); + MATE_SET_INTERNAL_FIELD_POINTER(wrapper, 0, this); + MATE_PERSISTENT_ASSIGN(v8::Object, isolate, wrapper_, wrapper); + MATE_PERSISTENT_SET_WEAK(wrapper_, this, WeakCallback); + return wrapper; +} + +namespace internal { + +void* FromV8Impl(v8::Isolate* isolate, v8::Handle val) { + if (!val->IsObject()) + return NULL; + v8::Handle obj = v8::Handle::Cast(val); + return MATE_GET_INTERNAL_FIELD_POINTER(obj, 0); +} + +} // namespace internal + +} // namespace mate diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h new file mode 100644 index 00000000000..949a9ebebd9 --- /dev/null +++ b/native_mate/wrappable.h @@ -0,0 +1,85 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_WRAPPABLE_H_ +#define NATIVE_MATE_WRAPPABLE_H_ + +#include "base/template_util.h" +#include "native_mate/compat.h" +#include "native_mate/converter.h" + +namespace mate { + +namespace internal { + +void* FromV8Impl(v8::Isolate* isolate, v8::Handle val); + +} // namespace internal + + +// Wrappable is a base class for C++ objects that have corresponding v8 wrapper +// objects. To retain a Wrappable object on the stack, use a mate::Handle. +// +// USAGE: +// // my_class.h +// class MyClass : Wrappable { +// public: +// // Optional, only required if non-empty template should be used. +// virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( +// v8::Isolate* isolate); +// ... +// }; +// +// mate::ObjectTemplateBuilder MyClass::GetObjectTemplateBuilder( +// v8::Isolate* isolate) { +// return Wrappable::GetObjectTemplateBuilder(isolate).SetValue("foobar", 42); +// } +// +// Subclasses should also typically have private constructors and expose a +// static Create function that returns a mate::Handle. Forcing creators through +// this static Create function will enforce that clients actually create a +// wrapper for the object. If clients fail to create a wrapper for a wrappable +// object, the object will leak because we use the weak callback from the +// wrapper as the signal to delete the wrapped object. +class ObjectTemplateBuilder; + +// Non-template base class to share code between templates instances. +class Wrappable { + public: + // Retrieve (or create) the v8 wrapper object cooresponding to this object. + v8::Handle GetWrapper(v8::Isolate* isolate); + + protected: + Wrappable(); + virtual ~Wrappable(); + + virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); + + private: + static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, Wrappable); + + v8::Persistent wrapper_; // Weak + + DISALLOW_COPY_AND_ASSIGN(Wrappable); +}; + + +// This converter handles any subclass of Wrappable. +template +struct Converter::value>::type> { + static v8::Handle ToV8(v8::Isolate* isolate, T* val) { + return val->GetWrapper(isolate); + } + + static bool FromV8(v8::Isolate* isolate, v8::Handle val, T** out) { + *out = static_cast(static_cast( + internal::FromV8Impl(isolate, val))); + return *out != NULL; + } +}; + +} // namespace mate + +#endif // NATIVE_MATE_WRAPPABLE_H_ diff --git a/native_mate_files.gypi b/native_mate_files.gypi new file mode 100644 index 00000000000..1496ab4f91e --- /dev/null +++ b/native_mate_files.gypi @@ -0,0 +1,23 @@ +{ + 'variables': { + 'native_mate_files': [ + 'native_mate/arguments.cc', + 'native_mate/arguments.h', + 'native_mate/compat.h', + 'native_mate/converter.cc', + 'native_mate/converter.h', + 'native_mate/dictionary.cc', + 'native_mate/dictionary.h', + 'native_mate/function_template.cc', + 'native_mate/function_template.h', + 'native_mate/handle.h', + 'native_mate/object_template_builder.cc', + 'native_mate/object_template_builder.h', + 'native_mate/scoped_persistent.h', + 'native_mate/try_catch.cc', + 'native_mate/try_catch.h', + 'native_mate/wrappable.cc', + 'native_mate/wrappable.h', + ], + }, +} From 4cada31f808994b297439dff429638debc4a4ee9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 15 Apr 2014 11:15:19 +0800 Subject: [PATCH 002/129] Do not rely on latest base/template_util. --- native_mate/object_template_builder.h | 6 +- native_mate/template_util.h | 150 ++++++++++++++++++++++++++ native_mate/wrappable.h | 6 +- native_mate_files.gypi | 1 + 4 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 native_mate/template_util.h diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index a0fad1569b5..fb4be832420 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -8,9 +8,9 @@ #include "base/bind.h" #include "base/callback.h" #include "base/strings/string_piece.h" -#include "base/template_util.h" #include "native_mate/converter.h" #include "native_mate/function_template.h" +#include "native_mate/template_util.h" #include "v8/include/v8.h" namespace mate { @@ -42,8 +42,8 @@ struct CallbackTraits > { // come from the the JavaScript "this" object the function was called on, not // from the first normal parameter. template -struct CallbackTraits::value>::type> { +struct CallbackTraits::value>::type> { static v8::Handle CreateTemplate(v8::Isolate* isolate, T callback) { return CreateFunctionTemplate(isolate, base::Bind(callback), diff --git a/native_mate/template_util.h b/native_mate/template_util.h new file mode 100644 index 00000000000..e1632a2d566 --- /dev/null +++ b/native_mate/template_util.h @@ -0,0 +1,150 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NATIVE_MATE_TEMPLATE_UTIL_H_ +#define NATIVE_MATE_TEMPLATE_UTIL_H_ + +#include // For size_t. + +#include "build/build_config.h" + +namespace mate { + +// template definitions from tr1 + +template +struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant type; +}; + +template const T integral_constant::value; + +typedef integral_constant true_type; +typedef integral_constant false_type; + +template struct is_pointer : false_type {}; +template struct is_pointer : true_type {}; + +// Member function pointer detection up to four params. Add more as needed +// below. This is built-in to C++ 11, and we can remove this when we switch. +template +struct is_member_function_pointer : false_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + + +template struct is_same : public false_type {}; +template struct is_same : true_type {}; + +template struct is_array : public false_type {}; +template struct is_array : public true_type {}; +template struct is_array : public true_type {}; + +template struct is_non_const_reference : false_type {}; +template struct is_non_const_reference : true_type {}; +template struct is_non_const_reference : false_type {}; + +template struct is_const : false_type {}; +template struct is_const : true_type {}; + +template struct is_void : false_type {}; +template <> struct is_void : true_type {}; + +namespace internal { + +// Types YesType and NoType are guaranteed such that sizeof(YesType) < +// sizeof(NoType). +typedef char YesType; + +struct NoType { + YesType dummy[2]; +}; + +// This class is an implementation detail for is_convertible, and you +// don't need to know how it works to use is_convertible. For those +// who care: we declare two different functions, one whose argument is +// of type To and one with a variadic argument list. We give them +// return types of different size, so we can use sizeof to trick the +// compiler into telling us which function it would have chosen if we +// had called it with an argument of type From. See Alexandrescu's +// _Modern C++ Design_ for more details on this sort of trick. + +struct ConvertHelper { + template + static YesType Test(To); + + template + static NoType Test(...); + + template + static From& Create(); +}; + +// Used to determine if a type is a struct/union/class. Inspired by Boost's +// is_class type_trait implementation. +struct IsClassHelper { + template + static YesType Test(void(C::*)(void)); + + template + static NoType Test(...); +}; + +} // namespace internal + +// Inherits from true_type if From is convertible to To, false_type otherwise. +// +// Note that if the type is convertible, this will be a true_type REGARDLESS +// of whether or not the conversion would emit a warning. +template +struct is_convertible + : integral_constant( + internal::ConvertHelper::Create())) == + sizeof(internal::YesType)> { +}; + +template +struct is_class + : integral_constant(0)) == + sizeof(internal::YesType)> { +}; + +template +struct enable_if {}; + +template +struct enable_if { typedef T type; }; + +} // namespace mate + +#endif // NATIVE_MATE_TEMPLATE_UTIL_H_ diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 949a9ebebd9..e4037c0bb5e 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -5,9 +5,9 @@ #ifndef NATIVE_MATE_WRAPPABLE_H_ #define NATIVE_MATE_WRAPPABLE_H_ -#include "base/template_util.h" #include "native_mate/compat.h" #include "native_mate/converter.h" +#include "native_mate/template_util.h" namespace mate { @@ -67,8 +67,8 @@ class Wrappable { // This converter handles any subclass of Wrappable. template -struct Converter::value>::type> { +struct Converter::value>::type> { static v8::Handle ToV8(v8::Isolate* isolate, T* val) { return val->GetWrapper(isolate); } diff --git a/native_mate_files.gypi b/native_mate_files.gypi index 1496ab4f91e..8d3952bdd8d 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -14,6 +14,7 @@ 'native_mate/object_template_builder.cc', 'native_mate/object_template_builder.h', 'native_mate/scoped_persistent.h', + 'native_mate/template_util.h', 'native_mate/try_catch.cc', 'native_mate/try_catch.h', 'native_mate/wrappable.cc', From 6ac926aa3248eb934212e2c2065446f00d765e09 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 15 Apr 2014 11:34:07 +0800 Subject: [PATCH 003/129] Enable modifying existing ObjectTemplate. --- native_mate/object_template_builder.cc | 6 ++++-- native_mate/object_template_builder.h | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/native_mate/object_template_builder.cc b/native_mate/object_template_builder.cc index a8022158fb6..7c40b582679 100644 --- a/native_mate/object_template_builder.cc +++ b/native_mate/object_template_builder.cc @@ -6,8 +6,10 @@ namespace mate { -ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate) - : isolate_(isolate), template_(v8::ObjectTemplate::New()) { +ObjectTemplateBuilder::ObjectTemplateBuilder( + v8::Isolate* isolate, + v8::Local templ) + : isolate_(isolate), template_(templ) { template_->SetInternalFieldCount(1); } diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index fb4be832420..cd69c47925a 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -68,7 +68,9 @@ struct CallbackTraits > { // v8::ObjectTemplate instances with various sorts of properties. class ObjectTemplateBuilder { public: - explicit ObjectTemplateBuilder(v8::Isolate* isolate); + explicit ObjectTemplateBuilder( + v8::Isolate* isolate, + v8::Local templ = v8::ObjectTemplate::New()); ~ObjectTemplateBuilder(); // It's against Google C++ style to return a non-const ref, but we take some From a20e02ee23631e3a9b9af526087950bd12975d38 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 15 Apr 2014 15:30:30 +0800 Subject: [PATCH 004/129] Fix compilation error of function_template. --- native_mate/function_template.h | 48 ++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 2dd5ba5cc4f..192aa8ed15e 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/logging.h" #include "native_mate/arguments.h" +#include "native_mate/compat.h" #include "native_mate/converter.h" #include "v8/include/v8.h" @@ -229,7 +230,8 @@ struct Invoker { Arguments& args, const base::Callback& callback, const P1& a1) { - MATE_METHOD_RETURN(callback.Run(a1)); + callback.Run(a1); + MATE_METHOD_RETURN_UNDEFINED(); } }; @@ -318,7 +320,7 @@ struct Dispatcher { HolderT* holder = static_cast(holder_base); typename CallbackParamTraits::LocalType a1; - if (!GetNextArgument(args, holder->flags, true, &a1)) { + if (!GetNextArgument(&args, holder->flags, true, &a1)) { args.ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); } @@ -341,8 +343,8 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; - if (!GetNextArgument(args, holder->flags, true, &a1) || - !GetNextArgument(args, holder->flags, false, &a2)) { + if (!GetNextArgument(&args, holder->flags, true, &a1) || + !GetNextArgument(&args, holder->flags, false, &a2)) { args.ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); } @@ -366,9 +368,9 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; - if (!GetNextArgument(args, holder->flags, true, &a1) || - !GetNextArgument(args, holder->flags, false, &a2) || - !GetNextArgument(args, holder->flags, false, &a3)) { + if (!GetNextArgument(&args, holder->flags, true, &a1) || + !GetNextArgument(&args, holder->flags, false, &a2) || + !GetNextArgument(&args, holder->flags, false, &a3)) { args.ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); } @@ -393,10 +395,10 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; typename CallbackParamTraits::LocalType a4; - if (!GetNextArgument(args, holder->flags, true, &a1) || - !GetNextArgument(args, holder->flags, false, &a2) || - !GetNextArgument(args, holder->flags, false, &a3) || - !GetNextArgument(args, holder->flags, false, &a4)) { + if (!GetNextArgument(&args, holder->flags, true, &a1) || + !GetNextArgument(&args, holder->flags, false, &a2) || + !GetNextArgument(&args, holder->flags, false, &a3) || + !GetNextArgument(&args, holder->flags, false, &a4)) { args.ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); } @@ -424,11 +426,11 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a3; typename CallbackParamTraits::LocalType a4; typename CallbackParamTraits::LocalType a5; - if (!GetNextArgument(args, holder->flags, true, &a1) || - !GetNextArgument(args, holder->flags, false, &a2) || - !GetNextArgument(args, holder->flags, false, &a3) || - !GetNextArgument(args, holder->flags, false, &a4) || - !GetNextArgument(args, holder->flags, false, &a5)) { + if (!GetNextArgument(&args, holder->flags, true, &a1) || + !GetNextArgument(&args, holder->flags, false, &a2) || + !GetNextArgument(&args, holder->flags, false, &a3) || + !GetNextArgument(&args, holder->flags, false, &a4) || + !GetNextArgument(&args, holder->flags, false, &a5)) { args.ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); } @@ -457,12 +459,12 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a4; typename CallbackParamTraits::LocalType a5; typename CallbackParamTraits::LocalType a6; - if (!GetNextArgument(args, holder->flags, true, &a1) || - !GetNextArgument(args, holder->flags, false, &a2) || - !GetNextArgument(args, holder->flags, false, &a3) || - !GetNextArgument(args, holder->flags, false, &a4) || - !GetNextArgument(args, holder->flags, false, &a5) || - !GetNextArgument(args, holder->flags, false, &a6)) { + if (!GetNextArgument(&args, holder->flags, true, &a1) || + !GetNextArgument(&args, holder->flags, false, &a2) || + !GetNextArgument(&args, holder->flags, false, &a3) || + !GetNextArgument(&args, holder->flags, false, &a4) || + !GetNextArgument(&args, holder->flags, false, &a5) || + !GetNextArgument(&args, holder->flags, false, &a6)) { args.ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); } @@ -487,7 +489,9 @@ v8::Local CreateFunctionTemplate( HolderT* holder = new HolderT(isolate, callback, callback_flags); return v8::FunctionTemplate::New( +#if NODE_VERSION_AT_LEAST(0, 11, 11) isolate, +#endif &internal::Dispatcher::DispatchToCallback, ConvertToV8 >(isolate, holder->GetHandle(isolate))); From caa5ea03167b64f623f6bb73346f36d110bc8b3b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 15 Apr 2014 15:30:46 +0800 Subject: [PATCH 005/129] Add initial Constructor type. --- native_mate/constructor.cc | 42 ++++++++++++++++++++++++++++++++++++++ native_mate/constructor.h | 34 ++++++++++++++++++++++++++++++ native_mate/wrappable.h | 4 ++++ native_mate_files.gypi | 2 ++ 4 files changed, 82 insertions(+) create mode 100644 native_mate/constructor.cc create mode 100644 native_mate/constructor.h diff --git a/native_mate/constructor.cc b/native_mate/constructor.cc new file mode 100644 index 00000000000..fca79212776 --- /dev/null +++ b/native_mate/constructor.cc @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#include "native_mate/wrappable_class.h" + +#include "native_mate/function_template.h" +#include "native_mate/object_template_builder.h" + +namespace mate { + +Constructor::Constructor(const base::StringPiece& name) : name_(name) { +} + +Constructor::~Constructor() { + constructor_.Reset(); +} + +v8::Handle Constructor::GetFunction(v8::Isolate* isolate) { + if (constructor_.IsEmpty()) { + v8::Local constructor = CreateFunctionTemplate( + isolate, + base::Bind(&Constructor::New, base::Unretained(this))); + constructor->InstanceTemplate()->SetInternalFieldCount(1); + constructor->SetClassName(StringToV8(isolate, name_)); + SetPrototype(isolate, constructor->PrototypeTemplate()); + + constructor_.Reset(isolate, constructor); + } + + return MATE_PERSISTENT_TO_LOCAL( + v8::FunctionTemplate, isolate, constructor_)->GetFunction(); +} + +void Constructor::New() { +} + +void Constructor::SetPrototype(v8::Isolate* isolate, + v8::Handle prototype) { +} + +} // namespace mate diff --git a/native_mate/constructor.h b/native_mate/constructor.h new file mode 100644 index 00000000000..45786fdb341 --- /dev/null +++ b/native_mate/constructor.h @@ -0,0 +1,34 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_WRAPPABLE_CLASS_H_ +#define NATIVE_MATE_WRAPPABLE_CLASS_H_ + +#include "native_mate/wrappable.h" + +namespace mate { + +class Constructor { + public: + v8::Handle GetFunction(v8::Isolate* isolate); + + protected: + Constructor(const base::StringPiece& name); + virtual ~Constructor(); + + virtual void New() = 0; + + virtual void SetPrototype(v8::Isolate* isolate, + v8::Handle prototype); + + private: + base::StringPiece name_; + v8::Persistent constructor_; + + DISALLOW_COPY_AND_ASSIGN(Constructor); +}; + +} // namespace mate + +#endif // NATIVE_MATE_WRAPPABLE_CLASS_H_ diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index e4037c0bb5e..b6b80789887 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -56,6 +56,10 @@ class Wrappable { virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); + // Override to change how the v8 wrapper is built (by default it was built + // from the ObjectTemplateBuilder. + // virtual v8::Handle BuildObject(); + private: static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, Wrappable); diff --git a/native_mate_files.gypi b/native_mate_files.gypi index 8d3952bdd8d..934c91f2323 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -4,6 +4,8 @@ 'native_mate/arguments.cc', 'native_mate/arguments.h', 'native_mate/compat.h', + 'native_mate/constructor.cc', + 'native_mate/constructor.h', 'native_mate/converter.cc', 'native_mate/converter.h', 'native_mate/dictionary.cc', From 78ab726ec7b14ecea6240a684002c6910561ef5c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 15 Apr 2014 15:39:13 +0800 Subject: [PATCH 006/129] Fix passing the wrong parameter. --- native_mate/constructor.cc | 2 +- native_mate/function_template.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native_mate/constructor.cc b/native_mate/constructor.cc index fca79212776..2ab6459e8d3 100644 --- a/native_mate/constructor.cc +++ b/native_mate/constructor.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.chromium file. -#include "native_mate/wrappable_class.h" +#include "native_mate/constructor.h" #include "native_mate/function_template.h" #include "native_mate/object_template_builder.h" diff --git a/native_mate/function_template.cc b/native_mate/function_template.cc index 711c04150a4..22bb6260d1e 100644 --- a/native_mate/function_template.cc +++ b/native_mate/function_template.cc @@ -9,7 +9,7 @@ namespace mate { namespace internal { CallbackHolderBase::CallbackHolderBase(v8::Isolate* isolate) - : MATE_PERSISTENT_INIT(isolate, v8_ref_, v8::External::New(isolate)) { + : MATE_PERSISTENT_INIT(isolate, v8_ref_, v8::External::New(this)) { MATE_PERSISTENT_SET_WEAK(v8_ref_, this, &CallbackHolderBase::WeakCallback); } From e2e1faa2250ef5a41666cca29ebeac681bc83fa1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Apr 2014 09:50:51 +0800 Subject: [PATCH 007/129] Make the Constructor accept arbitrary callback. --- native_mate/arguments.h | 4 + native_mate/constructor.cc | 28 +++---- native_mate/constructor.h | 162 +++++++++++++++++++++++++++++++++++-- native_mate/wrappable.cc | 12 +-- native_mate/wrappable.h | 50 +++++++----- native_mate_files.gypi | 2 +- 6 files changed, 210 insertions(+), 48 deletions(-) diff --git a/native_mate/arguments.h b/native_mate/arguments.h index 054e03abf84..ebe49e7c841 100644 --- a/native_mate/arguments.h +++ b/native_mate/arguments.h @@ -56,6 +56,10 @@ class Arguments { return true; } + v8::Handle GetThis() { + return info_->This(); + } + #if NODE_VERSION_AT_LEAST(0, 11, 0) template void Return(T val) { diff --git a/native_mate/constructor.cc b/native_mate/constructor.cc index 2ab6459e8d3..9c57fd09c31 100644 --- a/native_mate/constructor.cc +++ b/native_mate/constructor.cc @@ -4,39 +4,37 @@ #include "native_mate/constructor.h" +#include "base/bind.h" +#include "base/strings/string_piece.h" +#include "native_mate/arguments.h" #include "native_mate/function_template.h" -#include "native_mate/object_template_builder.h" namespace mate { -Constructor::Constructor(const base::StringPiece& name) : name_(name) { +Constructor::Constructor(const base::StringPiece& name, + const WrappableFactoryFunction& factory) + : name_(name), factory_(factory) { } -Constructor::~Constructor() { +virtual Constructor::~Constructor() { constructor_.Reset(); } -v8::Handle Constructor::GetFunction(v8::Isolate* isolate) { +v8::Handle Constructor::GetFunctionTemplate( + v8::Isolate* isolate) { if (constructor_.IsEmpty()) { v8::Local constructor = CreateFunctionTemplate( - isolate, - base::Bind(&Constructor::New, base::Unretained(this))); + isolate, base::Bind(&Constructor::New, base::Unretained(this))); constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->SetClassName(StringToV8(isolate, name_)); - SetPrototype(isolate, constructor->PrototypeTemplate()); - constructor_.Reset(isolate, constructor); } - return MATE_PERSISTENT_TO_LOCAL( - v8::FunctionTemplate, isolate, constructor_)->GetFunction(); + return MATE_PERSISTENT_TO_LOCAL(v8::FunctionTemplate, isolate, constructor_); } -void Constructor::New() { -} - -void Constructor::SetPrototype(v8::Isolate* isolate, - v8::Handle prototype) { +void Constructor::New(mate::Arguments* args) { + MATE_SET_INTERNAL_FIELD_POINTER(args->GetThis(), 0, factory_.Run()); } } // namespace mate diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 45786fdb341..77446faee50 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -5,30 +5,176 @@ #ifndef NATIVE_MATE_WRAPPABLE_CLASS_H_ #define NATIVE_MATE_WRAPPABLE_CLASS_H_ -#include "native_mate/wrappable.h" +#include "base/bind.h" +#include "base/compiler_specific.h" +#include "base/strings/string_piece.h" +#include "native_mate/function_template.h" +#include "v8/include/v8.h" namespace mate { +class WrappableBase; + +namespace internal { + +// This set of templates invokes a base::Callback by converting the Arguments +// into native types. It relies on the function_template.h to provide helper +// templates. +inline WrappableBase* InvokeFactory( + Arguments* args, + const base::Callback& callback) { + return callback.Run(); +}; + +template +inline WrappableBase* InvokeFactory( + Arguments* args, + const base::Callback& callback) { + typename CallbackParamTraits::LocalType a1; + if (!GetNextArgument(args, 0, false, &a1)) + return NULL; + return callback.Run(a1); +}; + +template +inline WrappableBase* InvokeFactory( + Arguments* args, + const base::Callback& callback) { + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + if (!GetNextArgument(args, 0, true, &a1) || + !GetNextArgument(args, 0, false, &a2)) + return NULL; + return callback.Run(a1, a2); +}; + +template +inline WrappableBase* InvokeFactory( + Arguments* args, + const base::Callback& callback) { + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + typename CallbackParamTraits::LocalType a3; + if (!GetNextArgument(args, 0, true, &a1) || + !GetNextArgument(args, 0, false, &a2) || + !GetNextArgument(args, 0, false, &a3)) + return NULL; + return callback.Run(a1, a2, a3); +}; + +template +inline WrappableBase* InvokeFactory( + Arguments* args, + const base::Callback& callback) { + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + typename CallbackParamTraits::LocalType a3; + typename CallbackParamTraits::LocalType a4; + if (!GetNextArgument(args, 0, true, &a1) || + !GetNextArgument(args, 0, false, &a2) || + !GetNextArgument(args, 0, false, &a3) || + !GetNextArgument(args, 0, false, &a4)) + return NULL; + return callback.Run(a1, a2, a3, a4); +}; + +template +inline WrappableBase* InvokeFactory( + Arguments* args, + const base::Callback& callback) { + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + typename CallbackParamTraits::LocalType a3; + typename CallbackParamTraits::LocalType a4; + typename CallbackParamTraits::LocalType a5; + if (!GetNextArgument(args, 0, true, &a1) || + !GetNextArgument(args, 0, false, &a2) || + !GetNextArgument(args, 0, false, &a3) || + !GetNextArgument(args, 0, false, &a4) || + !GetNextArgument(args, 0, false, &a5)) + return NULL; + return callback.Run(a1, a2, a3, a4, a5); +}; + +template +inline WrappableBase* InvokeFactory( + Arguments* args, + const base::Callback& callback) { + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + typename CallbackParamTraits::LocalType a3; + typename CallbackParamTraits::LocalType a4; + typename CallbackParamTraits::LocalType a5; + typename CallbackParamTraits::LocalType a6; + if (!GetNextArgument(args, 0, true, &a1) || + !GetNextArgument(args, 0, false, &a2) || + !GetNextArgument(args, 0, false, &a3) || + !GetNextArgument(args, 0, false, &a4) || + !GetNextArgument(args, 0, false, &a5) || + !GetNextArgument(args, 0, false, &a6)) + return NULL; + return callback.Run(a1, a2, a3, a4, a5, a6); +}; + +} // namespace internal + + +template class Constructor { public: - v8::Handle GetFunction(v8::Isolate* isolate); + typedef base::Callback WrappableFactoryFunction; - protected: - Constructor(const base::StringPiece& name); - virtual ~Constructor(); + Constructor(const base::StringPiece& name) : name_(name) {} + virtual ~Constructor() { + constructor_.Reset(); + } - virtual void New() = 0; + v8::Handle GetFunctionTemplate( + v8::Isolate* isolate, const WrappableFactoryFunction& factory) { + if (constructor_.IsEmpty()) { + v8::Local constructor = CreateFunctionTemplate( + isolate, base::Bind(&Constructor::New, factory)); + constructor->InstanceTemplate()->SetInternalFieldCount(1); + constructor->SetClassName(StringToV8(isolate, name_)); + constructor_.Reset(isolate, constructor); + } - virtual void SetPrototype(v8::Isolate* isolate, - v8::Handle prototype); + return MATE_PERSISTENT_TO_LOCAL( + v8::FunctionTemplate, isolate, constructor_); + } private: + static void New(const WrappableFactoryFunction& factory, Arguments* args) { + WrappableBase* object = internal::InvokeFactory(args, factory); + if (object) + MATE_SET_INTERNAL_FIELD_POINTER(args->GetThis(), 0, object); + else + args->ThrowError(); + + MATE_METHOD_RETURN_UNDEFINED(); + } + base::StringPiece name_; v8::Persistent constructor_; DISALLOW_COPY_AND_ASSIGN(Constructor); }; + +template +WrappableBase* NewOperatorFactory() { + return new T; +} + +template +v8::Local CreateConstructor( + v8::Isolate* isolate, + const base::StringPiece& name, + const base::Callback& constructor) { + return Constructor(name).GetFunctionTemplate(isolate, constructor); +} + } // namespace mate #endif // NATIVE_MATE_WRAPPABLE_CLASS_H_ diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 77bd721ad2f..e6dd876e966 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -9,26 +9,26 @@ namespace mate { -Wrappable::Wrappable() { +WrappableBase::WrappableBase() { } -Wrappable::~Wrappable() { +WrappableBase::~WrappableBase() { MATE_PERSISTENT_RESET(wrapper_); } -ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( +ObjectTemplateBuilder WrappableBase::GetObjectTemplateBuilder( v8::Isolate* isolate) { return ObjectTemplateBuilder(isolate); } // static -MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { - MATE_WEAK_CALLBACK_INIT(Wrappable); +MATE_WEAK_CALLBACK(WrappableBase::WeakCallback, v8::Object, WrappableBase) { + MATE_WEAK_CALLBACK_INIT(WrappableBase); MATE_PERSISTENT_RESET(self->wrapper_); delete self; } -v8::Handle Wrappable::GetWrapper(v8::Isolate* isolate) { +v8::Handle WrappableBase::GetWrapperImpl(v8::Isolate* isolate) { if (!wrapper_.IsEmpty()) { return MATE_PERSISTENT_TO_LOCAL(v8::Object, isolate, wrapper_); } diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index b6b80789887..10391fae1d1 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -18,12 +18,12 @@ void* FromV8Impl(v8::Isolate* isolate, v8::Handle val); } // namespace internal -// Wrappable is a base class for C++ objects that have corresponding v8 wrapper -// objects. To retain a Wrappable object on the stack, use a mate::Handle. +// WrappableBase is a base class for C++ objects that have corresponding v8 wrapper +// objects. To retain a WrappableBase object on the stack, use a mate::Handle. // // USAGE: // // my_class.h -// class MyClass : Wrappable { +// class MyClass : WrappableBase { // public: // // Optional, only required if non-empty template should be used. // virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( @@ -33,7 +33,7 @@ void* FromV8Impl(v8::Isolate* isolate, v8::Handle val); // // mate::ObjectTemplateBuilder MyClass::GetObjectTemplateBuilder( // v8::Isolate* isolate) { -// return Wrappable::GetObjectTemplateBuilder(isolate).SetValue("foobar", 42); +// return WrappableBase::GetObjectTemplateBuilder(isolate).SetValue("foobar", 42); // } // // Subclasses should also typically have private constructors and expose a @@ -42,43 +42,57 @@ void* FromV8Impl(v8::Isolate* isolate, v8::Handle val); // wrapper for the object. If clients fail to create a wrapper for a wrappable // object, the object will leak because we use the weak callback from the // wrapper as the signal to delete the wrapped object. +template +class Wrappable; + class ObjectTemplateBuilder; // Non-template base class to share code between templates instances. -class Wrappable { - public: - // Retrieve (or create) the v8 wrapper object cooresponding to this object. - v8::Handle GetWrapper(v8::Isolate* isolate); - +class WrappableBase { protected: - Wrappable(); - virtual ~Wrappable(); + WrappableBase(); + virtual ~WrappableBase(); virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); - // Override to change how the v8 wrapper is built (by default it was built - // from the ObjectTemplateBuilder. - // virtual v8::Handle BuildObject(); + v8::Handle GetWrapperImpl(v8::Isolate* isolate); private: - static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, Wrappable); + static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, WrappableBase); v8::Persistent wrapper_; // Weak + DISALLOW_COPY_AND_ASSIGN(WrappableBase); +}; + + +template +class Wrappable : public WrappableBase { + public: + // Retrieve (or create) the v8 wrapper object cooresponding to this object. + v8::Handle GetWrapper(v8::Isolate* isolate) { + return GetWrapperImpl(isolate); + } + + protected: + Wrappable() {} + virtual ~Wrappable() {} + + private: DISALLOW_COPY_AND_ASSIGN(Wrappable); }; -// This converter handles any subclass of Wrappable. +// This converter handles any subclass of WrappableBase. template struct Converter::value>::type> { + is_convertible::value>::type> { static v8::Handle ToV8(v8::Isolate* isolate, T* val) { return val->GetWrapper(isolate); } static bool FromV8(v8::Isolate* isolate, v8::Handle val, T** out) { - *out = static_cast(static_cast( + *out = static_cast(static_cast( internal::FromV8Impl(isolate, val))); return *out != NULL; } diff --git a/native_mate_files.gypi b/native_mate_files.gypi index 934c91f2323..944483e4863 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -4,7 +4,7 @@ 'native_mate/arguments.cc', 'native_mate/arguments.h', 'native_mate/compat.h', - 'native_mate/constructor.cc', +# 'native_mate/constructor.cc', 'native_mate/constructor.h', 'native_mate/converter.cc', 'native_mate/converter.h', From bdfbef41c6d81121f06c5bc2454954f4db706753 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Apr 2014 10:25:22 +0800 Subject: [PATCH 008/129] Cleanup. --- native_mate/constructor.cc | 40 --------------------------------- native_mate/constructor.h | 2 -- native_mate/scoped_persistent.h | 2 ++ 3 files changed, 2 insertions(+), 42 deletions(-) delete mode 100644 native_mate/constructor.cc diff --git a/native_mate/constructor.cc b/native_mate/constructor.cc deleted file mode 100644 index 9c57fd09c31..00000000000 --- a/native_mate/constructor.cc +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.chromium file. - -#include "native_mate/constructor.h" - -#include "base/bind.h" -#include "base/strings/string_piece.h" -#include "native_mate/arguments.h" -#include "native_mate/function_template.h" - -namespace mate { - -Constructor::Constructor(const base::StringPiece& name, - const WrappableFactoryFunction& factory) - : name_(name), factory_(factory) { -} - -virtual Constructor::~Constructor() { - constructor_.Reset(); -} - -v8::Handle Constructor::GetFunctionTemplate( - v8::Isolate* isolate) { - if (constructor_.IsEmpty()) { - v8::Local constructor = CreateFunctionTemplate( - isolate, base::Bind(&Constructor::New, base::Unretained(this))); - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(StringToV8(isolate, name_)); - constructor_.Reset(isolate, constructor); - } - - return MATE_PERSISTENT_TO_LOCAL(v8::FunctionTemplate, isolate, constructor_); -} - -void Constructor::New(mate::Arguments* args) { - MATE_SET_INTERNAL_FIELD_POINTER(args->GetThis(), 0, factory_.Run()); -} - -} // namespace mate diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 77446faee50..7e429cf62c7 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -7,9 +7,7 @@ #include "base/bind.h" #include "base/compiler_specific.h" -#include "base/strings/string_piece.h" #include "native_mate/function_template.h" -#include "v8/include/v8.h" namespace mate { diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index c1705676c28..bedf26b5250 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -106,6 +106,8 @@ class RefCountedPersistent : public ScopedPersistent, DISALLOW_COPY_AND_ASSIGN(RefCountedPersistent); }; +typedef scoped_refptr> RefCountedV8Object; + } // namespace mate #endif // NATIVE_MATE_SCOPED_PERSISTENT_H_ From ac5be7dad7b0b8b3ece684a60b4e7b6df73b225f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Apr 2014 10:36:54 +0800 Subject: [PATCH 009/129] Constructor should wrap the this pointer. --- native_mate/constructor.h | 6 ++++-- native_mate/wrappable.cc | 10 +++++++--- native_mate/wrappable.h | 3 +++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 7e429cf62c7..36c396f6f27 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -143,10 +143,12 @@ class Constructor { } private: - static void New(const WrappableFactoryFunction& factory, Arguments* args) { + static void New(const WrappableFactoryFunction& factory, + v8::Isolate* isolate, + Arguments* args) { WrappableBase* object = internal::InvokeFactory(args, factory); if (object) - MATE_SET_INTERNAL_FIELD_POINTER(args->GetThis(), 0, object); + object->Wrap(isolate, args->GetThis()); else args->ThrowError(); diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index e6dd876e966..d5bc55f3493 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -16,6 +16,12 @@ WrappableBase::~WrappableBase() { MATE_PERSISTENT_RESET(wrapper_); } +void WrappableBase::Wrap(v8::Isolate* isolate, v8::Handle wrapper) { + MATE_SET_INTERNAL_FIELD_POINTER(wrapper, 0, this); + MATE_PERSISTENT_ASSIGN(v8::Object, isolate, wrapper_, wrapper); + MATE_PERSISTENT_SET_WEAK(wrapper_, this, WeakCallback); +} + ObjectTemplateBuilder WrappableBase::GetObjectTemplateBuilder( v8::Isolate* isolate) { return ObjectTemplateBuilder(isolate); @@ -38,9 +44,7 @@ v8::Handle WrappableBase::GetWrapperImpl(v8::Isolate* isolate) { CHECK(!templ.IsEmpty()); CHECK_EQ(1, templ->InternalFieldCount()); v8::Handle wrapper = templ->NewInstance(); - MATE_SET_INTERNAL_FIELD_POINTER(wrapper, 0, this); - MATE_PERSISTENT_ASSIGN(v8::Object, isolate, wrapper_, wrapper); - MATE_PERSISTENT_SET_WEAK(wrapper_, this, WeakCallback); + Wrap(isolate, wrapper); return wrapper; } diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 10391fae1d1..9cc8141c499 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -49,6 +49,9 @@ class ObjectTemplateBuilder; // Non-template base class to share code between templates instances. class WrappableBase { + public: + void Wrap(v8::Isolate* isolate, v8::Handle wrapper); + protected: WrappableBase(); virtual ~WrappableBase(); From ace550d6b20a62ca1101153a06bccb4ba1484a14 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Apr 2014 11:58:17 +0800 Subject: [PATCH 010/129] Simplify Wrappable API. --- native_mate/constructor.h | 45 +++++++++++++++------------- native_mate/wrappable.cc | 19 +++++++----- native_mate/wrappable.h | 63 +++++++++++++++++---------------------- 3 files changed, 63 insertions(+), 64 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 36c396f6f27..d54cb518dce 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -11,23 +11,23 @@ namespace mate { -class WrappableBase; +class Wrappable; namespace internal { // This set of templates invokes a base::Callback by converting the Arguments // into native types. It relies on the function_template.h to provide helper // templates. -inline WrappableBase* InvokeFactory( +inline Wrappable* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { return callback.Run(); }; template -inline WrappableBase* InvokeFactory( +inline Wrappable* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; if (!GetNextArgument(args, 0, false, &a1)) return NULL; @@ -35,9 +35,9 @@ inline WrappableBase* InvokeFactory( }; template -inline WrappableBase* InvokeFactory( +inline Wrappable* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; if (!GetNextArgument(args, 0, true, &a1) || @@ -47,9 +47,9 @@ inline WrappableBase* InvokeFactory( }; template -inline WrappableBase* InvokeFactory( +inline Wrappable* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -61,9 +61,9 @@ inline WrappableBase* InvokeFactory( }; template -inline WrappableBase* InvokeFactory( +inline Wrappable* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -77,9 +77,9 @@ inline WrappableBase* InvokeFactory( }; template -inline WrappableBase* InvokeFactory( +inline Wrappable* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -96,9 +96,9 @@ inline WrappableBase* InvokeFactory( template -inline WrappableBase* InvokeFactory( +inline Wrappable* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -146,7 +146,7 @@ class Constructor { static void New(const WrappableFactoryFunction& factory, v8::Isolate* isolate, Arguments* args) { - WrappableBase* object = internal::InvokeFactory(args, factory); + Wrappable* object = internal::InvokeFactory(args, factory); if (object) object->Wrap(isolate, args->GetThis()); else @@ -163,16 +163,19 @@ class Constructor { template -WrappableBase* NewOperatorFactory() { +Wrappable* NewOperatorFactory() { return new T; } -template -v8::Local CreateConstructor( +template +v8::Local CreateConstructor( v8::Isolate* isolate, const base::StringPiece& name, - const base::Callback& constructor) { - return Constructor(name).GetFunctionTemplate(isolate, constructor); + const base::Callback& callback) { + v8::Local constructor = + Constructor(name).GetFunctionTemplate(isolate, callback); + T::BuildPrototype(isolate, constructor->PrototypeTemplate()); + return constructor->GetFunction(); } } // namespace mate diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index d5bc55f3493..ed7b49f3508 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -9,32 +9,37 @@ namespace mate { -WrappableBase::WrappableBase() { +Wrappable::Wrappable() { } -WrappableBase::~WrappableBase() { +Wrappable::~Wrappable() { MATE_PERSISTENT_RESET(wrapper_); } -void WrappableBase::Wrap(v8::Isolate* isolate, v8::Handle wrapper) { +void Wrappable::Wrap(v8::Isolate* isolate, v8::Handle wrapper) { MATE_SET_INTERNAL_FIELD_POINTER(wrapper, 0, this); MATE_PERSISTENT_ASSIGN(v8::Object, isolate, wrapper_, wrapper); MATE_PERSISTENT_SET_WEAK(wrapper_, this, WeakCallback); } -ObjectTemplateBuilder WrappableBase::GetObjectTemplateBuilder( +// static +void Wrappable::BuildPrototype(v8::Isolate* isolate, + v8::Handle prototype) { +} + +ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( v8::Isolate* isolate) { return ObjectTemplateBuilder(isolate); } // static -MATE_WEAK_CALLBACK(WrappableBase::WeakCallback, v8::Object, WrappableBase) { - MATE_WEAK_CALLBACK_INIT(WrappableBase); +MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { + MATE_WEAK_CALLBACK_INIT(Wrappable); MATE_PERSISTENT_RESET(self->wrapper_); delete self; } -v8::Handle WrappableBase::GetWrapperImpl(v8::Isolate* isolate) { +v8::Handle Wrappable::GetWrapper(v8::Isolate* isolate) { if (!wrapper_.IsEmpty()) { return MATE_PERSISTENT_TO_LOCAL(v8::Object, isolate, wrapper_); } diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 9cc8141c499..9db85496d6d 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -18,22 +18,24 @@ void* FromV8Impl(v8::Isolate* isolate, v8::Handle val); } // namespace internal -// WrappableBase is a base class for C++ objects that have corresponding v8 wrapper -// objects. To retain a WrappableBase object on the stack, use a mate::Handle. +// Wrappable is a base class for C++ objects that have corresponding v8 wrapper +// objects. To retain a Wrappable object on the stack, use a gin::Handle. // // USAGE: // // my_class.h -// class MyClass : WrappableBase { +// class MyClass : Wrappable { // public: // // Optional, only required if non-empty template should be used. -// virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( +// virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder( // v8::Isolate* isolate); // ... // }; // -// mate::ObjectTemplateBuilder MyClass::GetObjectTemplateBuilder( +// // my_class.cc +// gin::ObjectTemplateBuilder MyClass::GetObjectTemplateBuilder( // v8::Isolate* isolate) { -// return WrappableBase::GetObjectTemplateBuilder(isolate).SetValue("foobar", 42); +// return Wrappable::GetObjectTemplateBuilder(isolate) +// .SetValue("foobar", 42); // } // // Subclasses should also typically have private constructors and expose a @@ -42,60 +44,49 @@ void* FromV8Impl(v8::Isolate* isolate, v8::Handle val); // wrapper for the object. If clients fail to create a wrapper for a wrappable // object, the object will leak because we use the weak callback from the // wrapper as the signal to delete the wrapped object. -template -class Wrappable; - class ObjectTemplateBuilder; -// Non-template base class to share code between templates instances. -class WrappableBase { +class Wrappable { public: + // Retrieve (or create) the v8 wrapper object cooresponding to this object. + // If the type is created via the Constructor, then the GetWrapper would + // return the constructed object, otherwise it would try to create a new + // object constructed by GetObjectTemplateBuilder. + v8::Handle GetWrapper(v8::Isolate* isolate); + + // Bind the C++ class to the JS wrapper. void Wrap(v8::Isolate* isolate, v8::Handle wrapper); + // The user should define T::BuildPrototype if they want to use Constructor + // to build a constructor function for this type. + static void BuildPrototype(v8::Isolate* isolate, + v8::Handle prototype); + protected: - WrappableBase(); - virtual ~WrappableBase(); + Wrappable(); + virtual ~Wrappable(); virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); - v8::Handle GetWrapperImpl(v8::Isolate* isolate); - private: - static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, WrappableBase); + static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, Wrappable); v8::Persistent wrapper_; // Weak - DISALLOW_COPY_AND_ASSIGN(WrappableBase); -}; - - -template -class Wrappable : public WrappableBase { - public: - // Retrieve (or create) the v8 wrapper object cooresponding to this object. - v8::Handle GetWrapper(v8::Isolate* isolate) { - return GetWrapperImpl(isolate); - } - - protected: - Wrappable() {} - virtual ~Wrappable() {} - - private: DISALLOW_COPY_AND_ASSIGN(Wrappable); }; -// This converter handles any subclass of WrappableBase. +// This converter handles any subclass of Wrappable. template struct Converter::value>::type> { + is_convertible::value>::type> { static v8::Handle ToV8(v8::Isolate* isolate, T* val) { return val->GetWrapper(isolate); } static bool FromV8(v8::Isolate* isolate, v8::Handle val, T** out) { - *out = static_cast(static_cast( + *out = static_cast(static_cast( internal::FromV8Impl(isolate, val))); return *out != NULL; } From 2d3af6fc386ec5e1b0fab61a9f251b250441b430 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Apr 2014 14:29:45 +0800 Subject: [PATCH 011/129] Remove helper typedefs. --- native_mate/scoped_persistent.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index bedf26b5250..c1705676c28 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -106,8 +106,6 @@ class RefCountedPersistent : public ScopedPersistent, DISALLOW_COPY_AND_ASSIGN(RefCountedPersistent); }; -typedef scoped_refptr> RefCountedV8Object; - } // namespace mate #endif // NATIVE_MATE_SCOPED_PERSISTENT_H_ From d0bf1a842fb8dc4b6b704a4d2b9e6831b44ed26b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Apr 2014 14:56:05 +0800 Subject: [PATCH 012/129] Support function with 7 parameters. --- native_mate/function_template.h | 90 ++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 17 deletions(-) diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 192aa8ed15e..cfbc85935df 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -83,23 +83,42 @@ class CallbackHolder : public CallbackHolderBase { // have the void return type. template + typename P6 = void, typename P7 = void> struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, - const base::Callback& callback, + const base::Callback& callback, const P1& a1, const P2& a2, const P3& a3, const P4& a4, const P5& a5, - const P6& a6) { - MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4, a5, a6)); + const P6& a6, + const P7& a7) { + MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4, a5, a6, a7)); } }; +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3, + const P4& a4, + const P5& a5, + const P6& a6, + const P7& a7) { + callback.Run(a1, a2, a3, a4, a5, a6, a7); + MATE_METHOD_RETURN_UNDEFINED(); + } +}; + template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -116,7 +135,7 @@ struct Invoker { template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -129,7 +148,7 @@ struct Invoker { } }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -144,7 +163,7 @@ struct Invoker { }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -156,7 +175,7 @@ struct Invoker { } }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -170,7 +189,7 @@ struct Invoker { }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -181,7 +200,7 @@ struct Invoker { } }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -194,7 +213,7 @@ struct Invoker { }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -204,7 +223,7 @@ struct Invoker { } }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -216,7 +235,7 @@ struct Invoker { }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -225,7 +244,7 @@ struct Invoker { } }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback, @@ -236,7 +255,7 @@ struct Invoker { }; template -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback) { @@ -244,7 +263,7 @@ struct Invoker { } }; template<> -struct Invoker { +struct Invoker { inline static MATE_METHOD_RETURN_TYPE Go( Arguments& args, const base::Callback& callback) { @@ -474,6 +493,43 @@ struct Dispatcher { } }; +template +struct Dispatcher { + static MATE_METHOD(DispatchToCallback) { + Arguments args(info); + v8::Handle v8_holder; + CHECK(args.GetData(&v8_holder)); + CallbackHolderBase* holder_base = reinterpret_cast( + v8_holder->Value()); + + typedef CallbackHolder HolderT; + HolderT* holder = static_cast(holder_base); + + typename CallbackParamTraits::LocalType a1; + typename CallbackParamTraits::LocalType a2; + typename CallbackParamTraits::LocalType a3; + typename CallbackParamTraits::LocalType a4; + typename CallbackParamTraits::LocalType a5; + typename CallbackParamTraits::LocalType a6; + typename CallbackParamTraits::LocalType a7; + if (!GetNextArgument(&args, holder->flags, true, &a1) || + !GetNextArgument(&args, holder->flags, false, &a2) || + !GetNextArgument(&args, holder->flags, false, &a3) || + !GetNextArgument(&args, holder->flags, false, &a4) || + !GetNextArgument(&args, holder->flags, false, &a5) || + !GetNextArgument(&args, holder->flags, false, &a6) || + !GetNextArgument(&args, holder->flags, false, &a7)) { + args.ThrowError(); + MATE_METHOD_RETURN_UNDEFINED(); + } + + return Invoker::Go(args, holder->callback, + a1, a2, a3, a4, a5, a6, a7); + } +}; + + } // namespace internal From 213ac4372168d4627185e0dba62a3e7ed4e317d3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Apr 2014 14:56:33 +0800 Subject: [PATCH 013/129] Enable converting void*. --- native_mate/converter.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/native_mate/converter.h b/native_mate/converter.h index 44b7d4a882b..8f94aa81544 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -16,6 +16,13 @@ namespace mate { template struct Converter {}; +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, void* val) { + return v8::Undefined(); + } +}; + template<> struct Converter { static v8::Handle ToV8(v8::Isolate* isolate, From c9fa29ef640e8d3d2edf6b48c2311b16ce314464 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Apr 2014 15:13:44 +0800 Subject: [PATCH 014/129] Enable setting method in Dictionary. --- native_mate/dictionary.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 469746653f4..562d82a4204 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -6,6 +6,7 @@ #define NATIVE_MATE_DICTIONARY_H_ #include "native_mate/converter.h" +#include "native_mate/object_template_builder.h" namespace mate { @@ -30,16 +31,23 @@ class Dictionary { static Dictionary CreateEmpty(v8::Isolate* isolate); template - bool Get(const std::string& key, T* out) { + bool Get(const base::StringPiece& key, T* out) { v8::Handle val = object_->Get(StringToV8(isolate_, key)); return ConvertFromV8(isolate_, val, out); } template - bool Set(const std::string& key, T val) { + bool Set(const base::StringPiece& key, T val) { return object_->Set(StringToV8(isolate_, key), ConvertToV8(isolate_, val)); } + template + bool SetMethod(const base::StringPiece& key, const T& callback) { + return object_->Set( + StringToV8(isolate_, key), + CallbackTraits::CreateTemplate(isolate_, callback)->GetFunction()); + } + v8::Isolate* isolate() const { return isolate_; } private: From 94dec0ff85c9337d33cae01638897bc1059b7dca Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Apr 2014 15:28:43 +0800 Subject: [PATCH 015/129] Add v8::Handle to converter. --- native_mate/converter.cc | 13 +++++++++++++ native_mate/converter.h | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/native_mate/converter.cc b/native_mate/converter.cc index 4750e5a30a1..1bda229985c 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -146,6 +146,19 @@ bool Converter >::FromV8(Isolate* isolate, Handle val, return true; } +Handle Converter >::ToV8(Isolate* isolate, + Handle val) { + return val; +} + +bool Converter >::FromV8(Isolate* isolate, Handle val, + Handle* out) { + if (!val->IsString()) + return false; + *out = Handle::Cast(val); + return true; +} + Handle Converter >::ToV8(Isolate* isolate, Handle val) { return val; diff --git a/native_mate/converter.h b/native_mate/converter.h index 8f94aa81544..457d4d3341c 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -120,6 +120,15 @@ struct Converter > { v8::Handle* out); }; +template<> +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + v8::Handle val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + v8::Handle* out); +}; + template<> struct Converter > { static v8::Handle ToV8(v8::Isolate* isolate, From 9cc90ac7d52e04d909ffdceda130e12d8f79e0e8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 18 Apr 2014 16:45:44 +0800 Subject: [PATCH 016/129] Make ScopedPersistent do type conversion. --- native_mate/constructor.h | 1 + native_mate/scoped_persistent.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index d54cb518dce..5ac28829cae 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/compiler_specific.h" +#include "native_mate/wrappable.h" #include "native_mate/function_template.h" namespace mate { diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index c1705676c28..37c2e0a281f 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -18,8 +18,8 @@ class ScopedPersistent { ScopedPersistent() { } - explicit ScopedPersistent(v8::Handle handle) { - reset(handle); + explicit ScopedPersistent(v8::Handle handle) { + reset(v8::Handle::Cast(handle)); } ~ScopedPersistent() { @@ -93,7 +93,7 @@ class RefCountedPersistent : public ScopedPersistent, public: RefCountedPersistent() {} - explicit RefCountedPersistent(v8::Handle handle) + explicit RefCountedPersistent(v8::Handle handle) : ScopedPersistent(handle) { } From d950fe3736e3393911d6edc00d77e6fd2e8ed16b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 22 Apr 2014 15:57:11 +0800 Subject: [PATCH 017/129] Add Arguments.Length method. --- native_mate/arguments.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/native_mate/arguments.h b/native_mate/arguments.h index ebe49e7c841..7975a156c2d 100644 --- a/native_mate/arguments.h +++ b/native_mate/arguments.h @@ -60,6 +60,10 @@ class Arguments { return info_->This(); } + int Length() const { + return info_->Length(); + } + #if NODE_VERSION_AT_LEAST(0, 11, 0) template void Return(T val) { From 3d219b4be6f37fe99ca2e738eb0ea9d1b152af34 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 22 Apr 2014 15:57:23 +0800 Subject: [PATCH 018/129] Do not wrap an object when it's already wrapped. --- native_mate/wrappable.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index ed7b49f3508..17f87cadb64 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -17,6 +17,9 @@ Wrappable::~Wrappable() { } void Wrappable::Wrap(v8::Isolate* isolate, v8::Handle wrapper) { + if (!wrapper_.IsEmpty()) + return; + MATE_SET_INTERNAL_FIELD_POINTER(wrapper, 0, this); MATE_PERSISTENT_ASSIGN(v8::Object, isolate, wrapper_, wrapper); MATE_PERSISTENT_SET_WEAK(wrapper_, this, WeakCallback); @@ -40,9 +43,8 @@ MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { } v8::Handle Wrappable::GetWrapper(v8::Isolate* isolate) { - if (!wrapper_.IsEmpty()) { + if (!wrapper_.IsEmpty()) return MATE_PERSISTENT_TO_LOCAL(v8::Object, isolate, wrapper_); - } v8::Local templ = GetObjectTemplateBuilder(isolate).Build(); From f033e23ea3156db611e801af96eabd81d51ba85a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 23 Apr 2014 12:23:25 +0800 Subject: [PATCH 019/129] No need to reset wrapper_ when we would run destructor. --- native_mate/wrappable.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 17f87cadb64..51ff30136cf 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -38,7 +38,6 @@ ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( // static MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { MATE_WEAK_CALLBACK_INIT(Wrappable); - MATE_PERSISTENT_RESET(self->wrapper_); delete self; } From c79aecf64de260dd239c6aed8397d3e152d7589d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 27 May 2014 08:47:06 +0800 Subject: [PATCH 020/129] Call object._init if we have one. --- native_mate/wrappable.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 51ff30136cf..b98029a37eb 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -5,6 +5,7 @@ #include "native_mate/wrappable.h" #include "base/logging.h" +#include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" namespace mate { @@ -23,6 +24,11 @@ void Wrappable::Wrap(v8::Isolate* isolate, v8::Handle wrapper) { MATE_SET_INTERNAL_FIELD_POINTER(wrapper, 0, this); MATE_PERSISTENT_ASSIGN(v8::Object, isolate, wrapper_, wrapper); MATE_PERSISTENT_SET_WEAK(wrapper_, this, WeakCallback); + + // Call object._init if we have one. + v8::Handle init; + if (Dictionary(isolate, wrapper).Get("_init", &init)) + init->Call(wrapper, 0, NULL); } // static From 730acd59c757dec44c85ff4e8e7e8d7081f3d0ef Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 23 Jun 2014 21:11:00 +0800 Subject: [PATCH 021/129] Add object() accessor for Dictionary. --- native_mate/dictionary.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 562d82a4204..563916e4598 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -24,7 +24,7 @@ namespace mate { // class Dictionary { public: - explicit Dictionary(v8::Isolate* isolate); + explicit Dictionary(v8::Isolate* isolate = NULL); Dictionary(v8::Isolate* isolate, v8::Handle object); ~Dictionary(); @@ -48,6 +48,7 @@ class Dictionary { CallbackTraits::CreateTemplate(isolate_, callback)->GetFunction()); } + v8::Handle object() const { return object_; } v8::Isolate* isolate() const { return isolate_; } private: From 1884b9a235344a0a6f0b066f56163ea088d4eb47 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 23 Jun 2014 21:24:18 +0800 Subject: [PATCH 022/129] Add converter for const char*. --- native_mate/converter.cc | 5 +++++ native_mate/converter.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/native_mate/converter.cc b/native_mate/converter.cc index 1bda229985c..c7cf96c3042 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -103,6 +103,11 @@ bool Converter::FromV8(Isolate* isolate, Handle val, return true; } +Handle Converter::ToV8( + Isolate* isolate, const char* val) { + return MATE_STRING_NEW_FROM_UTF8(isolate, val, -1); +} + Handle Converter::ToV8( Isolate* isolate, const base::StringPiece& val) { return MATE_STRING_NEW_FROM_UTF8(isolate, val.data(), diff --git a/native_mate/converter.h b/native_mate/converter.h index 457d4d3341c..a94d8defbd6 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -88,6 +88,11 @@ struct Converter { double* out); }; +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, const char* val); +}; + template<> struct Converter { static v8::Handle ToV8(v8::Isolate* isolate, From 51a55810b95ac4153a133ef278031a04cc6fcada Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 23 Jun 2014 21:38:46 +0800 Subject: [PATCH 023/129] Enable creating empty Dictionary directly. --- native_mate/dictionary.cc | 3 ++- native_mate/dictionary.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc index 1504f683f0a..88bdefb1f79 100644 --- a/native_mate/dictionary.cc +++ b/native_mate/dictionary.cc @@ -7,7 +7,8 @@ namespace mate { Dictionary::Dictionary(v8::Isolate* isolate) - : isolate_(isolate) { + : isolate_(isolate), + object_(v8::Object::New()) { } Dictionary::Dictionary(v8::Isolate* isolate, diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 563916e4598..333bae0f7a5 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -24,7 +24,7 @@ namespace mate { // class Dictionary { public: - explicit Dictionary(v8::Isolate* isolate = NULL); + Dictionary(v8::Isolate* isolate = v8::Isolate::GetCurrent()); Dictionary(v8::Isolate* isolate, v8::Handle object); ~Dictionary(); From 94044b2950dfb0392d27616d589ba0c60a0d28ef Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 23 Jun 2014 21:39:03 +0800 Subject: [PATCH 024/129] Mark Dictionary.Get as const. --- native_mate/dictionary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 333bae0f7a5..8c5dfeaae35 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -31,7 +31,7 @@ class Dictionary { static Dictionary CreateEmpty(v8::Isolate* isolate); template - bool Get(const base::StringPiece& key, T* out) { + bool Get(const base::StringPiece& key, T* out) const { v8::Handle val = object_->Get(StringToV8(isolate_, key)); return ConvertFromV8(isolate_, val, out); } From bfd5f5d221b5b26c78c1336d3262e64b7cb43a5a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 23 Jun 2014 21:47:39 +0800 Subject: [PATCH 025/129] Strictly check for boolean type. --- native_mate/converter.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/native_mate/converter.cc b/native_mate/converter.cc index c7cf96c3042..7554ae787c1 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -25,6 +25,8 @@ Handle Converter::ToV8(Isolate* isolate, bool val) { } bool Converter::FromV8(Isolate* isolate, Handle val, bool* out) { + if (!val->IsBoolean()) + return false; *out = val->BooleanValue(); return true; } From a5c4a2c7c64239ec5d007342f00f16f3981d6d80 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 23 Jun 2014 21:50:00 +0800 Subject: [PATCH 026/129] Add .gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..1377554ebea --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp From 6f574c38020bdf9d6ed9dd079905f4b110fbd10e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 28 Jun 2014 19:29:14 +0800 Subject: [PATCH 027/129] Add APIs to match new V8 APIs. --- native_mate/compat.h | 20 ++++++++++++++++++++ native_mate/converter.h | 5 +++-- native_mate/scoped_persistent.h | 6 ------ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/native_mate/compat.h b/native_mate/compat.h index 5641613c42e..11a7ef40963 100644 --- a/native_mate/compat.h +++ b/native_mate/compat.h @@ -19,11 +19,21 @@ #define MATE_METHOD_RETURN_NULL() return info.GetReturnValue().SetNull() #define MATE_METHOD_RETURN(value) args.Return(value) +#define MATE_STRING_NEW(isolate, data) \ + v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString) #define MATE_STRING_NEW_FROM_UTF8(isolate, data, length) \ v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString, length) +#define MATE_STRING_NEW_FROM_UTF16(isolate, data, length) \ + v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString, length) #define MATE_STRING_NEW_SYMBOL(isolate, data, length) \ v8::String::NewFromUtf8(isolate, data, v8::String::kInternalizedString, length) +#define MATE_UNDEFINED(isolate) v8::Undefined(isolate) +#define MATE_TRUE(isolate) v8::True(isolate) +#define MATE_FALSE(isolate) v8::False(isolate) +#define MATE_ARRAY_NEW(isolate, size) v8::Array::New(isolate, size) +#define MATE_INTEGER_NEW(isolate, data) v8::Integer::New(isolate, data) + #define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ object->SetAlignedPointerInInternalField(index, value) #define MATE_GET_INTERNAL_FIELD_POINTER(object, index) \ @@ -58,11 +68,21 @@ #define MATE_METHOD_RETURN(value) \ MATE_METHOD_RETURN_VALUE(ConvertToV8(args.isolate(), value)) +#define MATE_STRING_NEW(isolate, data) \ + v8::String::New(data) #define MATE_STRING_NEW_FROM_UTF8(isolate, data, length) \ v8::String::New(data, length) +#define MATE_STRING_NEW_FROM_UTF16(isolate, data, length) \ + v8::String::NewFromTwoByte(data, v8::String::kNormalString, length) #define MATE_STRING_NEW_SYMBOL(isolate, data, length) \ v8::String::NewSymbol(data, length) +#define MATE_UNDEFINED(isolate) v8::Undefined() +#define MATE_TRUE(isolate) v8::True() +#define MATE_FALSE(isolate) v8::False() +#define MATE_ARRAY_NEW(isolate, size) v8::Array::New(size) +#define MATE_INTEGER_NEW(isolate, data) v8::Integer::New(data) + #define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ object->SetPointerInInternalField(index, value) #define MATE_GET_INTERNAL_FIELD_POINTER(object, index) \ diff --git a/native_mate/converter.h b/native_mate/converter.h index a94d8defbd6..c17e892c2b0 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -9,6 +9,7 @@ #include #include "base/strings/string_piece.h" +#include "native_mate/compat.h" #include "v8/include/v8.h" namespace mate { @@ -19,7 +20,7 @@ struct Converter {}; template<> struct Converter { static v8::Handle ToV8(v8::Isolate* isolate, void* val) { - return v8::Undefined(); + return MATE_UNDEFINED(isolate); } }; @@ -157,7 +158,7 @@ struct Converter > { static v8::Handle ToV8(v8::Isolate* isolate, const std::vector& val) { v8::Handle result( - v8::Array::New(static_cast(val.size()))); + MATE_ARRAY_NEW(isolate, static_cast(val.size()))); for (size_t i = 0; i < val.size(); ++i) { result->Set(static_cast(i), Converter::ToV8(isolate, val[i])); } diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index 37c2e0a281f..d2a8bd7fca6 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -53,12 +53,6 @@ class ScopedPersistent { return v8::Local::New(isolate, handle_); } - template - void MakeWeak(P* parameters, - typename v8::WeakReferenceCallbacks::Revivable callback) { - handle_.MakeWeak(parameters, callback); - } - private: template static v8::Isolate* GetIsolate(v8::Handle object_handle) { From 8e056672bcc8b5423b9893183e465b4d117966a0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 28 Jun 2014 21:26:34 +0800 Subject: [PATCH 028/129] Bring back ScopedPersistent.SetWeak. --- native_mate/scoped_persistent.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index d2a8bd7fca6..c653a1040a9 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -53,6 +53,12 @@ class ScopedPersistent { return v8::Local::New(isolate, handle_); } + template + void SetWeak(P* parameter, + typename v8::WeakCallbackData::Callback callback) { + handle_.SetWeak(parameter, callback); + } + private: template static v8::Isolate* GetIsolate(v8::Handle object_handle) { From e6db1875d0259d7750ad57d58d6fecaeeaea0cf6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 28 Jun 2014 22:32:35 +0800 Subject: [PATCH 029/129] Some more APIs fixes. --- native_mate/compat.h | 20 ++++++++++++++++---- native_mate/converter.cc | 14 +++++++------- native_mate/dictionary.cc | 4 ++-- native_mate/function_template.cc | 2 +- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/native_mate/compat.h b/native_mate/compat.h index 11a7ef40963..16b56b62dcf 100644 --- a/native_mate/compat.h +++ b/native_mate/compat.h @@ -32,7 +32,12 @@ #define MATE_TRUE(isolate) v8::True(isolate) #define MATE_FALSE(isolate) v8::False(isolate) #define MATE_ARRAY_NEW(isolate, size) v8::Array::New(isolate, size) +#define MATE_NUMBER_NEW(isolate, data) v8::Number::New(isolate, data) #define MATE_INTEGER_NEW(isolate, data) v8::Integer::New(isolate, data) +#define MATE_INTEGER_NEW_UNSIGNED(isolate, data) \ + v8::Integer::NewFromUnsigned(isolate, data) +#define MATE_EXTERNAL_NEW(isolate, data) v8::External::New(isolate, data) +#define MATE_BOOLEAN_NEW(isolate, data) v8::Boolean::New(isolate, data) #define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ object->SetAlignedPointerInInternalField(index, value) @@ -55,6 +60,9 @@ #define MATE_WEAK_CALLBACK_INIT(c_type) \ c_type* self = data.GetParameter() +#define MATE_THROW_EXCEPTION(isolate, value) \ + isolate->ThrowException(value) + #else // Node 0.8 and 0.10 #define MATE_HANDLE_SCOPE(isolate) v8::HandleScope handle_scope @@ -81,7 +89,12 @@ #define MATE_TRUE(isolate) v8::True() #define MATE_FALSE(isolate) v8::False() #define MATE_ARRAY_NEW(isolate, size) v8::Array::New(size) +#define MATE_NUMBER_NEW(isolate, data) v8::Number::New(data) #define MATE_INTEGER_NEW(isolate, data) v8::Integer::New(data) +#define MATE_INTEGER_NEW_UNSIGNED(isolate, data) \ + v8::Integer::NewFromUnsigned(data) +#define MATE_EXTERNAL_NEW(isolate, data) v8::External::New(data) +#define MATE_BOOLEAN_NEW(isolate, data) v8::Boolean::New(data) #define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ object->SetPointerInInternalField(index, value) @@ -105,6 +118,9 @@ #define MATE_WEAK_CALLBACK_INIT(c_type) \ c_type* self = static_cast(parameter) +#define MATE_THROW_EXCEPTION(isolate, value) \ + v8::ThrowException(value) + #endif // (NODE_MODULE_VERSION > 0x000B) @@ -113,8 +129,4 @@ #define MATE_METHOD(name) \ MATE_METHOD_RETURN_TYPE name(const MATE_METHOD_ARGS_TYPE& info) -// In lastest V8 ThrowException would need to pass isolate, be prepared for it. -#define MATE_THROW_EXCEPTION(isolate, value) \ - v8::ThrowException(value) - #endif // NATIVE_MATE_COMPAT_H_ diff --git a/native_mate/converter.cc b/native_mate/converter.cc index 7554ae787c1..e5e7c52467c 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -21,7 +21,7 @@ using v8::Value; namespace mate { Handle Converter::ToV8(Isolate* isolate, bool val) { - return Boolean::New(val); + return MATE_BOOLEAN_NEW(isolate, val); } bool Converter::FromV8(Isolate* isolate, Handle val, bool* out) { @@ -32,7 +32,7 @@ bool Converter::FromV8(Isolate* isolate, Handle val, bool* out) { } Handle Converter::ToV8(Isolate* isolate, int32_t val) { - return Integer::New(val); + return MATE_INTEGER_NEW(isolate, val); } bool Converter::FromV8(Isolate* isolate, Handle val, @@ -44,7 +44,7 @@ bool Converter::FromV8(Isolate* isolate, Handle val, } Handle Converter::ToV8(Isolate* isolate, uint32_t val) { - return Integer::NewFromUnsigned(val); + return MATE_INTEGER_NEW_UNSIGNED(isolate, val); } bool Converter::FromV8(Isolate* isolate, Handle val, @@ -56,7 +56,7 @@ bool Converter::FromV8(Isolate* isolate, Handle val, } Handle Converter::ToV8(Isolate* isolate, int64_t val) { - return Number::New(static_cast(val)); + return MATE_NUMBER_NEW(isolate, static_cast(val)); } bool Converter::FromV8(Isolate* isolate, Handle val, @@ -70,7 +70,7 @@ bool Converter::FromV8(Isolate* isolate, Handle val, } Handle Converter::ToV8(Isolate* isolate, uint64_t val) { - return Number::New(static_cast(val)); + return MATE_NUMBER_NEW(isolate, static_cast(val)); } bool Converter::FromV8(Isolate* isolate, Handle val, @@ -82,7 +82,7 @@ bool Converter::FromV8(Isolate* isolate, Handle val, } Handle Converter::ToV8(Isolate* isolate, float val) { - return Number::New(val); + return MATE_NUMBER_NEW(isolate, val); } bool Converter::FromV8(Isolate* isolate, Handle val, @@ -94,7 +94,7 @@ bool Converter::FromV8(Isolate* isolate, Handle val, } Handle Converter::ToV8(Isolate* isolate, double val) { - return Number::New(val); + return MATE_NUMBER_NEW(isolate, val); } bool Converter::FromV8(Isolate* isolate, Handle val, diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc index 88bdefb1f79..7ea17dd8fce 100644 --- a/native_mate/dictionary.cc +++ b/native_mate/dictionary.cc @@ -8,7 +8,7 @@ namespace mate { Dictionary::Dictionary(v8::Isolate* isolate) : isolate_(isolate), - object_(v8::Object::New()) { + object_(v8::Object::New(isolate)) { } Dictionary::Dictionary(v8::Isolate* isolate, @@ -22,7 +22,7 @@ Dictionary::~Dictionary() { Dictionary Dictionary::CreateEmpty(v8::Isolate* isolate) { Dictionary dictionary(isolate); - dictionary.object_ = v8::Object::New(); + dictionary.object_ = v8::Object::New(isolate); return dictionary; } diff --git a/native_mate/function_template.cc b/native_mate/function_template.cc index 22bb6260d1e..c8b71c49266 100644 --- a/native_mate/function_template.cc +++ b/native_mate/function_template.cc @@ -9,7 +9,7 @@ namespace mate { namespace internal { CallbackHolderBase::CallbackHolderBase(v8::Isolate* isolate) - : MATE_PERSISTENT_INIT(isolate, v8_ref_, v8::External::New(this)) { + : MATE_PERSISTENT_INIT(isolate, v8_ref_, MATE_EXTERNAL_NEW(isolate, this)) { MATE_PERSISTENT_SET_WEAK(v8_ref_, this, &CallbackHolderBase::WeakCallback); } From 14c851e9f887a09ac3e055aacb930b0b3c690df4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 18 Jul 2014 09:37:07 +0800 Subject: [PATCH 030/129] Reset handle in weak callback. This doesn't seem to be neccesary, but we had better follow what upstream does. --- native_mate/wrappable.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index b98029a37eb..9eed09cebfe 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -44,6 +44,7 @@ ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( // static MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { MATE_WEAK_CALLBACK_INIT(Wrappable); + self->wrapper_.Reset(); delete self; } From 3d713baa4c33baebfac82b242e8897504592c590 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 21 Jul 2014 13:07:56 +0800 Subject: [PATCH 031/129] Enable converting ScopedPersistent. --- native_mate/scoped_persistent.h | 68 ++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index c653a1040a9..4d7b0c07459 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -6,6 +6,7 @@ #define NATIVE_MATE_SCOPED_PERSISTENT_H_ #include "base/memory/ref_counted.h" +#include "native_mate/converter.h" #include "v8/include/v8.h" namespace mate { @@ -15,10 +16,11 @@ namespace mate { template class ScopedPersistent { public: - ScopedPersistent() { + ScopedPersistent(v8::Isolate* isolate = NULL) : isolate_(isolate) { } - explicit ScopedPersistent(v8::Handle handle) { + ScopedPersistent(v8::Handle handle, v8::Isolate* isolate = NULL) + : isolate_(isolate) { reset(v8::Handle::Cast(handle)); } @@ -27,10 +29,16 @@ class ScopedPersistent { } void reset(v8::Handle handle) { - if (!handle.IsEmpty()) - handle_.Reset(GetIsolate(handle), handle); - else + reset(GetIsolate(handle), handle); + } + + void reset(v8::Isolate* isolate, v8::Handle handle) { + if (!handle.IsEmpty()) { + isolate_ = isolate; + handle_.Reset(isolate, handle); + } else { reset(); + } } void reset() { @@ -42,9 +50,7 @@ class ScopedPersistent { } v8::Handle NewHandle() const { - if (handle_.IsEmpty()) - return v8::Local(); - return v8::Local::New(GetIsolate(handle_), handle_); + return NewHandle(GetIsolate(handle_)); } v8::Handle NewHandle(v8::Isolate* isolate) const { @@ -59,29 +65,38 @@ class ScopedPersistent { handle_.SetWeak(parameter, callback); } + v8::Isolate* isolate() const { return isolate_; } + private: template - static v8::Isolate* GetIsolate(v8::Handle object_handle) { + v8::Isolate* GetIsolate(v8::Handle object_handle) const { // Only works for v8::Object and its subclasses. Add specialisations for // anything else. if (!object_handle.IsEmpty()) return GetIsolate(object_handle->CreationContext()); - return v8::Isolate::GetCurrent(); + return GetIsolate(); } - static v8::Isolate* GetIsolate(v8::Handle context_handle) { + v8::Isolate* GetIsolate(v8::Handle context_handle) const { if (!context_handle.IsEmpty()) return context_handle->GetIsolate(); - return v8::Isolate::GetCurrent(); + return GetIsolate(); } - static v8::Isolate* GetIsolate( - v8::Handle template_handle) { - return v8::Isolate::GetCurrent(); + v8::Isolate* GetIsolate( + v8::Handle template_handle) const { + return GetIsolate(); } template - static v8::Isolate* GetIsolate(const U& any_handle) { - return v8::Isolate::GetCurrent(); + v8::Isolate* GetIsolate(const U& any_handle) const { + return GetIsolate(); + } + v8::Isolate* GetIsolate() const { + if (isolate_) + return isolate_; + else + return v8::Isolate::GetCurrent(); } + v8::Isolate* isolate_; v8::Persistent handle_; DISALLOW_COPY_AND_ASSIGN(ScopedPersistent); @@ -106,6 +121,25 @@ class RefCountedPersistent : public ScopedPersistent, DISALLOW_COPY_AND_ASSIGN(RefCountedPersistent); }; +template +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + const ScopedPersistent& val) { + return val.NewHandle(isolate); + } + + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + ScopedPersistent* out) { + v8::Handle converted; + if (!Converter >::FromV8(isolate, val, &converted)) + return false; + + out->reset(isolate, converted); + return true; + } +}; + } // namespace mate #endif // NATIVE_MATE_SCOPED_PERSISTENT_H_ From 9145a08395aa32fa2ca94660652aca9cdd7dd7ae Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 10 Aug 2014 11:20:41 +0800 Subject: [PATCH 032/129] Fix compilation error with node 0.10. --- native_mate/compat.h | 2 ++ native_mate/dictionary.cc | 4 ++-- native_mate/wrappable.cc | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/native_mate/compat.h b/native_mate/compat.h index 16b56b62dcf..710171eb26c 100644 --- a/native_mate/compat.h +++ b/native_mate/compat.h @@ -38,6 +38,7 @@ v8::Integer::NewFromUnsigned(isolate, data) #define MATE_EXTERNAL_NEW(isolate, data) v8::External::New(isolate, data) #define MATE_BOOLEAN_NEW(isolate, data) v8::Boolean::New(isolate, data) +#define MATE_OBJECT_NEW(isolate) v8::Object::New(isolate) #define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ object->SetAlignedPointerInInternalField(index, value) @@ -95,6 +96,7 @@ v8::Integer::NewFromUnsigned(data) #define MATE_EXTERNAL_NEW(isolate, data) v8::External::New(data) #define MATE_BOOLEAN_NEW(isolate, data) v8::Boolean::New(data) +#define MATE_OBJECT_NEW(isolate) v8::Object::New() #define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ object->SetPointerInInternalField(index, value) diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc index 7ea17dd8fce..1a1750ff12e 100644 --- a/native_mate/dictionary.cc +++ b/native_mate/dictionary.cc @@ -8,7 +8,7 @@ namespace mate { Dictionary::Dictionary(v8::Isolate* isolate) : isolate_(isolate), - object_(v8::Object::New(isolate)) { + object_(MATE_OBJECT_NEW(isolate)) { } Dictionary::Dictionary(v8::Isolate* isolate, @@ -22,7 +22,7 @@ Dictionary::~Dictionary() { Dictionary Dictionary::CreateEmpty(v8::Isolate* isolate) { Dictionary dictionary(isolate); - dictionary.object_ = v8::Object::New(isolate); + dictionary.object_ = MATE_OBJECT_NEW(isolate); return dictionary; } diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 9eed09cebfe..d783306c45b 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -44,7 +44,7 @@ ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( // static MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { MATE_WEAK_CALLBACK_INIT(Wrappable); - self->wrapper_.Reset(); + MATE_PERSISTENT_RESET(self->wrapper_); delete self; } From cbb5004ff97ba16823fd96666edde067799f8691 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 10 Aug 2014 12:17:47 +0800 Subject: [PATCH 033/129] Fix compilation error of Constructor and ScopedPersistent in node 0.10. --- native_mate/constructor.h | 10 +++++----- native_mate/scoped_persistent.h | 13 +++++++------ native_mate_files.gypi | 1 - 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 5ac28829cae..9a43b760289 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -126,7 +126,7 @@ class Constructor { Constructor(const base::StringPiece& name) : name_(name) {} virtual ~Constructor() { - constructor_.Reset(); + MATE_PERSISTENT_RESET(constructor_); } v8::Handle GetFunctionTemplate( @@ -136,7 +136,8 @@ class Constructor { isolate, base::Bind(&Constructor::New, factory)); constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->SetClassName(StringToV8(isolate, name_)); - constructor_.Reset(isolate, constructor); + MATE_PERSISTENT_ASSIGN(v8::FunctionTemplate, isolate, constructor_, + constructor); } return MATE_PERSISTENT_TO_LOCAL( @@ -144,9 +145,8 @@ class Constructor { } private: - static void New(const WrappableFactoryFunction& factory, - v8::Isolate* isolate, - Arguments* args) { + static MATE_METHOD_RETURN_TYPE New(const WrappableFactoryFunction& factory, + v8::Isolate* isolate, Arguments* args) { Wrappable* object = internal::InvokeFactory(args, factory); if (object) object->Wrap(isolate, args->GetThis()); diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index 4d7b0c07459..44580221ba0 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -35,14 +35,14 @@ class ScopedPersistent { void reset(v8::Isolate* isolate, v8::Handle handle) { if (!handle.IsEmpty()) { isolate_ = isolate; - handle_.Reset(isolate, handle); + MATE_PERSISTENT_ASSIGN(T, isolate, handle_, handle); } else { reset(); } } void reset() { - handle_.Reset(); + MATE_PERSISTENT_RESET(handle_); } bool IsEmpty() const { @@ -59,10 +59,9 @@ class ScopedPersistent { return v8::Local::New(isolate, handle_); } - template - void SetWeak(P* parameter, - typename v8::WeakCallbackData::Callback callback) { - handle_.SetWeak(parameter, callback); + template + void SetWeak(P* parameter, C callback) { + MATE_PERSISTENT_SET_WEAK(handle_, parameter, callback); } v8::Isolate* isolate() const { return isolate_; } @@ -76,11 +75,13 @@ class ScopedPersistent { return GetIsolate(object_handle->CreationContext()); return GetIsolate(); } +#if NODE_VERSION_AT_LEAST(0, 11, 0) v8::Isolate* GetIsolate(v8::Handle context_handle) const { if (!context_handle.IsEmpty()) return context_handle->GetIsolate(); return GetIsolate(); } +#endif v8::Isolate* GetIsolate( v8::Handle template_handle) const { return GetIsolate(); diff --git a/native_mate_files.gypi b/native_mate_files.gypi index 944483e4863..a9e9de3375a 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -4,7 +4,6 @@ 'native_mate/arguments.cc', 'native_mate/arguments.h', 'native_mate/compat.h', -# 'native_mate/constructor.cc', 'native_mate/constructor.h', 'native_mate/converter.cc', 'native_mate/converter.h', From 5d6921ff2a95ff6849057ee1c25fcda99e12ab55 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 10 Aug 2014 16:59:50 +0800 Subject: [PATCH 034/129] Use pump to generate source files. --- native_mate/constructor.h | 6 +- native_mate/constructor.h.pump | 124 ++++ native_mate/function_template.h | 20 +- native_mate/function_template.h.pump | 225 +++++++ script/pump.py | 855 +++++++++++++++++++++++++++ 5 files changed, 1228 insertions(+), 2 deletions(-) create mode 100644 native_mate/constructor.h.pump create mode 100644 native_mate/function_template.h.pump create mode 100755 script/pump.py diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 9a43b760289..f44238ed07c 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -1,3 +1,7 @@ +// This file was GENERATED by command: +// pump.py constructor.h.pump +// DO NOT EDIT BY HAND!!! + // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.chromium file. @@ -30,7 +34,7 @@ inline Wrappable* InvokeFactory( Arguments* args, const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; - if (!GetNextArgument(args, 0, false, &a1)) + if (!GetNextArgument(args, 0, true, &a1)) return NULL; return callback.Run(a1); }; diff --git a/native_mate/constructor.h.pump b/native_mate/constructor.h.pump new file mode 100644 index 00000000000..81a7524087e --- /dev/null +++ b/native_mate/constructor.h.pump @@ -0,0 +1,124 @@ +$$ This is a pump file for generating file templates. Pump is a python +$$ script that is part of the Google Test suite of utilities. Description +$$ can be found here: +$$ +$$ http://code.google.com/p/googletest/wiki/PumpManual +$$ +$var MAX_ARITY = 6 +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_WRAPPABLE_CLASS_H_ +#define NATIVE_MATE_WRAPPABLE_CLASS_H_ + +#include "base/bind.h" +#include "base/compiler_specific.h" +#include "native_mate/wrappable.h" +#include "native_mate/function_template.h" + +namespace mate { + +class Wrappable; + +namespace internal { + +// This set of templates invokes a base::Callback by converting the Arguments +// into native types. It relies on the function_template.h to provide helper +// templates. +$range ARITY 0..MAX_ARITY +$for ARITY [[ +$range ARG 1..ARITY + +$if ARITY == 0 [[ + +]] $else [[ + +template<$for ARG , [[typename P$(ARG)]]> +]] + +inline Wrappable* InvokeFactory( + Arguments* args, + const base::Callback& callback) { +$if ARITY != 0 [[ + + +$for ARG [[ typename CallbackParamTraits::LocalType a$(ARG); + +]] + if ($for ARG || + [[!GetNextArgument(args, 0, $if ARG == 1 [[true]] $else [[false]], &a$(ARG))]]) + return NULL; +]] + + return callback.Run($for ARG , [[a$(ARG)]]); +}; + +]] + +} // namespace internal + + +template +class Constructor { + public: + typedef base::Callback WrappableFactoryFunction; + + Constructor(const base::StringPiece& name) : name_(name) {} + virtual ~Constructor() { + MATE_PERSISTENT_RESET(constructor_); + } + + v8::Handle GetFunctionTemplate( + v8::Isolate* isolate, const WrappableFactoryFunction& factory) { + if (constructor_.IsEmpty()) { + v8::Local constructor = CreateFunctionTemplate( + isolate, base::Bind(&Constructor::New, factory)); + constructor->InstanceTemplate()->SetInternalFieldCount(1); + constructor->SetClassName(StringToV8(isolate, name_)); + MATE_PERSISTENT_ASSIGN(v8::FunctionTemplate, isolate, constructor_, + constructor); + } + + return MATE_PERSISTENT_TO_LOCAL( + v8::FunctionTemplate, isolate, constructor_); + } + + private: + static MATE_METHOD_RETURN_TYPE New(const WrappableFactoryFunction& factory, + v8::Isolate* isolate, Arguments* args) { + Wrappable* object = internal::InvokeFactory(args, factory); + if (object) + object->Wrap(isolate, args->GetThis()); + else + args->ThrowError(); + + MATE_METHOD_RETURN_UNDEFINED(); + } + + base::StringPiece name_; + v8::Persistent constructor_; + + DISALLOW_COPY_AND_ASSIGN(Constructor); +}; + + +template +Wrappable* NewOperatorFactory() { + return new T; +} + +template +v8::Local CreateConstructor( + v8::Isolate* isolate, + const base::StringPiece& name, + const base::Callback& callback) { + v8::Local constructor = + Constructor(name).GetFunctionTemplate(isolate, callback); + T::BuildPrototype(isolate, constructor->PrototypeTemplate()); + return constructor->GetFunction(); +} + +} // namespace mate + +#endif // NATIVE_MATE_WRAPPABLE_CLASS_H_ diff --git a/native_mate/function_template.h b/native_mate/function_template.h index cfbc85935df..54b71c04f88 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -1,3 +1,7 @@ +// This file was GENERATED by command: +// pump.py function_template.h.pump +// DO NOT EDIT BY HAND!!! + // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.chromium file. @@ -116,6 +120,21 @@ struct Invoker { } }; +template +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback, + const P1& a1, + const P2& a2, + const P3& a3, + const P4& a4, + const P5& a5, + const P6& a6) { + MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4, a5, a6)); + } +}; template struct Invoker { @@ -529,7 +548,6 @@ struct Dispatcher { } }; - } // namespace internal diff --git a/native_mate/function_template.h.pump b/native_mate/function_template.h.pump new file mode 100644 index 00000000000..ddfe29a25d1 --- /dev/null +++ b/native_mate/function_template.h.pump @@ -0,0 +1,225 @@ +$$ This is a pump file for generating file templates. Pump is a python +$$ script that is part of the Google Test suite of utilities. Description +$$ can be found here: +$$ +$$ http://code.google.com/p/googletest/wiki/PumpManual +$$ +$var MAX_ARITY = 7 +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_FUNCTION_TEMPLATE_H_ +#define NATIVE_MATE_FUNCTION_TEMPLATE_H_ + +#include "base/callback.h" +#include "base/logging.h" +#include "native_mate/arguments.h" +#include "native_mate/compat.h" +#include "native_mate/converter.h" +#include "v8/include/v8.h" + +namespace mate { + +class PerIsolateData; + +enum CreateFunctionTemplateFlags { + HolderIsFirstArgument = 1 << 0, +}; + +namespace internal { + +template +struct CallbackParamTraits { + typedef T LocalType; +}; +template +struct CallbackParamTraits { + typedef T LocalType; +}; +template +struct CallbackParamTraits { + typedef T* LocalType; +}; + + +// CallbackHolder and CallbackHolderBase are used to pass a base::Callback from +// CreateFunctionTemplate through v8 (via v8::FunctionTemplate) to +// DispatchToCallback, where it is invoked. + +// This simple base class is used so that we can share a single object template +// among every CallbackHolder instance. +class CallbackHolderBase { + public: + v8::Handle GetHandle(v8::Isolate* isolate); + + protected: + explicit CallbackHolderBase(v8::Isolate* isolate); + virtual ~CallbackHolderBase(); + + private: + static MATE_WEAK_CALLBACK(WeakCallback, v8::External, CallbackHolderBase); + + v8::Persistent v8_ref_; + + DISALLOW_COPY_AND_ASSIGN(CallbackHolderBase); +}; + +template +class CallbackHolder : public CallbackHolderBase { + public: + CallbackHolder(v8::Isolate* isolate, + const base::Callback& callback, + int flags) + : CallbackHolderBase(isolate), callback(callback), flags(flags) {} + base::Callback callback; + int flags; + private: + virtual ~CallbackHolder() {} + + DISALLOW_COPY_AND_ASSIGN(CallbackHolder); +}; + + +// This set of templates invokes a base::Callback, converts the return type to a +// JavaScript value, and returns that value to script via the provided +// mate::Arguments object. +// +// In C++, you can declare the function foo(void), but you can't pass a void +// expression to foo. As a result, we must specialize the case of Callbacks that +// have the void return type. + +$range ARITY 0..MAX_ARITY +$for ARITY [[ +$var INV_ARITY = MAX_ARITY - ARITY +$range ARG 1..INV_ARITY +$range VOID INV_ARITY+1..MAX_ARITY + +$if ARITY == 0 [[ +template +struct Invoker { +]] $else [[ +template +struct Invoker { +]] + + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback$for ARG [[, + const P$(ARG)& a$(ARG)]]) { + MATE_METHOD_RETURN(callback.Run($for ARG, [[a$(ARG)]])); + } +}; +template<$for ARG , [[typename P$(ARG)]]> +struct Invoker { + inline static MATE_METHOD_RETURN_TYPE Go( + Arguments& args, + const base::Callback& callback$for ARG [[, + const P$(ARG)& a$(ARG)]]) { + callback.Run($for ARG, [[a$(ARG)]]); + MATE_METHOD_RETURN_UNDEFINED(); + } +}; + + +]] + +template +bool GetNextArgument(Arguments* args, int create_flags, bool is_first, + T* result) { + if (is_first && (create_flags & HolderIsFirstArgument) != 0) { + return args->GetHolder(result); + } else { + return args->GetNext(result); + } +} + +// For advanced use cases, we allow callers to request the unparsed Arguments +// object and poke around in it directly. +inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first, + Arguments* result) { + *result = *args; + return true; +} +inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first, + Arguments** result) { + *result = args; + return true; +} + +// It's common for clients to just need the isolate, so we make that easy. +inline bool GetNextArgument(Arguments* args, int create_flags, + bool is_first, v8::Isolate** result) { + *result = args->isolate(); + return true; +} + + +// DispatchToCallback converts all the JavaScript arguments to C++ types and +// invokes the base::Callback. +template +struct Dispatcher { +}; + +$range ARITY 0..MAX_ARITY +$for ARITY [[ +$range ARG 1..ARITY + +template +struct Dispatcher { + static MATE_METHOD(DispatchToCallback) { + Arguments args(info); + v8::Handle v8_holder; + CHECK(args.GetData(&v8_holder)); + CallbackHolderBase* holder_base = reinterpret_cast( + v8_holder->Value()); + + typedef CallbackHolder HolderT; + HolderT* holder = static_cast(holder_base); + +$if ARITY != 0 [[ + + +$for ARG [[ typename CallbackParamTraits::LocalType a$(ARG); + +]] + if ($for ARG || + [[!GetNextArgument(&args, holder->flags, $if ARG == 1 [[true]] $else [[false]], &a$(ARG))]]) { + args.ThrowError(); + MATE_METHOD_RETURN_UNDEFINED(); + } + +]] + + return Invoker::Go(args, holder->callback$for ARG [[, a$(ARG)]]); + } +}; + +]] + +} // namespace internal + + +// CreateFunctionTemplate creates a v8::FunctionTemplate that will create +// JavaScript functions that execute a provided C++ function or base::Callback. +// JavaScript arguments are automatically converted via mate::Converter, as is +// the return value of the C++ function, if any. +template +v8::Local CreateFunctionTemplate( + v8::Isolate* isolate, const base::Callback callback, + int callback_flags = 0) { + typedef internal::CallbackHolder HolderT; + HolderT* holder = new HolderT(isolate, callback, callback_flags); + + return v8::FunctionTemplate::New( +#if NODE_VERSION_AT_LEAST(0, 11, 11) + isolate, +#endif + &internal::Dispatcher::DispatchToCallback, + ConvertToV8 >(isolate, + holder->GetHandle(isolate))); +} + +} // namespace mate + +#endif // NATIVE_MATE_FUNCTION_TEMPLATE_H_ diff --git a/script/pump.py b/script/pump.py new file mode 100755 index 00000000000..5efb653c207 --- /dev/null +++ b/script/pump.py @@ -0,0 +1,855 @@ +#!/usr/bin/env python +# +# Copyright 2008, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""pump v0.2.0 - Pretty Useful for Meta Programming. + +A tool for preprocessor meta programming. Useful for generating +repetitive boilerplate code. Especially useful for writing C++ +classes, functions, macros, and templates that need to work with +various number of arguments. + +USAGE: + pump.py SOURCE_FILE + +EXAMPLES: + pump.py foo.cc.pump + Converts foo.cc.pump to foo.cc. + +GRAMMAR: + CODE ::= ATOMIC_CODE* + ATOMIC_CODE ::= $var ID = EXPRESSION + | $var ID = [[ CODE ]] + | $range ID EXPRESSION..EXPRESSION + | $for ID SEPARATOR [[ CODE ]] + | $($) + | $ID + | $(EXPRESSION) + | $if EXPRESSION [[ CODE ]] ELSE_BRANCH + | [[ CODE ]] + | RAW_CODE + SEPARATOR ::= RAW_CODE | EMPTY + ELSE_BRANCH ::= $else [[ CODE ]] + | $elif EXPRESSION [[ CODE ]] ELSE_BRANCH + | EMPTY + EXPRESSION has Python syntax. +""" + +__author__ = 'wan@google.com (Zhanyong Wan)' + +import os +import re +import sys + + +TOKEN_TABLE = [ + (re.compile(r'\$var\s+'), '$var'), + (re.compile(r'\$elif\s+'), '$elif'), + (re.compile(r'\$else\s+'), '$else'), + (re.compile(r'\$for\s+'), '$for'), + (re.compile(r'\$if\s+'), '$if'), + (re.compile(r'\$range\s+'), '$range'), + (re.compile(r'\$[_A-Za-z]\w*'), '$id'), + (re.compile(r'\$\(\$\)'), '$($)'), + (re.compile(r'\$'), '$'), + (re.compile(r'\[\[\n?'), '[['), + (re.compile(r'\]\]\n?'), ']]'), + ] + + +class Cursor: + """Represents a position (line and column) in a text file.""" + + def __init__(self, line=-1, column=-1): + self.line = line + self.column = column + + def __eq__(self, rhs): + return self.line == rhs.line and self.column == rhs.column + + def __ne__(self, rhs): + return not self == rhs + + def __lt__(self, rhs): + return self.line < rhs.line or ( + self.line == rhs.line and self.column < rhs.column) + + def __le__(self, rhs): + return self < rhs or self == rhs + + def __gt__(self, rhs): + return rhs < self + + def __ge__(self, rhs): + return rhs <= self + + def __str__(self): + if self == Eof(): + return 'EOF' + else: + return '%s(%s)' % (self.line + 1, self.column) + + def __add__(self, offset): + return Cursor(self.line, self.column + offset) + + def __sub__(self, offset): + return Cursor(self.line, self.column - offset) + + def Clone(self): + """Returns a copy of self.""" + + return Cursor(self.line, self.column) + + +# Special cursor to indicate the end-of-file. +def Eof(): + """Returns the special cursor to denote the end-of-file.""" + return Cursor(-1, -1) + + +class Token: + """Represents a token in a Pump source file.""" + + def __init__(self, start=None, end=None, value=None, token_type=None): + if start is None: + self.start = Eof() + else: + self.start = start + if end is None: + self.end = Eof() + else: + self.end = end + self.value = value + self.token_type = token_type + + def __str__(self): + return 'Token @%s: \'%s\' type=%s' % ( + self.start, self.value, self.token_type) + + def Clone(self): + """Returns a copy of self.""" + + return Token(self.start.Clone(), self.end.Clone(), self.value, + self.token_type) + + +def StartsWith(lines, pos, string): + """Returns True iff the given position in lines starts with 'string'.""" + + return lines[pos.line][pos.column:].startswith(string) + + +def FindFirstInLine(line, token_table): + best_match_start = -1 + for (regex, token_type) in token_table: + m = regex.search(line) + if m: + # We found regex in lines + if best_match_start < 0 or m.start() < best_match_start: + best_match_start = m.start() + best_match_length = m.end() - m.start() + best_match_token_type = token_type + + if best_match_start < 0: + return None + + return (best_match_start, best_match_length, best_match_token_type) + + +def FindFirst(lines, token_table, cursor): + """Finds the first occurrence of any string in strings in lines.""" + + start = cursor.Clone() + cur_line_number = cursor.line + for line in lines[start.line:]: + if cur_line_number == start.line: + line = line[start.column:] + m = FindFirstInLine(line, token_table) + if m: + # We found a regex in line. + (start_column, length, token_type) = m + if cur_line_number == start.line: + start_column += start.column + found_start = Cursor(cur_line_number, start_column) + found_end = found_start + length + return MakeToken(lines, found_start, found_end, token_type) + cur_line_number += 1 + # We failed to find str in lines + return None + + +def SubString(lines, start, end): + """Returns a substring in lines.""" + + if end == Eof(): + end = Cursor(len(lines) - 1, len(lines[-1])) + + if start >= end: + return '' + + if start.line == end.line: + return lines[start.line][start.column:end.column] + + result_lines = ([lines[start.line][start.column:]] + + lines[start.line + 1:end.line] + + [lines[end.line][:end.column]]) + return ''.join(result_lines) + + +def StripMetaComments(str): + """Strip meta comments from each line in the given string.""" + + # First, completely remove lines containing nothing but a meta + # comment, including the trailing \n. + str = re.sub(r'^\s*\$\$.*\n', '', str) + + # Then, remove meta comments from contentful lines. + return re.sub(r'\s*\$\$.*', '', str) + + +def MakeToken(lines, start, end, token_type): + """Creates a new instance of Token.""" + + return Token(start, end, SubString(lines, start, end), token_type) + + +def ParseToken(lines, pos, regex, token_type): + line = lines[pos.line][pos.column:] + m = regex.search(line) + if m and not m.start(): + return MakeToken(lines, pos, pos + m.end(), token_type) + else: + print 'ERROR: %s expected at %s.' % (token_type, pos) + sys.exit(1) + + +ID_REGEX = re.compile(r'[_A-Za-z]\w*') +EQ_REGEX = re.compile(r'=') +REST_OF_LINE_REGEX = re.compile(r'.*?(?=$|\$\$)') +OPTIONAL_WHITE_SPACES_REGEX = re.compile(r'\s*') +WHITE_SPACE_REGEX = re.compile(r'\s') +DOT_DOT_REGEX = re.compile(r'\.\.') + + +def Skip(lines, pos, regex): + line = lines[pos.line][pos.column:] + m = re.search(regex, line) + if m and not m.start(): + return pos + m.end() + else: + return pos + + +def SkipUntil(lines, pos, regex, token_type): + line = lines[pos.line][pos.column:] + m = re.search(regex, line) + if m: + return pos + m.start() + else: + print ('ERROR: %s expected on line %s after column %s.' % + (token_type, pos.line + 1, pos.column)) + sys.exit(1) + + +def ParseExpTokenInParens(lines, pos): + def ParseInParens(pos): + pos = Skip(lines, pos, OPTIONAL_WHITE_SPACES_REGEX) + pos = Skip(lines, pos, r'\(') + pos = Parse(pos) + pos = Skip(lines, pos, r'\)') + return pos + + def Parse(pos): + pos = SkipUntil(lines, pos, r'\(|\)', ')') + if SubString(lines, pos, pos + 1) == '(': + pos = Parse(pos + 1) + pos = Skip(lines, pos, r'\)') + return Parse(pos) + else: + return pos + + start = pos.Clone() + pos = ParseInParens(pos) + return MakeToken(lines, start, pos, 'exp') + + +def RStripNewLineFromToken(token): + if token.value.endswith('\n'): + return Token(token.start, token.end, token.value[:-1], token.token_type) + else: + return token + + +def TokenizeLines(lines, pos): + while True: + found = FindFirst(lines, TOKEN_TABLE, pos) + if not found: + yield MakeToken(lines, pos, Eof(), 'code') + return + + if found.start == pos: + prev_token = None + prev_token_rstripped = None + else: + prev_token = MakeToken(lines, pos, found.start, 'code') + prev_token_rstripped = RStripNewLineFromToken(prev_token) + + if found.token_type == '$var': + if prev_token_rstripped: + yield prev_token_rstripped + yield found + id_token = ParseToken(lines, found.end, ID_REGEX, 'id') + yield id_token + pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX) + + eq_token = ParseToken(lines, pos, EQ_REGEX, '=') + yield eq_token + pos = Skip(lines, eq_token.end, r'\s*') + + if SubString(lines, pos, pos + 2) != '[[': + exp_token = ParseToken(lines, pos, REST_OF_LINE_REGEX, 'exp') + yield exp_token + pos = Cursor(exp_token.end.line + 1, 0) + elif found.token_type == '$for': + if prev_token_rstripped: + yield prev_token_rstripped + yield found + id_token = ParseToken(lines, found.end, ID_REGEX, 'id') + yield id_token + pos = Skip(lines, id_token.end, WHITE_SPACE_REGEX) + elif found.token_type == '$range': + if prev_token_rstripped: + yield prev_token_rstripped + yield found + id_token = ParseToken(lines, found.end, ID_REGEX, 'id') + yield id_token + pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX) + + dots_pos = SkipUntil(lines, pos, DOT_DOT_REGEX, '..') + yield MakeToken(lines, pos, dots_pos, 'exp') + yield MakeToken(lines, dots_pos, dots_pos + 2, '..') + pos = dots_pos + 2 + new_pos = Cursor(pos.line + 1, 0) + yield MakeToken(lines, pos, new_pos, 'exp') + pos = new_pos + elif found.token_type == '$': + if prev_token: + yield prev_token + yield found + exp_token = ParseExpTokenInParens(lines, found.end) + yield exp_token + pos = exp_token.end + elif (found.token_type == ']]' or found.token_type == '$if' or + found.token_type == '$elif' or found.token_type == '$else'): + if prev_token_rstripped: + yield prev_token_rstripped + yield found + pos = found.end + else: + if prev_token: + yield prev_token + yield found + pos = found.end + + +def Tokenize(s): + """A generator that yields the tokens in the given string.""" + if s != '': + lines = s.splitlines(True) + for token in TokenizeLines(lines, Cursor(0, 0)): + yield token + + +class CodeNode: + def __init__(self, atomic_code_list=None): + self.atomic_code = atomic_code_list + + +class VarNode: + def __init__(self, identifier=None, atomic_code=None): + self.identifier = identifier + self.atomic_code = atomic_code + + +class RangeNode: + def __init__(self, identifier=None, exp1=None, exp2=None): + self.identifier = identifier + self.exp1 = exp1 + self.exp2 = exp2 + + +class ForNode: + def __init__(self, identifier=None, sep=None, code=None): + self.identifier = identifier + self.sep = sep + self.code = code + + +class ElseNode: + def __init__(self, else_branch=None): + self.else_branch = else_branch + + +class IfNode: + def __init__(self, exp=None, then_branch=None, else_branch=None): + self.exp = exp + self.then_branch = then_branch + self.else_branch = else_branch + + +class RawCodeNode: + def __init__(self, token=None): + self.raw_code = token + + +class LiteralDollarNode: + def __init__(self, token): + self.token = token + + +class ExpNode: + def __init__(self, token, python_exp): + self.token = token + self.python_exp = python_exp + + +def PopFront(a_list): + head = a_list[0] + a_list[:1] = [] + return head + + +def PushFront(a_list, elem): + a_list[:0] = [elem] + + +def PopToken(a_list, token_type=None): + token = PopFront(a_list) + if token_type is not None and token.token_type != token_type: + print 'ERROR: %s expected at %s' % (token_type, token.start) + print 'ERROR: %s found instead' % (token,) + sys.exit(1) + + return token + + +def PeekToken(a_list): + if not a_list: + return None + + return a_list[0] + + +def ParseExpNode(token): + python_exp = re.sub(r'([_A-Za-z]\w*)', r'self.GetValue("\1")', token.value) + return ExpNode(token, python_exp) + + +def ParseElseNode(tokens): + def Pop(token_type=None): + return PopToken(tokens, token_type) + + next = PeekToken(tokens) + if not next: + return None + if next.token_type == '$else': + Pop('$else') + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + return code_node + elif next.token_type == '$elif': + Pop('$elif') + exp = Pop('code') + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + inner_else_node = ParseElseNode(tokens) + return CodeNode([IfNode(ParseExpNode(exp), code_node, inner_else_node)]) + elif not next.value.strip(): + Pop('code') + return ParseElseNode(tokens) + else: + return None + + +def ParseAtomicCodeNode(tokens): + def Pop(token_type=None): + return PopToken(tokens, token_type) + + head = PopFront(tokens) + t = head.token_type + if t == 'code': + return RawCodeNode(head) + elif t == '$var': + id_token = Pop('id') + Pop('=') + next = PeekToken(tokens) + if next.token_type == 'exp': + exp_token = Pop() + return VarNode(id_token, ParseExpNode(exp_token)) + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + return VarNode(id_token, code_node) + elif t == '$for': + id_token = Pop('id') + next_token = PeekToken(tokens) + if next_token.token_type == 'code': + sep_token = next_token + Pop('code') + else: + sep_token = None + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + return ForNode(id_token, sep_token, code_node) + elif t == '$if': + exp_token = Pop('code') + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + else_node = ParseElseNode(tokens) + return IfNode(ParseExpNode(exp_token), code_node, else_node) + elif t == '$range': + id_token = Pop('id') + exp1_token = Pop('exp') + Pop('..') + exp2_token = Pop('exp') + return RangeNode(id_token, ParseExpNode(exp1_token), + ParseExpNode(exp2_token)) + elif t == '$id': + return ParseExpNode(Token(head.start + 1, head.end, head.value[1:], 'id')) + elif t == '$($)': + return LiteralDollarNode(head) + elif t == '$': + exp_token = Pop('exp') + return ParseExpNode(exp_token) + elif t == '[[': + code_node = ParseCodeNode(tokens) + Pop(']]') + return code_node + else: + PushFront(tokens, head) + return None + + +def ParseCodeNode(tokens): + atomic_code_list = [] + while True: + if not tokens: + break + atomic_code_node = ParseAtomicCodeNode(tokens) + if atomic_code_node: + atomic_code_list.append(atomic_code_node) + else: + break + return CodeNode(atomic_code_list) + + +def ParseToAST(pump_src_text): + """Convert the given Pump source text into an AST.""" + tokens = list(Tokenize(pump_src_text)) + code_node = ParseCodeNode(tokens) + return code_node + + +class Env: + def __init__(self): + self.variables = [] + self.ranges = [] + + def Clone(self): + clone = Env() + clone.variables = self.variables[:] + clone.ranges = self.ranges[:] + return clone + + def PushVariable(self, var, value): + # If value looks like an int, store it as an int. + try: + int_value = int(value) + if ('%s' % int_value) == value: + value = int_value + except Exception: + pass + self.variables[:0] = [(var, value)] + + def PopVariable(self): + self.variables[:1] = [] + + def PushRange(self, var, lower, upper): + self.ranges[:0] = [(var, lower, upper)] + + def PopRange(self): + self.ranges[:1] = [] + + def GetValue(self, identifier): + for (var, value) in self.variables: + if identifier == var: + return value + + print 'ERROR: meta variable %s is undefined.' % (identifier,) + sys.exit(1) + + def EvalExp(self, exp): + try: + result = eval(exp.python_exp) + except Exception, e: + print 'ERROR: caught exception %s: %s' % (e.__class__.__name__, e) + print ('ERROR: failed to evaluate meta expression %s at %s' % + (exp.python_exp, exp.token.start)) + sys.exit(1) + return result + + def GetRange(self, identifier): + for (var, lower, upper) in self.ranges: + if identifier == var: + return (lower, upper) + + print 'ERROR: range %s is undefined.' % (identifier,) + sys.exit(1) + + +class Output: + def __init__(self): + self.string = '' + + def GetLastLine(self): + index = self.string.rfind('\n') + if index < 0: + return '' + + return self.string[index + 1:] + + def Append(self, s): + self.string += s + + +def RunAtomicCode(env, node, output): + if isinstance(node, VarNode): + identifier = node.identifier.value.strip() + result = Output() + RunAtomicCode(env.Clone(), node.atomic_code, result) + value = result.string + env.PushVariable(identifier, value) + elif isinstance(node, RangeNode): + identifier = node.identifier.value.strip() + lower = int(env.EvalExp(node.exp1)) + upper = int(env.EvalExp(node.exp2)) + env.PushRange(identifier, lower, upper) + elif isinstance(node, ForNode): + identifier = node.identifier.value.strip() + if node.sep is None: + sep = '' + else: + sep = node.sep.value + (lower, upper) = env.GetRange(identifier) + for i in range(lower, upper + 1): + new_env = env.Clone() + new_env.PushVariable(identifier, i) + RunCode(new_env, node.code, output) + if i != upper: + output.Append(sep) + elif isinstance(node, RawCodeNode): + output.Append(node.raw_code.value) + elif isinstance(node, IfNode): + cond = env.EvalExp(node.exp) + if cond: + RunCode(env.Clone(), node.then_branch, output) + elif node.else_branch is not None: + RunCode(env.Clone(), node.else_branch, output) + elif isinstance(node, ExpNode): + value = env.EvalExp(node) + output.Append('%s' % (value,)) + elif isinstance(node, LiteralDollarNode): + output.Append('$') + elif isinstance(node, CodeNode): + RunCode(env.Clone(), node, output) + else: + print 'BAD' + print node + sys.exit(1) + + +def RunCode(env, code_node, output): + for atomic_code in code_node.atomic_code: + RunAtomicCode(env, atomic_code, output) + + +def IsSingleLineComment(cur_line): + return '//' in cur_line + + +def IsInPreprocessorDirective(prev_lines, cur_line): + if cur_line.lstrip().startswith('#'): + return True + return prev_lines and prev_lines[-1].endswith('\\') + + +def WrapComment(line, output): + loc = line.find('//') + before_comment = line[:loc].rstrip() + if before_comment == '': + indent = loc + else: + output.append(before_comment) + indent = len(before_comment) - len(before_comment.lstrip()) + prefix = indent*' ' + '// ' + max_len = 80 - len(prefix) + comment = line[loc + 2:].strip() + segs = [seg for seg in re.split(r'(\w+\W*)', comment) if seg != ''] + cur_line = '' + for seg in segs: + if len((cur_line + seg).rstrip()) < max_len: + cur_line += seg + else: + if cur_line.strip() != '': + output.append(prefix + cur_line.rstrip()) + cur_line = seg.lstrip() + if cur_line.strip() != '': + output.append(prefix + cur_line.strip()) + + +def WrapCode(line, line_concat, output): + indent = len(line) - len(line.lstrip()) + prefix = indent*' ' # Prefix of the current line + max_len = 80 - indent - len(line_concat) # Maximum length of the current line + new_prefix = prefix + 4*' ' # Prefix of a continuation line + new_max_len = max_len - 4 # Maximum length of a continuation line + # Prefers to wrap a line after a ',' or ';'. + segs = [seg for seg in re.split(r'([^,;]+[,;]?)', line.strip()) if seg != ''] + cur_line = '' # The current line without leading spaces. + for seg in segs: + # If the line is still too long, wrap at a space. + while cur_line == '' and len(seg.strip()) > max_len: + seg = seg.lstrip() + split_at = seg.rfind(' ', 0, max_len) + output.append(prefix + seg[:split_at].strip() + line_concat) + seg = seg[split_at + 1:] + prefix = new_prefix + max_len = new_max_len + + if len((cur_line + seg).rstrip()) < max_len: + cur_line = (cur_line + seg).lstrip() + else: + output.append(prefix + cur_line.rstrip() + line_concat) + prefix = new_prefix + max_len = new_max_len + cur_line = seg.lstrip() + if cur_line.strip() != '': + output.append(prefix + cur_line.strip()) + + +def WrapPreprocessorDirective(line, output): + WrapCode(line, ' \\', output) + + +def WrapPlainCode(line, output): + WrapCode(line, '', output) + + +def IsMultiLineIWYUPragma(line): + return re.search(r'/\* IWYU pragma: ', line) + + +def IsHeaderGuardIncludeOrOneLineIWYUPragma(line): + return (re.match(r'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$', line) or + re.match(r'^#include\s', line) or + # Don't break IWYU pragmas, either; that causes iwyu.py problems. + re.search(r'// IWYU pragma: ', line)) + + +def WrapLongLine(line, output): + line = line.rstrip() + if len(line) <= 80: + output.append(line) + elif IsSingleLineComment(line): + if IsHeaderGuardIncludeOrOneLineIWYUPragma(line): + # The style guide made an exception to allow long header guard lines, + # includes and IWYU pragmas. + output.append(line) + else: + WrapComment(line, output) + elif IsInPreprocessorDirective(output, line): + if IsHeaderGuardIncludeOrOneLineIWYUPragma(line): + # The style guide made an exception to allow long header guard lines, + # includes and IWYU pragmas. + output.append(line) + else: + WrapPreprocessorDirective(line, output) + elif IsMultiLineIWYUPragma(line): + output.append(line) + else: + WrapPlainCode(line, output) + + +def BeautifyCode(string): + lines = string.splitlines() + output = [] + for line in lines: + WrapLongLine(line, output) + output2 = [line.rstrip() for line in output] + return '\n'.join(output2) + '\n' + + +def ConvertFromPumpSource(src_text): + """Return the text generated from the given Pump source text.""" + ast = ParseToAST(StripMetaComments(src_text)) + output = Output() + RunCode(Env(), ast, output) + return BeautifyCode(output.string) + + +def main(argv): + if len(argv) == 1: + print __doc__ + sys.exit(1) + + file_path = argv[-1] + output_str = ConvertFromPumpSource(file(file_path, 'r').read()) + if file_path.endswith('.pump'): + output_file_path = file_path[:-5] + else: + output_file_path = '-' + if output_file_path == '-': + print output_str, + else: + output_file = file(output_file_path, 'w') + output_file.write('// This file was GENERATED by command:\n') + output_file.write('// %s %s\n' % + (os.path.basename(__file__), os.path.basename(file_path))) + output_file.write('// DO NOT EDIT BY HAND!!!\n\n') + output_file.write(output_str) + output_file.close() + + +if __name__ == '__main__': + main(sys.argv) From 1387d3969eff042a214ffe02b33f4d41372d3d3d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 10 Aug 2014 19:05:25 +0800 Subject: [PATCH 035/129] Add callback converter. --- native_mate/callback.h | 291 ++++++++++++++++++++++++++++++++ native_mate/callback.h.pump | 111 ++++++++++++ native_mate/locker.cc | 17 ++ native_mate/locker.h | 30 ++++ native_mate/scoped_persistent.h | 2 +- native_mate_files.gypi | 3 + 6 files changed, 453 insertions(+), 1 deletion(-) create mode 100644 native_mate/callback.h create mode 100644 native_mate/callback.h.pump create mode 100644 native_mate/locker.cc create mode 100644 native_mate/locker.h diff --git a/native_mate/callback.h b/native_mate/callback.h new file mode 100644 index 00000000000..98a63a2e46e --- /dev/null +++ b/native_mate/callback.h @@ -0,0 +1,291 @@ +// This file was GENERATED by command: +// pump.py callback.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/callback.h" +#include "native_mate/function_template.h" +#include "native_mate/locker.h" +#include "native_mate/scoped_persistent.h" + +namespace mate { + +namespace internal { + +typedef scoped_refptr > SafeV8Function; + +// Helper to convert type to V8 with storage type (const T& to T). +template +v8::Handle ConvertToV8(v8::Isolate* isolate, T a) { + return Converter::StorageType> + ::ToV8(isolate, a); +} + +// This set of templates invokes a V8::Function by converting the C++ types. +template +struct V8FunctionInvoker; + +template +struct V8FunctionInvoker { + static R Go(v8::Isolate* isolate, SafeV8Function function) { + R ret; + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle val(holder->Call(holder, 0, NULL)); + Converter::FromV8(isolate, val, &ret); + return ret; + } +}; + +template<> +struct V8FunctionInvoker { + static void Go(v8::Isolate* isolate, SafeV8Function function) { + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + holder->Call(holder, 0, NULL); + } +}; + +template +struct V8FunctionInvoker { + static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) { + R ret; + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + }; + v8::Handle val(holder->Call(holder, arraysize(args), args)); + Converter::FromV8(isolate, val, &ret); + return ret; + } +}; + +template +struct V8FunctionInvoker { + static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) { + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + }; + holder->Call(holder, arraysize(args), args); + } +}; + +template +struct V8FunctionInvoker { + static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2) { + R ret; + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + }; + v8::Handle val(holder->Call(holder, arraysize(args), args)); + Converter::FromV8(isolate, val, &ret); + return ret; + } +}; + +template +struct V8FunctionInvoker { + static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2) { + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + }; + holder->Call(holder, arraysize(args), args); + } +}; + +template +struct V8FunctionInvoker { + static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, + P3 a3) { + R ret; + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + }; + v8::Handle val(holder->Call(holder, arraysize(args), args)); + Converter::FromV8(isolate, val, &ret); + return ret; + } +}; + +template +struct V8FunctionInvoker { + static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, + P3 a3) { + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + }; + holder->Call(holder, arraysize(args), args); + } +}; + +template +struct V8FunctionInvoker { + static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, + P3 a3, P4 a4) { + R ret; + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + ConvertToV8(isolate, a4), + }; + v8::Handle val(holder->Call(holder, arraysize(args), args)); + Converter::FromV8(isolate, val, &ret); + return ret; + } +}; + +template +struct V8FunctionInvoker { + static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, + P3 a3, P4 a4) { + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + ConvertToV8(isolate, a4), + }; + holder->Call(holder, arraysize(args), args); + } +}; + +template +struct V8FunctionInvoker { + static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, + P3 a3, P4 a4, P5 a5) { + R ret; + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + ConvertToV8(isolate, a4), + ConvertToV8(isolate, a5), + }; + v8::Handle val(holder->Call(holder, arraysize(args), args)); + Converter::FromV8(isolate, val, &ret); + return ret; + } +}; + +template +struct V8FunctionInvoker { + static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, + P3 a3, P4 a4, P5 a5) { + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + ConvertToV8(isolate, a4), + ConvertToV8(isolate, a5), + }; + holder->Call(holder, arraysize(args), args); + } +}; + +template +struct V8FunctionInvoker { + static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, + P3 a3, P4 a4, P5 a5, P6 a6) { + R ret; + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + ConvertToV8(isolate, a4), + ConvertToV8(isolate, a5), + ConvertToV8(isolate, a6), + }; + v8::Handle val(holder->Call(holder, arraysize(args), args)); + Converter::FromV8(isolate, val, &ret); + return ret; + } +}; + +template +struct V8FunctionInvoker { + static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, + P3 a3, P4 a4, P5 a5, P6 a6) { + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + v8::Handle args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + ConvertToV8(isolate, a4), + ConvertToV8(isolate, a5), + ConvertToV8(isolate, a6), + }; + holder->Call(holder, arraysize(args), args); + } +}; + +} // namespace internal + +template +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + const base::Callback& val) { + return CreateFunctionTemplate(isolate, val)->GetFunction(); + } + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + base::Callback* out) { + if (!val->IsFunction()) + return false; + + internal::SafeV8Function function( + new RefCountedPersistent(val)); + *out = base::Bind(&internal::V8FunctionInvoker::Go, isolate, function); + return true; + } +}; + +} // namespace mate diff --git a/native_mate/callback.h.pump b/native_mate/callback.h.pump new file mode 100644 index 00000000000..0203065ce0c --- /dev/null +++ b/native_mate/callback.h.pump @@ -0,0 +1,111 @@ +$$ This is a pump file for generating file templates. Pump is a python +$$ script that is part of the Google Test suite of utilities. Description +$$ can be found here: +$$ +$$ http://code.google.com/p/googletest/wiki/PumpManual +$$ +$var MAX_ARITY = 6 +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/callback.h" +#include "native_mate/function_template.h" +#include "native_mate/locker.h" +#include "native_mate/scoped_persistent.h" + +namespace mate { + +namespace internal { + +typedef scoped_refptr > SafeV8Function; + +// Helper to convert type to V8 with storage type (const T& to T). +template +v8::Handle ConvertToV8(v8::Isolate* isolate, T a) { + return Converter::StorageType> + ::ToV8(isolate, a); +} + +// This set of templates invokes a V8::Function by converting the C++ types. +template +struct V8FunctionInvoker; + +$range ARITY 0..MAX_ARITY +$for ARITY [[ +$range ARG 1..ARITY + +template +struct V8FunctionInvoker { + static R Go(v8::Isolate* isolate, SafeV8Function function$for ARG [[, P$(ARG) a$(ARG)]]) { + R ret; + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + +$if ARITY == 0 [[ + v8::Handle val(holder->Call(holder, 0, NULL)); +]] $else [[ + v8::Handle args[] = { +$for ARG [[ + + ConvertToV8(isolate, a$(ARG)), +]] + + }; + v8::Handle val(holder->Call(holder, arraysize(args), args)); +]] + + Converter::FromV8(isolate, val, &ret); + return ret; + } +}; + +template<$for ARG , [[typename P$(ARG)]]> +struct V8FunctionInvoker { + static void Go(v8::Isolate* isolate, SafeV8Function function$for ARG [[, P$(ARG) a$(ARG)]]) { + Locker locker(isolate); + MATE_HANDLE_SCOPE(isolate); + v8::Handle holder = function->NewHandle(); + +$if ARITY == 0 [[ + holder->Call(holder, 0, NULL); +]] $else [[ + v8::Handle args[] = { +$for ARG [[ + + ConvertToV8(isolate, a$(ARG)), +]] + + }; + holder->Call(holder, arraysize(args), args); +]] + + } +}; + +]] + +} // namespace internal + +template +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + const base::Callback& val) { + return CreateFunctionTemplate(isolate, val)->GetFunction(); + } + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + base::Callback* out) { + if (!val->IsFunction()) + return false; + + internal::SafeV8Function function( + new RefCountedPersistent(val)); + *out = base::Bind(&internal::V8FunctionInvoker::Go, isolate, function); + return true; + } +}; + +} // namespace mate diff --git a/native_mate/locker.cc b/native_mate/locker.cc new file mode 100644 index 00000000000..c85e68e35f3 --- /dev/null +++ b/native_mate/locker.cc @@ -0,0 +1,17 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#include "native_mate/locker.h" + +namespace mate { + +Locker::Locker(v8::Isolate* isolate) { + if (v8::Locker::IsActive()) + locker_.reset(new v8::Locker(isolate)); +} + +Locker::~Locker() { +} + +} // namespace mate diff --git a/native_mate/locker.h b/native_mate/locker.h new file mode 100644 index 00000000000..07acfbb0be9 --- /dev/null +++ b/native_mate/locker.h @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.chromium file. + +#ifndef NATIVE_MATE_LOCKER_H_ +#define NATIVE_MATE_LOCKER_H_ + +#include "base/memory/scoped_ptr.h" +#include "v8/include/v8.h" + +namespace mate { + +// Only lock when lockers are used in current thread. +class Locker { + public: + explicit Locker(v8::Isolate* isolate); + ~Locker(); + + private: + void* operator new(size_t size); + void operator delete(void*, size_t); + + scoped_ptr locker_; + + DISALLOW_COPY_AND_ASSIGN(Locker); +}; + +} // namespace mate + +#endif // NATIVE_MATE_LOCKER_H_ diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index 44580221ba0..8c6ee0c3580 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -56,7 +56,7 @@ class ScopedPersistent { v8::Handle NewHandle(v8::Isolate* isolate) const { if (handle_.IsEmpty()) return v8::Local(); - return v8::Local::New(isolate, handle_); + return MATE_PERSISTENT_TO_LOCAL(T, isolate, handle_); } template diff --git a/native_mate_files.gypi b/native_mate_files.gypi index a9e9de3375a..e67e5597371 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -3,6 +3,7 @@ 'native_mate_files': [ 'native_mate/arguments.cc', 'native_mate/arguments.h', + 'native_mate/callback.h', 'native_mate/compat.h', 'native_mate/constructor.h', 'native_mate/converter.cc', @@ -12,6 +13,8 @@ 'native_mate/function_template.cc', 'native_mate/function_template.h', 'native_mate/handle.h', + 'native_mate/locker.cc', + 'native_mate/locker.h', 'native_mate/object_template_builder.cc', 'native_mate/object_template_builder.h', 'native_mate/scoped_persistent.h', From 980036b78a132ab820ed1d7866a06aac9a5c95a8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 10 Aug 2014 21:18:42 +0800 Subject: [PATCH 036/129] Make ScopedPersistent's interface consistent with V8. --- native_mate/callback.h | 2 +- native_mate/converter.h | 2 +- native_mate/scoped_persistent.h | 47 +++++---------------------------- 3 files changed, 8 insertions(+), 43 deletions(-) diff --git a/native_mate/callback.h b/native_mate/callback.h index 98a63a2e46e..886b53b2d1f 100644 --- a/native_mate/callback.h +++ b/native_mate/callback.h @@ -282,7 +282,7 @@ struct Converter > { return false; internal::SafeV8Function function( - new RefCountedPersistent(val)); + new RefCountedPersistent(isolate, val)); *out = base::Bind(&internal::V8FunctionInvoker::Go, isolate, function); return true; } diff --git a/native_mate/converter.h b/native_mate/converter.h index c17e892c2b0..66fc2d31ab6 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -200,7 +200,7 @@ inline v8::Handle StringToV8( } v8::Handle StringToSymbol(v8::Isolate* isolate, - const base::StringPiece& val); + const base::StringPiece& input); template bool ConvertFromV8(v8::Isolate* isolate, v8::Handle input, diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index 8c6ee0c3580..bbc91b9c5e7 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -16,22 +16,17 @@ namespace mate { template class ScopedPersistent { public: - ScopedPersistent(v8::Isolate* isolate = NULL) : isolate_(isolate) { - } + ScopedPersistent() : isolate_(v8::Isolate::GetCurrent()) {} - ScopedPersistent(v8::Handle handle, v8::Isolate* isolate = NULL) + ScopedPersistent(v8::Isolate* isolate, v8::Handle handle) : isolate_(isolate) { - reset(v8::Handle::Cast(handle)); + reset(isolate, v8::Handle::Cast(handle)); } ~ScopedPersistent() { reset(); } - void reset(v8::Handle handle) { - reset(GetIsolate(handle), handle); - } - void reset(v8::Isolate* isolate, v8::Handle handle) { if (!handle.IsEmpty()) { isolate_ = isolate; @@ -50,7 +45,7 @@ class ScopedPersistent { } v8::Handle NewHandle() const { - return NewHandle(GetIsolate(handle_)); + return NewHandle(isolate_); } v8::Handle NewHandle(v8::Isolate* isolate) const { @@ -67,36 +62,6 @@ class ScopedPersistent { v8::Isolate* isolate() const { return isolate_; } private: - template - v8::Isolate* GetIsolate(v8::Handle object_handle) const { - // Only works for v8::Object and its subclasses. Add specialisations for - // anything else. - if (!object_handle.IsEmpty()) - return GetIsolate(object_handle->CreationContext()); - return GetIsolate(); - } -#if NODE_VERSION_AT_LEAST(0, 11, 0) - v8::Isolate* GetIsolate(v8::Handle context_handle) const { - if (!context_handle.IsEmpty()) - return context_handle->GetIsolate(); - return GetIsolate(); - } -#endif - v8::Isolate* GetIsolate( - v8::Handle template_handle) const { - return GetIsolate(); - } - template - v8::Isolate* GetIsolate(const U& any_handle) const { - return GetIsolate(); - } - v8::Isolate* GetIsolate() const { - if (isolate_) - return isolate_; - else - return v8::Isolate::GetCurrent(); - } - v8::Isolate* isolate_; v8::Persistent handle_; @@ -109,8 +74,8 @@ class RefCountedPersistent : public ScopedPersistent, public: RefCountedPersistent() {} - explicit RefCountedPersistent(v8::Handle handle) - : ScopedPersistent(handle) { + RefCountedPersistent(v8::Isolate* isolate, v8::Handle handle) + : ScopedPersistent(isolate, handle) { } protected: From 742923c73d9197884fb3ad09ab511a3673b74869 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Sep 2014 13:32:41 +0800 Subject: [PATCH 037/129] Remove unused constructor of Dictionary. --- native_mate/dictionary.cc | 11 ++--------- native_mate/dictionary.h | 4 +--- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc index 1a1750ff12e..168e5e75833 100644 --- a/native_mate/dictionary.cc +++ b/native_mate/dictionary.cc @@ -6,9 +6,8 @@ namespace mate { -Dictionary::Dictionary(v8::Isolate* isolate) - : isolate_(isolate), - object_(MATE_OBJECT_NEW(isolate)) { +Dictionary::Dictionary() + : isolate_(NULL) { } Dictionary::Dictionary(v8::Isolate* isolate, @@ -20,12 +19,6 @@ Dictionary::Dictionary(v8::Isolate* isolate, Dictionary::~Dictionary() { } -Dictionary Dictionary::CreateEmpty(v8::Isolate* isolate) { - Dictionary dictionary(isolate); - dictionary.object_ = MATE_OBJECT_NEW(isolate); - return dictionary; -} - v8::Handle Converter::ToV8(v8::Isolate* isolate, Dictionary val) { return val.object_; diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 8c5dfeaae35..f901e7e27dc 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -24,12 +24,10 @@ namespace mate { // class Dictionary { public: - Dictionary(v8::Isolate* isolate = v8::Isolate::GetCurrent()); + Dictionary(); Dictionary(v8::Isolate* isolate, v8::Handle object); ~Dictionary(); - static Dictionary CreateEmpty(v8::Isolate* isolate); - template bool Get(const base::StringPiece& key, T* out) const { v8::Handle val = object_->Get(StringToV8(isolate_, key)); From 12f4e9b7ea0038e58e52839142eff0a4d17069bf Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Sep 2014 14:12:59 +0800 Subject: [PATCH 038/129] Add PersistentDictionary. --- native_mate/dictionary.cc | 6 ++++- native_mate/dictionary.h | 19 ++++++++------- native_mate/persistent_dictionary.cc | 34 ++++++++++++++++++++++++++ native_mate/persistent_dictionary.h | 36 ++++++++++++++++++++++++++++ native_mate_files.gypi | 2 ++ 5 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 native_mate/persistent_dictionary.cc create mode 100644 native_mate/persistent_dictionary.h diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc index 168e5e75833..6c154eaad45 100644 --- a/native_mate/dictionary.cc +++ b/native_mate/dictionary.cc @@ -19,9 +19,13 @@ Dictionary::Dictionary(v8::Isolate* isolate, Dictionary::~Dictionary() { } +v8::Handle Dictionary::GetHandle() const { + return object_; +} + v8::Handle Converter::ToV8(v8::Isolate* isolate, Dictionary val) { - return val.object_; + return val.GetHandle(); } bool Converter::FromV8(v8::Isolate* isolate, diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index f901e7e27dc..fab215e2126 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -30,30 +30,33 @@ class Dictionary { template bool Get(const base::StringPiece& key, T* out) const { - v8::Handle val = object_->Get(StringToV8(isolate_, key)); + v8::Handle val = GetHandle()->Get(StringToV8(isolate_, key)); return ConvertFromV8(isolate_, val, out); } template bool Set(const base::StringPiece& key, T val) { - return object_->Set(StringToV8(isolate_, key), ConvertToV8(isolate_, val)); + return GetHandle()->Set(StringToV8(isolate_, key), + ConvertToV8(isolate_, val)); } template bool SetMethod(const base::StringPiece& key, const T& callback) { - return object_->Set( + return GetHandle()->Set( StringToV8(isolate_, key), CallbackTraits::CreateTemplate(isolate_, callback)->GetFunction()); } - v8::Handle object() const { return object_; } + bool IsEmpty() const { return isolate() == NULL; } + + virtual v8::Handle GetHandle() const; + v8::Isolate* isolate() const { return isolate_; } - private: - friend struct Converter; - - // TODO(aa): Remove this. Instead, get via FromV8(), Set(), and Get(). + protected: v8::Isolate* isolate_; + + private: v8::Handle object_; }; diff --git a/native_mate/persistent_dictionary.cc b/native_mate/persistent_dictionary.cc new file mode 100644 index 00000000000..05c83e5aa8d --- /dev/null +++ b/native_mate/persistent_dictionary.cc @@ -0,0 +1,34 @@ +// Copyright 2014 Cheng Zhao. All rights reserved. +// Use of this source code is governed by MIT license that can be found in the +// LICENSE file. + +#include "native_mate/persistent_dictionary.h" + +namespace mate { + +PersistentDictionary::PersistentDictionary() { +} + +PersistentDictionary::PersistentDictionary(v8::Isolate* isolate, + v8::Handle object) + : handle_(new RefCountedPersistent(isolate, object)) { + isolate_ = isolate; +} + +PersistentDictionary::~PersistentDictionary() { +} + +v8::Handle PersistentDictionary::GetHandle() const { + return handle_->NewHandle(); +} + +bool Converter::FromV8(v8::Isolate* isolate, + v8::Handle val, + PersistentDictionary* out) { + if (!val->IsObject()) + return false; + *out = PersistentDictionary(isolate, v8::Handle::Cast(val)); + return true; +} + +} // namespace mate diff --git a/native_mate/persistent_dictionary.h b/native_mate/persistent_dictionary.h new file mode 100644 index 00000000000..c0e79e54b17 --- /dev/null +++ b/native_mate/persistent_dictionary.h @@ -0,0 +1,36 @@ +// Copyright 2014 Cheng Zhao. All rights reserved. +// Use of this source code is governed by MIT license that can be found in the +// LICENSE file. + +#ifndef NATIVE_MATE_PERSISTENT_DICTIONARY_H_ +#define NATIVE_MATE_PERSISTENT_DICTIONARY_H_ + +#include "native_mate/dictionary.h" +#include "native_mate/scoped_persistent.h" + +namespace mate { + +// Like Dictionary, but stores object in persistent handle so you can keep it +// safely on heap. +class PersistentDictionary : public Dictionary { + public: + PersistentDictionary(); + PersistentDictionary(v8::Isolate* isolate, v8::Handle object); + virtual ~PersistentDictionary(); + + virtual v8::Handle GetHandle() const OVERRIDE; + + private: + scoped_refptr > handle_; +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + PersistentDictionary* out); +}; + +} // namespace mate + +#endif // NATIVE_MATE_PERSISTENT_DICTIONARY_H_ diff --git a/native_mate_files.gypi b/native_mate_files.gypi index e67e5597371..bc245f831a6 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -17,6 +17,8 @@ 'native_mate/locker.h', 'native_mate/object_template_builder.cc', 'native_mate/object_template_builder.h', + 'native_mate/persistent_dictionary.cc', + 'native_mate/persistent_dictionary.h', 'native_mate/scoped_persistent.h', 'native_mate/template_util.h', 'native_mate/try_catch.cc', From c5b39126ee7388acc61a25ac6b5fefb7a2cd6262 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 23 Sep 2014 23:28:52 +0800 Subject: [PATCH 039/129] Make throwing exception when parsing args easier --- native_mate/arguments.cc | 14 +++++++++++--- native_mate/arguments.h | 5 +++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/native_mate/arguments.cc b/native_mate/arguments.cc index 70351479a02..fcb34db76c0 100644 --- a/native_mate/arguments.cc +++ b/native_mate/arguments.cc @@ -32,17 +32,25 @@ v8::Handle Arguments::PeekNext() const { return (*info_)[next_]; } -void Arguments::ThrowError() const { +v8::Handle Arguments::ThrowError() const { if (insufficient_arguments_) return ThrowTypeError("Insufficient number of arguments."); - ThrowTypeError(base::StringPrintf( + return ThrowTypeError(base::StringPrintf( "Error processing argument %d.", next_ - 1)); } -void Arguments::ThrowTypeError(const std::string& message) const { +v8::Handle Arguments::ThrowError(const std::string& message) const { + MATE_THROW_EXCEPTION(isolate_, v8::Exception::Error( + StringToV8(isolate_, message))); + return MATE_UNDEFINED(isolate_); +} + +v8::Handle Arguments::ThrowTypeError( + const std::string& message) const { MATE_THROW_EXCEPTION(isolate_, v8::Exception::TypeError( StringToV8(isolate_, message))); + return MATE_UNDEFINED(isolate_); } } // namespace mate diff --git a/native_mate/arguments.h b/native_mate/arguments.h index 7975a156c2d..cee1477b678 100644 --- a/native_mate/arguments.h +++ b/native_mate/arguments.h @@ -73,8 +73,9 @@ class Arguments { v8::Handle PeekNext() const; - void ThrowError() const; - void ThrowTypeError(const std::string& message) const; + v8::Handle ThrowError() const; + v8::Handle ThrowError(const std::string& message) const; + v8::Handle ThrowTypeError(const std::string& message) const; v8::Isolate* isolate() const { return isolate_; } From cc9d22292361e8b74e82a4e6a77407c17b4bfda7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 30 Sep 2014 22:44:27 +0800 Subject: [PATCH 040/129] Use NODE_VERSION_AT_LEAST to determine node version --- native_mate/compat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_mate/compat.h b/native_mate/compat.h index 710171eb26c..021c0ca2cee 100644 --- a/native_mate/compat.h +++ b/native_mate/compat.h @@ -7,7 +7,7 @@ #include "node_version.h" -#if (NODE_MODULE_VERSION > 0x000B) // Node 0.11+ +#if NODE_VERSION_AT_LEAST(0, 11, 0) #define MATE_HANDLE_SCOPE(isolate) v8::HandleScope handle_scope(isolate) From b1f7cfa9da1f53158a4992428b40a780c9617632 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 30 Oct 2014 21:31:53 +0800 Subject: [PATCH 041/129] Don't throw error in Constructor --- native_mate/constructor.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index f44238ed07c..4dce532098b 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -154,8 +154,6 @@ class Constructor { Wrappable* object = internal::InvokeFactory(args, factory); if (object) object->Wrap(isolate, args->GetThis()); - else - args->ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); } From 4a1d11b2bea0907c66bf986ab635e161a1a16385 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 30 Oct 2014 21:54:29 +0800 Subject: [PATCH 042/129] Guard against non-constructor call in Constructor::New --- native_mate/arguments.h | 4 ++++ native_mate/constructor.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/native_mate/arguments.h b/native_mate/arguments.h index cee1477b678..29877a7c6b9 100644 --- a/native_mate/arguments.h +++ b/native_mate/arguments.h @@ -60,6 +60,10 @@ class Arguments { return info_->This(); } + bool IsConstructCall() const { + return info_->IsConstructCall(); + } + int Length() const { return info_->Length(); } diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 4dce532098b..16cec447d2a 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -151,6 +151,11 @@ class Constructor { private: static MATE_METHOD_RETURN_TYPE New(const WrappableFactoryFunction& factory, v8::Isolate* isolate, Arguments* args) { + if (!args->IsConstructCall()) { + args->ThrowError("Requires constructor call"); + MATE_METHOD_RETURN_UNDEFINED(); + } + Wrappable* object = internal::InvokeFactory(args, factory); if (object) object->Wrap(isolate, args->GetThis()); From be2934d9b5925cb017238c1b385340c2f9cfdcb7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 2 Jan 2015 18:04:46 -0800 Subject: [PATCH 043/129] Fix throwing error in constructor --- native_mate/constructor.h | 2 ++ native_mate/constructor.h.pump | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 16cec447d2a..3d2ed69c0ea 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -159,6 +159,8 @@ class Constructor { Wrappable* object = internal::InvokeFactory(args, factory); if (object) object->Wrap(isolate, args->GetThis()); + else + args->ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); } diff --git a/native_mate/constructor.h.pump b/native_mate/constructor.h.pump index 81a7524087e..a0ef452fde0 100644 --- a/native_mate/constructor.h.pump +++ b/native_mate/constructor.h.pump @@ -87,6 +87,11 @@ class Constructor { private: static MATE_METHOD_RETURN_TYPE New(const WrappableFactoryFunction& factory, v8::Isolate* isolate, Arguments* args) { + if (!args->IsConstructCall()) { + args->ThrowError("Requires constructor call"); + MATE_METHOD_RETURN_UNDEFINED(); + } + Wrappable* object = internal::InvokeFactory(args, factory); if (object) object->Wrap(isolate, args->GetThis()); From 753d5675dd58aab3d3c429a233803ad4598802bc Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Jan 2015 22:13:19 -0800 Subject: [PATCH 044/129] Fix ignored exception thrown from constructor. --- native_mate/constructor.h | 12 +++++++++++- native_mate/constructor.h.pump | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 3d2ed69c0ea..1b6a23c14cd 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -156,7 +156,17 @@ class Constructor { MATE_METHOD_RETURN_UNDEFINED(); } - Wrappable* object = internal::InvokeFactory(args, factory); + Wrappable* object; + { + // Don't continue if the constructor throws an exception. + v8::TryCatch try_catch; + object = internal::InvokeFactory(args, factory); + if (try_catch.HasCaught()) { + try_catch.ReThrow(); + MATE_METHOD_RETURN_UNDEFINED(); + } + } + if (object) object->Wrap(isolate, args->GetThis()); else diff --git a/native_mate/constructor.h.pump b/native_mate/constructor.h.pump index a0ef452fde0..87d10bbc68e 100644 --- a/native_mate/constructor.h.pump +++ b/native_mate/constructor.h.pump @@ -92,7 +92,17 @@ class Constructor { MATE_METHOD_RETURN_UNDEFINED(); } - Wrappable* object = internal::InvokeFactory(args, factory); + Wrappable* object; + { + // Don't continue if the constructor throws an exception. + v8::TryCatch try_catch; + object = internal::InvokeFactory(args, factory); + if (try_catch.HasCaught()) { + try_catch.ReThrow(); + MATE_METHOD_RETURN_UNDEFINED(); + } + } + if (object) object->Wrap(isolate, args->GetThis()); else From bcf87fd3c953a4006a2038a1b6a7a237f1c95232 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 9 Jan 2015 17:23:18 -0800 Subject: [PATCH 045/129] OVERRIDE => override --- native_mate/persistent_dictionary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_mate/persistent_dictionary.h b/native_mate/persistent_dictionary.h index c0e79e54b17..ae86c6b2414 100644 --- a/native_mate/persistent_dictionary.h +++ b/native_mate/persistent_dictionary.h @@ -18,7 +18,7 @@ class PersistentDictionary : public Dictionary { PersistentDictionary(v8::Isolate* isolate, v8::Handle object); virtual ~PersistentDictionary(); - virtual v8::Handle GetHandle() const OVERRIDE; + v8::Handle GetHandle() const override; private: scoped_refptr > handle_; From 1116a36c15ac3e65720cf12d38a3308f40f7ea58 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 14 Jan 2015 17:51:07 -0800 Subject: [PATCH 046/129] Avoid unnecessary copy in ConvertToV8 --- native_mate/converter.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/native_mate/converter.h b/native_mate/converter.h index 66fc2d31ab6..86a1cc4cd0e 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -189,10 +189,15 @@ struct Converter > { // Convenience functions that deduce T. template v8::Handle ConvertToV8(v8::Isolate* isolate, - T input) { + const T& input) { return Converter::ToV8(isolate, input); } +inline v8::Handle ConvertToV8(v8::Isolate* isolate, + const char* input) { + return Converter::ToV8(isolate, input); +} + inline v8::Handle StringToV8( v8::Isolate* isolate, const base::StringPiece& input) { From 3387f33a8e7b4107f4268dec2a72a3fa943d706c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 22:09:42 +0800 Subject: [PATCH 047/129] Check internal field before converting --- native_mate/wrappable.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index d783306c45b..fb051a8bbfa 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -67,6 +67,8 @@ void* FromV8Impl(v8::Isolate* isolate, v8::Handle val) { if (!val->IsObject()) return NULL; v8::Handle obj = v8::Handle::Cast(val); + if (obj->InternalFieldCount() != 1) + return NULL; return MATE_GET_INTERNAL_FIELD_POINTER(obj, 0); } From 8d537ee2b6da29c1aa38928590d4c56700e1c69b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 12:55:50 +0800 Subject: [PATCH 048/129] Remove unneeded helper --- native_mate/callback.h | 7 ------- native_mate/callback.h.pump | 9 +-------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/native_mate/callback.h b/native_mate/callback.h index 886b53b2d1f..d80d381fc36 100644 --- a/native_mate/callback.h +++ b/native_mate/callback.h @@ -18,13 +18,6 @@ namespace internal { typedef scoped_refptr > SafeV8Function; -// Helper to convert type to V8 with storage type (const T& to T). -template -v8::Handle ConvertToV8(v8::Isolate* isolate, T a) { - return Converter::StorageType> - ::ToV8(isolate, a); -} - // This set of templates invokes a V8::Function by converting the C++ types. template struct V8FunctionInvoker; diff --git a/native_mate/callback.h.pump b/native_mate/callback.h.pump index 0203065ce0c..9f0220ee6de 100644 --- a/native_mate/callback.h.pump +++ b/native_mate/callback.h.pump @@ -21,13 +21,6 @@ namespace internal { typedef scoped_refptr > SafeV8Function; -// Helper to convert type to V8 with storage type (const T& to T). -template -v8::Handle ConvertToV8(v8::Isolate* isolate, T a) { - return Converter::StorageType> - ::ToV8(isolate, a); -} - // This set of templates invokes a V8::Function by converting the C++ types. template struct V8FunctionInvoker; @@ -102,7 +95,7 @@ struct Converter > { return false; internal::SafeV8Function function( - new RefCountedPersistent(val)); + new RefCountedPersistent(isolate, val)); *out = base::Bind(&internal::V8FunctionInvoker::Go, isolate, function); return true; } From d0db7bfb586afe9f491bd4cb368353d2660ecfe1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Feb 2015 11:37:55 +0800 Subject: [PATCH 049/129] Add AfterInit method for Wrappable --- native_mate/wrappable.cc | 2 ++ native_mate/wrappable.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index fb051a8bbfa..4596d154bdb 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -29,6 +29,8 @@ void Wrappable::Wrap(v8::Isolate* isolate, v8::Handle wrapper) { v8::Handle init; if (Dictionary(isolate, wrapper).Get("_init", &init)) init->Call(wrapper, 0, NULL); + + AfterInit(isolate); } // static diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 9db85496d6d..6031674c06b 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -68,6 +68,9 @@ class Wrappable { virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); + // Called after the "_init" method gets called in JavaScript. + virtual void AfterInit(v8::Isolate* isolate) {} + private: static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, Wrappable); From a636fad51e862d52c7bdb527c91300c85ed3c254 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Mar 2015 16:08:30 -0700 Subject: [PATCH 050/129] Add converter for unsigned long --- native_mate/converter.cc | 14 ++++++++++++++ native_mate/converter.h | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/native_mate/converter.cc b/native_mate/converter.cc index e5e7c52467c..cc66b8d3907 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -31,6 +31,20 @@ bool Converter::FromV8(Isolate* isolate, Handle val, bool* out) { return true; } +Handle Converter::ToV8(Isolate* isolate, + unsigned long val) { + return MATE_INTEGER_NEW(isolate, val); +} + +bool Converter::FromV8(Isolate* isolate, Handle val, + unsigned long* out) { + if (!val->IsNumber()) + return false; + *out = val->IntegerValue(); + return true; +} + + Handle Converter::ToV8(Isolate* isolate, int32_t val) { return MATE_INTEGER_NEW(isolate, val); } diff --git a/native_mate/converter.h b/native_mate/converter.h index 86a1cc4cd0e..37d86f82bf0 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -33,6 +33,15 @@ struct Converter { bool* out); }; +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + unsigned long val); + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + unsigned long* out); +}; + template<> struct Converter { static v8::Handle ToV8(v8::Isolate* isolate, From 38aba072908357b4eebc68462714b01a9c2d0138 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 14 Mar 2015 18:47:08 +0000 Subject: [PATCH 051/129] usigned long is uint64 on Linux --- native_mate/converter.cc | 3 ++- native_mate/converter.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/native_mate/converter.cc b/native_mate/converter.cc index cc66b8d3907..2c9d95f9417 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -31,6 +31,7 @@ bool Converter::FromV8(Isolate* isolate, Handle val, bool* out) { return true; } +#if !defined(OS_LINUX) Handle Converter::ToV8(Isolate* isolate, unsigned long val) { return MATE_INTEGER_NEW(isolate, val); @@ -43,7 +44,7 @@ bool Converter::FromV8(Isolate* isolate, Handle val, *out = val->IntegerValue(); return true; } - +#endif Handle Converter::ToV8(Isolate* isolate, int32_t val) { return MATE_INTEGER_NEW(isolate, val); diff --git a/native_mate/converter.h b/native_mate/converter.h index 37d86f82bf0..e2fe3e885cf 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -33,6 +33,7 @@ struct Converter { bool* out); }; +#if !defined(OS_LINUX) template<> struct Converter { static v8::Handle ToV8(v8::Isolate* isolate, @@ -41,6 +42,7 @@ struct Converter { v8::Handle val, unsigned long* out); }; +#endif template<> struct Converter { From 40da835cbb7a5f76aacebf9d3ee4b66a62cece71 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 23 Mar 2015 16:19:55 +0800 Subject: [PATCH 052/129] Don't reset handle before Wrappable is destroyed It is possible that the user wants to use the V8 object in the destructor. Fixes atom/atom-shell#1112. --- native_mate/constructor.h | 2 +- native_mate/constructor.h.pump | 2 +- native_mate/function_template.h | 2 +- native_mate/function_template.h.pump | 2 +- native_mate/wrappable.cc | 1 - native_mate/wrappable.h | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 1b6a23c14cd..14ea119e56a 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -176,7 +176,7 @@ class Constructor { } base::StringPiece name_; - v8::Persistent constructor_; + v8::UniquePersistent constructor_; DISALLOW_COPY_AND_ASSIGN(Constructor); }; diff --git a/native_mate/constructor.h.pump b/native_mate/constructor.h.pump index 87d10bbc68e..94a56d424a9 100644 --- a/native_mate/constructor.h.pump +++ b/native_mate/constructor.h.pump @@ -112,7 +112,7 @@ class Constructor { } base::StringPiece name_; - v8::Persistent constructor_; + v8::UniquePersistent constructor_; DISALLOW_COPY_AND_ASSIGN(Constructor); }; diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 54b71c04f88..14ed170080b 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -57,7 +57,7 @@ class CallbackHolderBase { private: static MATE_WEAK_CALLBACK(WeakCallback, v8::External, CallbackHolderBase); - v8::Persistent v8_ref_; + v8::UniquePersistent v8_ref_; DISALLOW_COPY_AND_ASSIGN(CallbackHolderBase); }; diff --git a/native_mate/function_template.h.pump b/native_mate/function_template.h.pump index ddfe29a25d1..c3009f2a828 100644 --- a/native_mate/function_template.h.pump +++ b/native_mate/function_template.h.pump @@ -60,7 +60,7 @@ class CallbackHolderBase { private: static MATE_WEAK_CALLBACK(WeakCallback, v8::External, CallbackHolderBase); - v8::Persistent v8_ref_; + v8::UniquePersistent v8_ref_; DISALLOW_COPY_AND_ASSIGN(CallbackHolderBase); }; diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 4596d154bdb..070c3c59d92 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -46,7 +46,6 @@ ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( // static MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { MATE_WEAK_CALLBACK_INIT(Wrappable); - MATE_PERSISTENT_RESET(self->wrapper_); delete self; } diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 6031674c06b..f93bf6b3b24 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -74,7 +74,7 @@ class Wrappable { private: static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, Wrappable); - v8::Persistent wrapper_; // Weak + v8::UniquePersistent wrapper_; // Weak DISALLOW_COPY_AND_ASSIGN(Wrappable); }; From 39fae3a4807606aee040ef804badf127d90c8fc7 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Sat, 18 Apr 2015 01:33:54 +0530 Subject: [PATCH 053/129] added std::set converter --- native_mate/converter.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/native_mate/converter.h b/native_mate/converter.h index e2fe3e885cf..2093ce0ea45 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -7,6 +7,7 @@ #include #include +#include #include "base/strings/string_piece.h" #include "native_mate/compat.h" @@ -197,6 +198,40 @@ struct Converter > { } }; +template +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + const std::set& val) { + v8::Handle result( + MATE_ARRAY_NEW(isolate, static_cast(val.size()))); + typename std::set::const_iterator it; + int i; + for (i = 0, it = val.begin(); it != val.end(); ++it, ++i) + result->Set(i, Converter::ToV8(isolate, *it)); + return result; + } + + static bool FromV8(v8::Isolate* isolate, + v8::Handle val, + std::set* out) { + if (!val->IsArray()) + return false; + + std::set result; + v8::Handle array(v8::Handle::Cast(val)); + uint32_t length = array->Length(); + for (uint32_t i = 0; i < length; ++i) { + T item; + if (!Converter::FromV8(isolate, array->Get(i), &item)) + return false; + result.push_back(item); + } + + out->swap(result); + return true; + } +}; + // Convenience functions that deduce T. template v8::Handle ConvertToV8(v8::Isolate* isolate, From 269be869988bda9a7e8ad0ef56af178a741af09c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 22 May 2015 19:11:02 +0800 Subject: [PATCH 054/129] Use Local instead of Handle --- native_mate/arguments.cc | 10 +-- native_mate/arguments.h | 14 +-- native_mate/callback.h | 70 +++++++-------- native_mate/callback.h.pump | 16 ++-- native_mate/compat.h | 2 +- native_mate/constructor.h | 2 +- native_mate/constructor.h.pump | 2 +- native_mate/converter.cc | 94 ++++++++++---------- native_mate/converter.h | 116 ++++++++++++------------- native_mate/dictionary.cc | 10 +-- native_mate/dictionary.h | 12 +-- native_mate/function_template.cc | 2 +- native_mate/function_template.h | 20 ++--- native_mate/function_template.h.pump | 6 +- native_mate/handle.h | 10 +-- native_mate/object_template_builder.cc | 6 +- native_mate/object_template_builder.h | 18 ++-- native_mate/persistent_dictionary.cc | 8 +- native_mate/persistent_dictionary.h | 6 +- native_mate/scoped_persistent.h | 20 ++--- native_mate/try_catch.cc | 6 +- native_mate/wrappable.cc | 14 +-- native_mate/wrappable.h | 12 +-- 23 files changed, 238 insertions(+), 238 deletions(-) diff --git a/native_mate/arguments.cc b/native_mate/arguments.cc index fcb34db76c0..57aa55274ec 100644 --- a/native_mate/arguments.cc +++ b/native_mate/arguments.cc @@ -26,13 +26,13 @@ Arguments::Arguments(const MATE_METHOD_ARGS_TYPE& info) Arguments::~Arguments() { } -v8::Handle Arguments::PeekNext() const { +v8::Local Arguments::PeekNext() const { if (next_ >= info_->Length()) - return v8::Handle(); + return v8::Local(); return (*info_)[next_]; } -v8::Handle Arguments::ThrowError() const { +v8::Local Arguments::ThrowError() const { if (insufficient_arguments_) return ThrowTypeError("Insufficient number of arguments."); @@ -40,13 +40,13 @@ v8::Handle Arguments::ThrowError() const { "Error processing argument %d.", next_ - 1)); } -v8::Handle Arguments::ThrowError(const std::string& message) const { +v8::Local Arguments::ThrowError(const std::string& message) const { MATE_THROW_EXCEPTION(isolate_, v8::Exception::Error( StringToV8(isolate_, message))); return MATE_UNDEFINED(isolate_); } -v8::Handle Arguments::ThrowTypeError( +v8::Local Arguments::ThrowTypeError( const std::string& message) const { MATE_THROW_EXCEPTION(isolate_, v8::Exception::TypeError( StringToV8(isolate_, message))); diff --git a/native_mate/arguments.h b/native_mate/arguments.h index 29877a7c6b9..493af7c63bf 100644 --- a/native_mate/arguments.h +++ b/native_mate/arguments.h @@ -36,7 +36,7 @@ class Arguments { insufficient_arguments_ = true; return false; } - v8::Handle val = (*info_)[next_++]; + v8::Local val = (*info_)[next_++]; return ConvertFromV8(isolate_, val, out); } @@ -49,14 +49,14 @@ class Arguments { int remaining = info_->Length() - next_; out->resize(remaining); for (int i = 0; i < remaining; ++i) { - v8::Handle val = (*info_)[next_++]; + v8::Local val = (*info_)[next_++]; if (!ConvertFromV8(isolate_, val, &out->at(i))) return false; } return true; } - v8::Handle GetThis() { + v8::Local GetThis() { return info_->This(); } @@ -75,11 +75,11 @@ class Arguments { } #endif - v8::Handle PeekNext() const; + v8::Local PeekNext() const; - v8::Handle ThrowError() const; - v8::Handle ThrowError(const std::string& message) const; - v8::Handle ThrowTypeError(const std::string& message) const; + v8::Local ThrowError() const; + v8::Local ThrowError(const std::string& message) const; + v8::Local ThrowTypeError(const std::string& message) const; v8::Isolate* isolate() const { return isolate_; } diff --git a/native_mate/callback.h b/native_mate/callback.h index d80d381fc36..28e572f0e78 100644 --- a/native_mate/callback.h +++ b/native_mate/callback.h @@ -28,8 +28,8 @@ struct V8FunctionInvoker { R ret; Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle val(holder->Call(holder, 0, NULL)); + v8::Local holder = function->NewHandle(); + v8::Local val(holder->Call(holder, 0, NULL)); Converter::FromV8(isolate, val, &ret); return ret; } @@ -40,7 +40,7 @@ struct V8FunctionInvoker { static void Go(v8::Isolate* isolate, SafeV8Function function) { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); + v8::Local holder = function->NewHandle(); holder->Call(holder, 0, NULL); } }; @@ -51,11 +51,11 @@ struct V8FunctionInvoker { R ret; Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), }; - v8::Handle val(holder->Call(holder, arraysize(args), args)); + v8::Local val(holder->Call(holder, arraysize(args), args)); Converter::FromV8(isolate, val, &ret); return ret; } @@ -66,8 +66,8 @@ struct V8FunctionInvoker { static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), }; holder->Call(holder, arraysize(args), args); @@ -80,12 +80,12 @@ struct V8FunctionInvoker { R ret; Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), }; - v8::Handle val(holder->Call(holder, arraysize(args), args)); + v8::Local val(holder->Call(holder, arraysize(args), args)); Converter::FromV8(isolate, val, &ret); return ret; } @@ -96,8 +96,8 @@ struct V8FunctionInvoker { static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2) { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), }; @@ -112,13 +112,13 @@ struct V8FunctionInvoker { R ret; Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), ConvertToV8(isolate, a3), }; - v8::Handle val(holder->Call(holder, arraysize(args), args)); + v8::Local val(holder->Call(holder, arraysize(args), args)); Converter::FromV8(isolate, val, &ret); return ret; } @@ -130,8 +130,8 @@ struct V8FunctionInvoker { P3 a3) { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), ConvertToV8(isolate, a3), @@ -147,14 +147,14 @@ struct V8FunctionInvoker { R ret; Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), ConvertToV8(isolate, a3), ConvertToV8(isolate, a4), }; - v8::Handle val(holder->Call(holder, arraysize(args), args)); + v8::Local val(holder->Call(holder, arraysize(args), args)); Converter::FromV8(isolate, val, &ret); return ret; } @@ -166,8 +166,8 @@ struct V8FunctionInvoker { P3 a3, P4 a4) { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), ConvertToV8(isolate, a3), @@ -185,15 +185,15 @@ struct V8FunctionInvoker { R ret; Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), ConvertToV8(isolate, a3), ConvertToV8(isolate, a4), ConvertToV8(isolate, a5), }; - v8::Handle val(holder->Call(holder, arraysize(args), args)); + v8::Local val(holder->Call(holder, arraysize(args), args)); Converter::FromV8(isolate, val, &ret); return ret; } @@ -205,8 +205,8 @@ struct V8FunctionInvoker { P3 a3, P4 a4, P5 a5) { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), ConvertToV8(isolate, a3), @@ -225,8 +225,8 @@ struct V8FunctionInvoker { R ret; Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), ConvertToV8(isolate, a3), @@ -234,7 +234,7 @@ struct V8FunctionInvoker { ConvertToV8(isolate, a5), ConvertToV8(isolate, a6), }; - v8::Handle val(holder->Call(holder, arraysize(args), args)); + v8::Local val(holder->Call(holder, arraysize(args), args)); Converter::FromV8(isolate, val, &ret); return ret; } @@ -247,8 +247,8 @@ struct V8FunctionInvoker { P3 a3, P4 a4, P5 a5, P6 a6) { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); - v8::Handle args[] = { + v8::Local holder = function->NewHandle(); + v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), ConvertToV8(isolate, a3), @@ -264,12 +264,12 @@ struct V8FunctionInvoker { template struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, const base::Callback& val) { return CreateFunctionTemplate(isolate, val)->GetFunction(); } static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, base::Callback* out) { if (!val->IsFunction()) return false; diff --git a/native_mate/callback.h.pump b/native_mate/callback.h.pump index 9f0220ee6de..1286fd0a579 100644 --- a/native_mate/callback.h.pump +++ b/native_mate/callback.h.pump @@ -35,19 +35,19 @@ struct V8FunctionInvoker { R ret; Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); + v8::Local holder = function->NewHandle(); $if ARITY == 0 [[ - v8::Handle val(holder->Call(holder, 0, NULL)); + v8::Local val(holder->Call(holder, 0, NULL)); ]] $else [[ - v8::Handle args[] = { + v8::Local args[] = { $for ARG [[ ConvertToV8(isolate, a$(ARG)), ]] }; - v8::Handle val(holder->Call(holder, arraysize(args), args)); + v8::Local val(holder->Call(holder, arraysize(args), args)); ]] Converter::FromV8(isolate, val, &ret); @@ -60,12 +60,12 @@ struct V8FunctionInvoker { static void Go(v8::Isolate* isolate, SafeV8Function function$for ARG [[, P$(ARG) a$(ARG)]]) { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); - v8::Handle holder = function->NewHandle(); + v8::Local holder = function->NewHandle(); $if ARITY == 0 [[ holder->Call(holder, 0, NULL); ]] $else [[ - v8::Handle args[] = { + v8::Local args[] = { $for ARG [[ ConvertToV8(isolate, a$(ARG)), @@ -84,12 +84,12 @@ $for ARG [[ template struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, const base::Callback& val) { return CreateFunctionTemplate(isolate, val)->GetFunction(); } static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, base::Callback* out) { if (!val->IsFunction()) return false; diff --git a/native_mate/compat.h b/native_mate/compat.h index 021c0ca2cee..5baefb4f89f 100644 --- a/native_mate/compat.h +++ b/native_mate/compat.h @@ -69,7 +69,7 @@ #define MATE_HANDLE_SCOPE(isolate) v8::HandleScope handle_scope #define MATE_METHOD_ARGS_TYPE v8::Arguments -#define MATE_METHOD_RETURN_TYPE v8::Handle +#define MATE_METHOD_RETURN_TYPE v8::Local #define MATE_METHOD_RETURN_VALUE(value) return value #define MATE_METHOD_RETURN_UNDEFINED() return v8::Undefined() diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 14ea119e56a..98cd62bde89 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -133,7 +133,7 @@ class Constructor { MATE_PERSISTENT_RESET(constructor_); } - v8::Handle GetFunctionTemplate( + v8::Local GetFunctionTemplate( v8::Isolate* isolate, const WrappableFactoryFunction& factory) { if (constructor_.IsEmpty()) { v8::Local constructor = CreateFunctionTemplate( diff --git a/native_mate/constructor.h.pump b/native_mate/constructor.h.pump index 94a56d424a9..ec4944f4eb2 100644 --- a/native_mate/constructor.h.pump +++ b/native_mate/constructor.h.pump @@ -69,7 +69,7 @@ class Constructor { MATE_PERSISTENT_RESET(constructor_); } - v8::Handle GetFunctionTemplate( + v8::Local GetFunctionTemplate( v8::Isolate* isolate, const WrappableFactoryFunction& factory) { if (constructor_.IsEmpty()) { v8::Local constructor = CreateFunctionTemplate( diff --git a/native_mate/converter.cc b/native_mate/converter.cc index 2c9d95f9417..25ebf4cedfb 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -10,9 +10,9 @@ using v8::Boolean; using v8::External; using v8::Function; -using v8::Handle; using v8::Integer; using v8::Isolate; +using v8::Local; using v8::Number; using v8::Object; using v8::String; @@ -20,11 +20,11 @@ using v8::Value; namespace mate { -Handle Converter::ToV8(Isolate* isolate, bool val) { +Local Converter::ToV8(Isolate* isolate, bool val) { return MATE_BOOLEAN_NEW(isolate, val); } -bool Converter::FromV8(Isolate* isolate, Handle val, bool* out) { +bool Converter::FromV8(Isolate* isolate, Local val, bool* out) { if (!val->IsBoolean()) return false; *out = val->BooleanValue(); @@ -32,12 +32,12 @@ bool Converter::FromV8(Isolate* isolate, Handle val, bool* out) { } #if !defined(OS_LINUX) -Handle Converter::ToV8(Isolate* isolate, +Local Converter::ToV8(Isolate* isolate, unsigned long val) { return MATE_INTEGER_NEW(isolate, val); } -bool Converter::FromV8(Isolate* isolate, Handle val, +bool Converter::FromV8(Isolate* isolate, Local val, unsigned long* out) { if (!val->IsNumber()) return false; @@ -46,11 +46,11 @@ bool Converter::FromV8(Isolate* isolate, Handle val, } #endif -Handle Converter::ToV8(Isolate* isolate, int32_t val) { +Local Converter::ToV8(Isolate* isolate, int32_t val) { return MATE_INTEGER_NEW(isolate, val); } -bool Converter::FromV8(Isolate* isolate, Handle val, +bool Converter::FromV8(Isolate* isolate, Local val, int32_t* out) { if (!val->IsInt32()) return false; @@ -58,11 +58,11 @@ bool Converter::FromV8(Isolate* isolate, Handle val, return true; } -Handle Converter::ToV8(Isolate* isolate, uint32_t val) { +Local Converter::ToV8(Isolate* isolate, uint32_t val) { return MATE_INTEGER_NEW_UNSIGNED(isolate, val); } -bool Converter::FromV8(Isolate* isolate, Handle val, +bool Converter::FromV8(Isolate* isolate, Local val, uint32_t* out) { if (!val->IsUint32()) return false; @@ -70,11 +70,11 @@ bool Converter::FromV8(Isolate* isolate, Handle val, return true; } -Handle Converter::ToV8(Isolate* isolate, int64_t val) { +Local Converter::ToV8(Isolate* isolate, int64_t val) { return MATE_NUMBER_NEW(isolate, static_cast(val)); } -bool Converter::FromV8(Isolate* isolate, Handle val, +bool Converter::FromV8(Isolate* isolate, Local val, int64_t* out) { if (!val->IsNumber()) return false; @@ -84,11 +84,11 @@ bool Converter::FromV8(Isolate* isolate, Handle val, return true; } -Handle Converter::ToV8(Isolate* isolate, uint64_t val) { +Local Converter::ToV8(Isolate* isolate, uint64_t val) { return MATE_NUMBER_NEW(isolate, static_cast(val)); } -bool Converter::FromV8(Isolate* isolate, Handle val, +bool Converter::FromV8(Isolate* isolate, Local val, uint64_t* out) { if (!val->IsNumber()) return false; @@ -96,11 +96,11 @@ bool Converter::FromV8(Isolate* isolate, Handle val, return true; } -Handle Converter::ToV8(Isolate* isolate, float val) { +Local Converter::ToV8(Isolate* isolate, float val) { return MATE_NUMBER_NEW(isolate, val); } -bool Converter::FromV8(Isolate* isolate, Handle val, +bool Converter::FromV8(Isolate* isolate, Local val, float* out) { if (!val->IsNumber()) return false; @@ -108,11 +108,11 @@ bool Converter::FromV8(Isolate* isolate, Handle val, return true; } -Handle Converter::ToV8(Isolate* isolate, double val) { +Local Converter::ToV8(Isolate* isolate, double val) { return MATE_NUMBER_NEW(isolate, val); } -bool Converter::FromV8(Isolate* isolate, Handle val, +bool Converter::FromV8(Isolate* isolate, Local val, double* out) { if (!val->IsNumber()) return false; @@ -120,100 +120,100 @@ bool Converter::FromV8(Isolate* isolate, Handle val, return true; } -Handle Converter::ToV8( +Local Converter::ToV8( Isolate* isolate, const char* val) { return MATE_STRING_NEW_FROM_UTF8(isolate, val, -1); } -Handle Converter::ToV8( +Local Converter::ToV8( Isolate* isolate, const base::StringPiece& val) { return MATE_STRING_NEW_FROM_UTF8(isolate, val.data(), static_cast(val.length())); } -Handle Converter::ToV8(Isolate* isolate, +Local Converter::ToV8(Isolate* isolate, const std::string& val) { return Converter::ToV8(isolate, val); } -bool Converter::FromV8(Isolate* isolate, Handle val, +bool Converter::FromV8(Isolate* isolate, Local val, std::string* out) { if (!val->IsString()) return false; - Handle str = Handle::Cast(val); + Local str = Local::Cast(val); int length = str->Utf8Length(); out->resize(length); str->WriteUtf8(&(*out)[0], length, NULL, String::NO_NULL_TERMINATION); return true; } -bool Converter >::FromV8(Isolate* isolate, Handle val, - Handle* out) { +bool Converter >::FromV8(Isolate* isolate, Local val, + Local* out) { if (!val->IsFunction()) return false; - *out = Handle::Cast(val); + *out = Local::Cast(val); return true; } -Handle Converter >::ToV8(Isolate* isolate, - Handle val) { +Local Converter >::ToV8(Isolate* isolate, + Local val) { return val; } -bool Converter >::FromV8(Isolate* isolate, Handle val, - Handle* out) { +bool Converter >::FromV8(Isolate* isolate, Local val, + Local* out) { if (!val->IsObject()) return false; - *out = Handle::Cast(val); + *out = Local::Cast(val); return true; } -Handle Converter >::ToV8(Isolate* isolate, - Handle val) { +Local Converter >::ToV8(Isolate* isolate, + Local val) { return val; } -bool Converter >::FromV8(Isolate* isolate, Handle val, - Handle* out) { +bool Converter >::FromV8(Isolate* isolate, Local val, + Local* out) { if (!val->IsString()) return false; - *out = Handle::Cast(val); + *out = Local::Cast(val); return true; } -Handle Converter >::ToV8(Isolate* isolate, - Handle val) { +Local Converter >::ToV8(Isolate* isolate, + Local val) { return val; } -bool Converter >::FromV8(Isolate* isolate, - v8::Handle val, - Handle* out) { +bool Converter >::FromV8(Isolate* isolate, + v8::Local val, + Local* out) { if (!val->IsExternal()) return false; - *out = Handle::Cast(val); + *out = Local::Cast(val); return true; } -Handle Converter >::ToV8(Isolate* isolate, - Handle val) { +Local Converter >::ToV8(Isolate* isolate, + Local val) { return val; } -bool Converter >::FromV8(Isolate* isolate, Handle val, - Handle* out) { +bool Converter >::FromV8(Isolate* isolate, Local val, + Local* out) { *out = val; return true; } -v8::Handle StringToSymbol(v8::Isolate* isolate, +v8::Local StringToSymbol(v8::Isolate* isolate, const base::StringPiece& val) { return MATE_STRING_NEW_SYMBOL(isolate, val.data(), static_cast(val.length())); } -std::string V8ToString(v8::Handle value) { +std::string V8ToString(v8::Local value) { if (value.IsEmpty()) return std::string(); std::string result; diff --git a/native_mate/converter.h b/native_mate/converter.h index 2093ce0ea45..050b1c0d1c2 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -20,156 +20,156 @@ struct Converter {}; template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, void* val) { + static v8::Local ToV8(v8::Isolate* isolate, void* val) { return MATE_UNDEFINED(isolate); } }; template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, bool val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, bool* out); }; #if !defined(OS_LINUX) template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, unsigned long val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, unsigned long* out); }; #endif template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, int32_t val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, int32_t* out); }; template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, uint32_t val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, uint32_t* out); }; template<> struct Converter { // Warning: JavaScript cannot represent 64 integers precisely. - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, int64_t val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, int64_t* out); }; template<> struct Converter { // Warning: JavaScript cannot represent 64 integers precisely. - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, uint64_t val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, uint64_t* out); }; template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, float val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, float* out); }; template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, double val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, double* out); }; template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, const char* val); + static v8::Local ToV8(v8::Isolate* isolate, const char* val); }; template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, const base::StringPiece& val); // No conversion out is possible because StringPiece does not contain storage. }; template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, const std::string& val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, std::string* out); }; template<> -struct Converter > { +struct Converter > { static bool FromV8(v8::Isolate* isolate, - v8::Handle val, - v8::Handle* out); + v8::Local val, + v8::Local* out); }; template<> -struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, - v8::Handle val); +struct Converter > { + static v8::Local ToV8(v8::Isolate* isolate, + v8::Local val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, - v8::Handle* out); + v8::Local val, + v8::Local* out); }; template<> -struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, - v8::Handle val); +struct Converter > { + static v8::Local ToV8(v8::Isolate* isolate, + v8::Local val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, - v8::Handle* out); + v8::Local val, + v8::Local* out); }; template<> -struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, - v8::Handle val); +struct Converter > { + static v8::Local ToV8(v8::Isolate* isolate, + v8::Local val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, - v8::Handle* out); + v8::Local val, + v8::Local* out); }; template<> -struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, - v8::Handle val); +struct Converter > { + static v8::Local ToV8(v8::Isolate* isolate, + v8::Local val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, - v8::Handle* out); + v8::Local val, + v8::Local* out); }; template struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, const std::vector& val) { - v8::Handle result( + v8::Local result( MATE_ARRAY_NEW(isolate, static_cast(val.size()))); for (size_t i = 0; i < val.size(); ++i) { result->Set(static_cast(i), Converter::ToV8(isolate, val[i])); @@ -178,13 +178,13 @@ struct Converter > { } static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, std::vector* out) { if (!val->IsArray()) return false; std::vector result; - v8::Handle array(v8::Handle::Cast(val)); + v8::Local array(v8::Local::Cast(val)); uint32_t length = array->Length(); for (uint32_t i = 0; i < length; ++i) { T item; @@ -200,9 +200,9 @@ struct Converter > { template struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, const std::set& val) { - v8::Handle result( + v8::Local result( MATE_ARRAY_NEW(isolate, static_cast(val.size()))); typename std::set::const_iterator it; int i; @@ -212,13 +212,13 @@ struct Converter > { } static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, std::set* out) { if (!val->IsArray()) return false; std::set result; - v8::Handle array(v8::Handle::Cast(val)); + v8::Local array(v8::Local::Cast(val)); uint32_t length = array->Length(); for (uint32_t i = 0; i < length; ++i) { T item; @@ -234,32 +234,32 @@ struct Converter > { // Convenience functions that deduce T. template -v8::Handle ConvertToV8(v8::Isolate* isolate, +v8::Local ConvertToV8(v8::Isolate* isolate, const T& input) { return Converter::ToV8(isolate, input); } -inline v8::Handle ConvertToV8(v8::Isolate* isolate, +inline v8::Local ConvertToV8(v8::Isolate* isolate, const char* input) { return Converter::ToV8(isolate, input); } -inline v8::Handle StringToV8( +inline v8::Local StringToV8( v8::Isolate* isolate, const base::StringPiece& input) { return ConvertToV8(isolate, input).As(); } -v8::Handle StringToSymbol(v8::Isolate* isolate, +v8::Local StringToSymbol(v8::Isolate* isolate, const base::StringPiece& input); template -bool ConvertFromV8(v8::Isolate* isolate, v8::Handle input, +bool ConvertFromV8(v8::Isolate* isolate, v8::Local input, T* result) { return Converter::FromV8(isolate, input, result); } -std::string V8ToString(v8::Handle value); +std::string V8ToString(v8::Local value); } // namespace mate diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc index 6c154eaad45..7ab702088fb 100644 --- a/native_mate/dictionary.cc +++ b/native_mate/dictionary.cc @@ -11,7 +11,7 @@ Dictionary::Dictionary() } Dictionary::Dictionary(v8::Isolate* isolate, - v8::Handle object) + v8::Local object) : isolate_(isolate), object_(object) { } @@ -19,21 +19,21 @@ Dictionary::Dictionary(v8::Isolate* isolate, Dictionary::~Dictionary() { } -v8::Handle Dictionary::GetHandle() const { +v8::Local Dictionary::GetHandle() const { return object_; } -v8::Handle Converter::ToV8(v8::Isolate* isolate, +v8::Local Converter::ToV8(v8::Isolate* isolate, Dictionary val) { return val.GetHandle(); } bool Converter::FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, Dictionary* out) { if (!val->IsObject()) return false; - *out = Dictionary(isolate, v8::Handle::Cast(val)); + *out = Dictionary(isolate, v8::Local::Cast(val)); return true; } diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index fab215e2126..9279d490e1e 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -25,12 +25,12 @@ namespace mate { class Dictionary { public: Dictionary(); - Dictionary(v8::Isolate* isolate, v8::Handle object); + Dictionary(v8::Isolate* isolate, v8::Local object); ~Dictionary(); template bool Get(const base::StringPiece& key, T* out) const { - v8::Handle val = GetHandle()->Get(StringToV8(isolate_, key)); + v8::Local val = GetHandle()->Get(StringToV8(isolate_, key)); return ConvertFromV8(isolate_, val, out); } @@ -49,7 +49,7 @@ class Dictionary { bool IsEmpty() const { return isolate() == NULL; } - virtual v8::Handle GetHandle() const; + virtual v8::Local GetHandle() const; v8::Isolate* isolate() const { return isolate_; } @@ -57,15 +57,15 @@ class Dictionary { v8::Isolate* isolate_; private: - v8::Handle object_; + v8::Local object_; }; template<> struct Converter { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, Dictionary val); static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, Dictionary* out); }; diff --git a/native_mate/function_template.cc b/native_mate/function_template.cc index c8b71c49266..3d404369719 100644 --- a/native_mate/function_template.cc +++ b/native_mate/function_template.cc @@ -17,7 +17,7 @@ CallbackHolderBase::~CallbackHolderBase() { DCHECK(v8_ref_.IsEmpty()); } -v8::Handle CallbackHolderBase::GetHandle(v8::Isolate* isolate) { +v8::Local CallbackHolderBase::GetHandle(v8::Isolate* isolate) { return MATE_PERSISTENT_TO_LOCAL(v8::External, isolate, v8_ref_); } diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 14ed170080b..cb3c90d72d7 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -48,7 +48,7 @@ struct CallbackParamTraits { // among every CallbackHolder instance. class CallbackHolderBase { public: - v8::Handle GetHandle(v8::Isolate* isolate); + v8::Local GetHandle(v8::Isolate* isolate); protected: explicit CallbackHolderBase(v8::Isolate* isolate); @@ -333,7 +333,7 @@ template struct Dispatcher { static MATE_METHOD(DispatchToCallback) { Arguments args(info); - v8::Handle v8_holder; + v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); @@ -349,7 +349,7 @@ template struct Dispatcher { static MATE_METHOD(DispatchToCallback) { Arguments args(info); - v8::Handle v8_holder; + v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); @@ -371,7 +371,7 @@ template struct Dispatcher { static MATE_METHOD(DispatchToCallback) { Arguments args(info); - v8::Handle v8_holder; + v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); @@ -395,7 +395,7 @@ template struct Dispatcher { static MATE_METHOD(DispatchToCallback) { Arguments args(info); - v8::Handle v8_holder; + v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); @@ -421,7 +421,7 @@ template struct Dispatcher { static MATE_METHOD(DispatchToCallback) { Arguments args(info); - v8::Handle v8_holder; + v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); @@ -451,7 +451,7 @@ template { static MATE_METHOD(DispatchToCallback) { Arguments args(info); - v8::Handle v8_holder; + v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); @@ -483,7 +483,7 @@ template { static MATE_METHOD(DispatchToCallback) { Arguments args(info); - v8::Handle v8_holder; + v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); @@ -517,7 +517,7 @@ template { static MATE_METHOD(DispatchToCallback) { Arguments args(info); - v8::Handle v8_holder; + v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); @@ -567,7 +567,7 @@ v8::Local CreateFunctionTemplate( isolate, #endif &internal::Dispatcher::DispatchToCallback, - ConvertToV8 >(isolate, + ConvertToV8 >(isolate, holder->GetHandle(isolate))); } diff --git a/native_mate/function_template.h.pump b/native_mate/function_template.h.pump index c3009f2a828..e01bef42a17 100644 --- a/native_mate/function_template.h.pump +++ b/native_mate/function_template.h.pump @@ -51,7 +51,7 @@ struct CallbackParamTraits { // among every CallbackHolder instance. class CallbackHolderBase { public: - v8::Handle GetHandle(v8::Isolate* isolate); + v8::Local GetHandle(v8::Isolate* isolate); protected: explicit CallbackHolderBase(v8::Isolate* isolate); @@ -169,7 +169,7 @@ template struct Dispatcher { static MATE_METHOD(DispatchToCallback) { Arguments args(info); - v8::Handle v8_holder; + v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); @@ -216,7 +216,7 @@ v8::Local CreateFunctionTemplate( isolate, #endif &internal::Dispatcher::DispatchToCallback, - ConvertToV8 >(isolate, + ConvertToV8 >(isolate, holder->GetHandle(isolate))); } diff --git a/native_mate/handle.h b/native_mate/handle.h index f81b9d12509..15e0bb5bb8f 100644 --- a/native_mate/handle.h +++ b/native_mate/handle.h @@ -18,7 +18,7 @@ class Handle { public: Handle() : object_(NULL) {} - Handle(v8::Handle wrapper, T* object) + Handle(v8::Local wrapper, T* object) : wrapper_(wrapper), object_(object) { } @@ -31,21 +31,21 @@ class Handle { } T* operator->() const { return object_; } - v8::Handle ToV8() const { return wrapper_; } + v8::Local ToV8() const { return wrapper_; } T* get() const { return object_; } private: - v8::Handle wrapper_; + v8::Local wrapper_; T* object_; }; template struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, const mate::Handle& val) { return val.ToV8(); } - static bool FromV8(v8::Isolate* isolate, v8::Handle val, + static bool FromV8(v8::Isolate* isolate, v8::Local val, mate::Handle* out) { T* object = NULL; if (!Converter::FromV8(isolate, val, &object)) { diff --git a/native_mate/object_template_builder.cc b/native_mate/object_template_builder.cc index 7c40b582679..a2011f0c76e 100644 --- a/native_mate/object_template_builder.cc +++ b/native_mate/object_template_builder.cc @@ -17,14 +17,14 @@ ObjectTemplateBuilder::~ObjectTemplateBuilder() { } ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl( - const base::StringPiece& name, v8::Handle val) { + const base::StringPiece& name, v8::Local val) { template_->Set(StringToSymbol(isolate_, name), val); return *this; } ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl( - const base::StringPiece& name, v8::Handle getter, - v8::Handle setter) { + const base::StringPiece& name, v8::Local getter, + v8::Local setter) { #if NODE_VERSION_AT_LEAST(0, 11, 0) template_->SetAccessorProperty(StringToSymbol(isolate_, name), getter, setter); diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index cd69c47925a..d37f009060a 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -22,7 +22,7 @@ namespace { // because of base::Bind(). template struct CallbackTraits { - static v8::Handle CreateTemplate(v8::Isolate* isolate, + static v8::Local CreateTemplate(v8::Isolate* isolate, T callback) { return CreateFunctionTemplate(isolate, base::Bind(callback)); } @@ -31,7 +31,7 @@ struct CallbackTraits { // Specialization for base::Callback. template struct CallbackTraits > { - static v8::Handle CreateTemplate( + static v8::Local CreateTemplate( v8::Isolate* isolate, const base::Callback& callback) { return CreateFunctionTemplate(isolate, callback); } @@ -44,7 +44,7 @@ struct CallbackTraits > { template struct CallbackTraits::value>::type> { - static v8::Handle CreateTemplate(v8::Isolate* isolate, + static v8::Local CreateTemplate(v8::Isolate* isolate, T callback) { return CreateFunctionTemplate(isolate, base::Bind(callback), HolderIsFirstArgument); @@ -54,9 +54,9 @@ struct CallbackTraits -struct CallbackTraits > { - static v8::Handle CreateTemplate( - v8::Handle templ) { +struct CallbackTraits > { + static v8::Local CreateTemplate( + v8::Local templ) { return templ; } }; @@ -109,10 +109,10 @@ class ObjectTemplateBuilder { private: ObjectTemplateBuilder& SetImpl(const base::StringPiece& name, - v8::Handle val); + v8::Local val); ObjectTemplateBuilder& SetPropertyImpl( - const base::StringPiece& name, v8::Handle getter, - v8::Handle setter); + const base::StringPiece& name, v8::Local getter, + v8::Local setter); v8::Isolate* isolate_; diff --git a/native_mate/persistent_dictionary.cc b/native_mate/persistent_dictionary.cc index 05c83e5aa8d..fd68cdced27 100644 --- a/native_mate/persistent_dictionary.cc +++ b/native_mate/persistent_dictionary.cc @@ -10,7 +10,7 @@ PersistentDictionary::PersistentDictionary() { } PersistentDictionary::PersistentDictionary(v8::Isolate* isolate, - v8::Handle object) + v8::Local object) : handle_(new RefCountedPersistent(isolate, object)) { isolate_ = isolate; } @@ -18,16 +18,16 @@ PersistentDictionary::PersistentDictionary(v8::Isolate* isolate, PersistentDictionary::~PersistentDictionary() { } -v8::Handle PersistentDictionary::GetHandle() const { +v8::Local PersistentDictionary::GetHandle() const { return handle_->NewHandle(); } bool Converter::FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, PersistentDictionary* out) { if (!val->IsObject()) return false; - *out = PersistentDictionary(isolate, v8::Handle::Cast(val)); + *out = PersistentDictionary(isolate, v8::Local::Cast(val)); return true; } diff --git a/native_mate/persistent_dictionary.h b/native_mate/persistent_dictionary.h index ae86c6b2414..26c8998632b 100644 --- a/native_mate/persistent_dictionary.h +++ b/native_mate/persistent_dictionary.h @@ -15,10 +15,10 @@ namespace mate { class PersistentDictionary : public Dictionary { public: PersistentDictionary(); - PersistentDictionary(v8::Isolate* isolate, v8::Handle object); + PersistentDictionary(v8::Isolate* isolate, v8::Local object); virtual ~PersistentDictionary(); - v8::Handle GetHandle() const override; + v8::Local GetHandle() const override; private: scoped_refptr > handle_; @@ -27,7 +27,7 @@ class PersistentDictionary : public Dictionary { template<> struct Converter { static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, PersistentDictionary* out); }; diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index bbc91b9c5e7..c7c53554619 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -18,16 +18,16 @@ class ScopedPersistent { public: ScopedPersistent() : isolate_(v8::Isolate::GetCurrent()) {} - ScopedPersistent(v8::Isolate* isolate, v8::Handle handle) + ScopedPersistent(v8::Isolate* isolate, v8::Local handle) : isolate_(isolate) { - reset(isolate, v8::Handle::Cast(handle)); + reset(isolate, v8::Local::Cast(handle)); } ~ScopedPersistent() { reset(); } - void reset(v8::Isolate* isolate, v8::Handle handle) { + void reset(v8::Isolate* isolate, v8::Local handle) { if (!handle.IsEmpty()) { isolate_ = isolate; MATE_PERSISTENT_ASSIGN(T, isolate, handle_, handle); @@ -44,11 +44,11 @@ class ScopedPersistent { return handle_.IsEmpty(); } - v8::Handle NewHandle() const { + v8::Local NewHandle() const { return NewHandle(isolate_); } - v8::Handle NewHandle(v8::Isolate* isolate) const { + v8::Local NewHandle(v8::Isolate* isolate) const { if (handle_.IsEmpty()) return v8::Local(); return MATE_PERSISTENT_TO_LOCAL(T, isolate, handle_); @@ -74,7 +74,7 @@ class RefCountedPersistent : public ScopedPersistent, public: RefCountedPersistent() {} - RefCountedPersistent(v8::Isolate* isolate, v8::Handle handle) + RefCountedPersistent(v8::Isolate* isolate, v8::Local handle) : ScopedPersistent(isolate, handle) { } @@ -89,16 +89,16 @@ class RefCountedPersistent : public ScopedPersistent, template struct Converter > { - static v8::Handle ToV8(v8::Isolate* isolate, + static v8::Local ToV8(v8::Isolate* isolate, const ScopedPersistent& val) { return val.NewHandle(isolate); } static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + v8::Local val, ScopedPersistent* out) { - v8::Handle converted; - if (!Converter >::FromV8(isolate, val, &converted)) + v8::Local converted; + if (!Converter >::FromV8(isolate, val, &converted)) return false; out->reset(isolate, converted); diff --git a/native_mate/try_catch.cc b/native_mate/try_catch.cc index c3efd3cddd4..c7a9c00ad41 100644 --- a/native_mate/try_catch.cc +++ b/native_mate/try_catch.cc @@ -26,17 +26,17 @@ std::string TryCatch::GetStackTrace() { } std::stringstream ss; - v8::Handle message = try_catch_.Message(); + v8::Local message = try_catch_.Message(); ss << V8ToString(message->Get()) << std::endl << V8ToString(message->GetSourceLine()) << std::endl; - v8::Handle trace = message->GetStackTrace(); + v8::Local trace = message->GetStackTrace(); if (trace.IsEmpty()) return ss.str(); int len = trace->GetFrameCount(); for (int i = 0; i < len; ++i) { - v8::Handle frame = trace->GetFrame(i); + v8::Local frame = trace->GetFrame(i); ss << V8ToString(frame->GetScriptName()) << ":" << frame->GetLineNumber() << ":" << frame->GetColumn() << ": " diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 070c3c59d92..274c9c30df3 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -17,7 +17,7 @@ Wrappable::~Wrappable() { MATE_PERSISTENT_RESET(wrapper_); } -void Wrappable::Wrap(v8::Isolate* isolate, v8::Handle wrapper) { +void Wrappable::Wrap(v8::Isolate* isolate, v8::Local wrapper) { if (!wrapper_.IsEmpty()) return; @@ -26,7 +26,7 @@ void Wrappable::Wrap(v8::Isolate* isolate, v8::Handle wrapper) { MATE_PERSISTENT_SET_WEAK(wrapper_, this, WeakCallback); // Call object._init if we have one. - v8::Handle init; + v8::Local init; if (Dictionary(isolate, wrapper).Get("_init", &init)) init->Call(wrapper, 0, NULL); @@ -35,7 +35,7 @@ void Wrappable::Wrap(v8::Isolate* isolate, v8::Handle wrapper) { // static void Wrappable::BuildPrototype(v8::Isolate* isolate, - v8::Handle prototype) { + v8::Local prototype) { } ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( @@ -49,7 +49,7 @@ MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { delete self; } -v8::Handle Wrappable::GetWrapper(v8::Isolate* isolate) { +v8::Local Wrappable::GetWrapper(v8::Isolate* isolate) { if (!wrapper_.IsEmpty()) return MATE_PERSISTENT_TO_LOCAL(v8::Object, isolate, wrapper_); @@ -57,17 +57,17 @@ v8::Handle Wrappable::GetWrapper(v8::Isolate* isolate) { GetObjectTemplateBuilder(isolate).Build(); CHECK(!templ.IsEmpty()); CHECK_EQ(1, templ->InternalFieldCount()); - v8::Handle wrapper = templ->NewInstance(); + v8::Local wrapper = templ->NewInstance(); Wrap(isolate, wrapper); return wrapper; } namespace internal { -void* FromV8Impl(v8::Isolate* isolate, v8::Handle val) { +void* FromV8Impl(v8::Isolate* isolate, v8::Local val) { if (!val->IsObject()) return NULL; - v8::Handle obj = v8::Handle::Cast(val); + v8::Local obj = v8::Local::Cast(val); if (obj->InternalFieldCount() != 1) return NULL; return MATE_GET_INTERNAL_FIELD_POINTER(obj, 0); diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index f93bf6b3b24..b8708f3b3a0 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -13,7 +13,7 @@ namespace mate { namespace internal { -void* FromV8Impl(v8::Isolate* isolate, v8::Handle val); +void* FromV8Impl(v8::Isolate* isolate, v8::Local val); } // namespace internal @@ -52,15 +52,15 @@ class Wrappable { // If the type is created via the Constructor, then the GetWrapper would // return the constructed object, otherwise it would try to create a new // object constructed by GetObjectTemplateBuilder. - v8::Handle GetWrapper(v8::Isolate* isolate); + v8::Local GetWrapper(v8::Isolate* isolate); // Bind the C++ class to the JS wrapper. - void Wrap(v8::Isolate* isolate, v8::Handle wrapper); + void Wrap(v8::Isolate* isolate, v8::Local wrapper); // The user should define T::BuildPrototype if they want to use Constructor // to build a constructor function for this type. static void BuildPrototype(v8::Isolate* isolate, - v8::Handle prototype); + v8::Local prototype); protected: Wrappable(); @@ -84,11 +84,11 @@ class Wrappable { template struct Converter::value>::type> { - static v8::Handle ToV8(v8::Isolate* isolate, T* val) { + static v8::Local ToV8(v8::Isolate* isolate, T* val) { return val->GetWrapper(isolate); } - static bool FromV8(v8::Isolate* isolate, v8::Handle val, T** out) { + static bool FromV8(v8::Isolate* isolate, v8::Local val, T** out) { *out = static_cast(static_cast( internal::FromV8Impl(isolate, val))); return *out != NULL; From 1696237a3f444f0e33a8947749b4d70f6feb511b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 22 May 2015 21:23:16 +0800 Subject: [PATCH 055/129] Pass Handle to upper HandleScope when returning a V8 Handle --- native_mate/callback.h | 117 ++++++++++++++++++++++++++++++++++++ native_mate/callback.h.pump | 23 +++++++ 2 files changed, 140 insertions(+) diff --git a/native_mate/callback.h b/native_mate/callback.h index 28e572f0e78..310964196ff 100644 --- a/native_mate/callback.h +++ b/native_mate/callback.h @@ -22,6 +22,17 @@ typedef scoped_refptr > SafeV8Function; template struct V8FunctionInvoker; +template +struct V8FunctionInvoker()> { + static v8::Local Go(v8::Isolate* isolate, SafeV8Function function) { + Locker locker(isolate); + v8::EscapableHandleScope handle_scope(isolate); + v8::Local holder = function->NewHandle(); + v8::Local val(holder->Call(holder, 0, NULL)); + return handle_scope.Escape(val); + } +}; + template struct V8FunctionInvoker { static R Go(v8::Isolate* isolate, SafeV8Function function) { @@ -45,6 +56,20 @@ struct V8FunctionInvoker { } }; +template +struct V8FunctionInvoker(P1)> { + static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) { + Locker locker(isolate); + v8::EscapableHandleScope handle_scope(isolate); + v8::Local holder = function->NewHandle(); + v8::Local args[] = { + ConvertToV8(isolate, a1), + }; + v8::Local val(holder->Call(holder, arraysize(args), args)); + return handle_scope.Escape(val); + } +}; + template struct V8FunctionInvoker { static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) { @@ -74,6 +99,22 @@ struct V8FunctionInvoker { } }; +template +struct V8FunctionInvoker(P1, P2)> { + static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, + P2 a2) { + Locker locker(isolate); + v8::EscapableHandleScope handle_scope(isolate); + v8::Local holder = function->NewHandle(); + v8::Local args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + }; + v8::Local val(holder->Call(holder, arraysize(args), args)); + return handle_scope.Escape(val); + } +}; + template struct V8FunctionInvoker { static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2) { @@ -105,6 +146,23 @@ struct V8FunctionInvoker { } }; +template +struct V8FunctionInvoker(P1, P2, P3)> { + static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, + P2 a2, P3 a3) { + Locker locker(isolate); + v8::EscapableHandleScope handle_scope(isolate); + v8::Local holder = function->NewHandle(); + v8::Local args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + }; + v8::Local val(holder->Call(holder, arraysize(args), args)); + return handle_scope.Escape(val); + } +}; + template struct V8FunctionInvoker { static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, @@ -140,6 +198,24 @@ struct V8FunctionInvoker { } }; +template +struct V8FunctionInvoker(P1, P2, P3, P4)> { + static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, + P2 a2, P3 a3, P4 a4) { + Locker locker(isolate); + v8::EscapableHandleScope handle_scope(isolate); + v8::Local holder = function->NewHandle(); + v8::Local args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + ConvertToV8(isolate, a4), + }; + v8::Local val(holder->Call(holder, arraysize(args), args)); + return handle_scope.Escape(val); + } +}; + template struct V8FunctionInvoker { static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, @@ -177,6 +253,26 @@ struct V8FunctionInvoker { } }; +template +struct V8FunctionInvoker(P1, P2, P3, P4, P5)> { + static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, + P2 a2, P3 a3, P4 a4, P5 a5) { + Locker locker(isolate); + v8::EscapableHandleScope handle_scope(isolate); + v8::Local holder = function->NewHandle(); + v8::Local args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + ConvertToV8(isolate, a4), + ConvertToV8(isolate, a5), + }; + v8::Local val(holder->Call(holder, arraysize(args), args)); + return handle_scope.Escape(val); + } +}; + template struct V8FunctionInvoker { @@ -217,6 +313,27 @@ struct V8FunctionInvoker { } }; +template +struct V8FunctionInvoker(P1, P2, P3, P4, P5, P6)> { + static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, + P2 a2, P3 a3, P4 a4, P5 a5, P6 a6) { + Locker locker(isolate); + v8::EscapableHandleScope handle_scope(isolate); + v8::Local holder = function->NewHandle(); + v8::Local args[] = { + ConvertToV8(isolate, a1), + ConvertToV8(isolate, a2), + ConvertToV8(isolate, a3), + ConvertToV8(isolate, a4), + ConvertToV8(isolate, a5), + ConvertToV8(isolate, a6), + }; + v8::Local val(holder->Call(holder, arraysize(args), args)); + return handle_scope.Escape(val); + } +}; + template struct V8FunctionInvoker { diff --git a/native_mate/callback.h.pump b/native_mate/callback.h.pump index 1286fd0a579..67539138556 100644 --- a/native_mate/callback.h.pump +++ b/native_mate/callback.h.pump @@ -29,6 +29,29 @@ $range ARITY 0..MAX_ARITY $for ARITY [[ $range ARG 1..ARITY +template +struct V8FunctionInvoker($for ARG , [[P$(ARG)]])> { + static v8::Local Go(v8::Isolate* isolate, SafeV8Function function$for ARG [[, P$(ARG) a$(ARG)]]) { + Locker locker(isolate); + v8::EscapableHandleScope handle_scope(isolate); + v8::Local holder = function->NewHandle(); + +$if ARITY == 0 [[ + v8::Local val(holder->Call(holder, 0, NULL)); +]] $else [[ + v8::Local args[] = { +$for ARG [[ + + ConvertToV8(isolate, a$(ARG)), +]] + + }; + v8::Local val(holder->Call(holder, arraysize(args), args)); +]] + return handle_scope.Escape(val); + } +}; + template struct V8FunctionInvoker { static R Go(v8::Isolate* isolate, SafeV8Function function$for ARG [[, P$(ARG) a$(ARG)]]) { From ad207eeabb0185f74c017e70ca3411d522627ff0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 29 May 2015 13:41:59 +0800 Subject: [PATCH 056/129] Enter context before calling callback --- native_mate/callback.h | 42 +++++++++++++++++++++++++++++++++++++ native_mate/callback.h.pump | 6 ++++++ 2 files changed, 48 insertions(+) diff --git a/native_mate/callback.h b/native_mate/callback.h index 310964196ff..2b364005044 100644 --- a/native_mate/callback.h +++ b/native_mate/callback.h @@ -28,6 +28,8 @@ struct V8FunctionInvoker()> { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local val(holder->Call(holder, 0, NULL)); return handle_scope.Escape(val); } @@ -40,6 +42,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local val(holder->Call(holder, 0, NULL)); Converter::FromV8(isolate, val, &ret); return ret; @@ -52,6 +56,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); holder->Call(holder, 0, NULL); } }; @@ -62,6 +68,8 @@ struct V8FunctionInvoker(P1)> { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), }; @@ -77,6 +85,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), }; @@ -92,6 +102,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), }; @@ -106,6 +118,8 @@ struct V8FunctionInvoker(P1, P2)> { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -122,6 +136,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -138,6 +154,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -153,6 +171,8 @@ struct V8FunctionInvoker(P1, P2, P3)> { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -171,6 +191,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -189,6 +211,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -205,6 +229,8 @@ struct V8FunctionInvoker(P1, P2, P3, P4)> { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -224,6 +250,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -243,6 +271,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -261,6 +291,8 @@ struct V8FunctionInvoker(P1, P2, P3, P4, P5)> { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -282,6 +314,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -302,6 +336,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -321,6 +357,8 @@ struct V8FunctionInvoker(P1, P2, P3, P4, P5, P6)> { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -343,6 +381,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), @@ -365,6 +405,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); v8::Local args[] = { ConvertToV8(isolate, a1), ConvertToV8(isolate, a2), diff --git a/native_mate/callback.h.pump b/native_mate/callback.h.pump index 67539138556..4ed621dc1c6 100644 --- a/native_mate/callback.h.pump +++ b/native_mate/callback.h.pump @@ -35,6 +35,8 @@ struct V8FunctionInvoker($for ARG , [[P$(ARG)]])> { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); $if ARITY == 0 [[ v8::Local val(holder->Call(holder, 0, NULL)); @@ -59,6 +61,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); $if ARITY == 0 [[ v8::Local val(holder->Call(holder, 0, NULL)); @@ -84,6 +88,8 @@ struct V8FunctionInvoker { Locker locker(isolate); MATE_HANDLE_SCOPE(isolate); v8::Local holder = function->NewHandle(); + v8::Local context = holder->CreationContext(); + v8::Context::Scope context_scope(context); $if ARITY == 0 [[ holder->Call(holder, 0, NULL); From f310222ce1729cdd59af91da9c57cb21e03eb3ed Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 10 Jun 2015 11:14:42 +0800 Subject: [PATCH 057/129] Allow converting Array --- native_mate/converter.cc | 15 +++++++++++++++ native_mate/converter.h | 9 +++++++++ 2 files changed, 24 insertions(+) diff --git a/native_mate/converter.cc b/native_mate/converter.cc index 25ebf4cedfb..6f9b8f7700b 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -7,6 +7,7 @@ #include "native_mate/compat.h" #include "v8/include/v8.h" +using v8::Array; using v8::Boolean; using v8::External; using v8::Function; @@ -195,6 +196,20 @@ bool Converter >::FromV8(Isolate* isolate, return true; } +Local Converter >::ToV8(Isolate* isolate, + Local val) { + return val; +} + +bool Converter >::FromV8(Isolate* isolate, + v8::Local val, + Local* out) { + if (!val->IsArray()) + return false; + *out = Local::Cast(val); + return true; +} + Local Converter >::ToV8(Isolate* isolate, Local val) { return val; diff --git a/native_mate/converter.h b/native_mate/converter.h index 050b1c0d1c2..0ee0c0e6e59 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -156,6 +156,15 @@ struct Converter > { v8::Local* out); }; +template<> +struct Converter > { + static v8::Local ToV8(v8::Isolate* isolate, + v8::Local val); + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + v8::Local* out); +}; + template<> struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, From 05868228088084e55f91b94f21bca0b85a051d17 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 23 Jun 2015 17:08:52 +0800 Subject: [PATCH 058/129] Remember isolate in Wrappable --- native_mate/wrappable.cc | 4 +++- native_mate/wrappable.h | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 274c9c30df3..7c00e350e88 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -10,7 +10,7 @@ namespace mate { -Wrappable::Wrappable() { +Wrappable::Wrappable() : isolate_(NULL) { } Wrappable::~Wrappable() { @@ -21,6 +21,8 @@ void Wrappable::Wrap(v8::Isolate* isolate, v8::Local wrapper) { if (!wrapper_.IsEmpty()) return; + isolate_ = isolate; + MATE_SET_INTERNAL_FIELD_POINTER(wrapper, 0, this); MATE_PERSISTENT_ASSIGN(v8::Object, isolate, wrapper_, wrapper); MATE_PERSISTENT_SET_WEAK(wrapper_, this, WeakCallback); diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index b8708f3b3a0..172606f6853 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -66,6 +66,9 @@ class Wrappable { Wrappable(); virtual ~Wrappable(); + // Returns the Isolate this object is created in. + v8::Isolate* isolate() const { return isolate_; } + virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); // Called after the "_init" method gets called in JavaScript. @@ -74,6 +77,7 @@ class Wrappable { private: static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, Wrappable); + v8::Isolate* isolate_; v8::UniquePersistent wrapper_; // Weak DISALLOW_COPY_AND_ASSIGN(Wrappable); From cad1fa50a95ca4185c435846e4868d5bd6cc94df Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 23 Jun 2015 17:13:02 +0800 Subject: [PATCH 059/129] Make isolate() public --- native_mate/wrappable.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 172606f6853..c827a859c85 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -54,6 +54,9 @@ class Wrappable { // object constructed by GetObjectTemplateBuilder. v8::Local GetWrapper(v8::Isolate* isolate); + // Returns the Isolate this object is created in. + v8::Isolate* isolate() const { return isolate_; } + // Bind the C++ class to the JS wrapper. void Wrap(v8::Isolate* isolate, v8::Local wrapper); @@ -66,9 +69,6 @@ class Wrappable { Wrappable(); virtual ~Wrappable(); - // Returns the Isolate this object is created in. - v8::Isolate* isolate() const { return isolate_; } - virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); // Called after the "_init" method gets called in JavaScript. From cc4e2fcd94b5a22e6720f0fba1c586a89640f1f6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 24 Jun 2015 16:35:37 +0800 Subject: [PATCH 060/129] Check for null when converting Wrappable --- native_mate/wrappable.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index c827a859c85..6f027f2e417 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -89,7 +89,10 @@ template struct Converter::value>::type> { static v8::Local ToV8(v8::Isolate* isolate, T* val) { - return val->GetWrapper(isolate); + if (val) + return val->GetWrapper(isolate); + else + return v8::Null(isolate); } static bool FromV8(v8::Isolate* isolate, v8::Local val, T** out) { From 7b9926807d330ec173e912f28b86f843225a3286 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 6 Jul 2015 18:16:57 +0800 Subject: [PATCH 061/129] Add IsDestroyed method for Wrappable --- native_mate/function_template.h | 64 +++++++++++++++++++++++++++- native_mate/function_template.h.pump | 27 +++++++++++- native_mate/wrappable.cc | 4 ++ native_mate/wrappable.h | 4 ++ 4 files changed, 95 insertions(+), 4 deletions(-) diff --git a/native_mate/function_template.h b/native_mate/function_template.h index cb3c90d72d7..808d4b6deea 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -12,8 +12,7 @@ #include "base/callback.h" #include "base/logging.h" #include "native_mate/arguments.h" -#include "native_mate/compat.h" -#include "native_mate/converter.h" +#include "native_mate/wrappable.h" #include "v8/include/v8.h" namespace mate { @@ -26,6 +25,25 @@ enum CreateFunctionTemplateFlags { namespace internal { +// Check if the class has been destroyed. +template +struct DestroyedChecker { + static bool IsDestroyed(Arguments* args) { + return false; + } +}; +template +struct DestroyedChecker::value>::type> { + static bool IsDestroyed(Arguments* args) { + T* object; + if (args->GetHolder(&object)) + return static_cast(object)->IsDestroyed(); + else + return false; + } +}; + template struct CallbackParamTraits { typedef T LocalType; @@ -358,6 +376,12 @@ struct Dispatcher { HolderT* holder = static_cast(holder_base); typename CallbackParamTraits::LocalType a1; + if ((holder->flags & HolderIsFirstArgument) && + DestroyedChecker::LocalType>::IsDestroyed(&args)) { + args.ThrowError("Object has been destroyed"); + MATE_METHOD_RETURN_UNDEFINED(); + } if (!GetNextArgument(&args, holder->flags, true, &a1)) { args.ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); @@ -381,6 +405,12 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; + if ((holder->flags & HolderIsFirstArgument) && + DestroyedChecker::LocalType>::IsDestroyed(&args)) { + args.ThrowError("Object has been destroyed"); + MATE_METHOD_RETURN_UNDEFINED(); + } if (!GetNextArgument(&args, holder->flags, true, &a1) || !GetNextArgument(&args, holder->flags, false, &a2)) { args.ThrowError(); @@ -406,6 +436,12 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; + if ((holder->flags & HolderIsFirstArgument) && + DestroyedChecker::LocalType>::IsDestroyed(&args)) { + args.ThrowError("Object has been destroyed"); + MATE_METHOD_RETURN_UNDEFINED(); + } if (!GetNextArgument(&args, holder->flags, true, &a1) || !GetNextArgument(&args, holder->flags, false, &a2) || !GetNextArgument(&args, holder->flags, false, &a3)) { @@ -433,6 +469,12 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; typename CallbackParamTraits::LocalType a4; + if ((holder->flags & HolderIsFirstArgument) && + DestroyedChecker::LocalType>::IsDestroyed(&args)) { + args.ThrowError("Object has been destroyed"); + MATE_METHOD_RETURN_UNDEFINED(); + } if (!GetNextArgument(&args, holder->flags, true, &a1) || !GetNextArgument(&args, holder->flags, false, &a2) || !GetNextArgument(&args, holder->flags, false, &a3) || @@ -464,6 +506,12 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a3; typename CallbackParamTraits::LocalType a4; typename CallbackParamTraits::LocalType a5; + if ((holder->flags & HolderIsFirstArgument) && + DestroyedChecker::LocalType>::IsDestroyed(&args)) { + args.ThrowError("Object has been destroyed"); + MATE_METHOD_RETURN_UNDEFINED(); + } if (!GetNextArgument(&args, holder->flags, true, &a1) || !GetNextArgument(&args, holder->flags, false, &a2) || !GetNextArgument(&args, holder->flags, false, &a3) || @@ -497,6 +545,12 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a4; typename CallbackParamTraits::LocalType a5; typename CallbackParamTraits::LocalType a6; + if ((holder->flags & HolderIsFirstArgument) && + DestroyedChecker::LocalType>::IsDestroyed(&args)) { + args.ThrowError("Object has been destroyed"); + MATE_METHOD_RETURN_UNDEFINED(); + } if (!GetNextArgument(&args, holder->flags, true, &a1) || !GetNextArgument(&args, holder->flags, false, &a2) || !GetNextArgument(&args, holder->flags, false, &a3) || @@ -532,6 +586,12 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a5; typename CallbackParamTraits::LocalType a6; typename CallbackParamTraits::LocalType a7; + if ((holder->flags & HolderIsFirstArgument) && + DestroyedChecker::LocalType>::IsDestroyed(&args)) { + args.ThrowError("Object has been destroyed"); + MATE_METHOD_RETURN_UNDEFINED(); + } if (!GetNextArgument(&args, holder->flags, true, &a1) || !GetNextArgument(&args, holder->flags, false, &a2) || !GetNextArgument(&args, holder->flags, false, &a3) || diff --git a/native_mate/function_template.h.pump b/native_mate/function_template.h.pump index e01bef42a17..34033bc9d14 100644 --- a/native_mate/function_template.h.pump +++ b/native_mate/function_template.h.pump @@ -15,8 +15,7 @@ $var MAX_ARITY = 7 #include "base/callback.h" #include "base/logging.h" #include "native_mate/arguments.h" -#include "native_mate/compat.h" -#include "native_mate/converter.h" +#include "native_mate/wrappable.h" #include "v8/include/v8.h" namespace mate { @@ -29,6 +28,25 @@ enum CreateFunctionTemplateFlags { namespace internal { +// Check if the class has been destroyed. +template +struct DestroyedChecker { + static bool IsDestroyed(Arguments* args) { + return false; + } +}; +template +struct DestroyedChecker::value>::type> { + static bool IsDestroyed(Arguments* args) { + T* object; + if (args->GetHolder(&object)) + return static_cast(object)->IsDestroyed(); + else + return false; + } +}; + template struct CallbackParamTraits { typedef T LocalType; @@ -183,6 +201,11 @@ $if ARITY != 0 [[ $for ARG [[ typename CallbackParamTraits::LocalType a$(ARG); ]] + if ((holder->flags & HolderIsFirstArgument) && + DestroyedChecker::LocalType>::IsDestroyed(&args)) { + args.ThrowError("Object has been destroyed"); + MATE_METHOD_RETURN_UNDEFINED(); + } if ($for ARG || [[!GetNextArgument(&args, holder->flags, $if ARG == 1 [[true]] $else [[false]], &a$(ARG))]]) { args.ThrowError(); diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 7c00e350e88..94ec5365668 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -64,6 +64,10 @@ v8::Local Wrappable::GetWrapper(v8::Isolate* isolate) { return wrapper; } +bool Wrappable::IsDestroyed() const { + return false; +} + namespace internal { void* FromV8Impl(v8::Isolate* isolate, v8::Local val) { diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 6f027f2e417..d55ce42cf7f 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -54,6 +54,10 @@ class Wrappable { // object constructed by GetObjectTemplateBuilder. v8::Local GetWrapper(v8::Isolate* isolate); + // Returns whether this class has been destroyed, users should override this + // method to indicate the native type's state. + virtual bool IsDestroyed() const; + // Returns the Isolate this object is created in. v8::Isolate* isolate() const { return isolate_; } From 41cd6d13c9c9be164f427864277f3cc36b69eb39 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 6 Jul 2015 21:25:55 +0800 Subject: [PATCH 062/129] Allow specify methods that can be called after object is destroyed --- native_mate/function_template.h | 8 +++++ native_mate/function_template.h.pump | 2 ++ native_mate/object_template_builder.h | 47 ++++++++++++++++++--------- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 808d4b6deea..59a999627da 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -21,6 +21,7 @@ class PerIsolateData; enum CreateFunctionTemplateFlags { HolderIsFirstArgument = 1 << 0, + SafeAfterDestroyed = 1 << 1, }; namespace internal { @@ -377,6 +378,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a1; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -406,6 +408,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -437,6 +440,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -470,6 +474,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a3; typename CallbackParamTraits::LocalType a4; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -507,6 +512,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a4; typename CallbackParamTraits::LocalType a5; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -546,6 +552,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a5; typename CallbackParamTraits::LocalType a6; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -587,6 +594,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a6; typename CallbackParamTraits::LocalType a7; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); diff --git a/native_mate/function_template.h.pump b/native_mate/function_template.h.pump index 34033bc9d14..10e64751fb1 100644 --- a/native_mate/function_template.h.pump +++ b/native_mate/function_template.h.pump @@ -24,6 +24,7 @@ class PerIsolateData; enum CreateFunctionTemplateFlags { HolderIsFirstArgument = 1 << 0, + SafeAfterDestroyed = 1 << 1, }; namespace internal { @@ -202,6 +203,7 @@ $for ARG [[ typename CallbackParamTraits::LocalType a$(ARG); ]] if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); MATE_METHOD_RETURN_UNDEFINED(); diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index d37f009060a..2f30b37b701 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -23,7 +23,8 @@ namespace { template struct CallbackTraits { static v8::Local CreateTemplate(v8::Isolate* isolate, - T callback) { + T callback, + bool = true) { return CreateFunctionTemplate(isolate, base::Bind(callback)); } }; @@ -32,7 +33,7 @@ struct CallbackTraits { template struct CallbackTraits > { static v8::Local CreateTemplate( - v8::Isolate* isolate, const base::Callback& callback) { + v8::Isolate* isolate, const base::Callback& callback, bool = true) { return CreateFunctionTemplate(isolate, callback); } }; @@ -44,10 +45,12 @@ struct CallbackTraits > { template struct CallbackTraits::value>::type> { - static v8::Local CreateTemplate(v8::Isolate* isolate, - T callback) { - return CreateFunctionTemplate(isolate, base::Bind(callback), - HolderIsFirstArgument); + static v8::Local CreateTemplate( + v8::Isolate* isolate, T callback, bool safe_after_destroyed = false) { + int flags = HolderIsFirstArgument; + if (safe_after_destroyed) + flags |= SafeAfterDestroyed; + return CreateFunctionTemplate(isolate, base::Bind(callback), flags); } }; @@ -87,22 +90,34 @@ class ObjectTemplateBuilder { // for creating raw function templates. template ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, - const T& callback) { - return SetImpl(name, CallbackTraits::CreateTemplate(isolate_, callback)); + const T& callback, + bool safe_after_destroyed = false) { + return SetImpl(name, + CallbackTraits::CreateTemplate(isolate_, + callback, + safe_after_destroyed)); } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, - const T& getter) { - return SetPropertyImpl(name, - CallbackTraits::CreateTemplate(isolate_, getter), - v8::Local()); + const T& getter, + bool safe_after_destroyed = false) { + return SetPropertyImpl( + name, + CallbackTraits::CreateTemplate(isolate_, getter, + safe_after_destroyed), + v8::Local()); } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, - const T& getter, const U& setter) { - return SetPropertyImpl(name, - CallbackTraits::CreateTemplate(isolate_, getter), - CallbackTraits::CreateTemplate(isolate_, setter)); + const T& getter, + const U& setter, + bool safe_after_destroyed = false) { + return SetPropertyImpl( + name, + CallbackTraits::CreateTemplate(isolate_, getter, + safe_after_destroyed), + CallbackTraits::CreateTemplate(isolate_, setter, + safe_after_destroyed)); } v8::Local Build(); From 656e403f0102c59428261c1eaad22912d2bbd3c5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 23 Jul 2015 14:58:03 +0800 Subject: [PATCH 063/129] Use C++11 version of CreateFunctionTemplate --- native_mate/function_template.h | 606 ++++++--------------------- native_mate/function_template.h.pump | 250 ----------- 2 files changed, 122 insertions(+), 734 deletions(-) delete mode 100644 native_mate/function_template.h.pump diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 59a999627da..0761dca58b5 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -1,7 +1,3 @@ -// This file was GENERATED by command: -// pump.py function_template.h.pump -// DO NOT EDIT BY HAND!!! - // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.chromium file. @@ -17,8 +13,6 @@ namespace mate { -class PerIsolateData; - enum CreateFunctionTemplateFlags { HolderIsFirstArgument = 1 << 0, SafeAfterDestroyed = 1 << 1, @@ -96,221 +90,6 @@ class CallbackHolder : public CallbackHolderBase { DISALLOW_COPY_AND_ASSIGN(CallbackHolder); }; - -// This set of templates invokes a base::Callback, converts the return type to a -// JavaScript value, and returns that value to script via the provided -// mate::Arguments object. -// -// In C++, you can declare the function foo(void), but you can't pass a void -// expression to foo. As a result, we must specialize the case of Callbacks that -// have the void return type. -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3, - const P4& a4, - const P5& a5, - const P6& a6, - const P7& a7) { - MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4, a5, a6, a7)); - } -}; -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3, - const P4& a4, - const P5& a5, - const P6& a6, - const P7& a7) { - callback.Run(a1, a2, a3, a4, a5, a6, a7); - MATE_METHOD_RETURN_UNDEFINED(); - } -}; - -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3, - const P4& a4, - const P5& a5, - const P6& a6) { - MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4, a5, a6)); - } -}; -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3, - const P4& a4, - const P5& a5, - const P6& a6) { - callback.Run(a1, a2, a3, a4, a5, a6); - MATE_METHOD_RETURN_UNDEFINED(); - } -}; - -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3, - const P4& a4, - const P5& a5) { - MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4, a5)); - } -}; -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3, - const P4& a4, - const P5& a5) { - callback.Run(a1, a2, a3, a4, a5); - MATE_METHOD_RETURN_UNDEFINED(); - } -}; - -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3, - const P4& a4) { - MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4)); - } -}; -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3, - const P4& a4) { - callback.Run(a1, a2, a3, a4); - MATE_METHOD_RETURN_UNDEFINED(); - } -}; - -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3) { - MATE_METHOD_RETURN(callback.Run(a1, a2, a3)); - } -}; -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2, - const P3& a3) { - callback.Run(a1, a2, a3); - MATE_METHOD_RETURN_UNDEFINED(); - } -}; - -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2) { - MATE_METHOD_RETURN(callback.Run(a1, a2)); - } -}; -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1, - const P2& a2) { - callback.Run(a1, a2); - MATE_METHOD_RETURN_UNDEFINED(); - } -}; - -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1) { - MATE_METHOD_RETURN(callback.Run(a1)); - } -}; -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback, - const P1& a1) { - callback.Run(a1); - MATE_METHOD_RETURN_UNDEFINED(); - } -}; - -template -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback) { - MATE_METHOD_RETURN(callback.Run()); - } -}; -template<> -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback) { - callback.Run(); - MATE_METHOD_RETURN_UNDEFINED(); - } -}; - - template bool GetNextArgument(Arguments* args, int create_flags, bool is_first, T* result) { @@ -341,278 +120,120 @@ inline bool GetNextArgument(Arguments* args, int create_flags, return true; } +// Classes for generating and storing an argument pack of integer indices +// (based on well-known "indices trick", see: http://goo.gl/bKKojn): +template +struct IndicesHolder {}; + +template +struct IndicesGenerator { + using type = typename IndicesGenerator::type; +}; +template +struct IndicesGenerator<0, indices...> { + using type = IndicesHolder; +}; + +// Class template for extracting and storing single argument for callback +// at position |index|. +template +struct ArgumentHolder { + using ArgLocalType = typename CallbackParamTraits::LocalType; + + ArgLocalType value; + bool ok; + + ArgumentHolder(Arguments* args, int create_flags) + : ok(false) { + if (index == 0 && + (create_flags & HolderIsFirstArgument) && + !(create_flags & SafeAfterDestroyed) && + DestroyedChecker::IsDestroyed(args)) { + args->ThrowError("Object has been destroyed"); + return; + } + ok = GetNextArgument(args, create_flags, index == 0, &value); + if (!ok) { + // Ideally we would include the expected c++ type in the error + // message which we can access via typeid(ArgType).name() + // however we compile with no-rtti, which disables typeid. + args->ThrowError(); + } + } +}; + +// Class template for converting arguments from JavaScript to C++ and running +// the callback with them. +template +class Invoker {}; + +template +class Invoker, ArgTypes...> + : public ArgumentHolder... { + public: + // Invoker<> inherits from ArgumentHolder<> for each argument. + // C++ has always been strict about the class initialization order, + // so it is guaranteed ArgumentHolders will be initialized (and thus, will + // extract arguments from Arguments) in the right order. + Invoker(Arguments* args, int create_flags) + : ArgumentHolder(args, create_flags)..., args_(args) { + // GCC thinks that create_flags is going unused, even though the + // expansion above clearly makes use of it. Per jyasskin@, casting + // to void is the commonly accepted way to convince the compiler + // that you're actually using a parameter/varible. + (void)create_flags; + } + + bool IsOK() { + return And(ArgumentHolder::ok...); + } + + template + void DispatchToCallback(base::Callback callback) { + args_->Return(callback.Run(ArgumentHolder::value...)); + } + + // In C++, you can declare the function foo(void), but you can't pass a void + // expression to foo. As a result, we must specialize the case of Callbacks + // that have the void return type. + void DispatchToCallback(base::Callback callback) { + callback.Run(ArgumentHolder::value...); + } + + private: + static bool And() { return true; } + template + static bool And(bool arg1, T... args) { + return arg1 && And(args...); + } + + Arguments* args_; +}; // DispatchToCallback converts all the JavaScript arguments to C++ types and // invokes the base::Callback. -template -struct Dispatcher { -}; +template +struct Dispatcher {}; -template -struct Dispatcher { - static MATE_METHOD(DispatchToCallback) { +template +struct Dispatcher { + static void DispatchToCallback( + const v8::FunctionCallbackInfo& info) { Arguments args(info); v8::Local v8_holder; CHECK(args.GetData(&v8_holder)); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); - typedef CallbackHolder HolderT; + typedef CallbackHolder HolderT; HolderT* holder = static_cast(holder_base); - return Invoker::Go(args, holder->callback); - } -}; - -template -struct Dispatcher { - static MATE_METHOD(DispatchToCallback) { - Arguments args(info); - v8::Local v8_holder; - CHECK(args.GetData(&v8_holder)); - CallbackHolderBase* holder_base = reinterpret_cast( - v8_holder->Value()); - - typedef CallbackHolder HolderT; - HolderT* holder = static_cast(holder_base); - - typename CallbackParamTraits::LocalType a1; - if ((holder->flags & HolderIsFirstArgument) && - !(holder->flags & SafeAfterDestroyed) && - DestroyedChecker::LocalType>::IsDestroyed(&args)) { - args.ThrowError("Object has been destroyed"); - MATE_METHOD_RETURN_UNDEFINED(); - } - if (!GetNextArgument(&args, holder->flags, true, &a1)) { - args.ThrowError(); - MATE_METHOD_RETURN_UNDEFINED(); - } - - return Invoker::Go(args, holder->callback, a1); - } -}; - -template -struct Dispatcher { - static MATE_METHOD(DispatchToCallback) { - Arguments args(info); - v8::Local v8_holder; - CHECK(args.GetData(&v8_holder)); - CallbackHolderBase* holder_base = reinterpret_cast( - v8_holder->Value()); - - typedef CallbackHolder HolderT; - HolderT* holder = static_cast(holder_base); - - typename CallbackParamTraits::LocalType a1; - typename CallbackParamTraits::LocalType a2; - if ((holder->flags & HolderIsFirstArgument) && - !(holder->flags & SafeAfterDestroyed) && - DestroyedChecker::LocalType>::IsDestroyed(&args)) { - args.ThrowError("Object has been destroyed"); - MATE_METHOD_RETURN_UNDEFINED(); - } - if (!GetNextArgument(&args, holder->flags, true, &a1) || - !GetNextArgument(&args, holder->flags, false, &a2)) { - args.ThrowError(); - MATE_METHOD_RETURN_UNDEFINED(); - } - - return Invoker::Go(args, holder->callback, a1, a2); - } -}; - -template -struct Dispatcher { - static MATE_METHOD(DispatchToCallback) { - Arguments args(info); - v8::Local v8_holder; - CHECK(args.GetData(&v8_holder)); - CallbackHolderBase* holder_base = reinterpret_cast( - v8_holder->Value()); - - typedef CallbackHolder HolderT; - HolderT* holder = static_cast(holder_base); - - typename CallbackParamTraits::LocalType a1; - typename CallbackParamTraits::LocalType a2; - typename CallbackParamTraits::LocalType a3; - if ((holder->flags & HolderIsFirstArgument) && - !(holder->flags & SafeAfterDestroyed) && - DestroyedChecker::LocalType>::IsDestroyed(&args)) { - args.ThrowError("Object has been destroyed"); - MATE_METHOD_RETURN_UNDEFINED(); - } - if (!GetNextArgument(&args, holder->flags, true, &a1) || - !GetNextArgument(&args, holder->flags, false, &a2) || - !GetNextArgument(&args, holder->flags, false, &a3)) { - args.ThrowError(); - MATE_METHOD_RETURN_UNDEFINED(); - } - - return Invoker::Go(args, holder->callback, a1, a2, a3); - } -}; - -template -struct Dispatcher { - static MATE_METHOD(DispatchToCallback) { - Arguments args(info); - v8::Local v8_holder; - CHECK(args.GetData(&v8_holder)); - CallbackHolderBase* holder_base = reinterpret_cast( - v8_holder->Value()); - - typedef CallbackHolder HolderT; - HolderT* holder = static_cast(holder_base); - - typename CallbackParamTraits::LocalType a1; - typename CallbackParamTraits::LocalType a2; - typename CallbackParamTraits::LocalType a3; - typename CallbackParamTraits::LocalType a4; - if ((holder->flags & HolderIsFirstArgument) && - !(holder->flags & SafeAfterDestroyed) && - DestroyedChecker::LocalType>::IsDestroyed(&args)) { - args.ThrowError("Object has been destroyed"); - MATE_METHOD_RETURN_UNDEFINED(); - } - if (!GetNextArgument(&args, holder->flags, true, &a1) || - !GetNextArgument(&args, holder->flags, false, &a2) || - !GetNextArgument(&args, holder->flags, false, &a3) || - !GetNextArgument(&args, holder->flags, false, &a4)) { - args.ThrowError(); - MATE_METHOD_RETURN_UNDEFINED(); - } - - return Invoker::Go(args, holder->callback, a1, a2, a3, - a4); - } -}; - -template -struct Dispatcher { - static MATE_METHOD(DispatchToCallback) { - Arguments args(info); - v8::Local v8_holder; - CHECK(args.GetData(&v8_holder)); - CallbackHolderBase* holder_base = reinterpret_cast( - v8_holder->Value()); - - typedef CallbackHolder HolderT; - HolderT* holder = static_cast(holder_base); - - typename CallbackParamTraits::LocalType a1; - typename CallbackParamTraits::LocalType a2; - typename CallbackParamTraits::LocalType a3; - typename CallbackParamTraits::LocalType a4; - typename CallbackParamTraits::LocalType a5; - if ((holder->flags & HolderIsFirstArgument) && - !(holder->flags & SafeAfterDestroyed) && - DestroyedChecker::LocalType>::IsDestroyed(&args)) { - args.ThrowError("Object has been destroyed"); - MATE_METHOD_RETURN_UNDEFINED(); - } - if (!GetNextArgument(&args, holder->flags, true, &a1) || - !GetNextArgument(&args, holder->flags, false, &a2) || - !GetNextArgument(&args, holder->flags, false, &a3) || - !GetNextArgument(&args, holder->flags, false, &a4) || - !GetNextArgument(&args, holder->flags, false, &a5)) { - args.ThrowError(); - MATE_METHOD_RETURN_UNDEFINED(); - } - - return Invoker::Go(args, holder->callback, a1, a2, - a3, a4, a5); - } -}; - -template -struct Dispatcher { - static MATE_METHOD(DispatchToCallback) { - Arguments args(info); - v8::Local v8_holder; - CHECK(args.GetData(&v8_holder)); - CallbackHolderBase* holder_base = reinterpret_cast( - v8_holder->Value()); - - typedef CallbackHolder HolderT; - HolderT* holder = static_cast(holder_base); - - typename CallbackParamTraits::LocalType a1; - typename CallbackParamTraits::LocalType a2; - typename CallbackParamTraits::LocalType a3; - typename CallbackParamTraits::LocalType a4; - typename CallbackParamTraits::LocalType a5; - typename CallbackParamTraits::LocalType a6; - if ((holder->flags & HolderIsFirstArgument) && - !(holder->flags & SafeAfterDestroyed) && - DestroyedChecker::LocalType>::IsDestroyed(&args)) { - args.ThrowError("Object has been destroyed"); - MATE_METHOD_RETURN_UNDEFINED(); - } - if (!GetNextArgument(&args, holder->flags, true, &a1) || - !GetNextArgument(&args, holder->flags, false, &a2) || - !GetNextArgument(&args, holder->flags, false, &a3) || - !GetNextArgument(&args, holder->flags, false, &a4) || - !GetNextArgument(&args, holder->flags, false, &a5) || - !GetNextArgument(&args, holder->flags, false, &a6)) { - args.ThrowError(); - MATE_METHOD_RETURN_UNDEFINED(); - } - - return Invoker::Go(args, holder->callback, a1, - a2, a3, a4, a5, a6); - } -}; - -template -struct Dispatcher { - static MATE_METHOD(DispatchToCallback) { - Arguments args(info); - v8::Local v8_holder; - CHECK(args.GetData(&v8_holder)); - CallbackHolderBase* holder_base = reinterpret_cast( - v8_holder->Value()); - - typedef CallbackHolder HolderT; - HolderT* holder = static_cast(holder_base); - - typename CallbackParamTraits::LocalType a1; - typename CallbackParamTraits::LocalType a2; - typename CallbackParamTraits::LocalType a3; - typename CallbackParamTraits::LocalType a4; - typename CallbackParamTraits::LocalType a5; - typename CallbackParamTraits::LocalType a6; - typename CallbackParamTraits::LocalType a7; - if ((holder->flags & HolderIsFirstArgument) && - !(holder->flags & SafeAfterDestroyed) && - DestroyedChecker::LocalType>::IsDestroyed(&args)) { - args.ThrowError("Object has been destroyed"); - MATE_METHOD_RETURN_UNDEFINED(); - } - if (!GetNextArgument(&args, holder->flags, true, &a1) || - !GetNextArgument(&args, holder->flags, false, &a2) || - !GetNextArgument(&args, holder->flags, false, &a3) || - !GetNextArgument(&args, holder->flags, false, &a4) || - !GetNextArgument(&args, holder->flags, false, &a5) || - !GetNextArgument(&args, holder->flags, false, &a6) || - !GetNextArgument(&args, holder->flags, false, &a7)) { - args.ThrowError(); - MATE_METHOD_RETURN_UNDEFINED(); - } - - return Invoker::Go(args, holder->callback, - a1, a2, a3, a4, a5, a6, a7); + using Indices = typename IndicesGenerator::type; + Invoker invoker(&args, holder->flags); + if (invoker.IsOK()) + invoker.DispatchToCallback(holder->callback); } }; @@ -621,8 +242,13 @@ struct Dispatcher { // CreateFunctionTemplate creates a v8::FunctionTemplate that will create // JavaScript functions that execute a provided C++ function or base::Callback. -// JavaScript arguments are automatically converted via mate::Converter, as is +// JavaScript arguments are automatically converted via gin::Converter, as is // the return value of the C++ function, if any. +// +// NOTE: V8 caches FunctionTemplates for a lifetime of a web page for its own +// internal reasons, thus it is generally a good idea to cache the template +// returned by this function. Otherwise, repeated method invocations from JS +// will create substantial memory leaks. See http://crbug.com/463487. template v8::Local CreateFunctionTemplate( v8::Isolate* isolate, const base::Callback callback, @@ -631,14 +257,26 @@ v8::Local CreateFunctionTemplate( HolderT* holder = new HolderT(isolate, callback, callback_flags); return v8::FunctionTemplate::New( -#if NODE_VERSION_AT_LEAST(0, 11, 11) isolate, -#endif &internal::Dispatcher::DispatchToCallback, ConvertToV8 >(isolate, holder->GetHandle(isolate))); } +// CreateFunctionHandler installs a CallAsFunction handler on the given +// object template that forwards to a provided C++ function or base::Callback. +template +void CreateFunctionHandler(v8::Isolate* isolate, + v8::Local tmpl, + const base::Callback callback, + int callback_flags = 0) { + typedef internal::CallbackHolder HolderT; + HolderT* holder = new HolderT(isolate, callback, callback_flags); + tmpl->SetCallAsFunctionHandler(&internal::Dispatcher::DispatchToCallback, + ConvertToV8 >( + isolate, holder->GetHandle(isolate))); +} + } // namespace mate #endif // NATIVE_MATE_FUNCTION_TEMPLATE_H_ diff --git a/native_mate/function_template.h.pump b/native_mate/function_template.h.pump deleted file mode 100644 index 10e64751fb1..00000000000 --- a/native_mate/function_template.h.pump +++ /dev/null @@ -1,250 +0,0 @@ -$$ This is a pump file for generating file templates. Pump is a python -$$ script that is part of the Google Test suite of utilities. Description -$$ can be found here: -$$ -$$ http://code.google.com/p/googletest/wiki/PumpManual -$$ -$var MAX_ARITY = 7 -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.chromium file. - -#ifndef NATIVE_MATE_FUNCTION_TEMPLATE_H_ -#define NATIVE_MATE_FUNCTION_TEMPLATE_H_ - -#include "base/callback.h" -#include "base/logging.h" -#include "native_mate/arguments.h" -#include "native_mate/wrappable.h" -#include "v8/include/v8.h" - -namespace mate { - -class PerIsolateData; - -enum CreateFunctionTemplateFlags { - HolderIsFirstArgument = 1 << 0, - SafeAfterDestroyed = 1 << 1, -}; - -namespace internal { - -// Check if the class has been destroyed. -template -struct DestroyedChecker { - static bool IsDestroyed(Arguments* args) { - return false; - } -}; -template -struct DestroyedChecker::value>::type> { - static bool IsDestroyed(Arguments* args) { - T* object; - if (args->GetHolder(&object)) - return static_cast(object)->IsDestroyed(); - else - return false; - } -}; - -template -struct CallbackParamTraits { - typedef T LocalType; -}; -template -struct CallbackParamTraits { - typedef T LocalType; -}; -template -struct CallbackParamTraits { - typedef T* LocalType; -}; - - -// CallbackHolder and CallbackHolderBase are used to pass a base::Callback from -// CreateFunctionTemplate through v8 (via v8::FunctionTemplate) to -// DispatchToCallback, where it is invoked. - -// This simple base class is used so that we can share a single object template -// among every CallbackHolder instance. -class CallbackHolderBase { - public: - v8::Local GetHandle(v8::Isolate* isolate); - - protected: - explicit CallbackHolderBase(v8::Isolate* isolate); - virtual ~CallbackHolderBase(); - - private: - static MATE_WEAK_CALLBACK(WeakCallback, v8::External, CallbackHolderBase); - - v8::UniquePersistent v8_ref_; - - DISALLOW_COPY_AND_ASSIGN(CallbackHolderBase); -}; - -template -class CallbackHolder : public CallbackHolderBase { - public: - CallbackHolder(v8::Isolate* isolate, - const base::Callback& callback, - int flags) - : CallbackHolderBase(isolate), callback(callback), flags(flags) {} - base::Callback callback; - int flags; - private: - virtual ~CallbackHolder() {} - - DISALLOW_COPY_AND_ASSIGN(CallbackHolder); -}; - - -// This set of templates invokes a base::Callback, converts the return type to a -// JavaScript value, and returns that value to script via the provided -// mate::Arguments object. -// -// In C++, you can declare the function foo(void), but you can't pass a void -// expression to foo. As a result, we must specialize the case of Callbacks that -// have the void return type. - -$range ARITY 0..MAX_ARITY -$for ARITY [[ -$var INV_ARITY = MAX_ARITY - ARITY -$range ARG 1..INV_ARITY -$range VOID INV_ARITY+1..MAX_ARITY - -$if ARITY == 0 [[ -template -struct Invoker { -]] $else [[ -template -struct Invoker { -]] - - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback$for ARG [[, - const P$(ARG)& a$(ARG)]]) { - MATE_METHOD_RETURN(callback.Run($for ARG, [[a$(ARG)]])); - } -}; -template<$for ARG , [[typename P$(ARG)]]> -struct Invoker { - inline static MATE_METHOD_RETURN_TYPE Go( - Arguments& args, - const base::Callback& callback$for ARG [[, - const P$(ARG)& a$(ARG)]]) { - callback.Run($for ARG, [[a$(ARG)]]); - MATE_METHOD_RETURN_UNDEFINED(); - } -}; - - -]] - -template -bool GetNextArgument(Arguments* args, int create_flags, bool is_first, - T* result) { - if (is_first && (create_flags & HolderIsFirstArgument) != 0) { - return args->GetHolder(result); - } else { - return args->GetNext(result); - } -} - -// For advanced use cases, we allow callers to request the unparsed Arguments -// object and poke around in it directly. -inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first, - Arguments* result) { - *result = *args; - return true; -} -inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first, - Arguments** result) { - *result = args; - return true; -} - -// It's common for clients to just need the isolate, so we make that easy. -inline bool GetNextArgument(Arguments* args, int create_flags, - bool is_first, v8::Isolate** result) { - *result = args->isolate(); - return true; -} - - -// DispatchToCallback converts all the JavaScript arguments to C++ types and -// invokes the base::Callback. -template -struct Dispatcher { -}; - -$range ARITY 0..MAX_ARITY -$for ARITY [[ -$range ARG 1..ARITY - -template -struct Dispatcher { - static MATE_METHOD(DispatchToCallback) { - Arguments args(info); - v8::Local v8_holder; - CHECK(args.GetData(&v8_holder)); - CallbackHolderBase* holder_base = reinterpret_cast( - v8_holder->Value()); - - typedef CallbackHolder HolderT; - HolderT* holder = static_cast(holder_base); - -$if ARITY != 0 [[ - - -$for ARG [[ typename CallbackParamTraits::LocalType a$(ARG); - -]] - if ((holder->flags & HolderIsFirstArgument) && - !(holder->flags & SafeAfterDestroyed) && - DestroyedChecker::LocalType>::IsDestroyed(&args)) { - args.ThrowError("Object has been destroyed"); - MATE_METHOD_RETURN_UNDEFINED(); - } - if ($for ARG || - [[!GetNextArgument(&args, holder->flags, $if ARG == 1 [[true]] $else [[false]], &a$(ARG))]]) { - args.ThrowError(); - MATE_METHOD_RETURN_UNDEFINED(); - } - -]] - - return Invoker::Go(args, holder->callback$for ARG [[, a$(ARG)]]); - } -}; - -]] - -} // namespace internal - - -// CreateFunctionTemplate creates a v8::FunctionTemplate that will create -// JavaScript functions that execute a provided C++ function or base::Callback. -// JavaScript arguments are automatically converted via mate::Converter, as is -// the return value of the C++ function, if any. -template -v8::Local CreateFunctionTemplate( - v8::Isolate* isolate, const base::Callback callback, - int callback_flags = 0) { - typedef internal::CallbackHolder HolderT; - HolderT* holder = new HolderT(isolate, callback, callback_flags); - - return v8::FunctionTemplate::New( -#if NODE_VERSION_AT_LEAST(0, 11, 11) - isolate, -#endif - &internal::Dispatcher::DispatchToCallback, - ConvertToV8 >(isolate, - holder->GetHandle(isolate))); -} - -} // namespace mate - -#endif // NATIVE_MATE_FUNCTION_TEMPLATE_H_ From ebcf4c022467a43a5379446e1c031ffd10438b9c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 7 Aug 2015 18:09:37 +0800 Subject: [PATCH 064/129] Remove callback.h --- native_mate/callback.h | 443 ------------------------------------ native_mate/callback.h.pump | 133 ----------- 2 files changed, 576 deletions(-) delete mode 100644 native_mate/callback.h delete mode 100644 native_mate/callback.h.pump diff --git a/native_mate/callback.h b/native_mate/callback.h deleted file mode 100644 index 2b364005044..00000000000 --- a/native_mate/callback.h +++ /dev/null @@ -1,443 +0,0 @@ -// This file was GENERATED by command: -// pump.py callback.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright (c) 2014 GitHub, Inc. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/callback.h" -#include "native_mate/function_template.h" -#include "native_mate/locker.h" -#include "native_mate/scoped_persistent.h" - -namespace mate { - -namespace internal { - -typedef scoped_refptr > SafeV8Function; - -// This set of templates invokes a V8::Function by converting the C++ types. -template -struct V8FunctionInvoker; - -template -struct V8FunctionInvoker()> { - static v8::Local Go(v8::Isolate* isolate, SafeV8Function function) { - Locker locker(isolate); - v8::EscapableHandleScope handle_scope(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local val(holder->Call(holder, 0, NULL)); - return handle_scope.Escape(val); - } -}; - -template -struct V8FunctionInvoker { - static R Go(v8::Isolate* isolate, SafeV8Function function) { - R ret; - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local val(holder->Call(holder, 0, NULL)); - Converter::FromV8(isolate, val, &ret); - return ret; - } -}; - -template<> -struct V8FunctionInvoker { - static void Go(v8::Isolate* isolate, SafeV8Function function) { - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - holder->Call(holder, 0, NULL); - } -}; - -template -struct V8FunctionInvoker(P1)> { - static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) { - Locker locker(isolate); - v8::EscapableHandleScope handle_scope(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - return handle_scope.Escape(val); - } -}; - -template -struct V8FunctionInvoker { - static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) { - R ret; - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - Converter::FromV8(isolate, val, &ret); - return ret; - } -}; - -template -struct V8FunctionInvoker { - static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) { - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - }; - holder->Call(holder, arraysize(args), args); - } -}; - -template -struct V8FunctionInvoker(P1, P2)> { - static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, - P2 a2) { - Locker locker(isolate); - v8::EscapableHandleScope handle_scope(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - return handle_scope.Escape(val); - } -}; - -template -struct V8FunctionInvoker { - static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2) { - R ret; - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - Converter::FromV8(isolate, val, &ret); - return ret; - } -}; - -template -struct V8FunctionInvoker { - static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2) { - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - }; - holder->Call(holder, arraysize(args), args); - } -}; - -template -struct V8FunctionInvoker(P1, P2, P3)> { - static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, - P2 a2, P3 a3) { - Locker locker(isolate); - v8::EscapableHandleScope handle_scope(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - return handle_scope.Escape(val); - } -}; - -template -struct V8FunctionInvoker { - static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, - P3 a3) { - R ret; - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - Converter::FromV8(isolate, val, &ret); - return ret; - } -}; - -template -struct V8FunctionInvoker { - static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, - P3 a3) { - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - }; - holder->Call(holder, arraysize(args), args); - } -}; - -template -struct V8FunctionInvoker(P1, P2, P3, P4)> { - static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, - P2 a2, P3 a3, P4 a4) { - Locker locker(isolate); - v8::EscapableHandleScope handle_scope(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - ConvertToV8(isolate, a4), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - return handle_scope.Escape(val); - } -}; - -template -struct V8FunctionInvoker { - static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, - P3 a3, P4 a4) { - R ret; - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - ConvertToV8(isolate, a4), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - Converter::FromV8(isolate, val, &ret); - return ret; - } -}; - -template -struct V8FunctionInvoker { - static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, - P3 a3, P4 a4) { - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - ConvertToV8(isolate, a4), - }; - holder->Call(holder, arraysize(args), args); - } -}; - -template -struct V8FunctionInvoker(P1, P2, P3, P4, P5)> { - static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, - P2 a2, P3 a3, P4 a4, P5 a5) { - Locker locker(isolate); - v8::EscapableHandleScope handle_scope(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - ConvertToV8(isolate, a4), - ConvertToV8(isolate, a5), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - return handle_scope.Escape(val); - } -}; - -template -struct V8FunctionInvoker { - static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, - P3 a3, P4 a4, P5 a5) { - R ret; - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - ConvertToV8(isolate, a4), - ConvertToV8(isolate, a5), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - Converter::FromV8(isolate, val, &ret); - return ret; - } -}; - -template -struct V8FunctionInvoker { - static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, - P3 a3, P4 a4, P5 a5) { - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - ConvertToV8(isolate, a4), - ConvertToV8(isolate, a5), - }; - holder->Call(holder, arraysize(args), args); - } -}; - -template -struct V8FunctionInvoker(P1, P2, P3, P4, P5, P6)> { - static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, - P2 a2, P3 a3, P4 a4, P5 a5, P6 a6) { - Locker locker(isolate); - v8::EscapableHandleScope handle_scope(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - ConvertToV8(isolate, a4), - ConvertToV8(isolate, a5), - ConvertToV8(isolate, a6), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - return handle_scope.Escape(val); - } -}; - -template -struct V8FunctionInvoker { - static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, - P3 a3, P4 a4, P5 a5, P6 a6) { - R ret; - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - ConvertToV8(isolate, a4), - ConvertToV8(isolate, a5), - ConvertToV8(isolate, a6), - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); - Converter::FromV8(isolate, val, &ret); - return ret; - } -}; - -template -struct V8FunctionInvoker { - static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2, - P3 a3, P4 a4, P5 a5, P6 a6) { - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - v8::Local args[] = { - ConvertToV8(isolate, a1), - ConvertToV8(isolate, a2), - ConvertToV8(isolate, a3), - ConvertToV8(isolate, a4), - ConvertToV8(isolate, a5), - ConvertToV8(isolate, a6), - }; - holder->Call(holder, arraysize(args), args); - } -}; - -} // namespace internal - -template -struct Converter > { - static v8::Local ToV8(v8::Isolate* isolate, - const base::Callback& val) { - return CreateFunctionTemplate(isolate, val)->GetFunction(); - } - static bool FromV8(v8::Isolate* isolate, - v8::Local val, - base::Callback* out) { - if (!val->IsFunction()) - return false; - - internal::SafeV8Function function( - new RefCountedPersistent(isolate, val)); - *out = base::Bind(&internal::V8FunctionInvoker::Go, isolate, function); - return true; - } -}; - -} // namespace mate diff --git a/native_mate/callback.h.pump b/native_mate/callback.h.pump deleted file mode 100644 index 4ed621dc1c6..00000000000 --- a/native_mate/callback.h.pump +++ /dev/null @@ -1,133 +0,0 @@ -$$ This is a pump file for generating file templates. Pump is a python -$$ script that is part of the Google Test suite of utilities. Description -$$ can be found here: -$$ -$$ http://code.google.com/p/googletest/wiki/PumpManual -$$ -$var MAX_ARITY = 6 -// Copyright (c) 2014 GitHub, Inc. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/callback.h" -#include "native_mate/function_template.h" -#include "native_mate/locker.h" -#include "native_mate/scoped_persistent.h" - -namespace mate { - -namespace internal { - -typedef scoped_refptr > SafeV8Function; - -// This set of templates invokes a V8::Function by converting the C++ types. -template -struct V8FunctionInvoker; - -$range ARITY 0..MAX_ARITY -$for ARITY [[ -$range ARG 1..ARITY - -template -struct V8FunctionInvoker($for ARG , [[P$(ARG)]])> { - static v8::Local Go(v8::Isolate* isolate, SafeV8Function function$for ARG [[, P$(ARG) a$(ARG)]]) { - Locker locker(isolate); - v8::EscapableHandleScope handle_scope(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - -$if ARITY == 0 [[ - v8::Local val(holder->Call(holder, 0, NULL)); -]] $else [[ - v8::Local args[] = { -$for ARG [[ - - ConvertToV8(isolate, a$(ARG)), -]] - - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); -]] - return handle_scope.Escape(val); - } -}; - -template -struct V8FunctionInvoker { - static R Go(v8::Isolate* isolate, SafeV8Function function$for ARG [[, P$(ARG) a$(ARG)]]) { - R ret; - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - -$if ARITY == 0 [[ - v8::Local val(holder->Call(holder, 0, NULL)); -]] $else [[ - v8::Local args[] = { -$for ARG [[ - - ConvertToV8(isolate, a$(ARG)), -]] - - }; - v8::Local val(holder->Call(holder, arraysize(args), args)); -]] - - Converter::FromV8(isolate, val, &ret); - return ret; - } -}; - -template<$for ARG , [[typename P$(ARG)]]> -struct V8FunctionInvoker { - static void Go(v8::Isolate* isolate, SafeV8Function function$for ARG [[, P$(ARG) a$(ARG)]]) { - Locker locker(isolate); - MATE_HANDLE_SCOPE(isolate); - v8::Local holder = function->NewHandle(); - v8::Local context = holder->CreationContext(); - v8::Context::Scope context_scope(context); - -$if ARITY == 0 [[ - holder->Call(holder, 0, NULL); -]] $else [[ - v8::Local args[] = { -$for ARG [[ - - ConvertToV8(isolate, a$(ARG)), -]] - - }; - holder->Call(holder, arraysize(args), args); -]] - - } -}; - -]] - -} // namespace internal - -template -struct Converter > { - static v8::Local ToV8(v8::Isolate* isolate, - const base::Callback& val) { - return CreateFunctionTemplate(isolate, val)->GetFunction(); - } - static bool FromV8(v8::Isolate* isolate, - v8::Local val, - base::Callback* out) { - if (!val->IsFunction()) - return false; - - internal::SafeV8Function function( - new RefCountedPersistent(isolate, val)); - *out = base::Bind(&internal::V8FunctionInvoker::Go, isolate, function); - return true; - } -}; - -} // namespace mate From 67d9eaa215e8727d86dc7b1f7a10be8699848f1f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 7 Aug 2015 19:21:07 +0800 Subject: [PATCH 065/129] Remove locker.h --- native_mate/locker.cc | 17 ----------------- native_mate/locker.h | 30 ------------------------------ native_mate_files.gypi | 3 --- 3 files changed, 50 deletions(-) delete mode 100644 native_mate/locker.cc delete mode 100644 native_mate/locker.h diff --git a/native_mate/locker.cc b/native_mate/locker.cc deleted file mode 100644 index c85e68e35f3..00000000000 --- a/native_mate/locker.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.chromium file. - -#include "native_mate/locker.h" - -namespace mate { - -Locker::Locker(v8::Isolate* isolate) { - if (v8::Locker::IsActive()) - locker_.reset(new v8::Locker(isolate)); -} - -Locker::~Locker() { -} - -} // namespace mate diff --git a/native_mate/locker.h b/native_mate/locker.h deleted file mode 100644 index 07acfbb0be9..00000000000 --- a/native_mate/locker.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.chromium file. - -#ifndef NATIVE_MATE_LOCKER_H_ -#define NATIVE_MATE_LOCKER_H_ - -#include "base/memory/scoped_ptr.h" -#include "v8/include/v8.h" - -namespace mate { - -// Only lock when lockers are used in current thread. -class Locker { - public: - explicit Locker(v8::Isolate* isolate); - ~Locker(); - - private: - void* operator new(size_t size); - void operator delete(void*, size_t); - - scoped_ptr locker_; - - DISALLOW_COPY_AND_ASSIGN(Locker); -}; - -} // namespace mate - -#endif // NATIVE_MATE_LOCKER_H_ diff --git a/native_mate_files.gypi b/native_mate_files.gypi index bc245f831a6..f3035ee9ad6 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -3,7 +3,6 @@ 'native_mate_files': [ 'native_mate/arguments.cc', 'native_mate/arguments.h', - 'native_mate/callback.h', 'native_mate/compat.h', 'native_mate/constructor.h', 'native_mate/converter.cc', @@ -13,8 +12,6 @@ 'native_mate/function_template.cc', 'native_mate/function_template.h', 'native_mate/handle.h', - 'native_mate/locker.cc', - 'native_mate/locker.h', 'native_mate/object_template_builder.cc', 'native_mate/object_template_builder.h', 'native_mate/persistent_dictionary.cc', From b6c353ee80f5369b7305bc882ab390bd88e4d48b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 21:18:59 +0800 Subject: [PATCH 066/129] Add Dictionary::CreateEmpty --- native_mate/dictionary.cc | 4 ++++ native_mate/dictionary.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc index 7ab702088fb..6c21af8051a 100644 --- a/native_mate/dictionary.cc +++ b/native_mate/dictionary.cc @@ -19,6 +19,10 @@ Dictionary::Dictionary(v8::Isolate* isolate, Dictionary::~Dictionary() { } +Dictionary Dictionary::CreateEmpty(v8::Isolate* isolate) { + return Dictionary(isolate, v8::Object::New(isolate));; +} + v8::Local Dictionary::GetHandle() const { return object_; } diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 9279d490e1e..0ff05c9bb88 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -28,6 +28,8 @@ class Dictionary { Dictionary(v8::Isolate* isolate, v8::Local object); ~Dictionary(); + static Dictionary CreateEmpty(v8::Isolate* isolate); + template bool Get(const base::StringPiece& key, T* out) const { v8::Local val = GetHandle()->Get(StringToV8(isolate_, key)); From 71600549274ee380239d0af3f21729b066a14c29 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 21:31:31 +0800 Subject: [PATCH 067/129] GetNext should have no side effect when failed --- native_mate/arguments.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/native_mate/arguments.h b/native_mate/arguments.h index 493af7c63bf..701b5fecae4 100644 --- a/native_mate/arguments.h +++ b/native_mate/arguments.h @@ -36,8 +36,11 @@ class Arguments { insufficient_arguments_ = true; return false; } - v8::Local val = (*info_)[next_++]; - return ConvertFromV8(isolate_, val, out); + v8::Local val = (*info_)[next_]; + bool success = ConvertFromV8(isolate_, val, out); + if (success) + next_++; + return success; } template From 24d31e204698bafc65c50295167764fbb0f28bc0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 21:31:45 +0800 Subject: [PATCH 068/129] Don't convert Function to Dictionary --- native_mate/dictionary.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc index 6c21af8051a..b63acaf5b77 100644 --- a/native_mate/dictionary.cc +++ b/native_mate/dictionary.cc @@ -35,7 +35,7 @@ v8::Local Converter::ToV8(v8::Isolate* isolate, bool Converter::FromV8(v8::Isolate* isolate, v8::Local val, Dictionary* out) { - if (!val->IsObject()) + if (!val->IsObject() || val->IsFunction()) return false; *out = Dictionary(isolate, v8::Local::Cast(val)); return true; From b41635e80921bddbf1a36f030490e063cd593477 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 12:06:35 +0800 Subject: [PATCH 069/129] Don't pass callback as const reference --- native_mate/object_template_builder.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index 2f30b37b701..c7ea215e731 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -90,7 +90,7 @@ class ObjectTemplateBuilder { // for creating raw function templates. template ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, - const T& callback, + T callback, bool safe_after_destroyed = false) { return SetImpl(name, CallbackTraits::CreateTemplate(isolate_, @@ -99,7 +99,7 @@ class ObjectTemplateBuilder { } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, - const T& getter, + T getter, bool safe_after_destroyed = false) { return SetPropertyImpl( name, @@ -109,8 +109,8 @@ class ObjectTemplateBuilder { } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, - const T& getter, - const U& setter, + T getter, + U setter, bool safe_after_destroyed = false) { return SetPropertyImpl( name, From f5e34deb1a5226b4e7e620cb65fce0225471d4d9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 27 Aug 2015 15:21:27 +0800 Subject: [PATCH 070/129] Add SetHidden for Dictionary --- native_mate/dictionary.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 0ff05c9bb88..c15f8f902fd 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -36,12 +36,25 @@ class Dictionary { return ConvertFromV8(isolate_, val, out); } + template + bool GetHidden(const base::StringPiece& key, T* out) const { + v8::Local val = GetHandle()->GetHiddenValue( + StringToV8(isolate_, key)); + return ConvertFromV8(isolate_, val, out); + } + template bool Set(const base::StringPiece& key, T val) { return GetHandle()->Set(StringToV8(isolate_, key), ConvertToV8(isolate_, val)); } + template + bool SetHidden(const base::StringPiece& key, T val) { + return GetHandle()->SetHiddenValue(StringToV8(isolate_, key), + ConvertToV8(isolate_, val)); + } + template bool SetMethod(const base::StringPiece& key, const T& callback) { return GetHandle()->Set( From 8ca005eb41591f583ebab804945311903f866ad6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 27 Aug 2015 15:50:38 +0800 Subject: [PATCH 071/129] Use the new SetWeak in Wrappable --- native_mate/wrappable.cc | 34 ++++++++++++++++++++++++---------- native_mate/wrappable.h | 3 ++- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 94ec5365668..d9291ccd844 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -14,7 +14,7 @@ Wrappable::Wrappable() : isolate_(NULL) { } Wrappable::~Wrappable() { - MATE_PERSISTENT_RESET(wrapper_); + wrapper_.Reset(); } void Wrappable::Wrap(v8::Isolate* isolate, v8::Local wrapper) { @@ -23,14 +23,14 @@ void Wrappable::Wrap(v8::Isolate* isolate, v8::Local wrapper) { isolate_ = isolate; - MATE_SET_INTERNAL_FIELD_POINTER(wrapper, 0, this); - MATE_PERSISTENT_ASSIGN(v8::Object, isolate, wrapper_, wrapper); - MATE_PERSISTENT_SET_WEAK(wrapper_, this, WeakCallback); + wrapper->SetAlignedPointerInInternalField(0, this); + wrapper_.Reset(isolate, wrapper); + wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter); // Call object._init if we have one. v8::Local init; if (Dictionary(isolate, wrapper).Get("_init", &init)) - init->Call(wrapper, 0, NULL); + init->Call(wrapper, 0, nullptr); AfterInit(isolate); } @@ -45,10 +45,16 @@ ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( return ObjectTemplateBuilder(isolate); } -// static -MATE_WEAK_CALLBACK(Wrappable::WeakCallback, v8::Object, Wrappable) { - MATE_WEAK_CALLBACK_INIT(Wrappable); - delete self; +void Wrappable::FirstWeakCallback(const v8::WeakCallbackInfo& data) { + Wrappable* wrappable = data.GetParameter(); + wrappable->wrapper_.Reset(); + data.SetSecondPassCallback(SecondWeakCallback); +} + +void Wrappable::SecondWeakCallback( + const v8::WeakCallbackInfo& data) { + Wrappable* wrappable = data.GetParameter(); + delete wrappable; } v8::Local Wrappable::GetWrapper(v8::Isolate* isolate) { @@ -59,7 +65,15 @@ v8::Local Wrappable::GetWrapper(v8::Isolate* isolate) { GetObjectTemplateBuilder(isolate).Build(); CHECK(!templ.IsEmpty()); CHECK_EQ(1, templ->InternalFieldCount()); - v8::Local wrapper = templ->NewInstance(); + v8::Local wrapper; + // |wrapper| may be empty in some extreme cases, e.g., when + // Object.prototype.constructor is overwritten. + if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&wrapper)) { + // The current wrappable object will be no longer managed by V8. Delete this + // now. + delete this; + return wrapper; + } Wrap(isolate, wrapper); return wrapper; } diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index d55ce42cf7f..536772a2a39 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -79,7 +79,8 @@ class Wrappable { virtual void AfterInit(v8::Isolate* isolate) {} private: - static MATE_WEAK_CALLBACK(WeakCallback, v8::Object, Wrappable); + static void FirstWeakCallback(const v8::WeakCallbackInfo& data); + static void SecondWeakCallback(const v8::WeakCallbackInfo& data); v8::Isolate* isolate_; v8::UniquePersistent wrapper_; // Weak From b7387da0854b20d376fdae0d93a01f83d080668d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 10 Sep 2015 15:57:30 +0800 Subject: [PATCH 072/129] Check whether key exists in Dictionary::Get --- native_mate/converter.h | 61 ++++++++++++++++++++++++++++++++++++++-- native_mate/dictionary.h | 40 +++++++++++++++++++++----- 2 files changed, 91 insertions(+), 10 deletions(-) diff --git a/native_mate/converter.h b/native_mate/converter.h index 0ee0c0e6e59..86dc5e5d21c 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -15,6 +15,20 @@ namespace mate { +template +bool SetProperty(v8::Isolate* isolate, + v8::Local object, + KeyType key, + v8::Local value) { + auto maybe = object->Set(isolate->GetCurrentContext(), key, value); + return !maybe.IsNothing() && maybe.FromJust(); +} + +template +struct ToV8ReturnsMaybe { + static const bool value = false; +}; + template struct Converter {}; @@ -241,18 +255,59 @@ struct Converter > { } }; +template +struct ToV8ReturnsMaybe> { + static const bool value = true; +}; + // Convenience functions that deduce T. template -v8::Local ConvertToV8(v8::Isolate* isolate, - const T& input) { +v8::Local ConvertToV8(v8::Isolate* isolate, const T& input) { return Converter::ToV8(isolate, input); } inline v8::Local ConvertToV8(v8::Isolate* isolate, - const char* input) { + const char* input) { return Converter::ToV8(isolate, input); } +template +v8::MaybeLocal ConvertToV8(v8::Local context, + const T& input) { + return Converter::ToV8(context, input); +} + +template::value> struct ToV8Traits; + +template +struct ToV8Traits { + static bool TryConvertToV8(v8::Isolate* isolate, + const T& input, + v8::Local* output) { + auto maybe = ConvertToV8(isolate->GetCurrentContext(), input); + if (maybe.IsEmpty()) + return false; + *output = maybe.ToLocalChecked(); + return true; + } +}; + +template +struct ToV8Traits { + static bool TryConvertToV8(v8::Isolate* isolate, + const T& input, + v8::Local* output) { + *output = ConvertToV8(isolate, input); + return true; + } +}; + +template +bool TryConvertToV8(v8::Isolate* isolate, + T input, + v8::Local* output) { + return ToV8Traits::TryConvertToV8(isolate, input, output); +} inline v8::Local StringToV8( v8::Isolate* isolate, const base::StringPiece& input) { diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index c15f8f902fd..05b6b86463a 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -10,6 +10,15 @@ namespace mate { +namespace internal { + +// Returns true if |maybe| is both a value, and that value is true. +inline bool IsTrue(v8::Maybe maybe) { + return maybe.IsJust() && maybe.FromJust(); +} + +} // namespace internal + // Dictionary is useful when writing bindings for a function that either // receives an arbitrary JavaScript object as an argument or returns an // arbitrary JavaScript object as a result. For example, Dictionary is useful @@ -32,27 +41,44 @@ class Dictionary { template bool Get(const base::StringPiece& key, T* out) const { - v8::Local val = GetHandle()->Get(StringToV8(isolate_, key)); + // Check for existence before getting, otherwise this method will always + // returns true when T == v8::Local. + v8::Local context = isolate_->GetCurrentContext(); + v8::Local v8_key = StringToV8(isolate_, key); + if (!internal::IsTrue(GetHandle()->Has(context, v8_key))) + return false; + + v8::Local val; + if (!GetHandle()->Get(context, v8_key).ToLocal(&val)) + return false; return ConvertFromV8(isolate_, val, out); } template bool GetHidden(const base::StringPiece& key, T* out) const { - v8::Local val = GetHandle()->GetHiddenValue( - StringToV8(isolate_, key)); + v8::Local val = + GetHandle()->GetHiddenValue(StringToV8(isolate_, key)); return ConvertFromV8(isolate_, val, out); } template bool Set(const base::StringPiece& key, T val) { - return GetHandle()->Set(StringToV8(isolate_, key), - ConvertToV8(isolate_, val)); + v8::Local v8_value; + if (!TryConvertToV8(isolate_, val, &v8_value)) + return false; + v8::Maybe result = + GetHandle()->Set(isolate_->GetCurrentContext(), + StringToV8(isolate_, key), + v8_value); + return !result.IsNothing() && result.FromJust(); } template bool SetHidden(const base::StringPiece& key, T val) { - return GetHandle()->SetHiddenValue(StringToV8(isolate_, key), - ConvertToV8(isolate_, val)); + v8::Local v8_value; + if (!TryConvertToV8(isolate_, val, &v8_value)) + return false; + return GetHandle()->SetHiddenValue(StringToV8(isolate_, key), v8_value); } template From 21cda4e7fcff592f33f989c1fea575658281711d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 2 Nov 2015 20:44:37 +0800 Subject: [PATCH 073/129] Don't return v8::Maybe for std::vector --- native_mate/converter.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/native_mate/converter.h b/native_mate/converter.h index 86dc5e5d21c..427e3dd669f 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -255,11 +255,6 @@ struct Converter > { } }; -template -struct ToV8ReturnsMaybe> { - static const bool value = true; -}; - // Convenience functions that deduce T. template v8::Local ConvertToV8(v8::Isolate* isolate, const T& input) { From 93984941005bab194a2d47aff655d525c064efcb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Nov 2015 00:25:10 +0800 Subject: [PATCH 074/129] Add Dictionary::Delete --- native_mate/dictionary.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 05b6b86463a..e636ca5d2f5 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -88,6 +88,12 @@ class Dictionary { CallbackTraits::CreateTemplate(isolate_, callback)->GetFunction()); } + bool Delete(const base::StringPiece& key) { + v8::Maybe result = GetHandle()->Delete(isolate_->GetCurrentContext(), + StringToV8(isolate_, key)); + return !result.IsNothing() && result.FromJust(); + } + bool IsEmpty() const { return isolate() == NULL; } virtual v8::Local GetHandle() const; From e859228db163c27410fb200c2df0715478fdf0d7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 3 Dec 2015 15:37:27 +0800 Subject: [PATCH 075/129] Do not manually destroy native resources --- native_mate/arguments.h | 4 +++ native_mate/function_template.h | 26 +++++++------------ native_mate/object_template_builder.cc | 6 +++++ native_mate/object_template_builder.h | 36 ++++++++++---------------- native_mate/wrappable.cc | 4 --- native_mate/wrappable.h | 8 +++--- 6 files changed, 37 insertions(+), 47 deletions(-) diff --git a/native_mate/arguments.h b/native_mate/arguments.h index 701b5fecae4..3695cae36b3 100644 --- a/native_mate/arguments.h +++ b/native_mate/arguments.h @@ -20,6 +20,10 @@ class Arguments { explicit Arguments(const MATE_METHOD_ARGS_TYPE& info); ~Arguments(); + v8::Local GetHolder() const { + return info_->Holder(); + } + template bool GetHolder(T* out) { return ConvertFromV8(isolate_, info_->Holder(), out); diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 0761dca58b5..b1d0764688a 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -15,27 +15,20 @@ namespace mate { enum CreateFunctionTemplateFlags { HolderIsFirstArgument = 1 << 0, - SafeAfterDestroyed = 1 << 1, }; namespace internal { -// Check if the class has been destroyed. -template -struct DestroyedChecker { - static bool IsDestroyed(Arguments* args) { - return false; +struct Destroyable { + static void Destroy(Arguments* args) { + v8::Local holder = args->GetHolder(); + delete static_cast(holder->GetAlignedPointerFromInternalField(0)); + holder->SetAlignedPointerInInternalField(0, nullptr); } -}; -template -struct DestroyedChecker::value>::type> { static bool IsDestroyed(Arguments* args) { - T* object; - if (args->GetHolder(&object)) - return static_cast(object)->IsDestroyed(); - else - return false; + v8::Local holder = args->GetHolder(); + return holder->InternalFieldCount() == 0 || + holder->GetAlignedPointerFromInternalField(0) == nullptr; } }; @@ -149,8 +142,7 @@ struct ArgumentHolder { : ok(false) { if (index == 0 && (create_flags & HolderIsFirstArgument) && - !(create_flags & SafeAfterDestroyed) && - DestroyedChecker::IsDestroyed(args)) { + Destroyable::IsDestroyed(args)) { args->ThrowError("Object has been destroyed"); return; } diff --git a/native_mate/object_template_builder.cc b/native_mate/object_template_builder.cc index a2011f0c76e..b302a01634e 100644 --- a/native_mate/object_template_builder.cc +++ b/native_mate/object_template_builder.cc @@ -32,6 +32,12 @@ ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl( return *this; } +ObjectTemplateBuilder& ObjectTemplateBuilder::MakeDestroyable() { + SetMethod("destroy", base::Bind(internal::Destroyable::Destroy)); + SetMethod("isDestroy", base::Bind(internal::Destroyable::IsDestroyed)); + return *this; +} + v8::Local ObjectTemplateBuilder::Build() { v8::Local result = template_; template_.Clear(); diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index c7ea215e731..a4335901a1f 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -22,9 +22,8 @@ namespace { // because of base::Bind(). template struct CallbackTraits { - static v8::Local CreateTemplate(v8::Isolate* isolate, - T callback, - bool = true) { + static v8::Local CreateTemplate( + v8::Isolate* isolate, T callback) { return CreateFunctionTemplate(isolate, base::Bind(callback)); } }; @@ -33,7 +32,7 @@ struct CallbackTraits { template struct CallbackTraits > { static v8::Local CreateTemplate( - v8::Isolate* isolate, const base::Callback& callback, bool = true) { + v8::Isolate* isolate, const base::Callback& callback) { return CreateFunctionTemplate(isolate, callback); } }; @@ -46,10 +45,8 @@ template struct CallbackTraits::value>::type> { static v8::Local CreateTemplate( - v8::Isolate* isolate, T callback, bool safe_after_destroyed = false) { + v8::Isolate* isolate, T callback) { int flags = HolderIsFirstArgument; - if (safe_after_destroyed) - flags |= SafeAfterDestroyed; return CreateFunctionTemplate(isolate, base::Bind(callback), flags); } }; @@ -90,36 +87,31 @@ class ObjectTemplateBuilder { // for creating raw function templates. template ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, - T callback, - bool safe_after_destroyed = false) { + T callback) { return SetImpl(name, - CallbackTraits::CreateTemplate(isolate_, - callback, - safe_after_destroyed)); + CallbackTraits::CreateTemplate(isolate_, callback)); } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, - T getter, - bool safe_after_destroyed = false) { + T getter) { return SetPropertyImpl( name, - CallbackTraits::CreateTemplate(isolate_, getter, - safe_after_destroyed), + CallbackTraits::CreateTemplate(isolate_, getter), v8::Local()); } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, T getter, - U setter, - bool safe_after_destroyed = false) { + U setter) { return SetPropertyImpl( name, - CallbackTraits::CreateTemplate(isolate_, getter, - safe_after_destroyed), - CallbackTraits::CreateTemplate(isolate_, setter, - safe_after_destroyed)); + CallbackTraits::CreateTemplate(isolate_, getter), + CallbackTraits::CreateTemplate(isolate_, setter)); } + // Add "destroy" and "isDestroyed" methods. + ObjectTemplateBuilder& MakeDestroyable(); + v8::Local Build(); private: diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index d9291ccd844..48feec013bb 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -78,10 +78,6 @@ v8::Local Wrappable::GetWrapper(v8::Isolate* isolate) { return wrapper; } -bool Wrappable::IsDestroyed() const { - return false; -} - namespace internal { void* FromV8Impl(v8::Isolate* isolate, v8::Local val) { diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 536772a2a39..25338399b37 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -13,6 +13,8 @@ namespace mate { namespace internal { +struct Destroyable; + void* FromV8Impl(v8::Isolate* isolate, v8::Local val); } // namespace internal @@ -54,10 +56,6 @@ class Wrappable { // object constructed by GetObjectTemplateBuilder. v8::Local GetWrapper(v8::Isolate* isolate); - // Returns whether this class has been destroyed, users should override this - // method to indicate the native type's state. - virtual bool IsDestroyed() const; - // Returns the Isolate this object is created in. v8::Isolate* isolate() const { return isolate_; } @@ -79,6 +77,8 @@ class Wrappable { virtual void AfterInit(v8::Isolate* isolate) {} private: + friend struct internal::Destroyable; + static void FirstWeakCallback(const v8::WeakCallbackInfo& data); static void SecondWeakCallback(const v8::WeakCallbackInfo& data); From 5e70868fd0c005dc2c43bea15ca6e93da0b68741 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 4 Dec 2015 19:23:13 +0800 Subject: [PATCH 076/129] isDestroy => isDestroyed --- native_mate/object_template_builder.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_mate/object_template_builder.cc b/native_mate/object_template_builder.cc index b302a01634e..5bf2cfb193c 100644 --- a/native_mate/object_template_builder.cc +++ b/native_mate/object_template_builder.cc @@ -34,7 +34,7 @@ ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl( ObjectTemplateBuilder& ObjectTemplateBuilder::MakeDestroyable() { SetMethod("destroy", base::Bind(internal::Destroyable::Destroy)); - SetMethod("isDestroy", base::Bind(internal::Destroyable::IsDestroyed)); + SetMethod("isDestroyed", base::Bind(internal::Destroyable::IsDestroyed)); return *this; } From a3dcf8ced663e974ac94ad5e50a1d25a43995a9d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 11 Dec 2015 21:13:33 +0800 Subject: [PATCH 077/129] Fix converter for std::set --- native_mate/converter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/native_mate/converter.h b/native_mate/converter.h index 427e3dd669f..6e51bcdcd9f 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -230,7 +230,7 @@ struct Converter > { typename std::set::const_iterator it; int i; for (i = 0, it = val.begin(); it != val.end(); ++it, ++i) - result->Set(i, Converter::ToV8(isolate, *it)); + result->Set(i, Converter::ToV8(isolate, *it)); return result; } @@ -247,7 +247,7 @@ struct Converter > { T item; if (!Converter::FromV8(isolate, array->Get(i), &item)) return false; - result.push_back(item); + result.insert(item); } out->swap(result); From 26520c5cf4b6a60da2c5cba971393f94b82f5939 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Feb 2016 10:10:15 +0800 Subject: [PATCH 078/129] Improve error message for type error Close atom/electron#4307. --- native_mate/arguments.cc | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/native_mate/arguments.cc b/native_mate/arguments.cc index 57aa55274ec..ad62e207f84 100644 --- a/native_mate/arguments.cc +++ b/native_mate/arguments.cc @@ -9,6 +9,23 @@ namespace mate { +namespace { + +std::string V8TypeAsString(v8::Local value) { + if (value.IsEmpty()) + return ""; + if (value->IsUndefined()) + return "undefined"; + if (value->IsNull()) + return "null"; + std::string result; + if (!ConvertFromV8(NULL, value, &result)) + return std::string(); + return result; +} + +} // namespace + Arguments::Arguments() : isolate_(NULL), info_(NULL), @@ -37,7 +54,8 @@ v8::Local Arguments::ThrowError() const { return ThrowTypeError("Insufficient number of arguments."); return ThrowTypeError(base::StringPrintf( - "Error processing argument %d.", next_ - 1)); + "Error processing argument at index %d, conversion failure from %s", + next_, V8TypeAsString((*info_)[next_]).c_str())); } v8::Local Arguments::ThrowError(const std::string& message) const { From e719eab878c264bb03188d0cd6eb9ad6882bc13a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Feb 2016 19:50:27 +0800 Subject: [PATCH 079/129] Clear internal field when Wrapper is destroyed --- native_mate/wrappable.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 48feec013bb..3edb3b6d3f0 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -14,6 +14,8 @@ Wrappable::Wrappable() : isolate_(NULL) { } Wrappable::~Wrappable() { + if (!wrapper_.IsEmpty()) + GetWrapper(isolate())->SetAlignedPointerInInternalField(0, nullptr); wrapper_.Reset(); } From 16270fa080a29f8e4a499e58ebbac6986935abeb Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 7 Mar 2016 20:36:14 -0800 Subject: [PATCH 080/129] basic_types.h => macros.h --- native_mate/arguments.h | 2 +- native_mate/try_catch.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native_mate/arguments.h b/native_mate/arguments.h index 3695cae36b3..44250e8d2e2 100644 --- a/native_mate/arguments.h +++ b/native_mate/arguments.h @@ -5,7 +5,7 @@ #ifndef NATIVE_MATE_ARGUMENTS_H_ #define NATIVE_MATE_ARGUMENTS_H_ -#include "base/basictypes.h" +#include "base/macros.h" #include "native_mate/compat.h" #include "native_mate/converter.h" diff --git a/native_mate/try_catch.h b/native_mate/try_catch.h index 3b3ece87360..abd501e19b2 100644 --- a/native_mate/try_catch.h +++ b/native_mate/try_catch.h @@ -7,7 +7,7 @@ #include -#include "base/basictypes.h" +#include "base/macros.h" #include "v8/include/v8.h" namespace mate { From 309887c444947790b1efee8b2115f0537ce60a03 Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 24 Mar 2016 01:27:17 +0530 Subject: [PATCH 081/129] use v8::private symbols as identifiers for object properties --- native_mate/dictionary.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index e636ca5d2f5..38927c85374 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -56,9 +56,16 @@ class Dictionary { template bool GetHidden(const base::StringPiece& key, T* out) const { - v8::Local val = - GetHandle()->GetHiddenValue(StringToV8(isolate_, key)); - return ConvertFromV8(isolate_, val, out); + v8::Local context = isolate_->GetCurrentContext(); + v8::Local privateKey = + v8::Private::ForApi(isolate_, StringToV8(isolate_, key)); + v8::Local value; + v8::Maybe result = + GetHandle()->HasPrivate(context, privateKey); + if (internal::IsTrue(result) && + GetHandle()->GetPrivate(context, privateKey).ToLocal(&value)) + return ConvertFromV8(isolate_, value, out); + return false; } template @@ -78,7 +85,12 @@ class Dictionary { v8::Local v8_value; if (!TryConvertToV8(isolate_, val, &v8_value)) return false; - return GetHandle()->SetHiddenValue(StringToV8(isolate_, key), v8_value); + v8::Local context = isolate_->GetCurrentContext(); + v8::Local privateKey = + v8::Private::ForApi(isolate_, StringToV8(isolate_, key)); + v8::Maybe result = + GetHandle()->SetPrivate(context, privateKey, v8_value); + return !result.IsNothing() && result.FromJust(); } template From 0df2d882ea2286e6335f206b7002037fce66c4a5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 25 Apr 2016 10:17:39 +0900 Subject: [PATCH 082/129] Make Wrappable a template class --- native_mate/constructor.h | 50 ++++++++--------- native_mate/constructor.h.pump | 16 +++--- native_mate/function_template.h | 3 +- native_mate/handle.h | 2 +- native_mate/wrappable.cc | 66 ++++++++--------------- native_mate/wrappable.h | 95 ++++++++++++++++++++------------- 6 files changed, 114 insertions(+), 118 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 98cd62bde89..65c16c33598 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -16,59 +16,59 @@ namespace mate { -class Wrappable; +class WrappableBase; namespace internal { // This set of templates invokes a base::Callback by converting the Arguments // into native types. It relies on the function_template.h to provide helper // templates. -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { return callback.Run(); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; if (!GetNextArgument(args, 0, true, &a1)) - return NULL; + return nullptr; return callback.Run(a1); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; if (!GetNextArgument(args, 0, true, &a1) || !GetNextArgument(args, 0, false, &a2)) - return NULL; + return nullptr; return callback.Run(a1, a2); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; if (!GetNextArgument(args, 0, true, &a1) || !GetNextArgument(args, 0, false, &a2) || !GetNextArgument(args, 0, false, &a3)) - return NULL; + return nullptr; return callback.Run(a1, a2, a3); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -77,14 +77,14 @@ inline Wrappable* InvokeFactory( !GetNextArgument(args, 0, false, &a2) || !GetNextArgument(args, 0, false, &a3) || !GetNextArgument(args, 0, false, &a4)) - return NULL; + return nullptr; return callback.Run(a1, a2, a3, a4); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -95,15 +95,15 @@ inline Wrappable* InvokeFactory( !GetNextArgument(args, 0, false, &a3) || !GetNextArgument(args, 0, false, &a4) || !GetNextArgument(args, 0, false, &a5)) - return NULL; + return nullptr; return callback.Run(a1, a2, a3, a4, a5); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -116,7 +116,7 @@ inline Wrappable* InvokeFactory( !GetNextArgument(args, 0, false, &a4) || !GetNextArgument(args, 0, false, &a5) || !GetNextArgument(args, 0, false, &a6)) - return NULL; + return nullptr; return callback.Run(a1, a2, a3, a4, a5, a6); }; @@ -156,7 +156,7 @@ class Constructor { MATE_METHOD_RETURN_UNDEFINED(); } - Wrappable* object; + WrappableBase* object; { // Don't continue if the constructor throws an exception. v8::TryCatch try_catch; @@ -168,7 +168,7 @@ class Constructor { } if (object) - object->Wrap(isolate, args->GetThis()); + object->InitWith(isolate, args->GetThis()); else args->ThrowError(); @@ -176,14 +176,14 @@ class Constructor { } base::StringPiece name_; - v8::UniquePersistent constructor_; + v8::Global constructor_; DISALLOW_COPY_AND_ASSIGN(Constructor); }; template -Wrappable* NewOperatorFactory() { +WrappableBase* NewOperatorFactory() { return new T; } diff --git a/native_mate/constructor.h.pump b/native_mate/constructor.h.pump index ec4944f4eb2..540493ccd53 100644 --- a/native_mate/constructor.h.pump +++ b/native_mate/constructor.h.pump @@ -19,7 +19,7 @@ $var MAX_ARITY = 6 namespace mate { -class Wrappable; +class WrappableBase; namespace internal { @@ -37,9 +37,9 @@ $if ARITY == 0 [[ template<$for ARG , [[typename P$(ARG)]]> ]] -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { $if ARITY != 0 [[ @@ -48,7 +48,7 @@ $for ARG [[ typename CallbackParamTraits::LocalType a$(ARG); ]] if ($for ARG || [[!GetNextArgument(args, 0, $if ARG == 1 [[true]] $else [[false]], &a$(ARG))]]) - return NULL; + return nullptr; ]] return callback.Run($for ARG , [[a$(ARG)]]); @@ -92,7 +92,7 @@ class Constructor { MATE_METHOD_RETURN_UNDEFINED(); } - Wrappable* object; + WrappableBase* object; { // Don't continue if the constructor throws an exception. v8::TryCatch try_catch; @@ -104,7 +104,7 @@ class Constructor { } if (object) - object->Wrap(isolate, args->GetThis()); + object->InitWith(isolate, args->GetThis()); else args->ThrowError(); @@ -112,14 +112,14 @@ class Constructor { } base::StringPiece name_; - v8::UniquePersistent constructor_; + v8::Global constructor_; DISALLOW_COPY_AND_ASSIGN(Constructor); }; template -Wrappable* NewOperatorFactory() { +WrappableBase* NewOperatorFactory() { return new T; } diff --git a/native_mate/function_template.h b/native_mate/function_template.h index b1d0764688a..0a607c0da05 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -22,7 +22,8 @@ namespace internal { struct Destroyable { static void Destroy(Arguments* args) { v8::Local holder = args->GetHolder(); - delete static_cast(holder->GetAlignedPointerFromInternalField(0)); + delete static_cast( + holder->GetAlignedPointerFromInternalField(0)); holder->SetAlignedPointerInInternalField(0, nullptr); } static bool IsDestroyed(Arguments* args) { diff --git a/native_mate/handle.h b/native_mate/handle.h index 15e0bb5bb8f..0fbd171319a 100644 --- a/native_mate/handle.h +++ b/native_mate/handle.h @@ -60,7 +60,7 @@ struct Converter > { // without having to write out the type of the object explicitly. template mate::Handle CreateHandle(v8::Isolate* isolate, T* object) { - return mate::Handle(object->GetWrapper(isolate), object); + return mate::Handle(object->GetWrapper(), object); } } // namespace mate diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 3edb3b6d3f0..c42bc96dab6 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -10,21 +10,25 @@ namespace mate { -Wrappable::Wrappable() : isolate_(NULL) { +WrappableBase::WrappableBase() + : isolate_(nullptr) { } -Wrappable::~Wrappable() { +WrappableBase::~WrappableBase() { if (!wrapper_.IsEmpty()) - GetWrapper(isolate())->SetAlignedPointerInInternalField(0, nullptr); + GetWrapper()->SetAlignedPointerInInternalField(0, nullptr); wrapper_.Reset(); } -void Wrappable::Wrap(v8::Isolate* isolate, v8::Local wrapper) { - if (!wrapper_.IsEmpty()) - return; +v8::Local WrappableBase::GetWrapper() { + CHECK(!wrapper_.IsEmpty()); + return v8::Local::New(isolate_, wrapper_); +} +void WrappableBase::InitWith(v8::Isolate* isolate, + v8::Local wrapper) { + CHECK(wrapper_.IsEmpty()); isolate_ = isolate; - wrapper->SetAlignedPointerInInternalField(0, this); wrapper_.Reset(isolate, wrapper); wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter); @@ -38,57 +42,29 @@ void Wrappable::Wrap(v8::Isolate* isolate, v8::Local wrapper) { } // static -void Wrappable::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { -} - -ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return ObjectTemplateBuilder(isolate); -} - -void Wrappable::FirstWeakCallback(const v8::WeakCallbackInfo& data) { - Wrappable* wrappable = data.GetParameter(); +void WrappableBase::FirstWeakCallback( + const v8::WeakCallbackInfo& data) { + WrappableBase* wrappable = data.GetParameter(); wrappable->wrapper_.Reset(); data.SetSecondPassCallback(SecondWeakCallback); } -void Wrappable::SecondWeakCallback( - const v8::WeakCallbackInfo& data) { - Wrappable* wrappable = data.GetParameter(); +// static +void WrappableBase::SecondWeakCallback( + const v8::WeakCallbackInfo& data) { + WrappableBase* wrappable = data.GetParameter(); delete wrappable; } -v8::Local Wrappable::GetWrapper(v8::Isolate* isolate) { - if (!wrapper_.IsEmpty()) - return MATE_PERSISTENT_TO_LOCAL(v8::Object, isolate, wrapper_); - - v8::Local templ = - GetObjectTemplateBuilder(isolate).Build(); - CHECK(!templ.IsEmpty()); - CHECK_EQ(1, templ->InternalFieldCount()); - v8::Local wrapper; - // |wrapper| may be empty in some extreme cases, e.g., when - // Object.prototype.constructor is overwritten. - if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&wrapper)) { - // The current wrappable object will be no longer managed by V8. Delete this - // now. - delete this; - return wrapper; - } - Wrap(isolate, wrapper); - return wrapper; -} - namespace internal { void* FromV8Impl(v8::Isolate* isolate, v8::Local val) { if (!val->IsObject()) - return NULL; + return nullptr; v8::Local obj = v8::Local::Cast(val); if (obj->InternalFieldCount() != 1) - return NULL; - return MATE_GET_INTERNAL_FIELD_POINTER(obj, 0); + return nullptr; + return obj->GetAlignedPointerFromInternalField(0); } } // namespace internal diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 25338399b37..0cc1e3b8e12 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -27,83 +27,102 @@ void* FromV8Impl(v8::Isolate* isolate, v8::Local val); // // my_class.h // class MyClass : Wrappable { // public: -// // Optional, only required if non-empty template should be used. -// virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder( -// v8::Isolate* isolate); // ... // }; // -// // my_class.cc -// gin::ObjectTemplateBuilder MyClass::GetObjectTemplateBuilder( -// v8::Isolate* isolate) { -// return Wrappable::GetObjectTemplateBuilder(isolate) -// .SetValue("foobar", 42); -// } -// // Subclasses should also typically have private constructors and expose a // static Create function that returns a mate::Handle. Forcing creators through // this static Create function will enforce that clients actually create a // wrapper for the object. If clients fail to create a wrapper for a wrappable // object, the object will leak because we use the weak callback from the // wrapper as the signal to delete the wrapped object. -class ObjectTemplateBuilder; - -class Wrappable { +class WrappableBase { public: - // Retrieve (or create) the v8 wrapper object cooresponding to this object. - // If the type is created via the Constructor, then the GetWrapper would - // return the constructed object, otherwise it would try to create a new - // object constructed by GetObjectTemplateBuilder. - v8::Local GetWrapper(v8::Isolate* isolate); + WrappableBase(); + virtual ~WrappableBase(); + + // Retrieve the v8 wrapper object cooresponding to this object. + v8::Local GetWrapper(); // Returns the Isolate this object is created in. v8::Isolate* isolate() const { return isolate_; } // Bind the C++ class to the JS wrapper. - void Wrap(v8::Isolate* isolate, v8::Local wrapper); - - // The user should define T::BuildPrototype if they want to use Constructor - // to build a constructor function for this type. - static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + void InitWith(v8::Isolate* isolate, v8::Local wrapper); protected: - Wrappable(); - virtual ~Wrappable(); - - virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); - // Called after the "_init" method gets called in JavaScript. + // FIXME(zcbenz): Should remove this. virtual void AfterInit(v8::Isolate* isolate) {} private: friend struct internal::Destroyable; - static void FirstWeakCallback(const v8::WeakCallbackInfo& data); - static void SecondWeakCallback(const v8::WeakCallbackInfo& data); + static void FirstWeakCallback( + const v8::WeakCallbackInfo& data); + static void SecondWeakCallback( + const v8::WeakCallbackInfo& data); v8::Isolate* isolate_; - v8::UniquePersistent wrapper_; // Weak + v8::Global wrapper_; // Weak + + DISALLOW_COPY_AND_ASSIGN(WrappableBase); +}; + +template +class Wrappable : public WrappableBase { + public: + Wrappable() {} + + // Init the class with T::BuildPrototype. + void Init(v8::Isolate* isolate) { + // Fill the object template. + if (templ_.IsEmpty()) { + v8::Local templ = v8::ObjectTemplate::New(isolate); + T::BuildPrototype(isolate, templ); + templ_.Reset(isolate, templ); + } + + v8::Local wrapper; + v8::Local templ = v8::Local::New( + isolate, templ_); + // |wrapper| may be empty in some extreme cases, e.g., when + // Object.prototype.constructor is overwritten. + if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&wrapper)) { + // The current wrappable object will be no longer managed by V8. Delete + // this now. + delete this; + return; + } + InitWith(isolate, wrapper); + } + + private: + static v8::Global templ_; DISALLOW_COPY_AND_ASSIGN(Wrappable); }; +// static +template +v8::Global Wrappable::templ_; // This converter handles any subclass of Wrappable. -template -struct Converter::value>::type> { +template +struct Converter::value>::type> { static v8::Local ToV8(v8::Isolate* isolate, T* val) { if (val) - return val->GetWrapper(isolate); + return val->GetWrapper(); else return v8::Null(isolate); } static bool FromV8(v8::Isolate* isolate, v8::Local val, T** out) { - *out = static_cast(static_cast( + *out = static_cast(static_cast( internal::FromV8Impl(isolate, val))); - return *out != NULL; + return *out != nullptr; } }; From ea07d4c6c89d8d460e76b2d2ab9b0ebc51f9a432 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 May 2016 16:07:04 +0900 Subject: [PATCH 083/129] Leak Wrappable's template Since it is declared as static variable it will be released automatically when process exits, which causes crashes in renderer process because the template will then be released later than V8 is closed. This commit simply leaks the template so the crash won't happen, this leak should be fine since leaking resource on exit is not a bad thing. --- native_mate/wrappable.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 0cc1e3b8e12..6ec6420e117 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -77,15 +77,15 @@ class Wrappable : public WrappableBase { // Init the class with T::BuildPrototype. void Init(v8::Isolate* isolate) { // Fill the object template. - if (templ_.IsEmpty()) { + if (!templ_) { v8::Local templ = v8::ObjectTemplate::New(isolate); T::BuildPrototype(isolate, templ); - templ_.Reset(isolate, templ); + templ_ = new v8::Global(isolate, templ); } v8::Local wrapper; v8::Local templ = v8::Local::New( - isolate, templ_); + isolate, *templ_); // |wrapper| may be empty in some extreme cases, e.g., when // Object.prototype.constructor is overwritten. if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&wrapper)) { @@ -98,14 +98,14 @@ class Wrappable : public WrappableBase { } private: - static v8::Global templ_; + static v8::Global* templ_; // Leaked on purpose DISALLOW_COPY_AND_ASSIGN(Wrappable); }; // static template -v8::Global Wrappable::templ_; +v8::Global* Wrappable::templ_ = nullptr; // This converter handles any subclass of Wrappable. template From 4ad6ecd19617ac33c09e93ccb6d8e652ac1ac126 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 20 May 2016 15:38:26 +0900 Subject: [PATCH 084/129] Handle.ToV8 should return Object --- native_mate/handle.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/native_mate/handle.h b/native_mate/handle.h index 0fbd171319a..c5855f2f99b 100644 --- a/native_mate/handle.h +++ b/native_mate/handle.h @@ -18,7 +18,7 @@ class Handle { public: Handle() : object_(NULL) {} - Handle(v8::Local wrapper, T* object) + Handle(v8::Local wrapper, T* object) : wrapper_(wrapper), object_(object) { } @@ -31,11 +31,11 @@ class Handle { } T* operator->() const { return object_; } - v8::Local ToV8() const { return wrapper_; } + v8::Local ToV8() const { return wrapper_; } T* get() const { return object_; } private: - v8::Local wrapper_; + v8::Local wrapper_; T* object_; }; @@ -51,7 +51,7 @@ struct Converter > { if (!Converter::FromV8(isolate, val, &object)) { return false; } - *out = mate::Handle(val, object); + *out = mate::Handle(val->ToObject(), object); return true; } }; From e75f2aa087db346efc4b530f9e1ce7d3a72a3434 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 13 Jun 2016 09:26:04 +0900 Subject: [PATCH 085/129] Add converter for std::map --- native_mate/converter.h | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/native_mate/converter.h b/native_mate/converter.h index 6e51bcdcd9f..a891020b402 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -5,6 +5,7 @@ #ifndef NATIVE_MATE_CONVERTER_H_ #define NATIVE_MATE_CONVERTER_H_ +#include #include #include #include @@ -136,6 +137,11 @@ struct Converter { std::string* out); }; +v8::Local StringToSymbol(v8::Isolate* isolate, + const base::StringPiece& input); + +std::string V8ToString(v8::Local value); + template<> struct Converter > { static bool FromV8(v8::Isolate* isolate, @@ -255,6 +261,26 @@ struct Converter > { } }; +template +struct Converter > { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + std::map * out) { + if (!val->IsObject()) + return false; + + v8::Local dict = val->ToObject(); + v8::Local keys = dict->GetOwnPropertyNames(); + for (uint32_t i = 0; i < keys->Length(); ++i) { + v8::Local key = keys->Get(i); + T value; + if (Converter::FromV8(isolate, dict->Get(key), &value)) + (*out)[V8ToString(key)] = std::move(value); + } + return true; + } +}; + // Convenience functions that deduce T. template v8::Local ConvertToV8(v8::Isolate* isolate, const T& input) { @@ -303,14 +329,6 @@ bool TryConvertToV8(v8::Isolate* isolate, v8::Local* output) { return ToV8Traits::TryConvertToV8(isolate, input, output); } -inline v8::Local StringToV8( - v8::Isolate* isolate, - const base::StringPiece& input) { - return ConvertToV8(isolate, input).As(); -} - -v8::Local StringToSymbol(v8::Isolate* isolate, - const base::StringPiece& input); template bool ConvertFromV8(v8::Isolate* isolate, v8::Local input, @@ -318,7 +336,11 @@ bool ConvertFromV8(v8::Isolate* isolate, v8::Local input, return Converter::FromV8(isolate, input, result); } -std::string V8ToString(v8::Local value); +inline v8::Local StringToV8( + v8::Isolate* isolate, + const base::StringPiece& input) { + return ConvertToV8(isolate, input).As(); +} } // namespace mate From a1efa285204cb2fbbed450c317fb535a38ea8480 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 24 Jun 2016 14:40:47 +0900 Subject: [PATCH 086/129] Setup v8::MicrotasksScope for callbacks --- native_mate/function_template.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 0a607c0da05..4d347399f97 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -185,6 +185,8 @@ class Invoker, ArgTypes...> template void DispatchToCallback(base::Callback callback) { + v8::MicrotasksScope script_scope( + args_->isolate(), v8::MicrotasksScope::kRunMicrotasks); args_->Return(callback.Run(ArgumentHolder::value...)); } @@ -192,6 +194,8 @@ class Invoker, ArgTypes...> // expression to foo. As a result, we must specialize the case of Callbacks // that have the void return type. void DispatchToCallback(base::Callback callback) { + v8::MicrotasksScope script_scope( + args_->isolate(), v8::MicrotasksScope::kRunMicrotasks); callback.Run(ArgumentHolder::value...); } From 8a31e2d9c07fef117f2a5ad85dc67acb382b4d64 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 4 Jul 2016 15:07:50 +0900 Subject: [PATCH 087/129] Update to API changes of V8 5.2 --- native_mate/function_template.cc | 23 ++++++++++++++--------- native_mate/function_template.h | 7 +++++-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/native_mate/function_template.cc b/native_mate/function_template.cc index 3d404369719..a4bcb1141b7 100644 --- a/native_mate/function_template.cc +++ b/native_mate/function_template.cc @@ -9,8 +9,9 @@ namespace mate { namespace internal { CallbackHolderBase::CallbackHolderBase(v8::Isolate* isolate) - : MATE_PERSISTENT_INIT(isolate, v8_ref_, MATE_EXTERNAL_NEW(isolate, this)) { - MATE_PERSISTENT_SET_WEAK(v8_ref_, this, &CallbackHolderBase::WeakCallback); + : v8_ref_(isolate, v8::External::New(isolate, this)) { + v8_ref_.SetWeak(this, &CallbackHolderBase::FirstWeakCallback, + v8::WeakCallbackType::kParameter); } CallbackHolderBase::~CallbackHolderBase() { @@ -18,16 +19,20 @@ CallbackHolderBase::~CallbackHolderBase() { } v8::Local CallbackHolderBase::GetHandle(v8::Isolate* isolate) { - return MATE_PERSISTENT_TO_LOCAL(v8::External, isolate, v8_ref_); + return v8::Local::New(isolate, v8_ref_); } // static -MATE_WEAK_CALLBACK(CallbackHolderBase::WeakCallback, - v8::External, - CallbackHolderBase) { - MATE_WEAK_CALLBACK_INIT(CallbackHolderBase); - MATE_PERSISTENT_RESET(self->v8_ref_); - delete self; +void CallbackHolderBase::FirstWeakCallback( + const v8::WeakCallbackInfo& data) { + data.GetParameter()->v8_ref_.Reset(); + data.SetSecondPassCallback(SecondWeakCallback); +} + +// static +void CallbackHolderBase::SecondWeakCallback( + const v8::WeakCallbackInfo& data) { + delete data.GetParameter(); } } // namespace internal diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 4d347399f97..70b9921481f 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -62,9 +62,12 @@ class CallbackHolderBase { virtual ~CallbackHolderBase(); private: - static MATE_WEAK_CALLBACK(WeakCallback, v8::External, CallbackHolderBase); + static void FirstWeakCallback( + const v8::WeakCallbackInfo& data); + static void SecondWeakCallback( + const v8::WeakCallbackInfo& data); - v8::UniquePersistent v8_ref_; + v8::Global v8_ref_; DISALLOW_COPY_AND_ASSIGN(CallbackHolderBase); }; From d9bfe6a49d8585916bd8dc77165154afeee4e5b6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 21 Jul 2016 16:51:48 +0900 Subject: [PATCH 088/129] CHECK is not needed --- native_mate/function_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 70b9921481f..b390d8fb77a 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -223,7 +223,7 @@ struct Dispatcher { const v8::FunctionCallbackInfo& info) { Arguments args(info); v8::Local v8_holder; - CHECK(args.GetData(&v8_holder)); + args.GetData(&v8_holder); CallbackHolderBase* holder_base = reinterpret_cast( v8_holder->Value()); From bd20bde1a257b1b740dfeafc220c331ead3b66ab Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 15:14:48 +0900 Subject: [PATCH 089/129] Call the user call Init in Constructor --- native_mate/constructor.h | 10 ++++------ native_mate/wrappable.h | 8 +++++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 65c16c33598..278db078beb 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -123,7 +123,7 @@ inline WrappableBase* InvokeFactory( } // namespace internal -template +template class Constructor { public: typedef base::Callback WrappableFactoryFunction; @@ -140,6 +140,7 @@ class Constructor { isolate, base::Bind(&Constructor::New, factory)); constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->SetClassName(StringToV8(isolate, name_)); + T::BuildPrototype(isolate, constructor->PrototypeTemplate()); MATE_PERSISTENT_ASSIGN(v8::FunctionTemplate, isolate, constructor_, constructor); } @@ -167,9 +168,7 @@ class Constructor { } } - if (object) - object->InitWith(isolate, args->GetThis()); - else + if (!object) args->ThrowError(); MATE_METHOD_RETURN_UNDEFINED(); @@ -193,8 +192,7 @@ v8::Local CreateConstructor( const base::StringPiece& name, const base::Callback& callback) { v8::Local constructor = - Constructor(name).GetFunctionTemplate(isolate, callback); - T::BuildPrototype(isolate, constructor->PrototypeTemplate()); + Constructor(name).GetFunctionTemplate(isolate, callback); return constructor->GetFunction(); } diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 6ec6420e117..934cff7ee05 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -47,14 +47,15 @@ class WrappableBase { // Returns the Isolate this object is created in. v8::Isolate* isolate() const { return isolate_; } - // Bind the C++ class to the JS wrapper. - void InitWith(v8::Isolate* isolate, v8::Local wrapper); - protected: // Called after the "_init" method gets called in JavaScript. // FIXME(zcbenz): Should remove this. virtual void AfterInit(v8::Isolate* isolate) {} + // Bind the C++ class to the JS wrapper. + // This method should only be called by classes using Constructor. + void InitWith(v8::Isolate* isolate, v8::Local wrapper); + private: friend struct internal::Destroyable; @@ -74,6 +75,7 @@ class Wrappable : public WrappableBase { public: Wrappable() {} + protected: // Init the class with T::BuildPrototype. void Init(v8::Isolate* isolate) { // Fill the object template. From ab62755a886d424727f4959f4339555865490ae8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 15:28:09 +0900 Subject: [PATCH 090/129] Make InitWith virtual --- native_mate/wrappable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 934cff7ee05..4fd16bffc64 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -54,7 +54,7 @@ class WrappableBase { // Bind the C++ class to the JS wrapper. // This method should only be called by classes using Constructor. - void InitWith(v8::Isolate* isolate, v8::Local wrapper); + virtual void InitWith(v8::Isolate* isolate, v8::Local wrapper); private: friend struct internal::Destroyable; From d55c3c5030222a64726d01588188bc90019c47dd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 15:56:47 +0900 Subject: [PATCH 091/129] Turn Wrappable into using FunctionTemplate --- native_mate/wrappable.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 4fd16bffc64..3e696410467 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -49,7 +49,6 @@ class WrappableBase { protected: // Called after the "_init" method gets called in JavaScript. - // FIXME(zcbenz): Should remove this. virtual void AfterInit(v8::Isolate* isolate) {} // Bind the C++ class to the JS wrapper. @@ -80,17 +79,18 @@ class Wrappable : public WrappableBase { void Init(v8::Isolate* isolate) { // Fill the object template. if (!templ_) { - v8::Local templ = v8::ObjectTemplate::New(isolate); - T::BuildPrototype(isolate, templ); - templ_ = new v8::Global(isolate, templ); + v8::Local templ = v8::FunctionTemplate::New(isolate); + T::BuildPrototype(isolate, templ->PrototypeTemplate()); + templ_ = new v8::Global(isolate, templ); } v8::Local wrapper; - v8::Local templ = v8::Local::New( - isolate, *templ_); + v8::Local templ = + v8::Local::New(isolate, *templ_); // |wrapper| may be empty in some extreme cases, e.g., when // Object.prototype.constructor is overwritten. - if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&wrapper)) { + if (!templ->PrototypeTemplate()->NewInstance( + isolate->GetCurrentContext()).ToLocal(&wrapper)) { // The current wrappable object will be no longer managed by V8. Delete // this now. delete this; @@ -100,14 +100,14 @@ class Wrappable : public WrappableBase { } private: - static v8::Global* templ_; // Leaked on purpose + static v8::Global* templ_; // Leaked on purpose DISALLOW_COPY_AND_ASSIGN(Wrappable); }; // static template -v8::Global* Wrappable::templ_ = nullptr; +v8::Global* Wrappable::templ_ = nullptr; // This converter handles any subclass of Wrappable. template From 0a48af9ff75b31200da2a832dd8783e10bf77e3c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 16:08:00 +0900 Subject: [PATCH 092/129] Create objects from InstanceTemplate --- native_mate/object_template_builder.cc | 1 - native_mate/wrappable.h | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/native_mate/object_template_builder.cc b/native_mate/object_template_builder.cc index 5bf2cfb193c..ab4079e4eef 100644 --- a/native_mate/object_template_builder.cc +++ b/native_mate/object_template_builder.cc @@ -10,7 +10,6 @@ ObjectTemplateBuilder::ObjectTemplateBuilder( v8::Isolate* isolate, v8::Local templ) : isolate_(isolate), template_(templ) { - template_->SetInternalFieldCount(1); } ObjectTemplateBuilder::~ObjectTemplateBuilder() { diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 3e696410467..935028115ce 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -80,6 +80,7 @@ class Wrappable : public WrappableBase { // Fill the object template. if (!templ_) { v8::Local templ = v8::FunctionTemplate::New(isolate); + templ->InstanceTemplate()->SetInternalFieldCount(1); T::BuildPrototype(isolate, templ->PrototypeTemplate()); templ_ = new v8::Global(isolate, templ); } @@ -89,8 +90,8 @@ class Wrappable : public WrappableBase { v8::Local::New(isolate, *templ_); // |wrapper| may be empty in some extreme cases, e.g., when // Object.prototype.constructor is overwritten. - if (!templ->PrototypeTemplate()->NewInstance( - isolate->GetCurrentContext()).ToLocal(&wrapper)) { + if (!templ->InstanceTemplate()->NewInstance( + isolate->GetCurrentContext()).ToLocal(&wrapper)) { // The current wrappable object will be no longer managed by V8. Delete // this now. delete this; From a259d10bcbe4405259e5eb161f8319da8e791f39 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 16:20:29 +0900 Subject: [PATCH 093/129] NewOperatorFactory is not used --- native_mate/constructor.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 278db078beb..0bb81d019f8 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -180,12 +180,6 @@ class Constructor { DISALLOW_COPY_AND_ASSIGN(Constructor); }; - -template -WrappableBase* NewOperatorFactory() { - return new T; -} - template v8::Local CreateConstructor( v8::Isolate* isolate, From 2d26eebca8d6e0e8fdfdf68197699ae78018fbda Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 17:01:19 +0900 Subject: [PATCH 094/129] Remove the Constructor class --- native_mate/constructor.h | 87 +++++--------------- native_mate/constructor.h.pump | 139 -------------------------------- native_mate/function_template.h | 2 +- native_mate/wrappable.h | 70 +++++----------- native_mate/wrappable_base.h | 63 +++++++++++++++ native_mate_files.gypi | 1 + 6 files changed, 103 insertions(+), 259 deletions(-) delete mode 100644 native_mate/constructor.h.pump create mode 100644 native_mate/wrappable_base.h diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 0bb81d019f8..c6deead3ece 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -10,14 +10,10 @@ #define NATIVE_MATE_WRAPPABLE_CLASS_H_ #include "base/bind.h" -#include "base/compiler_specific.h" -#include "native_mate/wrappable.h" #include "native_mate/function_template.h" namespace mate { -class WrappableBase; - namespace internal { // This set of templates invokes a base::Callback by converting the Arguments @@ -120,76 +116,33 @@ inline WrappableBase* InvokeFactory( return callback.Run(a1, a2, a3, a4, a5, a6); }; -} // namespace internal - - -template -class Constructor { - public: - typedef base::Callback WrappableFactoryFunction; - - Constructor(const base::StringPiece& name) : name_(name) {} - virtual ~Constructor() { - MATE_PERSISTENT_RESET(constructor_); - } - - v8::Local GetFunctionTemplate( - v8::Isolate* isolate, const WrappableFactoryFunction& factory) { - if (constructor_.IsEmpty()) { - v8::Local constructor = CreateFunctionTemplate( - isolate, base::Bind(&Constructor::New, factory)); - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(StringToV8(isolate, name_)); - T::BuildPrototype(isolate, constructor->PrototypeTemplate()); - MATE_PERSISTENT_ASSIGN(v8::FunctionTemplate, isolate, constructor_, - constructor); - } - - return MATE_PERSISTENT_TO_LOCAL( - v8::FunctionTemplate, isolate, constructor_); - } - - private: - static MATE_METHOD_RETURN_TYPE New(const WrappableFactoryFunction& factory, - v8::Isolate* isolate, Arguments* args) { - if (!args->IsConstructCall()) { - args->ThrowError("Requires constructor call"); - MATE_METHOD_RETURN_UNDEFINED(); - } - - WrappableBase* object; - { - // Don't continue if the constructor throws an exception. - v8::TryCatch try_catch; - object = internal::InvokeFactory(args, factory); - if (try_catch.HasCaught()) { - try_catch.ReThrow(); - MATE_METHOD_RETURN_UNDEFINED(); - } - } - - if (!object) - args->ThrowError(); - +template +MATE_METHOD_RETURN_TYPE InvokeNew(const base::Callback& factory, + v8::Isolate* isolate, Arguments* args) { + if (!args->IsConstructCall()) { + args->ThrowError("Requires constructor call"); MATE_METHOD_RETURN_UNDEFINED(); } - base::StringPiece name_; - v8::Global constructor_; + WrappableBase* object; + { + // Don't continue if the constructor throws an exception. + v8::TryCatch try_catch; + object = internal::InvokeFactory(args, factory); + if (try_catch.HasCaught()) { + try_catch.ReThrow(); + MATE_METHOD_RETURN_UNDEFINED(); + } + } - DISALLOW_COPY_AND_ASSIGN(Constructor); -}; + if (!object) + args->ThrowError(); -template -v8::Local CreateConstructor( - v8::Isolate* isolate, - const base::StringPiece& name, - const base::Callback& callback) { - v8::Local constructor = - Constructor(name).GetFunctionTemplate(isolate, callback); - return constructor->GetFunction(); + MATE_METHOD_RETURN_UNDEFINED(); } +} // namespace internal + } // namespace mate #endif // NATIVE_MATE_WRAPPABLE_CLASS_H_ diff --git a/native_mate/constructor.h.pump b/native_mate/constructor.h.pump deleted file mode 100644 index 540493ccd53..00000000000 --- a/native_mate/constructor.h.pump +++ /dev/null @@ -1,139 +0,0 @@ -$$ This is a pump file for generating file templates. Pump is a python -$$ script that is part of the Google Test suite of utilities. Description -$$ can be found here: -$$ -$$ http://code.google.com/p/googletest/wiki/PumpManual -$$ -$var MAX_ARITY = 6 -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.chromium file. - -#ifndef NATIVE_MATE_WRAPPABLE_CLASS_H_ -#define NATIVE_MATE_WRAPPABLE_CLASS_H_ - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "native_mate/wrappable.h" -#include "native_mate/function_template.h" - -namespace mate { - -class WrappableBase; - -namespace internal { - -// This set of templates invokes a base::Callback by converting the Arguments -// into native types. It relies on the function_template.h to provide helper -// templates. -$range ARITY 0..MAX_ARITY -$for ARITY [[ -$range ARG 1..ARITY - -$if ARITY == 0 [[ - -]] $else [[ - -template<$for ARG , [[typename P$(ARG)]]> -]] - -inline WrappableBase* InvokeFactory( - Arguments* args, - const base::Callback& callback) { -$if ARITY != 0 [[ - - -$for ARG [[ typename CallbackParamTraits::LocalType a$(ARG); - -]] - if ($for ARG || - [[!GetNextArgument(args, 0, $if ARG == 1 [[true]] $else [[false]], &a$(ARG))]]) - return nullptr; -]] - - return callback.Run($for ARG , [[a$(ARG)]]); -}; - -]] - -} // namespace internal - - -template -class Constructor { - public: - typedef base::Callback WrappableFactoryFunction; - - Constructor(const base::StringPiece& name) : name_(name) {} - virtual ~Constructor() { - MATE_PERSISTENT_RESET(constructor_); - } - - v8::Local GetFunctionTemplate( - v8::Isolate* isolate, const WrappableFactoryFunction& factory) { - if (constructor_.IsEmpty()) { - v8::Local constructor = CreateFunctionTemplate( - isolate, base::Bind(&Constructor::New, factory)); - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(StringToV8(isolate, name_)); - MATE_PERSISTENT_ASSIGN(v8::FunctionTemplate, isolate, constructor_, - constructor); - } - - return MATE_PERSISTENT_TO_LOCAL( - v8::FunctionTemplate, isolate, constructor_); - } - - private: - static MATE_METHOD_RETURN_TYPE New(const WrappableFactoryFunction& factory, - v8::Isolate* isolate, Arguments* args) { - if (!args->IsConstructCall()) { - args->ThrowError("Requires constructor call"); - MATE_METHOD_RETURN_UNDEFINED(); - } - - WrappableBase* object; - { - // Don't continue if the constructor throws an exception. - v8::TryCatch try_catch; - object = internal::InvokeFactory(args, factory); - if (try_catch.HasCaught()) { - try_catch.ReThrow(); - MATE_METHOD_RETURN_UNDEFINED(); - } - } - - if (object) - object->InitWith(isolate, args->GetThis()); - else - args->ThrowError(); - - MATE_METHOD_RETURN_UNDEFINED(); - } - - base::StringPiece name_; - v8::Global constructor_; - - DISALLOW_COPY_AND_ASSIGN(Constructor); -}; - - -template -WrappableBase* NewOperatorFactory() { - return new T; -} - -template -v8::Local CreateConstructor( - v8::Isolate* isolate, - const base::StringPiece& name, - const base::Callback& callback) { - v8::Local constructor = - Constructor(name).GetFunctionTemplate(isolate, callback); - T::BuildPrototype(isolate, constructor->PrototypeTemplate()); - return constructor->GetFunction(); -} - -} // namespace mate - -#endif // NATIVE_MATE_WRAPPABLE_CLASS_H_ diff --git a/native_mate/function_template.h b/native_mate/function_template.h index b390d8fb77a..50c427a1dab 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -8,7 +8,7 @@ #include "base/callback.h" #include "base/logging.h" #include "native_mate/arguments.h" -#include "native_mate/wrappable.h" +#include "native_mate/wrappable_base.h" #include "v8/include/v8.h" namespace mate { diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 935028115ce..af4f796a1c3 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -5,75 +5,41 @@ #ifndef NATIVE_MATE_WRAPPABLE_H_ #define NATIVE_MATE_WRAPPABLE_H_ +#include "base/bind.h" #include "native_mate/compat.h" #include "native_mate/converter.h" +#include "native_mate/constructor.h" #include "native_mate/template_util.h" namespace mate { namespace internal { -struct Destroyable; - void* FromV8Impl(v8::Isolate* isolate, v8::Local val); } // namespace internal - -// Wrappable is a base class for C++ objects that have corresponding v8 wrapper -// objects. To retain a Wrappable object on the stack, use a gin::Handle. -// -// USAGE: -// // my_class.h -// class MyClass : Wrappable { -// public: -// ... -// }; -// -// Subclasses should also typically have private constructors and expose a -// static Create function that returns a mate::Handle. Forcing creators through -// this static Create function will enforce that clients actually create a -// wrapper for the object. If clients fail to create a wrapper for a wrappable -// object, the object will leak because we use the weak callback from the -// wrapper as the signal to delete the wrapped object. -class WrappableBase { - public: - WrappableBase(); - virtual ~WrappableBase(); - - // Retrieve the v8 wrapper object cooresponding to this object. - v8::Local GetWrapper(); - - // Returns the Isolate this object is created in. - v8::Isolate* isolate() const { return isolate_; } - - protected: - // Called after the "_init" method gets called in JavaScript. - virtual void AfterInit(v8::Isolate* isolate) {} - - // Bind the C++ class to the JS wrapper. - // This method should only be called by classes using Constructor. - virtual void InitWith(v8::Isolate* isolate, v8::Local wrapper); - - private: - friend struct internal::Destroyable; - - static void FirstWeakCallback( - const v8::WeakCallbackInfo& data); - static void SecondWeakCallback( - const v8::WeakCallbackInfo& data); - - v8::Isolate* isolate_; - v8::Global wrapper_; // Weak - - DISALLOW_COPY_AND_ASSIGN(WrappableBase); -}; - template class Wrappable : public WrappableBase { public: Wrappable() {} + template + static void SetConstructor(v8::Isolate* isolate, + const std::string& name, + const base::Callback& factory) { + v8::Local constructor = CreateFunctionTemplate( + isolate, base::Bind(&internal::InvokeNew, factory)); + constructor->InstanceTemplate()->SetInternalFieldCount(1); + constructor->SetClassName(StringToV8(isolate, name)); + T::BuildPrototype(isolate, constructor->PrototypeTemplate()); + templ_ = new v8::Global(isolate, constructor); + } + + static v8::Local GetConstructor(v8::Isolate* isolate) { + return v8::Local::New(isolate, *templ_)->GetFunction(); + } + protected: // Init the class with T::BuildPrototype. void Init(v8::Isolate* isolate) { diff --git a/native_mate/wrappable_base.h b/native_mate/wrappable_base.h new file mode 100644 index 00000000000..942d699f205 --- /dev/null +++ b/native_mate/wrappable_base.h @@ -0,0 +1,63 @@ +#ifndef NATIVE_MATE_WRAPPABLE_BASE_H_ +#define NATIVE_MATE_WRAPPABLE_BASE_H_ + +#include "native_mate/compat.h" + +namespace mate { + +namespace internal { +struct Destroyable; +} + +// Wrappable is a base class for C++ objects that have corresponding v8 wrapper +// objects. To retain a Wrappable object on the stack, use a gin::Handle. +// +// USAGE: +// // my_class.h +// class MyClass : Wrappable { +// public: +// ... +// }; +// +// Subclasses should also typically have private constructors and expose a +// static Create function that returns a mate::Handle. Forcing creators through +// this static Create function will enforce that clients actually create a +// wrapper for the object. If clients fail to create a wrapper for a wrappable +// object, the object will leak because we use the weak callback from the +// wrapper as the signal to delete the wrapped object. +class WrappableBase { + public: + WrappableBase(); + virtual ~WrappableBase(); + + // Retrieve the v8 wrapper object cooresponding to this object. + v8::Local GetWrapper(); + + // Returns the Isolate this object is created in. + v8::Isolate* isolate() const { return isolate_; } + + protected: + // Called after the "_init" method gets called in JavaScript. + virtual void AfterInit(v8::Isolate* isolate) {} + + // Bind the C++ class to the JS wrapper. + // This method should only be called by classes using Constructor. + virtual void InitWith(v8::Isolate* isolate, v8::Local wrapper); + + private: + friend struct internal::Destroyable; + + static void FirstWeakCallback( + const v8::WeakCallbackInfo& data); + static void SecondWeakCallback( + const v8::WeakCallbackInfo& data); + + v8::Isolate* isolate_; + v8::Global wrapper_; // Weak + + DISALLOW_COPY_AND_ASSIGN(WrappableBase); +}; + +} // namespace mate + +#endif // NATIVE_MATE_WRAPPABLE_BASE_H_ diff --git a/native_mate_files.gypi b/native_mate_files.gypi index f3035ee9ad6..cc4467804dd 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -22,6 +22,7 @@ 'native_mate/try_catch.h', 'native_mate/wrappable.cc', 'native_mate/wrappable.h', + 'native_mate/wrappable_base.h', ], }, } From 3a7a6efffb4b3cd68967466cb1cab337509e3b07 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 17:20:41 +0900 Subject: [PATCH 095/129] GetConstructor should init default constructor --- native_mate/converter.cc | 5 +++++ native_mate/converter.h | 2 ++ native_mate/wrappable.h | 19 +++++++++---------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/native_mate/converter.cc b/native_mate/converter.cc index 6f9b8f7700b..97fa455bbad 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -148,6 +148,11 @@ bool Converter::FromV8(Isolate* isolate, Local val, return true; } +Local Converter>::ToV8(Isolate* isolate, + Local val) { + return val; +} + bool Converter >::FromV8(Isolate* isolate, Local val, Local* out) { if (!val->IsFunction()) diff --git a/native_mate/converter.h b/native_mate/converter.h index a891020b402..ebb6273789d 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -144,6 +144,8 @@ std::string V8ToString(v8::Local value); template<> struct Converter > { + static v8::Local ToV8(v8::Isolate* isolate, + v8::Local val); static bool FromV8(v8::Isolate* isolate, v8::Local val, v8::Local* out); diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index af4f796a1c3..2dedc31547f 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -36,13 +36,7 @@ class Wrappable : public WrappableBase { templ_ = new v8::Global(isolate, constructor); } - static v8::Local GetConstructor(v8::Isolate* isolate) { - return v8::Local::New(isolate, *templ_)->GetFunction(); - } - - protected: - // Init the class with T::BuildPrototype. - void Init(v8::Isolate* isolate) { + static v8::Local GetConstructor(v8::Isolate* isolate) { // Fill the object template. if (!templ_) { v8::Local templ = v8::FunctionTemplate::New(isolate); @@ -50,12 +44,17 @@ class Wrappable : public WrappableBase { T::BuildPrototype(isolate, templ->PrototypeTemplate()); templ_ = new v8::Global(isolate, templ); } + return v8::Local::New(isolate, *templ_); + } + + protected: + // Init the class with T::BuildPrototype. + void Init(v8::Isolate* isolate) { + v8::Local templ = GetConstructor(isolate); - v8::Local wrapper; - v8::Local templ = - v8::Local::New(isolate, *templ_); // |wrapper| may be empty in some extreme cases, e.g., when // Object.prototype.constructor is overwritten. + v8::Local wrapper; if (!templ->InstanceTemplate()->NewInstance( isolate->GetCurrentContext()).ToLocal(&wrapper)) { // The current wrappable object will be no longer managed by V8. Delete From 4dbe0514941b3e6176414d7ceccc90d364726c30 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 18:06:20 +0900 Subject: [PATCH 096/129] Pass FunctionTemplate in BuildPrototype --- native_mate/wrappable.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 2dedc31547f..19552ce3c46 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -27,13 +27,13 @@ class Wrappable : public WrappableBase { template static void SetConstructor(v8::Isolate* isolate, const std::string& name, - const base::Callback& factory) { - v8::Local constructor = CreateFunctionTemplate( - isolate, base::Bind(&internal::InvokeNew, factory)); - constructor->InstanceTemplate()->SetInternalFieldCount(1); - constructor->SetClassName(StringToV8(isolate, name)); - T::BuildPrototype(isolate, constructor->PrototypeTemplate()); - templ_ = new v8::Global(isolate, constructor); + const base::Callback& constructor) { + v8::Local templ = CreateFunctionTemplate( + isolate, base::Bind(&internal::InvokeNew, constructor)); + templ->InstanceTemplate()->SetInternalFieldCount(1); + templ->SetClassName(StringToV8(isolate, name)); + T::BuildPrototype(isolate, templ); + templ_ = new v8::Global(isolate, templ); } static v8::Local GetConstructor(v8::Isolate* isolate) { @@ -41,7 +41,7 @@ class Wrappable : public WrappableBase { if (!templ_) { v8::Local templ = v8::FunctionTemplate::New(isolate); templ->InstanceTemplate()->SetInternalFieldCount(1); - T::BuildPrototype(isolate, templ->PrototypeTemplate()); + T::BuildPrototype(isolate, templ); templ_ = new v8::Global(isolate, templ); } return v8::Local::New(isolate, *templ_); From fa483e1fe012f873ad9812a67a66e2b7dbb570c6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 2 Aug 2016 19:27:58 +0900 Subject: [PATCH 097/129] Do not set constructor name in SetConstructor --- native_mate/wrappable.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 19552ce3c46..48f70ddf741 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -26,12 +26,10 @@ class Wrappable : public WrappableBase { template static void SetConstructor(v8::Isolate* isolate, - const std::string& name, const base::Callback& constructor) { v8::Local templ = CreateFunctionTemplate( isolate, base::Bind(&internal::InvokeNew, constructor)); templ->InstanceTemplate()->SetInternalFieldCount(1); - templ->SetClassName(StringToV8(isolate, name)); T::BuildPrototype(isolate, templ); templ_ = new v8::Global(isolate, templ); } From 1dbaec0edd919b9c0e51226a6e7127d911de4c31 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Aug 2016 09:34:33 -0700 Subject: [PATCH 098/129] Use ToDetailString for processing error message --- native_mate/arguments.cc | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/native_mate/arguments.cc b/native_mate/arguments.cc index ad62e207f84..a3b6cbf12ee 100644 --- a/native_mate/arguments.cc +++ b/native_mate/arguments.cc @@ -11,16 +11,11 @@ namespace mate { namespace { -std::string V8TypeAsString(v8::Local value) { - if (value.IsEmpty()) - return ""; - if (value->IsUndefined()) - return "undefined"; - if (value->IsNull()) - return "null"; +std::string V8TypeAsString(v8::Isolate* isolate, v8::Local value) { + v8::MaybeLocal details = value->ToDetailString(isolate); std::string result; - if (!ConvertFromV8(NULL, value, &result)) - return std::string(); + if (!details.IsEmpty()) + ConvertFromV8(isolate, details.ToLocalChecked(), &result); return result; } @@ -55,7 +50,7 @@ v8::Local Arguments::ThrowError() const { return ThrowTypeError(base::StringPrintf( "Error processing argument at index %d, conversion failure from %s", - next_, V8TypeAsString((*info_)[next_]).c_str())); + next_, V8TypeAsString(isolate_, (*info_)[next_]).c_str())); } v8::Local Arguments::ThrowError(const std::string& message) const { From 8155da152fb0cb458bfa8bf21298612097c4b5cc Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Aug 2016 10:04:04 -0700 Subject: [PATCH 099/129] Add back empty handle string --- native_mate/arguments.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/native_mate/arguments.cc b/native_mate/arguments.cc index a3b6cbf12ee..47915dd4265 100644 --- a/native_mate/arguments.cc +++ b/native_mate/arguments.cc @@ -12,6 +12,8 @@ namespace mate { namespace { std::string V8TypeAsString(v8::Isolate* isolate, v8::Local value) { + if (value.IsEmpty()) + return ""; v8::MaybeLocal details = value->ToDetailString(isolate); std::string result; if (!details.IsEmpty()) From 03b4f57d238ca8815dfe9957c5a608f2989c0237 Mon Sep 17 00:00:00 2001 From: Vadim Macagon Date: Fri, 12 Aug 2016 17:33:41 +0700 Subject: [PATCH 100/129] Add README --- README.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000000..bee64458722 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +> A fork of Chromium's [gin library][chromium-gin-lib] that makes it easier to +> marshal types between C++ and JavaScript. + +# Overview + +`native-mate` was forked from `gin` so that it could be used in +[Electron][electron] without conflicting with Node's Environment. It has also +been extended to allow Electron to create classes in JavaScript. + +With the help of Chromium's `base` library, `native-mate` makes writing JS +bindings very easy, and most of the intricate details of converting V8 types +to C++ types and back are taken care of auto-magically. In most cases there's +no need to use the raw V8 API to implement an API binding. + +For example, here's an API binding that doesn't use `native-mate`: + +```c++ +// static +void Shell::OpenItem(const v8::FunctionCallbackInfo& args) { + base::FilePath file_path; + if (!FromV8Arguments(args, &file_path)) + return node::ThrowTypeError("Bad argument"); + + platform_util::OpenItem(file_path); +} + +// static +void Shell::Initialize(v8::Handle target) { + NODE_SET_METHOD(target, "openItem", OpenItem); +} +``` + +And here's the same API binding using `native-mate`: + +```c++ +void Initialize(v8::Handle exports) { + mate::Dictionary dict(v8::Isolate::GetCurrent(), exports); + dict.SetMethod("openItem", &platform_util::OpenItem); +} +``` + +# Code Structure + +* `converter.h` - Templatized JS<->C++ conversion routines for many common C++ + types. You can define your own by specializing `Converter`. +* `function_template.h` - Create JavaScript functions that dispatch to any C++ + function, member function pointer, or `base::Callback`. +* `object_template_builder.h` - A handy utility for creation of `v8::ObjectTemplate`. +* `wrappable.h` - Base class for C++ classes that want to be owned by the V8 GC. + Wrappable objects are automatically deleted when GC discovers that nothing in + the V8 heap refers to them. This is also an easy way to expose C++ objects to + JavaScript. + + +[chromium-gin-lib]: https://code.google.com/p/chromium/codesearch#chromium/src/gin/README&sq=package:chromium +[electron]: http://electron.atom.io/ From 70092b493e9d17dfc8009c6b60ba35332bee8507 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 28 Nov 2016 00:41:44 +0530 Subject: [PATCH 101/129] create empty handle for null or undefined value --- native_mate/handle.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/native_mate/handle.h b/native_mate/handle.h index c5855f2f99b..60bd2348dd6 100644 --- a/native_mate/handle.h +++ b/native_mate/handle.h @@ -48,6 +48,10 @@ struct Converter > { static bool FromV8(v8::Isolate* isolate, v8::Local val, mate::Handle* out) { T* object = NULL; + if (val->IsNull() || val->IsUndefined()) { + *out = mate::Handle(); + return true; + } if (!Converter::FromV8(isolate, val, &object)) { return false; } From c78a6fa7d4d3e828290e5c95dd0573b843158a13 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 11 Jan 2017 17:49:41 -0800 Subject: [PATCH 102/129] Support setting read-only property value --- native_mate/dictionary.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 38927c85374..2eb52922d26 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -93,6 +93,19 @@ class Dictionary { return !result.IsNothing() && result.FromJust(); } + template + bool SetReadOnly(const base::StringPiece& key, T val) { + v8::Local v8_value; + if (!TryConvertToV8(isolate_, val, &v8_value)) + return false; + v8::Maybe result = + GetHandle()->DefineOwnProperty(isolate_->GetCurrentContext(), + StringToV8(isolate_, key), + v8_value, + v8::ReadOnly); + return !result.IsNothing() && result.FromJust(); + } + template bool SetMethod(const base::StringPiece& key, const T& callback) { return GetHandle()->Set( From 7197368c6d9e36696d23d33ec603701789da329d Mon Sep 17 00:00:00 2001 From: renaesop Date: Mon, 6 Feb 2017 16:54:11 +0800 Subject: [PATCH 103/129] Add Converter>::ToV8 --- native_mate/converter.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/native_mate/converter.h b/native_mate/converter.h index ebb6273789d..02e79b8d8b0 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -281,6 +281,15 @@ struct Converter > { } return true; } + static v8::Local ToV8(v8::Isolate* isolate, + const std::map& val) { + v8::Local result = v8::Object::New(isolate); + for (auto i = val.begin(); i != val.end(); i++) { + result->Set(Converter::ToV8(isolate, i->first), + Converter::ToV8(isolate, i->second)); + } + return result; + } }; // Convenience functions that deduce T. From db542f2a261acbab8582a4a2445af13c80c39903 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 17 Feb 2017 08:39:54 -0800 Subject: [PATCH 104/129] Add CI build through Electron --- .travis.yml | 18 ++++++++++++++++++ appveyor.yml | 24 ++++++++++++++++++++++++ script/cibuild | 27 +++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 .travis.yml create mode 100644 appveyor.yml create mode 100755 script/cibuild diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..06118787cb7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +notifications: + email: false + +language: node_js +node_js: + - "6" +os: + - linux + - osx +env: + - TARGET_ARCH=x64 +osx_image: xcode7.3 + +script: './script/cibuild' + +branches: + only: + - master diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000000..46a91007e6e --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,24 @@ +version: "{build}" + +clone_depth: 10 + +os: Visual Studio 2015 + +init: + - git config --global core.autocrlf input + +platform: + - x64 + +install: + - cmd: SET PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH% + - cmd: SET PATH=C:\python27;%PATH% + - cmd: bash script/cibuild + +branches: + only: + - master + +# disable build and test phases +build: off +test: off diff --git a/script/cibuild b/script/cibuild new file mode 100755 index 00000000000..5370b287fe4 --- /dev/null +++ b/script/cibuild @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -ex + +# Make cloned repository complete +git fetch --unshallow origin HEAD + +# Clone Electron +git clone https://github.com/electron/electron --depth 1 --recursive + +# Checkout current native_mate commit into Electron +cd electron/vendor/native_mate +git fetch ../../.. +git reset --hard FETCH_HEAD + +# Commit change +cd ../.. +git add vendor/native_mate +git config --local user.email "test@github.com" +git config --local user.name "Test" +git commit --message 'Upgrading native_mate' + +# Bootstrap Electron +npm run bootstrap -- --dev + +# Build Electron with native_mate commit +npm run build From f56ec818fba673d51e3205a13026333e65eb7f6f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 15 Feb 2017 15:18:11 -0800 Subject: [PATCH 105/129] Support 5 argument member function --- native_mate/template_util.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/native_mate/template_util.h b/native_mate/template_util.h index e1632a2d566..d4ce819d7e8 100644 --- a/native_mate/template_util.h +++ b/native_mate/template_util.h @@ -60,6 +60,13 @@ template struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + template struct is_same : public false_type {}; template struct is_same : true_type {}; From d2b97668862ffe5570b602e59a95782312979d09 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 17 Feb 2017 08:51:21 -0800 Subject: [PATCH 106/129] Use std functions instead of template_util --- native_mate/object_template_builder.h | 5 +- native_mate/template_util.h | 157 -------------------------- native_mate/wrappable.h | 1 - native_mate_files.gypi | 1 - 4 files changed, 2 insertions(+), 162 deletions(-) delete mode 100644 native_mate/template_util.h diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index a4335901a1f..de953d381c2 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -10,7 +10,6 @@ #include "base/strings/string_piece.h" #include "native_mate/converter.h" #include "native_mate/function_template.h" -#include "native_mate/template_util.h" #include "v8/include/v8.h" namespace mate { @@ -42,8 +41,8 @@ struct CallbackTraits > { // come from the the JavaScript "this" object the function was called on, not // from the first normal parameter. template -struct CallbackTraits::value>::type> { +struct CallbackTraits::value>::type> { static v8::Local CreateTemplate( v8::Isolate* isolate, T callback) { int flags = HolderIsFirstArgument; diff --git a/native_mate/template_util.h b/native_mate/template_util.h deleted file mode 100644 index d4ce819d7e8..00000000000 --- a/native_mate/template_util.h +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NATIVE_MATE_TEMPLATE_UTIL_H_ -#define NATIVE_MATE_TEMPLATE_UTIL_H_ - -#include // For size_t. - -#include "build/build_config.h" - -namespace mate { - -// template definitions from tr1 - -template -struct integral_constant { - static const T value = v; - typedef T value_type; - typedef integral_constant type; -}; - -template const T integral_constant::value; - -typedef integral_constant true_type; -typedef integral_constant false_type; - -template struct is_pointer : false_type {}; -template struct is_pointer : true_type {}; - -// Member function pointer detection up to four params. Add more as needed -// below. This is built-in to C++ 11, and we can remove this when we switch. -template -struct is_member_function_pointer : false_type {}; - -template -struct is_member_function_pointer : true_type {}; -template -struct is_member_function_pointer : true_type {}; - -template -struct is_member_function_pointer : true_type {}; -template -struct is_member_function_pointer : true_type {}; - -template -struct is_member_function_pointer : true_type {}; -template -struct is_member_function_pointer : true_type {}; - -template -struct is_member_function_pointer : true_type {}; -template -struct is_member_function_pointer : true_type {}; - -template -struct is_member_function_pointer : true_type {}; -template -struct is_member_function_pointer : true_type {}; - -template -struct is_member_function_pointer : true_type {}; -template -struct is_member_function_pointer : true_type {}; - - -template struct is_same : public false_type {}; -template struct is_same : true_type {}; - -template struct is_array : public false_type {}; -template struct is_array : public true_type {}; -template struct is_array : public true_type {}; - -template struct is_non_const_reference : false_type {}; -template struct is_non_const_reference : true_type {}; -template struct is_non_const_reference : false_type {}; - -template struct is_const : false_type {}; -template struct is_const : true_type {}; - -template struct is_void : false_type {}; -template <> struct is_void : true_type {}; - -namespace internal { - -// Types YesType and NoType are guaranteed such that sizeof(YesType) < -// sizeof(NoType). -typedef char YesType; - -struct NoType { - YesType dummy[2]; -}; - -// This class is an implementation detail for is_convertible, and you -// don't need to know how it works to use is_convertible. For those -// who care: we declare two different functions, one whose argument is -// of type To and one with a variadic argument list. We give them -// return types of different size, so we can use sizeof to trick the -// compiler into telling us which function it would have chosen if we -// had called it with an argument of type From. See Alexandrescu's -// _Modern C++ Design_ for more details on this sort of trick. - -struct ConvertHelper { - template - static YesType Test(To); - - template - static NoType Test(...); - - template - static From& Create(); -}; - -// Used to determine if a type is a struct/union/class. Inspired by Boost's -// is_class type_trait implementation. -struct IsClassHelper { - template - static YesType Test(void(C::*)(void)); - - template - static NoType Test(...); -}; - -} // namespace internal - -// Inherits from true_type if From is convertible to To, false_type otherwise. -// -// Note that if the type is convertible, this will be a true_type REGARDLESS -// of whether or not the conversion would emit a warning. -template -struct is_convertible - : integral_constant( - internal::ConvertHelper::Create())) == - sizeof(internal::YesType)> { -}; - -template -struct is_class - : integral_constant(0)) == - sizeof(internal::YesType)> { -}; - -template -struct enable_if {}; - -template -struct enable_if { typedef T type; }; - -} // namespace mate - -#endif // NATIVE_MATE_TEMPLATE_UTIL_H_ diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 48f70ddf741..29c2844fbfe 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -9,7 +9,6 @@ #include "native_mate/compat.h" #include "native_mate/converter.h" #include "native_mate/constructor.h" -#include "native_mate/template_util.h" namespace mate { diff --git a/native_mate_files.gypi b/native_mate_files.gypi index cc4467804dd..867ec7999c8 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -17,7 +17,6 @@ 'native_mate/persistent_dictionary.cc', 'native_mate/persistent_dictionary.h', 'native_mate/scoped_persistent.h', - 'native_mate/template_util.h', 'native_mate/try_catch.cc', 'native_mate/try_catch.h', 'native_mate/wrappable.cc', From ed909cd54c5f3d01d15672d79c5b7cf924e24463 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 8 Mar 2017 16:33:05 +0900 Subject: [PATCH 107/129] Make Wrappable thread safe --- native_mate/wrappable.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 29c2844fbfe..561f9d2a988 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -6,6 +6,8 @@ #define NATIVE_MATE_WRAPPABLE_H_ #include "base/bind.h" +#include "base/lazy_instance.h" +#include "base/threading/thread_local.h" #include "native_mate/compat.h" #include "native_mate/converter.h" #include "native_mate/constructor.h" @@ -30,18 +32,18 @@ class Wrappable : public WrappableBase { isolate, base::Bind(&internal::InvokeNew, constructor)); templ->InstanceTemplate()->SetInternalFieldCount(1); T::BuildPrototype(isolate, templ); - templ_ = new v8::Global(isolate, templ); + templ_.Get().Set(new v8::Global(isolate, templ)); } static v8::Local GetConstructor(v8::Isolate* isolate) { // Fill the object template. - if (!templ_) { + if (!templ_.Get().Get()) { v8::Local templ = v8::FunctionTemplate::New(isolate); templ->InstanceTemplate()->SetInternalFieldCount(1); T::BuildPrototype(isolate, templ); - templ_ = new v8::Global(isolate, templ); + templ_.Get().Set(new v8::Global(isolate, templ)); } - return v8::Local::New(isolate, *templ_); + return v8::Local::New(isolate, *templ_.Get().Get()); } protected: @@ -63,14 +65,16 @@ class Wrappable : public WrappableBase { } private: - static v8::Global* templ_; // Leaked on purpose + static base::LazyInstance>> templ_; DISALLOW_COPY_AND_ASSIGN(Wrappable); }; // static template -v8::Global* Wrappable::templ_ = nullptr; +base::LazyInstance>> +Wrappable::templ_ = LAZY_INSTANCE_INITIALIZER; // This converter handles any subclass of Wrappable. template From fd0e7dc4ab778f0d1ccda6c9640464ea06ee771e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 8 Mar 2017 17:11:29 +0900 Subject: [PATCH 108/129] Use gin to manage FunctionTemplate Sadly there is no way for us to know when V8 is closing, thus it is impossible for us to clean the FunctionTemplate on exit at the right time, which is critcal for multi-thread environment. --- native_mate/wrappable.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 561f9d2a988..8c1b480fc64 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -6,11 +6,10 @@ #define NATIVE_MATE_WRAPPABLE_H_ #include "base/bind.h" -#include "base/lazy_instance.h" -#include "base/threading/thread_local.h" #include "native_mate/compat.h" #include "native_mate/converter.h" #include "native_mate/constructor.h" +#include "gin/per_isolate_data.h" namespace mate { @@ -32,18 +31,21 @@ class Wrappable : public WrappableBase { isolate, base::Bind(&internal::InvokeNew, constructor)); templ->InstanceTemplate()->SetInternalFieldCount(1); T::BuildPrototype(isolate, templ); - templ_.Get().Set(new v8::Global(isolate, templ)); + gin::PerIsolateData::From(isolate)->SetFunctionTemplate( + &kWrapperInfo, templ); } static v8::Local GetConstructor(v8::Isolate* isolate) { // Fill the object template. - if (!templ_.Get().Get()) { - v8::Local templ = v8::FunctionTemplate::New(isolate); + auto data = gin::PerIsolateData::From(isolate); + auto templ = data->GetFunctionTemplate(&kWrapperInfo); + if (templ.IsEmpty()) { + templ = v8::FunctionTemplate::New(isolate); templ->InstanceTemplate()->SetInternalFieldCount(1); T::BuildPrototype(isolate, templ); - templ_.Get().Set(new v8::Global(isolate, templ)); + data->SetFunctionTemplate(&kWrapperInfo, templ); } - return v8::Local::New(isolate, *templ_.Get().Get()); + return templ; } protected: @@ -65,16 +67,14 @@ class Wrappable : public WrappableBase { } private: - static base::LazyInstance>> templ_; + static gin::WrapperInfo kWrapperInfo; DISALLOW_COPY_AND_ASSIGN(Wrappable); }; // static template -base::LazyInstance>> -Wrappable::templ_ = LAZY_INSTANCE_INITIALIZER; +gin::WrapperInfo Wrappable::kWrapperInfo = { gin::kEmbedderNativeGin }; // This converter handles any subclass of Wrappable. template From ff8f439afdccc5693906e994655994ef0308a212 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Wed, 12 Apr 2017 15:51:28 +0200 Subject: [PATCH 109/129] add ability to set high memory usage, skipping the second round of GC callbacks --- native_mate/wrappable.cc | 16 ++++++++++++---- native_mate/wrappable_base.h | 5 +++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index c42bc96dab6..6743a139f54 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -11,12 +11,15 @@ namespace mate { WrappableBase::WrappableBase() - : isolate_(nullptr) { + : isolate_(nullptr), high_memory_(false) { } WrappableBase::~WrappableBase() { - if (!wrapper_.IsEmpty()) - GetWrapper()->SetAlignedPointerInInternalField(0, nullptr); + if (wrapper_.IsEmpty()) + return; + + GetWrapper()->SetAlignedPointerInInternalField(0, nullptr); + wrapper_.ClearWeak(); wrapper_.Reset(); } @@ -32,6 +35,7 @@ void WrappableBase::InitWith(v8::Isolate* isolate, wrapper->SetAlignedPointerInInternalField(0, this); wrapper_.Reset(isolate, wrapper); wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter); + wrapper_.MarkIndependent(); // Call object._init if we have one. v8::Local init; @@ -46,7 +50,11 @@ void WrappableBase::FirstWeakCallback( const v8::WeakCallbackInfo& data) { WrappableBase* wrappable = data.GetParameter(); wrappable->wrapper_.Reset(); - data.SetSecondPassCallback(SecondWeakCallback); + if (wrappable->high_memory_) { + delete wrappable; + } else { + data.SetSecondPassCallback(SecondWeakCallback); + } } // static diff --git a/native_mate/wrappable_base.h b/native_mate/wrappable_base.h index 942d699f205..17a10fc0d8b 100644 --- a/native_mate/wrappable_base.h +++ b/native_mate/wrappable_base.h @@ -44,6 +44,10 @@ class WrappableBase { // This method should only be called by classes using Constructor. virtual void InitWith(v8::Isolate* isolate, v8::Local wrapper); + // Marks wrapped object as high memory usage + // Deletes the wrapped object on the first round of GC callbacks + void MarkHighMemoryUsage() { high_memory_ = true; } + private: friend struct internal::Destroyable; @@ -54,6 +58,7 @@ class WrappableBase { v8::Isolate* isolate_; v8::Global wrapper_; // Weak + bool high_memory_; DISALLOW_COPY_AND_ASSIGN(WrappableBase); }; From c8cc021ea126132764504ec7a794600d2f5cb3fb Mon Sep 17 00:00:00 2001 From: Tse Kit Yam Date: Tue, 9 May 2017 15:24:43 +0800 Subject: [PATCH 110/129] Fix broken link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bee64458722..e5d056bfed9 100644 --- a/README.md +++ b/README.md @@ -52,5 +52,5 @@ void Initialize(v8::Handle exports) { JavaScript. -[chromium-gin-lib]: https://code.google.com/p/chromium/codesearch#chromium/src/gin/README&sq=package:chromium +[chromium-gin-lib]: https://code.google.com/p/chromium/codesearch#chromium/src/gin/README.md&sq=package:chromium [electron]: http://electron.atom.io/ From 747495e77c69e457286c262057daece54058e577 Mon Sep 17 00:00:00 2001 From: Vadim Macagon Date: Tue, 15 Aug 2017 22:39:11 +0700 Subject: [PATCH 111/129] Add a converter for `nullptr_t` --- native_mate/converter.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/native_mate/converter.h b/native_mate/converter.h index 02e79b8d8b0..07c01d6529a 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -40,6 +40,13 @@ struct Converter { } }; +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, std::nullptr_t val) { + return v8::Null(isolate); + } +}; + template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, From 6ea2755095a6d5a73e94da5d4de11214201a1ce7 Mon Sep 17 00:00:00 2001 From: Matt Crocker Date: Mon, 23 Oct 2017 23:19:23 -0700 Subject: [PATCH 112/129] Upstream Muon changes to avoid crashing --- native_mate/function_template.h | 3 +++ native_mate/wrappable.cc | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 50c427a1dab..abbe7b5326e 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -21,6 +21,9 @@ namespace internal { struct Destroyable { static void Destroy(Arguments* args) { + if (IsDestroyed(args)) + return; + v8::Local holder = args->GetHolder(); delete static_cast( holder->GetAlignedPointerFromInternalField(0)); diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 6743a139f54..005c83b8dc0 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -24,8 +24,11 @@ WrappableBase::~WrappableBase() { } v8::Local WrappableBase::GetWrapper() { - CHECK(!wrapper_.IsEmpty()); - return v8::Local::New(isolate_, wrapper_); + DCHECK(!wrapper_.IsEmpty()); + if (!wrapper_.IsEmpty()) + return v8::Local::New(isolate_, wrapper_); + else + return v8::Local(); } void WrappableBase::InitWith(v8::Isolate* isolate, From 40bd3336a5ce6ee0323b50c33641bb2e734f7f51 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Mon, 27 Nov 2017 00:50:51 +0100 Subject: [PATCH 113/129] only mark handle as independent when it's a high memory user --- native_mate/wrappable.cc | 12 ++++++++++-- native_mate/wrappable_base.h | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 005c83b8dc0..8a284b76445 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -17,7 +17,7 @@ WrappableBase::WrappableBase() WrappableBase::~WrappableBase() { if (wrapper_.IsEmpty()) return; - + GetWrapper()->SetAlignedPointerInInternalField(0, nullptr); wrapper_.ClearWeak(); wrapper_.Reset(); @@ -38,7 +38,9 @@ void WrappableBase::InitWith(v8::Isolate* isolate, wrapper->SetAlignedPointerInInternalField(0, this); wrapper_.Reset(isolate, wrapper); wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter); - wrapper_.MarkIndependent(); + + if (high_memory_) + wrapper_.MarkIndependent(); // Call object._init if we have one. v8::Local init; @@ -48,6 +50,12 @@ void WrappableBase::InitWith(v8::Isolate* isolate, AfterInit(isolate); } +void WrappableBase::MarkHighMemoryUsage() { + high_memory_ = true; + if (!wrapper_.IsEmpty()) + wrapper_.MarkIndependent(); +} + // static void WrappableBase::FirstWeakCallback( const v8::WeakCallbackInfo& data) { diff --git a/native_mate/wrappable_base.h b/native_mate/wrappable_base.h index 17a10fc0d8b..ba0087fa06d 100644 --- a/native_mate/wrappable_base.h +++ b/native_mate/wrappable_base.h @@ -46,7 +46,7 @@ class WrappableBase { // Marks wrapped object as high memory usage // Deletes the wrapped object on the first round of GC callbacks - void MarkHighMemoryUsage() { high_memory_ = true; } + virtual void MarkHighMemoryUsage(); private: friend struct internal::Destroyable; From e0b77db46f9dc5ae49fe4440290b7036569eca5f Mon Sep 17 00:00:00 2001 From: Zhuo Lu Date: Wed, 13 Dec 2017 13:26:51 -0800 Subject: [PATCH 114/129] Remove WrappableBase::GetWrapper() DCHECK --- native_mate/wrappable.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 8a284b76445..589517ee903 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -24,7 +24,6 @@ WrappableBase::~WrappableBase() { } v8::Local WrappableBase::GetWrapper() { - DCHECK(!wrapper_.IsEmpty()); if (!wrapper_.IsEmpty()) return v8::Local::New(isolate_, wrapper_); else From 66c0d6620b6cd49b2e1f807759741794754fc926 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 18 Dec 2017 14:55:27 +1100 Subject: [PATCH 115/129] virtual members need a virtual destructor --- native_mate/dictionary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 2eb52922d26..5a56a9e06bb 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -35,7 +35,7 @@ class Dictionary { public: Dictionary(); Dictionary(v8::Isolate* isolate, v8::Local object); - ~Dictionary(); + virtual ~Dictionary(); static Dictionary CreateEmpty(v8::Isolate* isolate); From 91ee99ab8a66f7cd1b3ecb874d16a7ca38e35793 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 20 Feb 2018 09:29:02 +0900 Subject: [PATCH 116/129] GetWrapper should be const --- native_mate/wrappable.cc | 2 +- native_mate/wrappable_base.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 589517ee903..256198502e6 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -23,7 +23,7 @@ WrappableBase::~WrappableBase() { wrapper_.Reset(); } -v8::Local WrappableBase::GetWrapper() { +v8::Local WrappableBase::GetWrapper() const { if (!wrapper_.IsEmpty()) return v8::Local::New(isolate_, wrapper_); else diff --git a/native_mate/wrappable_base.h b/native_mate/wrappable_base.h index ba0087fa06d..11212c21011 100644 --- a/native_mate/wrappable_base.h +++ b/native_mate/wrappable_base.h @@ -31,7 +31,7 @@ class WrappableBase { virtual ~WrappableBase(); // Retrieve the v8 wrapper object cooresponding to this object. - v8::Local GetWrapper(); + v8::Local GetWrapper() const; // Returns the Isolate this object is created in. v8::Isolate* isolate() const { return isolate_; } From 31206cfa0a108df1ba65efe1f4430188b156f790 Mon Sep 17 00:00:00 2001 From: Guangyuan Yang Date: Thu, 22 Mar 2018 14:14:26 -0400 Subject: [PATCH 117/129] Add support for FreeBSD --- native_mate/converter.cc | 2 +- native_mate/converter.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native_mate/converter.cc b/native_mate/converter.cc index 97fa455bbad..9edf940938d 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -32,7 +32,7 @@ bool Converter::FromV8(Isolate* isolate, Local val, bool* out) { return true; } -#if !defined(OS_LINUX) +#if !defined(OS_LINUX) && !defined(OS_FREEBSD) Local Converter::ToV8(Isolate* isolate, unsigned long val) { return MATE_INTEGER_NEW(isolate, val); diff --git a/native_mate/converter.h b/native_mate/converter.h index 07c01d6529a..b0321c19a8b 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -56,7 +56,7 @@ struct Converter { bool* out); }; -#if !defined(OS_LINUX) +#if !defined(OS_LINUX) && !defined(OS_FREEBSD) template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, From 894c96f39fd0faafece86842e4b45a05727c483c Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Sat, 31 Mar 2018 15:08:17 +0530 Subject: [PATCH 118/129] Remove usage of MarkIndependent api https://bugs.chromium.org/p/chromium/issues/detail?id=780749 Use Active/Not Active as indicator whether the Scavenger can drop wrappers --- native_mate/wrappable.cc | 19 ++----------------- native_mate/wrappable_base.h | 5 ----- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 256198502e6..3d5ce44ac0a 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -10,9 +10,7 @@ namespace mate { -WrappableBase::WrappableBase() - : isolate_(nullptr), high_memory_(false) { -} +WrappableBase::WrappableBase() : isolate_(nullptr) {} WrappableBase::~WrappableBase() { if (wrapper_.IsEmpty()) @@ -38,9 +36,6 @@ void WrappableBase::InitWith(v8::Isolate* isolate, wrapper_.Reset(isolate, wrapper); wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter); - if (high_memory_) - wrapper_.MarkIndependent(); - // Call object._init if we have one. v8::Local init; if (Dictionary(isolate, wrapper).Get("_init", &init)) @@ -49,22 +44,12 @@ void WrappableBase::InitWith(v8::Isolate* isolate, AfterInit(isolate); } -void WrappableBase::MarkHighMemoryUsage() { - high_memory_ = true; - if (!wrapper_.IsEmpty()) - wrapper_.MarkIndependent(); -} - // static void WrappableBase::FirstWeakCallback( const v8::WeakCallbackInfo& data) { WrappableBase* wrappable = data.GetParameter(); wrappable->wrapper_.Reset(); - if (wrappable->high_memory_) { - delete wrappable; - } else { - data.SetSecondPassCallback(SecondWeakCallback); - } + data.SetSecondPassCallback(SecondWeakCallback); } // static diff --git a/native_mate/wrappable_base.h b/native_mate/wrappable_base.h index 11212c21011..501bbee961e 100644 --- a/native_mate/wrappable_base.h +++ b/native_mate/wrappable_base.h @@ -44,10 +44,6 @@ class WrappableBase { // This method should only be called by classes using Constructor. virtual void InitWith(v8::Isolate* isolate, v8::Local wrapper); - // Marks wrapped object as high memory usage - // Deletes the wrapped object on the first round of GC callbacks - virtual void MarkHighMemoryUsage(); - private: friend struct internal::Destroyable; @@ -58,7 +54,6 @@ class WrappableBase { v8::Isolate* isolate_; v8::Global wrapper_; // Weak - bool high_memory_; DISALLOW_COPY_AND_ASSIGN(WrappableBase); }; From e20cf8687e5e0e1b807ced4c90695ee22de220b8 Mon Sep 17 00:00:00 2001 From: Nitish Sakhawalkar Date: Tue, 10 Apr 2018 16:17:20 -0700 Subject: [PATCH 119/129] Address breaking API --- native_mate/constructor.h | 2 +- native_mate/object_template_builder.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index c6deead3ece..7cad253e0ea 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -127,7 +127,7 @@ MATE_METHOD_RETURN_TYPE InvokeNew(const base::Callback& factory, WrappableBase* object; { // Don't continue if the constructor throws an exception. - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); object = internal::InvokeFactory(args, factory); if (try_catch.HasCaught()) { try_catch.ReThrow(); diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index de953d381c2..533576f9863 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -69,7 +69,7 @@ class ObjectTemplateBuilder { public: explicit ObjectTemplateBuilder( v8::Isolate* isolate, - v8::Local templ = v8::ObjectTemplate::New()); + v8::Local templ); ~ObjectTemplateBuilder(); // It's against Google C++ style to return a non-const ref, but we take some From 3dce1dd240d1e5cf44318d7badd81084e4af3155 Mon Sep 17 00:00:00 2001 From: Aleksei Kuzmin Date: Thu, 12 Apr 2018 15:36:44 +0200 Subject: [PATCH 120/129] Fix Value::ToDetailString() call See https://chromium-review.googlesource.com/848782 --- native_mate/arguments.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native_mate/arguments.cc b/native_mate/arguments.cc index 47915dd4265..130d77d435a 100644 --- a/native_mate/arguments.cc +++ b/native_mate/arguments.cc @@ -14,7 +14,8 @@ namespace { std::string V8TypeAsString(v8::Isolate* isolate, v8::Local value) { if (value.IsEmpty()) return ""; - v8::MaybeLocal details = value->ToDetailString(isolate); + v8::MaybeLocal details = + value->ToDetailString(isolate->GetCurrentContext()); std::string result; if (!details.IsEmpty()) ConvertFromV8(isolate, details.ToLocalChecked(), &result); From a10564c3b10c7827914f5c3b77e2879408739ad7 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Sun, 15 Apr 2018 13:26:35 -0400 Subject: [PATCH 121/129] Revert "Address breaking API" This reverts commit e20cf8687e5e0e1b807ced4c90695ee22de220b8. --- native_mate/constructor.h | 2 +- native_mate/object_template_builder.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 7cad253e0ea..c6deead3ece 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -127,7 +127,7 @@ MATE_METHOD_RETURN_TYPE InvokeNew(const base::Callback& factory, WrappableBase* object; { // Don't continue if the constructor throws an exception. - v8::TryCatch try_catch(isolate); + v8::TryCatch try_catch; object = internal::InvokeFactory(args, factory); if (try_catch.HasCaught()) { try_catch.ReThrow(); diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index 533576f9863..de953d381c2 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -69,7 +69,7 @@ class ObjectTemplateBuilder { public: explicit ObjectTemplateBuilder( v8::Isolate* isolate, - v8::Local templ); + v8::Local templ = v8::ObjectTemplate::New()); ~ObjectTemplateBuilder(); // It's against Google C++ style to return a non-const ref, but we take some From b180f18b7eaabe066c79b1b60043e3b593a25adb Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Wed, 28 Mar 2018 11:32:10 +1100 Subject: [PATCH 122/129] Add mate::Promise --- native_mate/dictionary.cc | 2 +- native_mate/promise.cc | 45 +++++++++++++++++++++++++++++++ native_mate/promise.h | 57 +++++++++++++++++++++++++++++++++++++++ native_mate_files.gypi | 2 ++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 native_mate/promise.cc create mode 100644 native_mate/promise.h diff --git a/native_mate/dictionary.cc b/native_mate/dictionary.cc index b63acaf5b77..3caff114597 100644 --- a/native_mate/dictionary.cc +++ b/native_mate/dictionary.cc @@ -20,7 +20,7 @@ Dictionary::~Dictionary() { } Dictionary Dictionary::CreateEmpty(v8::Isolate* isolate) { - return Dictionary(isolate, v8::Object::New(isolate));; + return Dictionary(isolate, v8::Object::New(isolate)); } v8::Local Dictionary::GetHandle() const { diff --git a/native_mate/promise.cc b/native_mate/promise.cc new file mode 100644 index 00000000000..81b79441e72 --- /dev/null +++ b/native_mate/promise.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "native_mate/promise.h" + +namespace mate { + +Promise::Promise() + : isolate_(NULL) { +} + +Promise::Promise(v8::Isolate* isolate) + : isolate_(isolate) { + resolver_ = v8::Promise::Resolver::New(isolate); +} + +Promise::~Promise() { +} + +Promise Promise::Create(v8::Isolate* isolate) { + return Promise(isolate); +} + +Promise Promise::Create() { + return Promise::Create(v8::Isolate::GetCurrent()); +} + +void Promise::RejectWithErrorMessage(const std::string& string) { + v8::Local error_message = + v8::String::NewFromUtf8(isolate(), string.c_str()); + v8::Local error = v8::Exception::Error(error_message); + resolver_->Reject(mate::ConvertToV8(isolate(), error)); +} + +v8::Local Promise::GetHandle() const { + return resolver_->GetPromise(); +} + +v8::Local Converter::ToV8(v8::Isolate* isolate, + Promise val) { + return val.GetHandle(); +} + +} // namespace mate diff --git a/native_mate/promise.h b/native_mate/promise.h new file mode 100644 index 00000000000..225ac6d048f --- /dev/null +++ b/native_mate/promise.h @@ -0,0 +1,57 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef NATIVE_MATE_PROMISE_H_ +#define NATIVE_MATE_PROMISE_H_ + +#include "native_mate/converter.h" + +namespace mate { + +class Promise { + public: + Promise(); + Promise(v8::Isolate* isolate); + virtual ~Promise(); + + static Promise Create(v8::Isolate* isolate); + static Promise Create(); + + v8::Isolate* isolate() const { return isolate_; } + + virtual v8::Local GetHandle() const; + + template + void Resolve(T* value) { + resolver_->Resolve(mate::ConvertToV8(isolate(), value)); + } + + template + void Reject(T* value) { + resolver_->Reject(mate::ConvertToV8(isolate(), value)); + } + + void RejectWithErrorMessage(const std::string& error); + + protected: + v8::Isolate* isolate_; + + private: + v8::Local resolver_; +}; + +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + Promise val); + // TODO(MarshallOfSound): Implement FromV8 to allow promise chaining + // in native land + // static bool FromV8(v8::Isolate* isolate, + // v8::Local val, + // Promise* out); +}; + +} // namespace mate + +#endif // NATIVE_MATE_PROMISE_H_ diff --git a/native_mate_files.gypi b/native_mate_files.gypi index 867ec7999c8..bf10470d02a 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -22,6 +22,8 @@ 'native_mate/wrappable.cc', 'native_mate/wrappable.h', 'native_mate/wrappable_base.h', + 'native_mate/promise.h', + 'native_mate/promise.cc', ], }, } From 1e2828b80e3823d77be887fcbb0590d83d0ae989 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Sun, 15 Apr 2018 13:52:40 -0400 Subject: [PATCH 123/129] Update travis settings Use Node.js 9.7.0 and Xcode 9.3. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 06118787cb7..ca3cdc93533 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,13 +3,13 @@ notifications: language: node_js node_js: - - "6" + - "9.7.0" os: - linux - osx env: - TARGET_ARCH=x64 -osx_image: xcode7.3 +osx_image: xcode9.3 script: './script/cibuild' From 91f97ca02f28041ecf598d9d3b07420bf8cf2238 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Sun, 15 Apr 2018 14:11:20 -0400 Subject: [PATCH 124/129] Update appveyor settings Use Visual Studio 2017. --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 46a91007e6e..ddf8088c94a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,7 @@ version: "{build}" clone_depth: 10 -os: Visual Studio 2015 +os: Visual Studio 2017 init: - git config --global core.autocrlf input @@ -11,7 +11,7 @@ platform: - x64 install: - - cmd: SET PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH% + - cmd: SET PATH=C:\Program Files (x86)\MSBuild\15.0\bin\;%PATH% - cmd: SET PATH=C:\python27;%PATH% - cmd: bash script/cibuild From d0c80b5b55e5a95f81c6493580fa7368e3e6894f Mon Sep 17 00:00:00 2001 From: Alexey Kuzmin Date: Mon, 16 Apr 2018 15:16:48 +0200 Subject: [PATCH 125/129] Remove mate::TryCatch (#26) It's not used anywhere. We use v8::TryCatch instead. --- native_mate/try_catch.cc | 49 ---------------------------------------- native_mate/try_catch.h | 32 -------------------------- native_mate_files.gypi | 2 -- 3 files changed, 83 deletions(-) delete mode 100644 native_mate/try_catch.cc delete mode 100644 native_mate/try_catch.h diff --git a/native_mate/try_catch.cc b/native_mate/try_catch.cc deleted file mode 100644 index c7a9c00ad41..00000000000 --- a/native_mate/try_catch.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.chromium file. - -#include "native_mate/try_catch.h" - -#include - -#include "native_mate/converter.h" - -namespace mate { - -TryCatch::TryCatch() { -} - -TryCatch::~TryCatch() { -} - -bool TryCatch::HasCaught() { - return try_catch_.HasCaught(); -} - -std::string TryCatch::GetStackTrace() { - if (!HasCaught()) { - return ""; - } - - std::stringstream ss; - v8::Local message = try_catch_.Message(); - ss << V8ToString(message->Get()) << std::endl - << V8ToString(message->GetSourceLine()) << std::endl; - - v8::Local trace = message->GetStackTrace(); - if (trace.IsEmpty()) - return ss.str(); - - int len = trace->GetFrameCount(); - for (int i = 0; i < len; ++i) { - v8::Local frame = trace->GetFrame(i); - ss << V8ToString(frame->GetScriptName()) << ":" - << frame->GetLineNumber() << ":" - << frame->GetColumn() << ": " - << V8ToString(frame->GetFunctionName()) - << std::endl; - } - return ss.str(); -} - -} // namespace mate diff --git a/native_mate/try_catch.h b/native_mate/try_catch.h deleted file mode 100644 index abd501e19b2..00000000000 --- a/native_mate/try_catch.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.chromium file. - -#ifndef NATIVE_MATE_TRY_CATCH_H_ -#define NATIVE_MATE_TRY_CATCH_H_ - -#include - -#include "base/macros.h" -#include "v8/include/v8.h" - -namespace mate { - -// TryCatch is a convenient wrapper around v8::TryCatch. -class TryCatch { - public: - TryCatch(); - ~TryCatch(); - - bool HasCaught(); - std::string GetStackTrace(); - - private: - v8::TryCatch try_catch_; - - DISALLOW_COPY_AND_ASSIGN(TryCatch); -}; - -} // namespace mate - -#endif // NATIVE_MATE_TRY_CATCH_H_ diff --git a/native_mate_files.gypi b/native_mate_files.gypi index bf10470d02a..b67f0c775fe 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -17,8 +17,6 @@ 'native_mate/persistent_dictionary.cc', 'native_mate/persistent_dictionary.h', 'native_mate/scoped_persistent.h', - 'native_mate/try_catch.cc', - 'native_mate/try_catch.h', 'native_mate/wrappable.cc', 'native_mate/wrappable.h', 'native_mate/wrappable_base.h', From 875706f66008e03a0c7a699de16d7e2bde0efb90 Mon Sep 17 00:00:00 2001 From: Nitish Sakhawalkar Date: Tue, 10 Apr 2018 16:17:20 -0700 Subject: [PATCH 126/129] Address breaking API --- native_mate/constructor.h | 2 +- native_mate/object_template_builder.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native_mate/constructor.h b/native_mate/constructor.h index c6deead3ece..7cad253e0ea 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -127,7 +127,7 @@ MATE_METHOD_RETURN_TYPE InvokeNew(const base::Callback& factory, WrappableBase* object; { // Don't continue if the constructor throws an exception. - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); object = internal::InvokeFactory(args, factory); if (try_catch.HasCaught()) { try_catch.ReThrow(); diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index de953d381c2..533576f9863 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -69,7 +69,7 @@ class ObjectTemplateBuilder { public: explicit ObjectTemplateBuilder( v8::Isolate* isolate, - v8::Local templ = v8::ObjectTemplate::New()); + v8::Local templ); ~ObjectTemplateBuilder(); // It's against Google C++ style to return a non-const ref, but we take some From 7733b8743193845ee5e6728bddc7ce14352b06af Mon Sep 17 00:00:00 2001 From: Jeremy Apthorp Date: Wed, 25 Apr 2018 15:18:27 -0700 Subject: [PATCH 127/129] Don't copy things on Dictionary::Set --- native_mate/converter.h | 2 +- native_mate/dictionary.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native_mate/converter.h b/native_mate/converter.h index 07c01d6529a..0574a8f3860 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -343,7 +343,7 @@ struct ToV8Traits { template bool TryConvertToV8(v8::Isolate* isolate, - T input, + const T& input, v8::Local* output) { return ToV8Traits::TryConvertToV8(isolate, input, output); } diff --git a/native_mate/dictionary.h b/native_mate/dictionary.h index 5a56a9e06bb..9e80cb99acf 100644 --- a/native_mate/dictionary.h +++ b/native_mate/dictionary.h @@ -69,7 +69,7 @@ class Dictionary { } template - bool Set(const base::StringPiece& key, T val) { + bool Set(const base::StringPiece& key, const T& val) { v8::Local v8_value; if (!TryConvertToV8(isolate_, val, &v8_value)) return false; From d7b8cce162fc9639c4f976304832f391f0d9f38f Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Thu, 17 May 2018 23:36:15 +0200 Subject: [PATCH 128/129] Remove native_mate/compat.h --- native_mate/arguments.cc | 10 +- native_mate/arguments.h | 7 +- native_mate/compat.h | 134 ------------------------- native_mate/constructor.h | 10 +- native_mate/converter.cc | 32 +++--- native_mate/converter.h | 7 +- native_mate/object_template_builder.cc | 2 - native_mate/scoped_persistent.h | 8 +- native_mate/wrappable.h | 1 - native_mate/wrappable_base.h | 2 - native_mate_files.gypi | 1 - 11 files changed, 36 insertions(+), 178 deletions(-) delete mode 100644 native_mate/compat.h diff --git a/native_mate/arguments.cc b/native_mate/arguments.cc index 130d77d435a..a23e6523cac 100644 --- a/native_mate/arguments.cc +++ b/native_mate/arguments.cc @@ -31,7 +31,7 @@ Arguments::Arguments() insufficient_arguments_(false) { } -Arguments::Arguments(const MATE_METHOD_ARGS_TYPE& info) +Arguments::Arguments(const v8::FunctionCallbackInfo& info) : isolate_(info.GetIsolate()), info_(&info), next_(0), @@ -57,16 +57,16 @@ v8::Local Arguments::ThrowError() const { } v8::Local Arguments::ThrowError(const std::string& message) const { - MATE_THROW_EXCEPTION(isolate_, v8::Exception::Error( + isolate_->ThrowException(v8::Exception::Error( StringToV8(isolate_, message))); - return MATE_UNDEFINED(isolate_); + return v8::Undefined(isolate_); } v8::Local Arguments::ThrowTypeError( const std::string& message) const { - MATE_THROW_EXCEPTION(isolate_, v8::Exception::TypeError( + isolate_->ThrowException(v8::Exception::TypeError( StringToV8(isolate_, message))); - return MATE_UNDEFINED(isolate_); + return v8::Undefined(isolate_); } } // namespace mate diff --git a/native_mate/arguments.h b/native_mate/arguments.h index 44250e8d2e2..9198f289d6e 100644 --- a/native_mate/arguments.h +++ b/native_mate/arguments.h @@ -6,7 +6,6 @@ #define NATIVE_MATE_ARGUMENTS_H_ #include "base/macros.h" -#include "native_mate/compat.h" #include "native_mate/converter.h" namespace mate { @@ -17,7 +16,7 @@ namespace mate { class Arguments { public: Arguments(); - explicit Arguments(const MATE_METHOD_ARGS_TYPE& info); + explicit Arguments(const v8::FunctionCallbackInfo& info); ~Arguments(); v8::Local GetHolder() const { @@ -75,12 +74,10 @@ class Arguments { return info_->Length(); } -#if NODE_VERSION_AT_LEAST(0, 11, 0) template void Return(T val) { info_->GetReturnValue().Set(ConvertToV8(isolate_, val)); } -#endif v8::Local PeekNext() const; @@ -92,7 +89,7 @@ class Arguments { private: v8::Isolate* isolate_; - const MATE_METHOD_ARGS_TYPE* info_; + const v8::FunctionCallbackInfo* info_; int next_; bool insufficient_arguments_; }; diff --git a/native_mate/compat.h b/native_mate/compat.h deleted file mode 100644 index 5baefb4f89f..00000000000 --- a/native_mate/compat.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2014 Cheng Zhao. All rights reserved. -// Use of this source code is governed by MIT license that can be found in the -// LICENSE file. - -#ifndef NATIVE_MATE_COMPAT_H_ -#define NATIVE_MATE_COMPAT_H_ - -#include "node_version.h" - -#if NODE_VERSION_AT_LEAST(0, 11, 0) - -#define MATE_HANDLE_SCOPE(isolate) v8::HandleScope handle_scope(isolate) - -#define MATE_METHOD_ARGS_TYPE v8::FunctionCallbackInfo -#define MATE_METHOD_RETURN_TYPE void - -#define MATE_METHOD_RETURN_VALUE(value) return info.GetReturnValue().Set(value) -#define MATE_METHOD_RETURN_UNDEFINED() return -#define MATE_METHOD_RETURN_NULL() return info.GetReturnValue().SetNull() -#define MATE_METHOD_RETURN(value) args.Return(value) - -#define MATE_STRING_NEW(isolate, data) \ - v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString) -#define MATE_STRING_NEW_FROM_UTF8(isolate, data, length) \ - v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString, length) -#define MATE_STRING_NEW_FROM_UTF16(isolate, data, length) \ - v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString, length) -#define MATE_STRING_NEW_SYMBOL(isolate, data, length) \ - v8::String::NewFromUtf8(isolate, data, v8::String::kInternalizedString, length) - -#define MATE_UNDEFINED(isolate) v8::Undefined(isolate) -#define MATE_TRUE(isolate) v8::True(isolate) -#define MATE_FALSE(isolate) v8::False(isolate) -#define MATE_ARRAY_NEW(isolate, size) v8::Array::New(isolate, size) -#define MATE_NUMBER_NEW(isolate, data) v8::Number::New(isolate, data) -#define MATE_INTEGER_NEW(isolate, data) v8::Integer::New(isolate, data) -#define MATE_INTEGER_NEW_UNSIGNED(isolate, data) \ - v8::Integer::NewFromUnsigned(isolate, data) -#define MATE_EXTERNAL_NEW(isolate, data) v8::External::New(isolate, data) -#define MATE_BOOLEAN_NEW(isolate, data) v8::Boolean::New(isolate, data) -#define MATE_OBJECT_NEW(isolate) v8::Object::New(isolate) - -#define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ - object->SetAlignedPointerInInternalField(index, value) -#define MATE_GET_INTERNAL_FIELD_POINTER(object, index) \ - object->GetAlignedPointerFromInternalField(index) - -#define MATE_PERSISTENT_INIT(isolate, handle, value) \ - handle(isolate, value) -#define MATE_PERSISTENT_ASSIGN(type, isolate, handle, value) \ - handle.Reset(isolate, value) -#define MATE_PERSISTENT_RESET(handle) \ - handle.Reset() -#define MATE_PERSISTENT_TO_LOCAL(type, isolate, handle) \ - v8::Local::New(isolate, handle) -#define MATE_PERSISTENT_SET_WEAK(handle, parameter, callback) \ - handle.SetWeak(parameter, callback) - -#define MATE_WEAK_CALLBACK(name, v8_type, c_type) \ - void name(const v8::WeakCallbackData& data) -#define MATE_WEAK_CALLBACK_INIT(c_type) \ - c_type* self = data.GetParameter() - -#define MATE_THROW_EXCEPTION(isolate, value) \ - isolate->ThrowException(value) - -#else // Node 0.8 and 0.10 - -#define MATE_HANDLE_SCOPE(isolate) v8::HandleScope handle_scope - -#define MATE_METHOD_ARGS_TYPE v8::Arguments -#define MATE_METHOD_RETURN_TYPE v8::Local - -#define MATE_METHOD_RETURN_VALUE(value) return value -#define MATE_METHOD_RETURN_UNDEFINED() return v8::Undefined() -#define MATE_METHOD_RETURN_NULL() return v8::Null() -#define MATE_METHOD_RETURN(value) \ - MATE_METHOD_RETURN_VALUE(ConvertToV8(args.isolate(), value)) - -#define MATE_STRING_NEW(isolate, data) \ - v8::String::New(data) -#define MATE_STRING_NEW_FROM_UTF8(isolate, data, length) \ - v8::String::New(data, length) -#define MATE_STRING_NEW_FROM_UTF16(isolate, data, length) \ - v8::String::NewFromTwoByte(data, v8::String::kNormalString, length) -#define MATE_STRING_NEW_SYMBOL(isolate, data, length) \ - v8::String::NewSymbol(data, length) - -#define MATE_UNDEFINED(isolate) v8::Undefined() -#define MATE_TRUE(isolate) v8::True() -#define MATE_FALSE(isolate) v8::False() -#define MATE_ARRAY_NEW(isolate, size) v8::Array::New(size) -#define MATE_NUMBER_NEW(isolate, data) v8::Number::New(data) -#define MATE_INTEGER_NEW(isolate, data) v8::Integer::New(data) -#define MATE_INTEGER_NEW_UNSIGNED(isolate, data) \ - v8::Integer::NewFromUnsigned(data) -#define MATE_EXTERNAL_NEW(isolate, data) v8::External::New(data) -#define MATE_BOOLEAN_NEW(isolate, data) v8::Boolean::New(data) -#define MATE_OBJECT_NEW(isolate) v8::Object::New() - -#define MATE_SET_INTERNAL_FIELD_POINTER(object, index, value) \ - object->SetPointerInInternalField(index, value) -#define MATE_GET_INTERNAL_FIELD_POINTER(object, index) \ - object->GetPointerFromInternalField(index) - -#define MATE_PERSISTENT_INIT(isolate, handle, value) \ - handle(value) -#define MATE_PERSISTENT_ASSIGN(type, isolate, handle, value) \ - handle = v8::Persistent::New(value) -#define MATE_PERSISTENT_RESET(handle) \ - handle.Dispose(); \ - handle.Clear() -#define MATE_PERSISTENT_TO_LOCAL(type, isolate, handle) \ - v8::Local::New(handle) -#define MATE_PERSISTENT_SET_WEAK(handle, parameter, callback) \ - handle.MakeWeak(parameter, callback) - -#define MATE_WEAK_CALLBACK(name, v8_type, c_type) \ - void name(v8::Persistent object, void* parameter) -#define MATE_WEAK_CALLBACK_INIT(c_type) \ - c_type* self = static_cast(parameter) - -#define MATE_THROW_EXCEPTION(isolate, value) \ - v8::ThrowException(value) - -#endif // (NODE_MODULE_VERSION > 0x000B) - - -// Generally we should not provide utility macros, but this just makes things -// much more comfortable so we keep it. -#define MATE_METHOD(name) \ - MATE_METHOD_RETURN_TYPE name(const MATE_METHOD_ARGS_TYPE& info) - -#endif // NATIVE_MATE_COMPAT_H_ diff --git a/native_mate/constructor.h b/native_mate/constructor.h index c6deead3ece..6a91ebe59ed 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -117,11 +117,11 @@ inline WrappableBase* InvokeFactory( }; template -MATE_METHOD_RETURN_TYPE InvokeNew(const base::Callback& factory, - v8::Isolate* isolate, Arguments* args) { +void InvokeNew(const base::Callback& factory, + v8::Isolate* isolate, Arguments* args) { if (!args->IsConstructCall()) { args->ThrowError("Requires constructor call"); - MATE_METHOD_RETURN_UNDEFINED(); + return; } WrappableBase* object; @@ -131,14 +131,14 @@ MATE_METHOD_RETURN_TYPE InvokeNew(const base::Callback& factory, object = internal::InvokeFactory(args, factory); if (try_catch.HasCaught()) { try_catch.ReThrow(); - MATE_METHOD_RETURN_UNDEFINED(); + return; } } if (!object) args->ThrowError(); - MATE_METHOD_RETURN_UNDEFINED(); + return; } } // namespace internal diff --git a/native_mate/converter.cc b/native_mate/converter.cc index 9edf940938d..260bdf105f6 100644 --- a/native_mate/converter.cc +++ b/native_mate/converter.cc @@ -4,7 +4,6 @@ #include "native_mate/converter.h" -#include "native_mate/compat.h" #include "v8/include/v8.h" using v8::Array; @@ -22,7 +21,7 @@ using v8::Value; namespace mate { Local Converter::ToV8(Isolate* isolate, bool val) { - return MATE_BOOLEAN_NEW(isolate, val); + return v8::Boolean::New(isolate, val); } bool Converter::FromV8(Isolate* isolate, Local val, bool* out) { @@ -35,7 +34,7 @@ bool Converter::FromV8(Isolate* isolate, Local val, bool* out) { #if !defined(OS_LINUX) && !defined(OS_FREEBSD) Local Converter::ToV8(Isolate* isolate, unsigned long val) { - return MATE_INTEGER_NEW(isolate, val); + return v8::Integer::New(isolate, val); } bool Converter::FromV8(Isolate* isolate, Local val, @@ -48,7 +47,7 @@ bool Converter::FromV8(Isolate* isolate, Local val, #endif Local Converter::ToV8(Isolate* isolate, int32_t val) { - return MATE_INTEGER_NEW(isolate, val); + return v8::Integer::New(isolate, val); } bool Converter::FromV8(Isolate* isolate, Local val, @@ -60,7 +59,7 @@ bool Converter::FromV8(Isolate* isolate, Local val, } Local Converter::ToV8(Isolate* isolate, uint32_t val) { - return MATE_INTEGER_NEW_UNSIGNED(isolate, val); + return v8::Integer::NewFromUnsigned(isolate, val); } bool Converter::FromV8(Isolate* isolate, Local val, @@ -72,7 +71,7 @@ bool Converter::FromV8(Isolate* isolate, Local val, } Local Converter::ToV8(Isolate* isolate, int64_t val) { - return MATE_NUMBER_NEW(isolate, static_cast(val)); + return v8::Number::New(isolate, static_cast(val)); } bool Converter::FromV8(Isolate* isolate, Local val, @@ -86,7 +85,7 @@ bool Converter::FromV8(Isolate* isolate, Local val, } Local Converter::ToV8(Isolate* isolate, uint64_t val) { - return MATE_NUMBER_NEW(isolate, static_cast(val)); + return v8::Number::New(isolate, static_cast(val)); } bool Converter::FromV8(Isolate* isolate, Local val, @@ -98,7 +97,7 @@ bool Converter::FromV8(Isolate* isolate, Local val, } Local Converter::ToV8(Isolate* isolate, float val) { - return MATE_NUMBER_NEW(isolate, val); + return v8::Number::New(isolate, val); } bool Converter::FromV8(Isolate* isolate, Local val, @@ -110,7 +109,7 @@ bool Converter::FromV8(Isolate* isolate, Local val, } Local Converter::ToV8(Isolate* isolate, double val) { - return MATE_NUMBER_NEW(isolate, val); + return v8::Number::New(isolate, val); } bool Converter::FromV8(Isolate* isolate, Local val, @@ -123,13 +122,15 @@ bool Converter::FromV8(Isolate* isolate, Local val, Local Converter::ToV8( Isolate* isolate, const char* val) { - return MATE_STRING_NEW_FROM_UTF8(isolate, val, -1); + return v8::String::NewFromUtf8(isolate, val); } Local Converter::ToV8( Isolate* isolate, const base::StringPiece& val) { - return MATE_STRING_NEW_FROM_UTF8(isolate, val.data(), - static_cast(val.length())); + return v8::String::NewFromUtf8(isolate, + val.data(), + v8::String::kNormalString, + static_cast(val.length())); } Local Converter::ToV8(Isolate* isolate, @@ -228,9 +229,10 @@ bool Converter >::FromV8(Isolate* isolate, Local val, v8::Local StringToSymbol(v8::Isolate* isolate, const base::StringPiece& val) { - return MATE_STRING_NEW_SYMBOL(isolate, - val.data(), - static_cast(val.length())); + return v8::String::NewFromUtf8(isolate, + val.data(), + v8::String::kInternalizedString, + static_cast(val.length())); } std::string V8ToString(v8::Local value) { diff --git a/native_mate/converter.h b/native_mate/converter.h index 53e682a6b65..ec3649c19bb 100644 --- a/native_mate/converter.h +++ b/native_mate/converter.h @@ -11,7 +11,6 @@ #include #include "base/strings/string_piece.h" -#include "native_mate/compat.h" #include "v8/include/v8.h" namespace mate { @@ -36,7 +35,7 @@ struct Converter {}; template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, void* val) { - return MATE_UNDEFINED(isolate); + return v8::Undefined(isolate); } }; @@ -208,7 +207,7 @@ struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, const std::vector& val) { v8::Local result( - MATE_ARRAY_NEW(isolate, static_cast(val.size()))); + v8::Array::New(isolate, static_cast(val.size()))); for (size_t i = 0; i < val.size(); ++i) { result->Set(static_cast(i), Converter::ToV8(isolate, val[i])); } @@ -241,7 +240,7 @@ struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, const std::set& val) { v8::Local result( - MATE_ARRAY_NEW(isolate, static_cast(val.size()))); + v8::Array::New(isolate, static_cast(val.size()))); typename std::set::const_iterator it; int i; for (i = 0, it = val.begin(); it != val.end(); ++it, ++i) diff --git a/native_mate/object_template_builder.cc b/native_mate/object_template_builder.cc index ab4079e4eef..c64e38fa1e2 100644 --- a/native_mate/object_template_builder.cc +++ b/native_mate/object_template_builder.cc @@ -24,10 +24,8 @@ ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl( ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl( const base::StringPiece& name, v8::Local getter, v8::Local setter) { -#if NODE_VERSION_AT_LEAST(0, 11, 0) template_->SetAccessorProperty(StringToSymbol(isolate_, name), getter, setter); -#endif return *this; } diff --git a/native_mate/scoped_persistent.h b/native_mate/scoped_persistent.h index c7c53554619..5d9c8fff423 100644 --- a/native_mate/scoped_persistent.h +++ b/native_mate/scoped_persistent.h @@ -30,14 +30,14 @@ class ScopedPersistent { void reset(v8::Isolate* isolate, v8::Local handle) { if (!handle.IsEmpty()) { isolate_ = isolate; - MATE_PERSISTENT_ASSIGN(T, isolate, handle_, handle); + handle_.Reset(isolate, handle); } else { reset(); } } void reset() { - MATE_PERSISTENT_RESET(handle_); + handle_.Reset(); } bool IsEmpty() const { @@ -51,12 +51,12 @@ class ScopedPersistent { v8::Local NewHandle(v8::Isolate* isolate) const { if (handle_.IsEmpty()) return v8::Local(); - return MATE_PERSISTENT_TO_LOCAL(T, isolate, handle_); + return v8::Local::New(isolate, handle_); } template void SetWeak(P* parameter, C callback) { - MATE_PERSISTENT_SET_WEAK(handle_, parameter, callback); + handle_.SetWeak(parameter, callback); } v8::Isolate* isolate() const { return isolate_; } diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 8c1b480fc64..489c5817481 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -6,7 +6,6 @@ #define NATIVE_MATE_WRAPPABLE_H_ #include "base/bind.h" -#include "native_mate/compat.h" #include "native_mate/converter.h" #include "native_mate/constructor.h" #include "gin/per_isolate_data.h" diff --git a/native_mate/wrappable_base.h b/native_mate/wrappable_base.h index 501bbee961e..1c489cc37af 100644 --- a/native_mate/wrappable_base.h +++ b/native_mate/wrappable_base.h @@ -1,8 +1,6 @@ #ifndef NATIVE_MATE_WRAPPABLE_BASE_H_ #define NATIVE_MATE_WRAPPABLE_BASE_H_ -#include "native_mate/compat.h" - namespace mate { namespace internal { diff --git a/native_mate_files.gypi b/native_mate_files.gypi index b67f0c775fe..d7e9374971c 100644 --- a/native_mate_files.gypi +++ b/native_mate_files.gypi @@ -3,7 +3,6 @@ 'native_mate_files': [ 'native_mate/arguments.cc', 'native_mate/arguments.h', - 'native_mate/compat.h', 'native_mate/constructor.h', 'native_mate/converter.cc', 'native_mate/converter.h', From 4cada5e845be16534b3680125d77db355a5ca2b7 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Fri, 22 Jun 2018 11:29:57 +1000 Subject: [PATCH 129/129] prepare for merging to electron --- .gitignore | 1 - .travis.yml | 18 ------------- LICENSE | 20 -------------- appveyor.yml | 24 ----------------- .../LICENSE.chromium | 0 README.md => native_mate/README.md | 0 native_mate/{ => mate}/arguments.cc | 0 native_mate/{ => mate}/arguments.h | 0 native_mate/{ => mate}/constructor.h | 0 native_mate/{ => mate}/converter.cc | 0 native_mate/{ => mate}/converter.h | 0 native_mate/{ => mate}/dictionary.cc | 0 native_mate/{ => mate}/dictionary.h | 0 native_mate/{ => mate}/function_template.cc | 0 native_mate/{ => mate}/function_template.h | 0 native_mate/{ => mate}/handle.h | 0 .../{ => mate}/object_template_builder.cc | 0 .../{ => mate}/object_template_builder.h | 0 .../{ => mate}/persistent_dictionary.cc | 0 .../{ => mate}/persistent_dictionary.h | 0 native_mate/{ => mate}/promise.cc | 0 native_mate/{ => mate}/promise.h | 0 native_mate/{ => mate}/scoped_persistent.h | 0 native_mate/{ => mate}/wrappable.cc | 0 native_mate/{ => mate}/wrappable.h | 0 native_mate/{ => mate}/wrappable_base.h | 0 native_mate/native_mate_files.gypi | 26 ++++++++++++++++++ {script => native_mate/script}/pump.py | 0 native_mate_files.gypi | 26 ------------------ script/cibuild | 27 ------------------- 30 files changed, 26 insertions(+), 116 deletions(-) delete mode 100644 .gitignore delete mode 100644 .travis.yml delete mode 100644 LICENSE delete mode 100644 appveyor.yml rename LICENSE.chromium => native_mate/LICENSE.chromium (100%) rename README.md => native_mate/README.md (100%) rename native_mate/{ => mate}/arguments.cc (100%) rename native_mate/{ => mate}/arguments.h (100%) rename native_mate/{ => mate}/constructor.h (100%) rename native_mate/{ => mate}/converter.cc (100%) rename native_mate/{ => mate}/converter.h (100%) rename native_mate/{ => mate}/dictionary.cc (100%) rename native_mate/{ => mate}/dictionary.h (100%) rename native_mate/{ => mate}/function_template.cc (100%) rename native_mate/{ => mate}/function_template.h (100%) rename native_mate/{ => mate}/handle.h (100%) rename native_mate/{ => mate}/object_template_builder.cc (100%) rename native_mate/{ => mate}/object_template_builder.h (100%) rename native_mate/{ => mate}/persistent_dictionary.cc (100%) rename native_mate/{ => mate}/persistent_dictionary.h (100%) rename native_mate/{ => mate}/promise.cc (100%) rename native_mate/{ => mate}/promise.h (100%) rename native_mate/{ => mate}/scoped_persistent.h (100%) rename native_mate/{ => mate}/wrappable.cc (100%) rename native_mate/{ => mate}/wrappable.h (100%) rename native_mate/{ => mate}/wrappable_base.h (100%) create mode 100644 native_mate/native_mate_files.gypi rename {script => native_mate/script}/pump.py (100%) delete mode 100644 native_mate_files.gypi delete mode 100755 script/cibuild diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1377554ebea..00000000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.swp diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ca3cdc93533..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -notifications: - email: false - -language: node_js -node_js: - - "9.7.0" -os: - - linux - - osx -env: - - TARGET_ARCH=x64 -osx_image: xcode9.3 - -script: './script/cibuild' - -branches: - only: - - master diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 5f39f8bd955..00000000000 --- a/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2014 Cheng Zhao. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index ddf8088c94a..00000000000 --- a/appveyor.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: "{build}" - -clone_depth: 10 - -os: Visual Studio 2017 - -init: - - git config --global core.autocrlf input - -platform: - - x64 - -install: - - cmd: SET PATH=C:\Program Files (x86)\MSBuild\15.0\bin\;%PATH% - - cmd: SET PATH=C:\python27;%PATH% - - cmd: bash script/cibuild - -branches: - only: - - master - -# disable build and test phases -build: off -test: off diff --git a/LICENSE.chromium b/native_mate/LICENSE.chromium similarity index 100% rename from LICENSE.chromium rename to native_mate/LICENSE.chromium diff --git a/README.md b/native_mate/README.md similarity index 100% rename from README.md rename to native_mate/README.md diff --git a/native_mate/arguments.cc b/native_mate/mate/arguments.cc similarity index 100% rename from native_mate/arguments.cc rename to native_mate/mate/arguments.cc diff --git a/native_mate/arguments.h b/native_mate/mate/arguments.h similarity index 100% rename from native_mate/arguments.h rename to native_mate/mate/arguments.h diff --git a/native_mate/constructor.h b/native_mate/mate/constructor.h similarity index 100% rename from native_mate/constructor.h rename to native_mate/mate/constructor.h diff --git a/native_mate/converter.cc b/native_mate/mate/converter.cc similarity index 100% rename from native_mate/converter.cc rename to native_mate/mate/converter.cc diff --git a/native_mate/converter.h b/native_mate/mate/converter.h similarity index 100% rename from native_mate/converter.h rename to native_mate/mate/converter.h diff --git a/native_mate/dictionary.cc b/native_mate/mate/dictionary.cc similarity index 100% rename from native_mate/dictionary.cc rename to native_mate/mate/dictionary.cc diff --git a/native_mate/dictionary.h b/native_mate/mate/dictionary.h similarity index 100% rename from native_mate/dictionary.h rename to native_mate/mate/dictionary.h diff --git a/native_mate/function_template.cc b/native_mate/mate/function_template.cc similarity index 100% rename from native_mate/function_template.cc rename to native_mate/mate/function_template.cc diff --git a/native_mate/function_template.h b/native_mate/mate/function_template.h similarity index 100% rename from native_mate/function_template.h rename to native_mate/mate/function_template.h diff --git a/native_mate/handle.h b/native_mate/mate/handle.h similarity index 100% rename from native_mate/handle.h rename to native_mate/mate/handle.h diff --git a/native_mate/object_template_builder.cc b/native_mate/mate/object_template_builder.cc similarity index 100% rename from native_mate/object_template_builder.cc rename to native_mate/mate/object_template_builder.cc diff --git a/native_mate/object_template_builder.h b/native_mate/mate/object_template_builder.h similarity index 100% rename from native_mate/object_template_builder.h rename to native_mate/mate/object_template_builder.h diff --git a/native_mate/persistent_dictionary.cc b/native_mate/mate/persistent_dictionary.cc similarity index 100% rename from native_mate/persistent_dictionary.cc rename to native_mate/mate/persistent_dictionary.cc diff --git a/native_mate/persistent_dictionary.h b/native_mate/mate/persistent_dictionary.h similarity index 100% rename from native_mate/persistent_dictionary.h rename to native_mate/mate/persistent_dictionary.h diff --git a/native_mate/promise.cc b/native_mate/mate/promise.cc similarity index 100% rename from native_mate/promise.cc rename to native_mate/mate/promise.cc diff --git a/native_mate/promise.h b/native_mate/mate/promise.h similarity index 100% rename from native_mate/promise.h rename to native_mate/mate/promise.h diff --git a/native_mate/scoped_persistent.h b/native_mate/mate/scoped_persistent.h similarity index 100% rename from native_mate/scoped_persistent.h rename to native_mate/mate/scoped_persistent.h diff --git a/native_mate/wrappable.cc b/native_mate/mate/wrappable.cc similarity index 100% rename from native_mate/wrappable.cc rename to native_mate/mate/wrappable.cc diff --git a/native_mate/wrappable.h b/native_mate/mate/wrappable.h similarity index 100% rename from native_mate/wrappable.h rename to native_mate/mate/wrappable.h diff --git a/native_mate/wrappable_base.h b/native_mate/mate/wrappable_base.h similarity index 100% rename from native_mate/wrappable_base.h rename to native_mate/mate/wrappable_base.h diff --git a/native_mate/native_mate_files.gypi b/native_mate/native_mate_files.gypi new file mode 100644 index 00000000000..6756a5ad1d0 --- /dev/null +++ b/native_mate/native_mate_files.gypi @@ -0,0 +1,26 @@ +{ + 'variables': { + 'native_mate_files': [ + 'mate/arguments.cc', + 'mate/arguments.h', + 'mate/constructor.h', + 'mate/converter.cc', + 'mate/converter.h', + 'mate/dictionary.cc', + 'mate/dictionary.h', + 'mate/function_template.cc', + 'mate/function_template.h', + 'mate/handle.h', + 'mate/object_template_builder.cc', + 'mate/object_template_builder.h', + 'mate/persistent_dictionary.cc', + 'mate/persistent_dictionary.h', + 'mate/scoped_persistent.h', + 'mate/wrappable.cc', + 'mate/wrappable.h', + 'mate/wrappable_base.h', + 'mate/promise.h', + 'mate/promise.cc', + ], + }, +} diff --git a/script/pump.py b/native_mate/script/pump.py similarity index 100% rename from script/pump.py rename to native_mate/script/pump.py diff --git a/native_mate_files.gypi b/native_mate_files.gypi deleted file mode 100644 index d7e9374971c..00000000000 --- a/native_mate_files.gypi +++ /dev/null @@ -1,26 +0,0 @@ -{ - 'variables': { - 'native_mate_files': [ - 'native_mate/arguments.cc', - 'native_mate/arguments.h', - 'native_mate/constructor.h', - 'native_mate/converter.cc', - 'native_mate/converter.h', - 'native_mate/dictionary.cc', - 'native_mate/dictionary.h', - 'native_mate/function_template.cc', - 'native_mate/function_template.h', - 'native_mate/handle.h', - 'native_mate/object_template_builder.cc', - 'native_mate/object_template_builder.h', - 'native_mate/persistent_dictionary.cc', - 'native_mate/persistent_dictionary.h', - 'native_mate/scoped_persistent.h', - 'native_mate/wrappable.cc', - 'native_mate/wrappable.h', - 'native_mate/wrappable_base.h', - 'native_mate/promise.h', - 'native_mate/promise.cc', - ], - }, -} diff --git a/script/cibuild b/script/cibuild deleted file mode 100755 index 5370b287fe4..00000000000 --- a/script/cibuild +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -# Make cloned repository complete -git fetch --unshallow origin HEAD - -# Clone Electron -git clone https://github.com/electron/electron --depth 1 --recursive - -# Checkout current native_mate commit into Electron -cd electron/vendor/native_mate -git fetch ../../.. -git reset --hard FETCH_HEAD - -# Commit change -cd ../.. -git add vendor/native_mate -git config --local user.email "test@github.com" -git config --local user.name "Test" -git commit --message 'Upgrading native_mate' - -# Bootstrap Electron -npm run bootstrap -- --dev - -# Build Electron with native_mate commit -npm run build