This commit is contained in:
Cheng Zhao 2014-04-15 11:04:36 +08:00
Коммит ff65b7dae1
20 изменённых файлов: 1887 добавлений и 0 удалений

20
LICENSE Normal file
Просмотреть файл

@ -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.

27
LICENSE.chromium Normal file
Просмотреть файл

@ -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.

48
native_mate/arguments.cc Normal file
Просмотреть файл

@ -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<v8::Value> Arguments::PeekNext() const {
if (next_ >= info_->Length())
return v8::Handle<v8::Value>();
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

82
native_mate/arguments.h Normal file
Просмотреть файл

@ -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<typename T>
bool GetHolder(T* out) {
return ConvertFromV8(isolate_, info_->Holder(), out);
}
template<typename T>
bool GetData(T* out) {
return ConvertFromV8(isolate_, info_->Data(), out);
}
template<typename T>
bool GetNext(T* out) {
if (next_ >= info_->Length()) {
insufficient_arguments_ = true;
return false;
}
v8::Handle<v8::Value> val = (*info_)[next_++];
return ConvertFromV8(isolate_, val, out);
}
template<typename T>
bool GetRemaining(std::vector<T>* 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<v8::Value> val = (*info_)[next_++];
if (!ConvertFromV8(isolate_, val, &out->at(i)))
return false;
}
return true;
}
#if NODE_VERSION_AT_LEAST(0, 11, 0)
template<typename T>
void Return(T val) {
info_->GetReturnValue().Set(ConvertToV8(isolate_, val));
}
#endif
v8::Handle<v8::Value> 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_

100
native_mate/compat.h Normal file
Просмотреть файл

