Initial commit.
This commit is contained in:
Коммит
ff65b7dae1
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
|
@ -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_
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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',
|
||||
],
|
||||
},
|
||||
}
|
Загрузка…
Ссылка в новой задаче