Skip to content

Commit

Permalink
Native mate in electron 3 (#13450)
Browse files Browse the repository at this point in the history
* Initial commit.

* Do not rely on latest base/template_util.

* Enable modifying existing ObjectTemplate.

* Fix compilation error of function_template.

* Add initial Constructor type.

* Fix passing the wrong parameter.

* Make the Constructor accept arbitrary callback.

* Cleanup.

* Constructor should wrap the this pointer.

* Simplify Wrappable API.

* Remove helper typedefs.

* Support function with 7 parameters.

* Enable converting void*.

* Enable setting method in Dictionary.

* Add v8::Handle<v8::String> to converter.

* Make ScopedPersistent do type conversion.

* Add Arguments.Length method.

* Do not wrap an object when it's already wrapped.

* No need to reset wrapper_ when we would run destructor.

* Call object._init if we have one.

* Add object() accessor for Dictionary.

* Add converter for const char*.

* Enable creating empty Dictionary directly.

* Mark Dictionary.Get as const.

* Strictly check for boolean type.

* Add .gitignore.

* Add APIs to match new V8 APIs.

* Bring back ScopedPersistent.SetWeak.

* Some more APIs fixes.

* Reset handle in weak callback.

This doesn't seem to be neccesary, but we had better follow what upstream does.

* Enable converting ScopedPersistent.

* Fix compilation error with node 0.10.

* Fix compilation error of Constructor and ScopedPersistent in node 0.10.

* Use pump to generate source files.

* Add callback converter.

* Make ScopedPersistent's interface consistent with V8.

* Remove unused constructor of Dictionary.

* Add PersistentDictionary.

* Make throwing exception when parsing args easier

* Use NODE_VERSION_AT_LEAST to determine node version

* Don't throw error in Constructor

* Guard against non-constructor call in Constructor::New

* Fix throwing error in constructor

* Fix ignored exception thrown from constructor.

* OVERRIDE => override

* Avoid unnecessary copy in ConvertToV8

* Check internal field before converting

* Remove unneeded helper

* Add AfterInit method for Wrappable

* Add converter for unsigned long

* usigned long is uint64 on Linux

* Don't reset handle before Wrappable is destroyed

It is possible that the user wants to use the V8 object in the destructor.

Fixes #1112.

* added std::set converter

* Use Local instead of Handle

* Pass Handle to upper HandleScope when returning a V8 Handle

* Enter context before calling callback

* Allow converting Array

* Remember isolate in Wrappable

* Make isolate() public

* Check for null when converting Wrappable

* Add IsDestroyed method for Wrappable

* Allow specify methods that can be called after object is destroyed

* Use C++11 version of CreateFunctionTemplate

* Remove callback.h

* Remove locker.h

* Add Dictionary::CreateEmpty

* GetNext should have no side effect when failed

* Don't convert Function to Dictionary

* Don't pass callback as const reference

* Add SetHidden for Dictionary

* Use the new SetWeak in Wrappable

* Check whether key exists in Dictionary::Get

* Don't return v8::Maybe for std::vector

* Add Dictionary::Delete

* Do not manually destroy native resources

* isDestroy => isDestroyed

* Fix converter for std::set

* Improve error message for type error

Close #4307.

* Clear internal field when Wrapper is destroyed

* basic_types.h => macros.h

* use v8::private symbols as identifiers for object properties

* Make Wrappable a template class

* Leak Wrappable's template

Since it is declared as static variable it will be released
automatically when process exits, which causes crashes in
renderer process because the template will then be released
later than V8 is closed.

This commit simply leaks the template so the crash won't happen,
this leak should be fine since leaking resource on exit is not
a bad thing.

* Handle.ToV8 should return Object

* Add converter for std::map

* Setup v8::MicrotasksScope for callbacks

* Update to API changes of V8 5.2

* CHECK is not needed

* Call the user call Init in Constructor

* Make InitWith virtual

* Turn Wrappable into using FunctionTemplate

* Create objects from InstanceTemplate

* NewOperatorFactory is not used

* Remove the Constructor class

* GetConstructor should init default constructor

* Pass FunctionTemplate in BuildPrototype

* Do not set constructor name in SetConstructor

* Use ToDetailString for processing error message

* Add back empty handle string

* Add README

* create empty handle for null or undefined value

* Support setting read-only property value

* Add Converter<std::map<std::string, T>>::ToV8

* Add CI build through Electron

* Support 5 argument member function

* Use std functions instead of template_util

* Make Wrappable thread safe

* Use gin to manage FunctionTemplate

Sadly there is no way for us to know when V8 is closing, thus it is
impossible for us to clean the FunctionTemplate on exit at the right
time, which is critcal for multi-thread environment.

* add ability to set high memory usage, skipping the second round of GC callbacks

* Fix broken link

* Add a converter for `nullptr_t`

* Upstream Muon changes to avoid crashing

* only mark handle as independent when it's a high memory user

* Remove WrappableBase::GetWrapper() DCHECK

* virtual members need a virtual destructor

* GetWrapper should be const

* Add support for FreeBSD

* Remove usage of MarkIndependent api

https://bugs.chromium.org/p/chromium/issues/detail?id=780749
Use Active/Not Active as indicator whether the Scavenger can drop wrappers

* Address breaking API

* Fix Value::ToDetailString() call

See https://chromium-review.googlesource.com/848782

* Revert "Address breaking API"

This reverts commit e20cf86.

* Add mate::Promise

* Update travis settings

Use Node.js 9.7.0 and Xcode 9.3.

* Update appveyor settings

Use Visual Studio 2017.

* Remove mate::TryCatch (#26)

It's not used anywhere. We use v8::TryCatch instead.

* Address breaking API

* Don't copy things on Dictionary::Set

* Remove native_mate/compat.h

* prepare for merging to electron

* remove native_mate submodule

* update paths for native_mate

* move native_mate script to the electron scripts dir

* rename back to expected values

* fix linting
  • Loading branch information
MarshallOfSound committed Jun 27, 2018
1 parent 21d4ef5 commit 7f3620b
Show file tree
Hide file tree
Showing 29 changed files with 3,178 additions and 8 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Expand Up @@ -7,9 +7,6 @@
[submodule "vendor/breakpad"]
path = vendor/breakpad
url = https://github.com/electron/chromium-breakpad.git
[submodule "vendor/native_mate"]
path = vendor/native_mate
url = https://github.com/electron/native-mate.git
[submodule "vendor/crashpad"]
path = vendor/crashpad
url = https://github.com/electron/crashpad.git
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Expand Up @@ -129,7 +129,7 @@ These individual tutorials expand on topics discussed in the guide above.
* [Menu](api/menu.md)
* [MenuItem](api/menu-item.md)
* [net](api/net.md)
* [netLog](api/netLog.md)
* [netLog](api/net-log.md)
* [powerMonitor](api/power-monitor.md)
* [powerSaveBlocker](api/power-save-blocker.md)
* [protocol](api/protocol.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/api/breaking-changes.md
@@ -1,6 +1,6 @@
# API Contract

Breaking changes will be documented here, and deprecation warnings added to JS code where possible, at least [one major version](electron-versioning.md#semver) before the change is made.
Breaking changes will be documented here, and deprecation warnings added to JS code where possible, at least [one major version](../tutorial/electron-versioning.md#semver) before the change is made.

# `FIXME` comments

Expand Down
4 changes: 2 additions & 2 deletions electron.gyp
Expand Up @@ -10,7 +10,7 @@
'includes': [
'features.gypi',
'filenames.gypi',
'vendor/native_mate/native_mate_files.gypi',
'native_mate/native_mate_files.gypi',
],
'target_defaults': {
'defines': [
Expand Down Expand Up @@ -295,7 +295,7 @@
'include_dirs': [
'.',
'chromium_src',
'vendor/native_mate',
'native_mate',
# Include atom_natives.h.
'<(SHARED_INTERMEDIATE_DIR)',
# Include directories for uv and node.
Expand Down
27 changes: 27 additions & 0 deletions native_mate/LICENSE.chromium
@@ -0,0 +1,27 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 changes: 56 additions & 0 deletions native_mate/README.md
@@ -0,0 +1,56 @@
> A fork of Chromium's [gin library][chromium-gin-lib] that makes it easier to
> marshal types between C++ and JavaScript.
# Overview

`native-mate` was forked from `gin` so that it could be used in
[Electron][electron] without conflicting with Node's Environment. It has also
been extended to allow Electron to create classes in JavaScript.

With the help of Chromium's `base` library, `native-mate` makes writing JS
bindings very easy, and most of the intricate details of converting V8 types
to C++ types and back are taken care of auto-magically. In most cases there's
no need to use the raw V8 API to implement an API binding.

For example, here's an API binding that doesn't use `native-mate`:

```c++
// static
void Shell::OpenItem(const v8::FunctionCallbackInfo<v8::Value>& args) {
base::FilePath file_path;
if (!FromV8Arguments(args, &file_path))
return node::ThrowTypeError("Bad argument");

platform_util::OpenItem(file_path);
}

// static
void Shell::Initialize(v8::Handle<v8::Object> target) {
NODE_SET_METHOD(target, "openItem", OpenItem);
}
```
And here's the same API binding using `native-mate`:
```c++
void Initialize(v8::Handle<v8::Object> exports) {
mate::Dictionary dict(v8::Isolate::GetCurrent(), exports);
dict.SetMethod("openItem", &platform_util::OpenItem);
}
```

# Code Structure

* `converter.h` - Templatized JS<->C++ conversion routines for many common C++
types. You can define your own by specializing `Converter`.
* `function_template.h` - Create JavaScript functions that dispatch to any C++
function, member function pointer, or `base::Callback`.
* `object_template_builder.h` - A handy utility for creation of `v8::ObjectTemplate`.
* `wrappable.h` - Base class for C++ classes that want to be owned by the V8 GC.
Wrappable objects are automatically deleted when GC discovers that nothing in
the V8 heap refers to them. This is also an easy way to expose C++ objects to
JavaScript.


[chromium-gin-lib]: https://code.google.com/p/chromium/codesearch#chromium/src/gin/README.md&sq=package:chromium
[electron]: http://electron.atom.io/
72 changes: 72 additions & 0 deletions native_mate/native_mate/arguments.cc
@@ -0,0 +1,72 @@
// 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 {

namespace {

std::string V8TypeAsString(v8::Isolate* isolate, v8::Local<v8::Value> value) {
if (value.IsEmpty())
return "<empty handle>";
v8::MaybeLocal<v8::String> details =
value->ToDetailString(isolate->GetCurrentContext());
std::string result;
if (!details.IsEmpty())
ConvertFromV8(isolate, details.ToLocalChecked(), &result);
return result;
}

} // namespace

Arguments::Arguments()
: isolate_(NULL),
info_(NULL),
next_(0),
insufficient_arguments_(false) {
}

Arguments::Arguments(const v8::FunctionCallbackInfo<v8::Value>& info)
: isolate_(info.GetIsolate()),
info_(&info),
next_(0),
insufficient_arguments_(false) {
}

Arguments::~Arguments() {
}

v8::Local<v8::Value> Arguments::PeekNext() const {
if (next_ >= info_->Length())
return v8::Local<v8::Value>();
return (*info_)[next_];
}

v8::Local<v8::Value> Arguments::ThrowError() const {
if (insufficient_arguments_)
return ThrowTypeError("Insufficient number of arguments.");

return ThrowTypeError(base::StringPrintf(
"Error processing argument at index %d, conversion failure from %s",
next_, V8TypeAsString(isolate_, (*info_)[next_]).c_str()));
}

v8::Local<v8::Value> Arguments::ThrowError(const std::string& message) const {
isolate_->ThrowException(v8::Exception::Error(
StringToV8(isolate_, message)));
return v8::Undefined(isolate_);
}

v8::Local<v8::Value> Arguments::ThrowTypeError(
const std::string& message) const {
isolate_->ThrowException(v8::Exception::TypeError(
StringToV8(isolate_, message)));
return v8::Undefined(isolate_);
}

} // namespace mate
99 changes: 99 additions & 0 deletions native_mate/native_mate/arguments.h
@@ -0,0 +1,99 @@
// 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/macros.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 v8::FunctionCallbackInfo<v8::Value>& info);
~Arguments();

v8::Local<v8::Object> GetHolder() const {
return info_->Holder();
}

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::Local<v8::Value> val = (*info_)[next_];
bool success = ConvertFromV8(isolate_, val, out);
if (success)
next_++;
return success;
}

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::Local<v8::Value> val = (*info_)[next_++];
if (!ConvertFromV8(isolate_, val, &out->at(i)))
return false;
}
return true;
}

v8::Local<v8::Object> GetThis() {
return info_->This();
}

bool IsConstructCall() const {
return info_->IsConstructCall();
}

int Length() const {
return info_->Length();
}

template<typename T>
void Return(T val) {
info_->GetReturnValue().Set(ConvertToV8(isolate_, val));
}

v8::Local<v8::Value> PeekNext() const;

v8::Local<v8::Value> ThrowError() const;
v8::Local<v8::Value> ThrowError(const std::string& message) const;
v8::Local<v8::Value> ThrowTypeError(const std::string& message) const;

v8::Isolate* isolate() const { return isolate_; }

private:
v8::Isolate* isolate_;
const v8::FunctionCallbackInfo<v8::Value>* info_;
int next_;
bool insufficient_arguments_;
};

} // namespace mate

#endif // NATIVE_MATE_ARGUMENTS_H_

0 comments on commit 7f3620b

Please sign in to comment.