@ -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<v8::Value>
#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<type>::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<v8_type, c_type>& 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<v8::Value>
#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<type>::New(value)
#define MATE_PERSISTENT_RESET(handle) \
handle.Dispose(); \
handle.Clear()
#define MATE_PERSISTENT_TO_LOCAL(type, isolate, handle) \
v8::Local<type>::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<v8::Value> object, void* parameter)
#define MATE_WEAK_CALLBACK_INIT(c_type) \
c_type* self = static_cast<c_type*>(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_

190
native_mate/converter.cc Normal file
Просмотреть файл

@ -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<Value> Converter<bool>::ToV8(Isolate* isolate, bool val) {
return Boolean::New(val);
}
bool Converter<bool>::FromV8(Isolate* isolate, Handle<Value> val, bool* out) {
*out = val->BooleanValue();
return true;
}
Handle<Value> Converter<int32_t>::ToV8(Isolate* isolate, int32_t val) {
return Integer::New(val);
}
bool Converter<int32_t>::FromV8(Isolate* isolate, Handle<Value> val,
int32_t* out) {
if (!val->IsInt32())
return false;
*out = val->Int32Value();
return true;
}
Handle<Value> Converter<uint32_t>::ToV8(Isolate* isolate, uint32_t val) {
return Integer::NewFromUnsigned(val);
}
bool Converter<uint32_t>::FromV8(Isolate* isolate, Handle<Value> val,
uint32_t* out) {
if (!val->IsUint32())
return false;
*out = val->Uint32Value();
return true;
}
Handle<Value> Converter<int64_t>::ToV8(Isolate* isolate, int64_t val) {
return Number::New(static_cast<double>(val));
}
bool Converter<int64_t>::FromV8(Isolate* isolate, Handle<Value> 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<Value> Converter<uint64_t>::ToV8(Isolate* isolate, uint64_t val) {
return Number::New(static_cast<double>(val));
}
bool Converter<uint64_t>::FromV8(Isolate* isolate, Handle<Value> val,
uint64_t* out) {
if (!val->IsNumber())
return false;
*out = static_cast<uint64_t>(val->IntegerValue());
return true;
}
Handle<Value> Converter<float>::ToV8(Isolate* isolate, float val) {
return Number::New(val);
}
bool Converter<float>::FromV8(Isolate* isolate, Handle<Value> val,
float* out) {
if (!val->IsNumber())
return false;
*out = static_cast<float>(val->NumberValue());
return true;
}
Handle<Value> Converter<double>::ToV8(Isolate* isolate, double val) {
return Number::New(val);
}
bool Converter<double>::FromV8(Isolate* isolate, Handle<Value> val,
double* out) {
if (!val->IsNumber())
return false;
*out = val->NumberValue();
return true;
}
Handle<Value> Converter<base::StringPiece>::ToV8(
Isolate* isolate, const base::StringPiece& val) {
return MATE_STRING_NEW_FROM_UTF8(isolate, val.data(),
static_cast<uint32_t>(val.length()));
}
Handle<Value> Converter<std::string>::ToV8(Isolate* isolate,
const std::string& val) {
return Converter<base::StringPiece>::ToV8(isolate, val);
}
bool Converter<std::string>::FromV8(Isolate* isolate, Handle<Value> val,
std::string* out) {
if (!val->IsString())
return false;
Handle<String> str = Handle<String>::Cast(val);
int length = str->Utf8Length();
out->resize(length);
str->WriteUtf8(&(*out)[0], length, NULL, String::NO_NULL_TERMINATION);
return true;
}
bool Converter<Handle<Function> >::FromV8(Isolate* isolate, Handle<Value> val,
Handle<Function>* out) {
if (!val->IsFunction())
return false;
*out = Handle<Function>::Cast(val);
return true;
}
Handle<Value> Converter<Handle<Object> >::ToV8(Isolate* isolate,
Handle<Object> val) {
return val;
}
bool Converter<Handle<Object> >::FromV8(Isolate* isolate, Handle<Value> val,
Handle<Object>* out) {
if (!val->IsObject())
return false;
*out = Handle<Object>::Cast(val);
return true;
}
Handle<Value> Converter<Handle<External> >::ToV8(Isolate* isolate,
Handle<External> val) {
return val;
}
bool Converter<Handle<External> >::FromV8(Isolate* isolate,
v8::Handle<Value> val,
Handle<External>* out) {
if (!val->IsExternal())
return false;
*out = Handle<External>::Cast(val);
return true;
}
Handle<Value> Converter<Handle<Value> >::ToV8(Isolate* isolate,
Handle<Value> val) {
return val;
}
bool Converter<Handle<Value> >::FromV8(Isolate* isolate, Handle<Value> val,
Handle<Value>* out) {
*out = val;
return true;
}
v8::Handle<v8::String> StringToSymbol(v8::Isolate* isolate,
const base::StringPiece& val) {
return MATE_STRING_NEW_SYMBOL(isolate,
val.data(),
static_cast<uint32_t>(val.length()));
}
std::string V8ToString(v8::Handle<v8::Value> value) {
if (value.IsEmpty())
return std::string();
std::string result;
if (!ConvertFromV8(NULL, value, &result))
return std::string();
return result;
}
} // namespace mate

193
native_mate/converter.h Normal file
Просмотреть файл

@ -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 <string>
#include <vector>
#include "base/strings/string_piece.h"
#include "v8/include/v8.h"
namespace mate {
template<typename T, typename Enable = void>
struct Converter {};
template<>
struct Converter<bool> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
bool val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
bool* out);
};
template<>
struct Converter<int32_t> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
int32_t val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
int32_t* out);
};
template<>
struct Converter<uint32_t> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
uint32_t val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
uint32_t* out);
};
template<>
struct Converter<int64_t> {
// Warning: JavaScript cannot represent 64 integers precisely.
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
int64_t val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
int64_t* out);
};
template<>
struct Converter<uint64_t> {
// Warning: JavaScript cannot represent 64 integers precisely.
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
uint64_t val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
uint64_t* out);
};
template<>
struct Converter<float> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
float val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
float* out);
};
template<>
struct Converter<double> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
double val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
double* out);
};
template<>
struct Converter<base::StringPiece> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const base::StringPiece& val);
// No conversion out is possible because StringPiece does not contain storage.
};
template<>
struct Converter<std::string> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const std::string& val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
std::string* out);
};
template<>
struct Converter<v8::Handle<v8::Function> > {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
v8::Handle<v8::Function>* out);
};
template<>
struct Converter<v8::Handle<v8::Object> > {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
v8::Handle<v8::Object> val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
v8::Handle<v8::Object>* out);
};
template<>
struct Converter<v8::Handle<v8::External> > {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
v8::Handle<v8::External> val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
v8::Handle<v8::External>* out);
};
template<>
struct Converter<v8::Handle<v8::Value> > {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
v8::Handle<v8::Value>* out);
};
template<typename T>
struct Converter<std::vector<T> > {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const std::vector<T>& val) {
v8::Handle<v8::Array> result(
v8::Array::New(static_cast<int>(val.size())));
for (size_t i = 0; i < val.size(); ++i) {
result->Set(static_cast<int>(i), Converter<T>::ToV8(isolate, val[i]));
}
return result;
}
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
std::vector<T>* out) {
if (!val->IsArray())
return false;
std::vector<T> result;
v8::Handle<v8::Array> array(v8::Handle<v8::Array>::Cast(val));
uint32_t length = array->Length();
for (uint32_t i = 0; i < length; ++i) {
T item;
if (!Converter<T>::FromV8(isolate, array->Get(i), &item))
return false;
result.push_back(item);
}
out->swap(result);
return true;
}
};
// Convenience functions that deduce T.
template<typename T>
v8::Handle<v8::Value> ConvertToV8(v8::Isolate* isolate,
T input) {
return Converter<T>::ToV8(isolate, input);
}
inline v8::Handle<v8::String> StringToV8(
v8::Isolate* isolate,
const base::StringPiece& input) {
return ConvertToV8(isolate, input).As<v8::String>();
}
v8::Handle<v8::String> StringToSymbol(v8::Isolate* isolate,
const base::StringPiece& val);
template<typename T>
bool ConvertFromV8(v8::Isolate* isolate, v8::Handle<v8::Value> input,
T* result) {
return Converter<T>::FromV8(isolate, input, result);
}
std::string V8ToString(v8::Handle<v8::Value> value);
} // namespace mate
#endif // NATIVE_MATE_CONVERTER_H_

42
native_mate/dictionary.cc Normal file
Просмотреть файл

@ -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<v8::Object> 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<v8::Value> Converter<Dictionary>::ToV8(v8::Isolate* isolate,
Dictionary val) {
return val.object_;
}
bool Converter<Dictionary>::FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
Dictionary* out) {
if (!val->IsObject())
return false;
*out = Dictionary(isolate, v8::Handle<v8::Object>::Cast(val));
return true;
}
} // namespace mate

64
native_mate/dictionary.h Normal file
Просмотреть файл

@ -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<v8::Object> object);
~Dictionary();
static Dictionary CreateEmpty(v8::Isolate* isolate);
template<typename T>
bool Get(const std::string& key, T* out) {
v8::Handle<v8::Value> val = object_->Get(StringToV8(isolate_, key));
return ConvertFromV8(isolate_, val, out);
}
template<typename T>
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<Dictionary>;
// TODO(aa): Remove this. Instead, get via FromV8(), Set(), and Get().
v8::Isolate* isolate_;
v8::Handle<v8::Object> object_;
};
template<>
struct Converter<Dictionary> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
Dictionary val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
Dictionary* out);
};
} // namespace mate
#endif // NATIVE_MATE_DICTIONARY_H_

Просмотреть файл

@ -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<v8::External> 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

Просмотреть файл

@ -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<typename T>
struct CallbackParamTraits {
typedef T LocalType;
};
template<typename T>
struct CallbackParamTraits<const T&> {
typedef T LocalType;
};
template<typename T>
struct CallbackParamTraits<const T*> {
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<v8::External> GetHandle(v8::Isolate* isolate);
protected:
explicit CallbackHolderBase(v8::Isolate* isolate);
virtual ~CallbackHolderBase();
private:
static MATE_WEAK_CALLBACK(WeakCallback, v8::External, CallbackHolderBase);
v8::Persistent<v8::External> v8_ref_;
DISALLOW_COPY_AND_ASSIGN(CallbackHolderBase);
};
template<typename Sig>
class CallbackHolder : public CallbackHolderBase {
public:
CallbackHolder(v8::Isolate* isolate,
const base::Callback<Sig>& callback,
int flags)
: CallbackHolderBase(isolate), callback(callback), flags(flags) {}
base::Callback<Sig> 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<typename R, typename P1 = void, typename P2 = void,
typename P3 = void, typename P4 = void, typename P5 = void,
typename P6 = void>
struct Invoker {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<R(P1, P2, P3, P4, P5, P6)>& 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<typename P1, typename P2, typename P3, typename P4, typename P5,
typename P6>
struct Invoker<void, P1, P2, P3, P4, P5, P6> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<void(P1, P2, P3, P4, P5, P6)>& 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<typename R, typename P1, typename P2, typename P3, typename P4,
typename P5>
struct Invoker<R, P1, P2, P3, P4, P5, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<R(P1, P2, P3, P4, P5)>& 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<typename P1, typename P2, typename P3, typename P4, typename P5>
struct Invoker<void, P1, P2, P3, P4, P5, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<void(P1, P2, P3, P4, P5)>& 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<typename R, typename P1, typename P2, typename P3, typename P4>
struct Invoker<R, P1, P2, P3, P4, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<R(P1, P2, P3, P4)>& callback,
const P1& a1,
const P2& a2,
const P3& a3,
const P4& a4) {
MATE_METHOD_RETURN(callback.Run(a1, a2, a3, a4));
}
};
template<typename P1, typename P2, typename P3, typename P4>
struct Invoker<void, P1, P2, P3, P4, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<void(P1, P2, P3, P4)>& callback,
const P1& a1,
const P2& a2,
const P3& a3,
const P4& a4) {
callback.Run(a1, a2, a3, a4);
MATE_METHOD_RETURN_UNDEFINED();
}
};
template<typename R, typename P1, typename P2, typename P3>
struct Invoker<R, P1, P2, P3, void, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<R(P1, P2, P3)>& callback,
const P1& a1,
const P2& a2,
const P3& a3) {
MATE_METHOD_RETURN(callback.Run(a1, a2, a3));
}
};
template<typename P1, typename P2, typename P3>
struct Invoker<void, P1, P2, P3, void, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<void(P1, P2, P3)>& callback,
const P1& a1,
const P2& a2,
const P3& a3) {
callback.Run(a1, a2, a3);
MATE_METHOD_RETURN_UNDEFINED();
}
};
template<typename R, typename P1, typename P2>
struct Invoker<R, P1, P2, void, void, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<R(P1, P2)>& callback,
const P1& a1,
const P2& a2) {
MATE_METHOD_RETURN(callback.Run(a1, a2));
}
};
template<typename P1, typename P2>
struct Invoker<void, P1, P2, void, void, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<void(P1, P2)>& callback,
const P1& a1,
const P2& a2) {
callback.Run(a1, a2);
MATE_METHOD_RETURN_UNDEFINED();
}
};
template<typename R, typename P1>
struct Invoker<R, P1, void, void, void, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<R(P1)>& callback,
const P1& a1) {
MATE_METHOD_RETURN(callback.Run(a1));
}
};
template<typename P1>
struct Invoker<void, P1, void, void, void, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<void(P1)>& callback,
const P1& a1) {
MATE_METHOD_RETURN(callback.Run(a1));
}
};
template<typename R>
struct Invoker<R, void, void, void, void, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<R()>& callback) {
MATE_METHOD_RETURN(callback.Run());
}
};
template<>
struct Invoker<void, void, void, void, void, void, void> {
inline static MATE_METHOD_RETURN_TYPE Go(
Arguments& args,
const base::Callback<void()>& callback) {
callback.Run();
MATE_METHOD_RETURN_UNDEFINED();
}
};
template<typename T>
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<typename Sig>
struct Dispatcher {
};
template<typename R>
struct Dispatcher<R()> {
static MATE_METHOD(DispatchToCallback) {
Arguments args(info);
v8::Handle<v8::External> v8_holder;
CHECK(args.GetData(&v8_holder));
CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
v8_holder->Value());
typedef CallbackHolder<R()> HolderT;
HolderT* holder = static_cast<HolderT*>(holder_base);
return Invoker<R>::Go(args, holder->callback);
}
};
template<typename R, typename P1>
struct Dispatcher<R(P1)> {
static MATE_METHOD(DispatchToCallback) {
Arguments args(info);
v8::Handle<v8::External> v8_holder;
CHECK(args.GetData(&v8_holder));
CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
v8_holder->Value());
typedef CallbackHolder<R(P1)> HolderT;
HolderT* holder = static_cast<HolderT*>(holder_base);
typename CallbackParamTraits<P1>::LocalType a1;
if (!GetNextArgument(args, holder->flags, true, &a1)) {
args.ThrowError();
MATE_METHOD_RETURN_UNDEFINED();
}
return Invoker<R, P1>::Go(args, holder->callback, a1);
}
};
template<typename R, typename P1, typename P2>
struct Dispatcher<R(P1, P2)> {
static MATE_METHOD(DispatchToCallback) {
Arguments args(info);
v8::Handle<v8::External> v8_holder;
CHECK(args.GetData(&v8_holder));
CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
v8_holder->Value());
typedef CallbackHolder<R(P1, P2)> HolderT;
HolderT* holder = static_cast<HolderT*>(holder_base);
typename CallbackParamTraits<P1>::LocalType a1;
typename CallbackParamTraits<P2>::LocalType a2;
if (!GetNextArgument(args, holder->flags, true, &a1) ||
!GetNextArgument(args, holder->flags, false, &a2)) {
args.ThrowError();
MATE_METHOD_RETURN_UNDEFINED();
}
return Invoker<R, P1, P2>::Go(args, holder->callback, a1, a2);
}
};
template<typename R, typename P1, typename P2, typename P3>
struct Dispatcher<R(P1, P2, P3)> {
static MATE_METHOD(DispatchToCallback) {
Arguments args(info);
v8::Handle<v8::External> v8_holder;
CHECK(args.GetData(&v8_holder));
CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
v8_holder->Value());
typedef CallbackHolder<R(P1, P2, P3)> HolderT;
HolderT* holder = static_cast<HolderT*>(holder_base);
typename CallbackParamTraits<P1>::LocalType a1;
typename CallbackParamTraits<P2>::LocalType a2;
typename CallbackParamTraits<P3>::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<R, P1, P2, P3>::Go(args, holder->callback, a1, a2, a3);
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4>
struct Dispatcher<R(P1, P2, P3, P4)> {
static MATE_METHOD(DispatchToCallback) {
Arguments args(info);
v8::Handle<v8::External> v8_holder;
CHECK(args.GetData(&v8_holder));
CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
v8_holder->Value());
typedef CallbackHolder<R(P1, P2, P3, P4)> HolderT;
HolderT* holder = static_cast<HolderT*>(holder_base);
typename CallbackParamTraits<P1>::LocalType a1;
typename CallbackParamTraits<P2>::LocalType a2;
typename CallbackParamTraits<P3>::LocalType a3;
typename CallbackParamTraits<P4>::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<R, P1, P2, P3, P4>::Go(args, holder->callback, a1, a2, a3,
a4);
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4,
typename P5>
struct Dispatcher<R(P1, P2, P3, P4, P5)> {
static MATE_METHOD(DispatchToCallback) {
Arguments args(info);
v8::Handle<v8::External> v8_holder;
CHECK(args.GetData(&v8_holder));
CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
v8_holder->Value());
typedef CallbackHolder<R(P1, P2, P3, P4, P5)> HolderT;
HolderT* holder = static_cast<HolderT*>(holder_base);
typename CallbackParamTraits<P1>::LocalType a1;
typename CallbackParamTraits<P2>::LocalType a2;
typename CallbackParamTraits<P3>::LocalType a3;
typename CallbackParamTraits<P4>::LocalType a4;
typename CallbackParamTraits<P5>::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<R, P1, P2, P3, P4, P5>::Go(args, holder->callback, a1, a2,
a3, a4, a5);
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6>
struct Dispatcher<R(P1, P2, P3, P4, P5, P6)> {
static MATE_METHOD(DispatchToCallback) {
Arguments args(info);
v8::Handle<v8::External> v8_holder;
CHECK(args.GetData(&v8_holder));
CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
v8_holder->Value());
typedef CallbackHolder<R(P1, P2, P3, P4, P5, P6)> HolderT;
HolderT* holder = static_cast<HolderT*>(holder_base);
typename CallbackParamTraits<P1>::LocalType a1;
typename CallbackParamTraits<P2>::LocalType a2;
typename CallbackParamTraits<P3>::LocalType a3;
typename CallbackParamTraits<P4>::LocalType a4;
typename CallbackParamTraits<P5>::LocalType a5;
typename CallbackParamTraits<P6>::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<R, P1, P2, P3, P4, P5, P6>::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<typename Sig>
v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
v8::Isolate* isolate, const base::Callback<Sig> callback,
int callback_flags = 0) {
typedef internal::CallbackHolder<Sig> HolderT;
HolderT* holder = new HolderT(isolate, callback, callback_flags);
return v8::FunctionTemplate::New(
isolate,
&internal::Dispatcher<Sig>::DispatchToCallback,
ConvertToV8<v8::Handle<v8::External> >(isolate,
holder->GetHandle(isolate)));
}
} // namespace mate
#endif // NATIVE_MATE_FUNCTION_TEMPLATE_H_

68
native_mate/handle.h Normal file
Просмотреть файл

@ -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<typename T>
class Handle {
public:
Handle() : object_(NULL) {}
Handle(v8::Handle<v8::Value> 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<v8::Value> ToV8() const { return wrapper_; }
T* get() const { return object_; }
private:
v8::Handle<v8::Value> wrapper_;
T* object_;
};
template<typename T>
struct Converter<mate::Handle<T> > {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const mate::Handle<T>& val) {
return val.ToV8();
}
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
mate::Handle<T>* out) {
T* object = NULL;
if (!Converter<T*>::FromV8(isolate, val, &object)) {
return false;
}
*out = mate::Handle<T>(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<typename T>
mate::Handle<T> CreateHandle(v8::Isolate* isolate, T* object) {
return mate::Handle<T>(object->GetWrapper(isolate), object);
}
} // namespace mate
#endif // NATIVE_MATE_HANDLE_H_

Просмотреть файл

@ -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<v8::Data> val) {
template_->Set(StringToSymbol(isolate_, name), val);
return *this;
}
ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl(
const base::StringPiece& name, v8::Handle<v8::FunctionTemplate> getter,
v8::Handle<v8::FunctionTemplate> setter) {
#if NODE_VERSION_AT_LEAST(0, 11, 0)
template_->SetAccessorProperty(StringToSymbol(isolate_, name), getter,
setter);
#endif
return *this;
}
v8::Local<v8::ObjectTemplate> ObjectTemplateBuilder::Build() {
v8::Local<v8::ObjectTemplate> result = template_;
template_.Clear();
return result;
}
} // namespace mate

Просмотреть файл

@ -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<typename T, typename Enable = void>
struct CallbackTraits {
static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate,
T callback) {
return CreateFunctionTemplate(isolate, base::Bind(callback));
}
};
// Specialization for base::Callback.
template<typename T>
struct CallbackTraits<base::Callback<T> > {
static v8::Handle<v8::FunctionTemplate> CreateTemplate(
v8::Isolate* isolate, const base::Callback<T>& 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<typename T>
struct CallbackTraits<T, typename base::enable_if<
base::is_member_function_pointer<T>::value>::type> {
static v8::Handle<v8::FunctionTemplate> 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<v8::Handle<v8::FunctionTemplate> > {
static v8::Handle<v8::FunctionTemplate> CreateTemplate(
v8::Handle<v8::FunctionTemplate> 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<typename T>
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<typename T>
ObjectTemplateBuilder& SetMethod(const base::StringPiece& name,
const T& callback) {
return SetImpl(name, CallbackTraits<T>::CreateTemplate(isolate_, callback));
}
template<typename T>
ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
const T& getter) {
return SetPropertyImpl(name,
CallbackTraits<T>::CreateTemplate(isolate_, getter),
v8::Local<v8::FunctionTemplate>());
}
template<typename T, typename U>
ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
const T& getter, const U& setter) {
return SetPropertyImpl(name,
CallbackTraits<T>::CreateTemplate(isolate_, getter),
CallbackTraits<U>::CreateTemplate(isolate_, setter));
}
v8::Local<v8::ObjectTemplate> Build();
private:
ObjectTemplateBuilder& SetImpl(const base::StringPiece& name,
v8::Handle<v8::Data> val);
ObjectTemplateBuilder& SetPropertyImpl(
const base::StringPiece& name, v8::Handle<v8::FunctionTemplate> getter,
v8::Handle<v8::FunctionTemplate> setter);
v8::Isolate* isolate_;
// ObjectTemplateBuilder should only be used on the stack.
v8::Local<v8::ObjectTemplate> template_;
};
} // namespace mate
#endif // NATIVE_MATE_OBJECT_TEMPLATE_BUILDER_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 <typename T>
class ScopedPersistent {
public:
ScopedPersistent() {
}
explicit ScopedPersistent(v8::Handle<T> handle) {
reset(handle);
}
~ScopedPersistent() {
reset();
}
void reset(v8::Handle<T> handle) {
if (!handle.IsEmpty())
handle_.Reset(GetIsolate(handle), handle);
else
reset();
}
void reset() {
handle_.Reset();
}
bool IsEmpty() const {
return handle_.IsEmpty();
}
v8::Handle<T> NewHandle() const {
if (handle_.IsEmpty())
return v8::Local<T>();
return v8::Local<T>::New(GetIsolate(handle_), handle_);
}
v8::Handle<T> NewHandle(v8::Isolate* isolate) const {
if (handle_.IsEmpty())
return v8::Local<T>();
return v8::Local<T>::New(isolate, handle_);
}
template <typename P>
void MakeWeak(P* parameters,
typename v8::WeakReferenceCallbacks<T, P>::Revivable callback) {
handle_.MakeWeak(parameters, callback);
}
private:
template <typename U>
static v8::Isolate* GetIsolate(v8::Handle<U> 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<v8::Context> context_handle) {
if (!context_handle.IsEmpty())
return context_handle->GetIsolate();
return v8::Isolate::GetCurrent();
}
static v8::Isolate* GetIsolate(
v8::Handle<v8::ObjectTemplate> template_handle) {
return v8::Isolate::GetCurrent();
}
template <typename U>
static v8::Isolate* GetIsolate(const U& any_handle) {
return v8::Isolate::GetCurrent();
}
v8::Persistent<T> handle_;
DISALLOW_COPY_AND_ASSIGN(ScopedPersistent);
};
template <typename T>
class RefCountedPersistent : public ScopedPersistent<T>,
public base::RefCounted<RefCountedPersistent<T>> {
public:
RefCountedPersistent() {}
explicit RefCountedPersistent(v8::Handle<T> handle)
: ScopedPersistent<T>(handle) {
}
protected:
friend class base::RefCounted<RefCountedPersistent<T>>;
~RefCountedPersistent() {}
private:
DISALLOW_COPY_AND_ASSIGN(RefCountedPersistent);
};
} // namespace mate
#endif // NATIVE_MATE_SCOPED_PERSISTENT_H_

49
native_mate/try_catch.cc Normal file
Просмотреть файл

@ -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 <sstream>
#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<v8::Message> message = try_catch_.Message();
ss << V8ToString(message->Get()) << std::endl
<< V8ToString(message->GetSourceLine()) << std::endl;
v8::Handle<v8::StackTrace> trace = message->GetStackTrace();
if (trace.IsEmpty())
return ss.str();
int len = trace->GetFrameCount();
for (int i = 0; i < len; ++i) {
v8::Handle<v8::StackFrame> frame = trace->GetFrame(i);
ss << V8ToString(frame->GetScriptName()) << ":"
<< frame->GetLineNumber() << ":"
<< frame->GetColumn() << ": "
<< V8ToString(frame->GetFunctionName())
<< std::endl;
}
return ss.str();
}
} // namespace mate

32
native_mate/try_catch.h Normal file
Просмотреть файл

@ -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 <string>
#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_

58
native_mate/wrappable.cc Normal file
Просмотреть файл

@ -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<v8::Object> Wrappable::GetWrapper(v8::Isolate* isolate) {
if (!wrapper_.IsEmpty()) {
return MATE_PERSISTENT_TO_LOCAL(v8::Object, isolate, wrapper_);
}
v8::Local<v8::ObjectTemplate> templ =
GetObjectTemplateBuilder(isolate).Build();
CHECK(!templ.IsEmpty());
CHECK_EQ(1, templ->InternalFieldCount());
v8::Handle<v8::Object> 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<v8::Value> val) {
if (!val->IsObject())
return NULL;
v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val);
return MATE_GET_INTERNAL_FIELD_POINTER(obj, 0);
}
} // namespace internal
} // namespace mate

85
native_mate/wrappable.h Normal file
Просмотреть файл

@ -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<v8::Value> 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<v8::Object> 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<v8::Object> wrapper_; // Weak
DISALLOW_COPY_AND_ASSIGN(Wrappable);
};
// This converter handles any subclass of Wrappable.
template<typename T>
struct Converter<T*, typename base::enable_if<
base::is_convertible<T*, Wrappable*>::value>::type> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) {
return val->GetWrapper(isolate);
}
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) {
*out = static_cast<T*>(static_cast<Wrappable*>(
internal::FromV8Impl(isolate, val)));
return *out != NULL;
}
};
} // namespace mate
#endif // NATIVE_MATE_WRAPPABLE_H_

23
native_mate_files.gypi Normal file
Просмотреть файл

@ -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',
],
},
}