Merge branch 'master' into linux

Conflicts:
	vendor/apm
This commit is contained in:
Cheng Zhao 2014-01-15 11:18:40 +00:00
commit 2f798c5116
43 changed files with 478 additions and 75 deletions

View file

@ -50,8 +50,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,8,1,0 FILEVERSION 0,8,5,0
PRODUCTVERSION 0,8,1,0 PRODUCTVERSION 0,8,5,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -68,12 +68,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "GitHub, Inc." VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Atom-Shell" VALUE "FileDescription", "Atom-Shell"
VALUE "FileVersion", "0.8.1" VALUE "FileVersion", "0.8.5"
VALUE "InternalName", "atom.exe" VALUE "InternalName", "atom.exe"
VALUE "LegalCopyright", "Copyright (C) 2013 GitHub, Inc. All rights reserved." VALUE "LegalCopyright", "Copyright (C) 2013 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "atom.exe" VALUE "OriginalFilename", "atom.exe"
VALUE "ProductName", "Atom-Shell" VALUE "ProductName", "Atom-Shell"
VALUE "ProductVersion", "0.8.1" VALUE "ProductVersion", "0.8.5"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -12,6 +12,7 @@
], ],
'coffee_sources': [ 'coffee_sources': [
'browser/api/lib/app.coffee', 'browser/api/lib/app.coffee',
'browser/api/lib/atom-delegate.coffee',
'browser/api/lib/auto-updater.coffee', 'browser/api/lib/auto-updater.coffee',
'browser/api/lib/browser-window.coffee', 'browser/api/lib/browser-window.coffee',
'browser/api/lib/dialog.coffee', 'browser/api/lib/dialog.coffee',
@ -27,7 +28,9 @@
'common/api/lib/clipboard.coffee', 'common/api/lib/clipboard.coffee',
'common/api/lib/crash-reporter.coffee', 'common/api/lib/crash-reporter.coffee',
'common/api/lib/id-weak-map.coffee', 'common/api/lib/id-weak-map.coffee',
'common/api/lib/screen.coffee',
'common/api/lib/shell.coffee', 'common/api/lib/shell.coffee',
'common/lib/init.coffee',
'renderer/lib/init.coffee', 'renderer/lib/init.coffee',
'renderer/api/lib/ipc.coffee', 'renderer/api/lib/ipc.coffee',
'renderer/api/lib/remote.coffee', 'renderer/api/lib/remote.coffee',
@ -46,8 +49,6 @@
'browser/api/atom_api_dialog.h', 'browser/api/atom_api_dialog.h',
'browser/api/atom_api_event.cc', 'browser/api/atom_api_event.cc',
'browser/api/atom_api_event.h', 'browser/api/atom_api_event.h',
'browser/api/atom_api_event_emitter.cc',
'browser/api/atom_api_event_emitter.h',
'browser/api/atom_api_menu.cc', 'browser/api/atom_api_menu.cc',
'browser/api/atom_api_menu.h', 'browser/api/atom_api_menu.h',
'browser/api/atom_api_menu_mac.h', 'browser/api/atom_api_menu_mac.h',
@ -133,8 +134,12 @@
'common/api/atom_api_clipboard.h', 'common/api/atom_api_clipboard.h',
'common/api/atom_api_crash_reporter.cc', 'common/api/atom_api_crash_reporter.cc',
'common/api/atom_api_crash_reporter.h', 'common/api/atom_api_crash_reporter.h',
'common/api/atom_api_event_emitter.cc',
'common/api/atom_api_event_emitter.h',
'common/api/atom_api_id_weak_map.cc', 'common/api/atom_api_id_weak_map.cc',
'common/api/atom_api_id_weak_map.h', 'common/api/atom_api_id_weak_map.h',
'common/api/atom_api_screen.cc',
'common/api/atom_api_screen.h',
'common/api/atom_api_shell.cc', 'common/api/atom_api_shell.cc',
'common/api/atom_api_shell.h', 'common/api/atom_api_shell.h',
'common/api/atom_api_v8_util.cc', 'common/api/atom_api_v8_util.cc',

View file

@ -6,8 +6,8 @@
#define ATOM_BROWSER_API_ATOM_API_APP_H_ #define ATOM_BROWSER_API_ATOM_API_APP_H_
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "browser/api/atom_api_event_emitter.h"
#include "browser/browser_observer.h" #include "browser/browser_observer.h"
#include "common/api/atom_api_event_emitter.h"
namespace atom { namespace atom {

View file

@ -7,8 +7,8 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "browser/api/atom_api_event_emitter.h"
#include "browser/auto_updater_delegate.h" #include "browser/auto_updater_delegate.h"
#include "common/api/atom_api_event_emitter.h"
namespace atom { namespace atom {

View file

@ -19,6 +19,7 @@ namespace {
template<typename T> template<typename T>
void CallV8Function(const RefCountedV8Function& callback, T arg) { void CallV8Function(const RefCountedV8Function& callback, T arg) {
v8::HandleScope handle_scope(node_isolate);
v8::Handle<v8::Value> value = ToV8Value(arg); v8::Handle<v8::Value> value = ToV8Value(arg);
callback->NewHandle(node_isolate)->Call( callback->NewHandle(node_isolate)->Call(
v8::Context::GetCurrent()->Global(), 1, &value); v8::Context::GetCurrent()->Global(), 1, &value);

View file

@ -6,7 +6,7 @@
#define ATOM_BROWSER_API_ATOM_API_MENU_H_ #define ATOM_BROWSER_API_ATOM_API_MENU_H_
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "browser/api/atom_api_event_emitter.h" #include "common/api/atom_api_event_emitter.h"
#include "ui/base/models/simple_menu_model.h" #include "ui/base/models/simple_menu_model.h"
namespace atom { namespace atom {

View file

@ -5,10 +5,9 @@
#ifndef ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_ #ifndef ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_
#define ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_ #define ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_
#include "browser/api/atom_api_event_emitter.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/power_monitor/power_observer.h" #include "base/power_monitor/power_observer.h"
#include "common/api/atom_api_event_emitter.h"
namespace atom { namespace atom {

View file

@ -8,8 +8,8 @@
#include <vector> #include <vector>
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "browser/api/atom_api_event_emitter.h"
#include "browser/native_window_observer.h" #include "browser/native_window_observer.h"
#include "common/api/atom_api_event_emitter.h"
#include "common/v8/scoped_persistent.h" #include "common/v8/scoped_persistent.h"
namespace base { namespace base {

View file

@ -0,0 +1,6 @@
module.exports =
browserMainParts:
preMainMessageLoopRun: ->
setImmediate ->
module.exports.browserMainParts.preMainMessageLoopRun()

View file

@ -50,8 +50,8 @@ bool AtomBrowserClient::ShouldSwapProcessesForNavigation(
content::SiteInstance* site_instance, content::SiteInstance* site_instance,
const GURL& current_url, const GURL& current_url,
const GURL& new_url) { const GURL& new_url) {
// Restart renderer process if navigating to the same url. // Restart renderer process for all navigations.
return current_url == new_url; return true;
} }
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts( brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(

View file

@ -14,12 +14,12 @@ process.argv.splice 1, 1
globalPaths = require('module').globalPaths globalPaths = require('module').globalPaths
globalPaths.push path.join process.resourcesPath, 'browser', 'api', 'lib' globalPaths.push path.join process.resourcesPath, 'browser', 'api', 'lib'
# And also common/api/lib
globalPaths.push path.join process.resourcesPath, 'common', 'api', 'lib'
# Do loading in next tick since we still need some initialize work before # Do loading in next tick since we still need some initialize work before
# native bindings can work. # native bindings can work.
setImmediate -> setImmediate ->
# Import common settings.
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init.js')
if process.platform is 'win32' if process.platform is 'win32'
# Redirect node's console to use our own implementations, since node can not # Redirect node's console to use our own implementations, since node can not
# handle console output when running as GUI program. # handle console output when running as GUI program.

View file

@ -11,7 +11,7 @@
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>atom.icns</string> <string>atom.icns</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.8.1</string> <string>0.8.5</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>

View file

@ -283,6 +283,30 @@ void NativeWindow::NotifyWindowBlur() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowBlur()); FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowBlur());
} }
// In atom-shell all reloads and navigations started by renderer process would
// be redirected to this method, so we can have precise control of how we
// would open the url (in our case, is to restart the renderer process). See
// AtomRendererClient::ShouldFork for how this is done.
content::WebContents* NativeWindow::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
if (params.disposition != CURRENT_TAB)
return NULL;
content::NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.referrer = params.referrer;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.transferred_global_request_id =
params.transferred_global_request_id;
source->GetController().LoadURLWithParams(load_url_params);
return source;
}
content::JavaScriptDialogManager* NativeWindow::GetJavaScriptDialogManager() { content::JavaScriptDialogManager* NativeWindow::GetJavaScriptDialogManager() {
if (!dialog_manager_) if (!dialog_manager_)
dialog_manager_.reset(new AtomJavaScriptDialogManager); dialog_manager_.reset(new AtomJavaScriptDialogManager);

View file

@ -157,6 +157,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
const std::vector<DraggableRegion>& regions) = 0; const std::vector<DraggableRegion>& regions) = 0;
// Implementations of content::WebContentsDelegate. // Implementations of content::WebContentsDelegate.
virtual content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) OVERRIDE;
virtual content::JavaScriptDialogManager* virtual content::JavaScriptDialogManager*
GetJavaScriptDialogManager() OVERRIDE; GetJavaScriptDialogManager() OVERRIDE;
virtual void BeforeUnloadFired(content::WebContents* tab, virtual void BeforeUnloadFired(content::WebContents* tab,

View file

@ -142,7 +142,7 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
: NativeWindow(web_contents, options), : NativeWindow(web_contents, options),
is_kiosk_(false), is_kiosk_(false),
attention_request_id_(0) { attention_request_id_(0) {
int width, height; int width = 800, height = 600;
options->GetInteger(switches::kWidth, &width); options->GetInteger(switches::kWidth, &width);
options->GetInteger(switches::kHeight, &height); options->GetInteger(switches::kHeight, &height);

View file

@ -35,7 +35,7 @@
# Settings to compile node under Windows. # Settings to compile node under Windows.
'target_defaults': { 'target_defaults': {
'target_conditions': [ 'target_conditions': [
['_target_name in ["libuv", "http_parser", "cares", "openssl", "node_lib", "zlib"]', { ['_target_name in ["libuv", "http_parser", "cares", "openssl", "openssl-cli", "node_lib", "zlib"]', {
'msvs_disabled_warnings': [ 'msvs_disabled_warnings': [
4013, # 'free' undefined; assuming extern returning int 4013, # 'free' undefined; assuming extern returning int
4054, # 4054, #
@ -49,13 +49,14 @@
4204, # non-constant aggregate initializer 4204, # non-constant aggregate initializer
4214, # bit field types other than int 4214, # bit field types other than int
4232, # address of dllimport 'free' is not static, identity not guaranteed 4232, # address of dllimport 'free' is not static, identity not guaranteed
4291, # no matching operator delete found
4295, # array is too small to include a terminating null character 4295, # array is too small to include a terminating null character
4389, # '==' : signed/unsigned mismatch 4389, # '==' : signed/unsigned mismatch
4505, # unreferenced local function has been removed 4505, # unreferenced local function has been removed
4701, # potentially uninitialized local variable 'sizew' used 4701, # potentially uninitialized local variable 'sizew' used
4706, # assignment within conditional expression 4706, # assignment within conditional expression
4804, # unsafe use of type 'bool' in operation 4804, # unsafe use of type 'bool' in operation
4996, # 4996, # this function or variable may be unsafe.
], ],
'msvs_settings': { 'msvs_settings': {
'VCCLCompilerTool': { 'VCCLCompilerTool': {

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "browser/api/atom_api_event_emitter.h" #include "common/api/atom_api_event_emitter.h"
#include <vector> #include <vector>

View file

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_EVENT_EMITTER_H_ #ifndef ATOM_COMMON_API_ATOM_API_EVENT_EMITTER_H_
#define ATOM_BROWSER_API_ATOM_API_EVENT_EMITTER_H_ #define ATOM_COMMON_API_ATOM_API_EVENT_EMITTER_H_
#include <string> #include <string>
@ -40,4 +40,4 @@ class EventEmitter : public node::ObjectWrap {
} // namespace atom } // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_EVENT_EMITTER_H_ #endif // ATOM_COMMON_API_ATOM_API_EVENT_EMITTER_H_

View file

@ -0,0 +1,86 @@
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "common/api/atom_api_screen.h"
#include "common/v8/native_type_conversions.h"
#include "ui/gfx/screen.h"
#include "common/v8/node_common.h"
#define UNWRAP_SCREEN_AND_CHECK \
Screen* self = ObjectWrap::Unwrap<Screen>(args.This()); \
if (self == NULL) \
return node::ThrowError("Screen is already destroyed")
namespace atom {
namespace api {
namespace {
v8::Handle<v8::Object> DisplayToV8Value(const gfx::Display& display) {
v8::Handle<v8::Object> obj = v8::Object::New();
obj->Set(ToV8Value("bounds"), ToV8Value(display.bounds()));
obj->Set(ToV8Value("workArea"), ToV8Value(display.work_area()));
obj->Set(ToV8Value("size"), ToV8Value(display.size()));
obj->Set(ToV8Value("workAreaSize"), ToV8Value(display.work_area_size()));
obj->Set(ToV8Value("scaleFactor"), ToV8Value(display.device_scale_factor()));
return obj;
}
} // namespace
Screen::Screen(v8::Handle<v8::Object> wrapper)
: EventEmitter(wrapper),
screen_(gfx::Screen::GetNativeScreen()) {
}
Screen::~Screen() {
}
// static
void Screen::New(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::HandleScope scope(args.GetIsolate());
if (!args.IsConstructCall())
return node::ThrowError("Require constructor call");
new Screen(args.This());
}
// static
void Screen::GetCursorScreenPoint(
const v8::FunctionCallbackInfo<v8::Value>& args) {
UNWRAP_SCREEN_AND_CHECK;
args.GetReturnValue().Set(ToV8Value(self->screen_->GetCursorScreenPoint()));
}
// static
void Screen::GetPrimaryDisplay(
const v8::FunctionCallbackInfo<v8::Value>& args) {
UNWRAP_SCREEN_AND_CHECK;
gfx::Display display = self->screen_->GetPrimaryDisplay();
args.GetReturnValue().Set(DisplayToV8Value(display));
}
// static
void Screen::Initialize(v8::Handle<v8::Object> target) {
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->SetClassName(v8::String::NewSymbol("Screen"));
NODE_SET_PROTOTYPE_METHOD(t, "getCursorScreenPoint", GetCursorScreenPoint);
NODE_SET_PROTOTYPE_METHOD(t, "getPrimaryDisplay", GetPrimaryDisplay);
target->Set(v8::String::NewSymbol("Screen"), t->GetFunction());
}
} // namespace api
} // namespace atom
NODE_MODULE(atom_common_screen, atom::api::Screen::Initialize)

View file

@ -0,0 +1,44 @@
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_API_ATOM_API_SCREEN_H_
#define ATOM_COMMON_API_ATOM_API_SCREEN_H_
#include "common/api/atom_api_event_emitter.h"
namespace gfx {
class Screen;
}
namespace atom {
namespace api {
class Screen : public EventEmitter {
public:
virtual ~Screen();
static void Initialize(v8::Handle<v8::Object> target);
protected:
explicit Screen(v8::Handle<v8::Object> wrapper);
private:
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetCursorScreenPoint(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetPrimaryDisplay(
const v8::FunctionCallbackInfo<v8::Value>& args);
gfx::Screen* screen_;
DISALLOW_COPY_AND_ASSIGN(Screen);
};
} // namespace api
} // namespace atom
#endif // ATOM_COMMON_API_ATOM_API_SCREEN_H_

View file

@ -16,11 +16,41 @@ namespace {
static int kMaxCallStackSize = 200; // Same with WebKit. static int kMaxCallStackSize = 200; // Same with WebKit.
static uv_async_t dummy_uv_handle; // Async handle to wake up uv loop.
static uv_async_t g_next_tick_uv_handle;
// Async handle to execute the stored v8 callback.
static uv_async_t g_callback_uv_handle;
// Stored v8 callback, to be called by the async handler.
RefCountedV8Function g_v8_callback;
// Dummy class type that used for crashing the program.
struct DummyClass { bool crash; }; struct DummyClass { bool crash; };
void UvNoOp(uv_async_t* handle, int status) { // Async handler to call next process.nextTick callbacks.
void UvCallNextTick(uv_async_t* handle, int status) {
node::Environment* env = node::Environment::GetCurrent(node_isolate);
node::Environment::TickInfo* tick_info = env->tick_info();
if (tick_info->in_tick())
return;
if (tick_info->length() == 0) {
tick_info->set_index(0);
return;
}
tick_info->set_in_tick(true);
env->tick_callback_function()->Call(env->process_object(), 0, NULL);
tick_info->set_in_tick(false);
}
// Async handler to execute the stored v8 callback.
void UvOnCallback(uv_async_t* handle, int status) {
v8::HandleScope handle_scope(node_isolate);
v8::Handle<v8::Object> global = v8::Context::GetCurrent()->Global();
g_v8_callback->NewHandle()->Call(global, 0, NULL);
} }
v8::Handle<v8::Object> DumpStackFrame(v8::Handle<v8::StackFrame> stack_frame) { v8::Handle<v8::Object> DumpStackFrame(v8::Handle<v8::StackFrame> stack_frame) {
@ -44,7 +74,8 @@ v8::Handle<v8::Object> DumpStackFrame(v8::Handle<v8::StackFrame> stack_frame) {
node::node_module_struct* GetBuiltinModule(const char *name, bool is_browser); node::node_module_struct* GetBuiltinModule(const char *name, bool is_browser);
AtomBindings::AtomBindings() { AtomBindings::AtomBindings() {
uv_async_init(uv_default_loop(), &dummy_uv_handle, UvNoOp); uv_async_init(uv_default_loop(), &g_next_tick_uv_handle, UvCallNextTick);
uv_async_init(uv_default_loop(), &g_callback_uv_handle, UvOnCallback);
} }
AtomBindings::~AtomBindings() { AtomBindings::~AtomBindings() {
@ -58,6 +89,7 @@ void AtomBindings::BindTo(v8::Handle<v8::Object> process) {
NODE_SET_METHOD(process, "activateUvLoop", ActivateUVLoop); NODE_SET_METHOD(process, "activateUvLoop", ActivateUVLoop);
NODE_SET_METHOD(process, "log", Log); NODE_SET_METHOD(process, "log", Log);
NODE_SET_METHOD(process, "getCurrentStackTrace", GetCurrentStackTrace); NODE_SET_METHOD(process, "getCurrentStackTrace", GetCurrentStackTrace);
NODE_SET_METHOD(process, "scheduleCallback", ScheduleCallback);
process->Get(v8::String::New("versions"))->ToObject()-> process->Get(v8::String::New("versions"))->ToObject()->
Set(v8::String::New("atom-shell"), v8::String::New(ATOM_VERSION_STRING)); Set(v8::String::New("atom-shell"), v8::String::New(ATOM_VERSION_STRING));
@ -115,7 +147,7 @@ void AtomBindings::Crash(const v8::FunctionCallbackInfo<v8::Value>& args) {
// static // static
void AtomBindings::ActivateUVLoop( void AtomBindings::ActivateUVLoop(
const v8::FunctionCallbackInfo<v8::Value>& args) { const v8::FunctionCallbackInfo<v8::Value>& args) {
uv_async_send(&dummy_uv_handle); uv_async_send(&g_next_tick_uv_handle);
} }
// static // static
@ -146,4 +178,12 @@ void AtomBindings::GetCurrentStackTrace(
args.GetReturnValue().Set(result); args.GetReturnValue().Set(result);
} }
// static
void AtomBindings::ScheduleCallback(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (!FromV8Arguments(args, &g_v8_callback))
return node::ThrowTypeError("Bad arguments");
uv_async_send(&g_callback_uv_handle);
}
} // namespace atom } // namespace atom

View file

@ -26,6 +26,7 @@ class AtomBindings {
static void Log(const v8::FunctionCallbackInfo<v8::Value>& args); static void Log(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetCurrentStackTrace( static void GetCurrentStackTrace(
const v8::FunctionCallbackInfo<v8::Value>& args); const v8::FunctionCallbackInfo<v8::Value>& args);
static void ScheduleCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
DISALLOW_COPY_AND_ASSIGN(AtomBindings); DISALLOW_COPY_AND_ASSIGN(AtomBindings);
}; };

View file

@ -27,6 +27,7 @@ NODE_EXT_LIST_ITEM(atom_renderer_ipc)
NODE_EXT_LIST_ITEM(atom_common_clipboard) NODE_EXT_LIST_ITEM(atom_common_clipboard)
NODE_EXT_LIST_ITEM(atom_common_crash_reporter) NODE_EXT_LIST_ITEM(atom_common_crash_reporter)
NODE_EXT_LIST_ITEM(atom_common_id_weak_map) NODE_EXT_LIST_ITEM(atom_common_id_weak_map)
NODE_EXT_LIST_ITEM(atom_common_screen)
NODE_EXT_LIST_ITEM(atom_common_shell) NODE_EXT_LIST_ITEM(atom_common_shell)
NODE_EXT_LIST_ITEM(atom_common_v8_util) NODE_EXT_LIST_ITEM(atom_common_v8_util)

View file

@ -0,0 +1,3 @@
{Screen} = process.atomBinding 'screen'
module.exports = new Screen

View file

@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 0 #define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 8 #define ATOM_MINOR_VERSION 8
#define ATOM_PATCH_VERSION 1 #define ATOM_PATCH_VERSION 5
#define ATOM_VERSION_IS_RELEASE 1 #define ATOM_VERSION_IS_RELEASE 1

28
common/lib/init.coffee Normal file
View file

@ -0,0 +1,28 @@
path = require 'path'
timers = require 'timers'
Module = require 'module'
# Add common/api/lib to module search paths.
globalPaths = Module.globalPaths
globalPaths.push path.join(process.resourcesPath, 'common', 'api', 'lib')
# setImmediate and process.nextTick makes use of uv_check and uv_prepare to
# run the callbacks, however since we only run uv loop on requests, the
# callbacks wouldn't be called until something else activated the uv loop,
# which would delay the callbacks for arbitrary long time. So we should
# initiatively activate the uv loop once setImmediate and process.nextTick is
# called.
wrapWithActivateUvLoop = (func) ->
->
process.activateUvLoop()
func.apply this, arguments
process.nextTick = wrapWithActivateUvLoop process.nextTick
global.setImmediate = wrapWithActivateUvLoop timers.setImmediate
global.clearImmediate = timers.clearImmediate
# The child_process module also needs to activate the uv loop to make the ipc
# channel setup.
# TODO(zcbenz): Find out why this is needed.
childProcess = require 'child_process'
childProcess.spawn = wrapWithActivateUvLoop childProcess.spawn
childProcess.fork = wrapWithActivateUvLoop childProcess.fork

View file

@ -65,7 +65,9 @@ NodeBindings::NodeBindings(bool is_browser)
: is_browser_(is_browser), : is_browser_(is_browser),
message_loop_(NULL), message_loop_(NULL),
uv_loop_(uv_default_loop()), uv_loop_(uv_default_loop()),
embed_closed_(false) { embed_closed_(false),
uv_env_(NULL),
weak_factory_(this) {
} }
NodeBindings::~NodeBindings() { NodeBindings::~NodeBindings() {
@ -76,7 +78,6 @@ NodeBindings::~NodeBindings() {
// Wait for everything to be done. // Wait for everything to be done.
uv_thread_join(&embed_thread_); uv_thread_join(&embed_thread_);
message_loop_->RunUntilIdle();
// Clear uv. // Clear uv.
uv_sem_destroy(&embed_sem_); uv_sem_destroy(&embed_sem_);
@ -193,9 +194,13 @@ void NodeBindings::RunMessageLoop() {
void NodeBindings::UvRunOnce() { void NodeBindings::UvRunOnce() {
DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI));
// Enter node context while dealing with uv events.
v8::HandleScope handle_scope(node_isolate); v8::HandleScope handle_scope(node_isolate);
v8::Context::Scope context_scope(global_env->context());
// Enter node context while dealing with uv events, by default the global
// env would be used unless user specified another one (this happens for
// renderer process, which wraps the uv loop with web page context).
node::Environment* env = uv_env() ? uv_env() : global_env;
v8::Context::Scope context_scope(env->context());
// Deal with uv events. // Deal with uv events.
int r = uv_run(uv_loop_, (uv_run_mode)(UV_RUN_ONCE | UV_RUN_NOWAIT)); int r = uv_run(uv_loop_, (uv_run_mode)(UV_RUN_ONCE | UV_RUN_NOWAIT));
@ -209,7 +214,7 @@ void NodeBindings::UvRunOnce() {
void NodeBindings::WakeupMainThread() { void NodeBindings::WakeupMainThread() {
DCHECK(message_loop_); DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(&NodeBindings::UvRunOnce, message_loop_->PostTask(FROM_HERE, base::Bind(&NodeBindings::UvRunOnce,
base::Unretained(this))); weak_factory_.GetWeakPtr()));
} }
void NodeBindings::WakeupEmbedThread() { void NodeBindings::WakeupEmbedThread() {
@ -220,11 +225,20 @@ void NodeBindings::WakeupEmbedThread() {
void NodeBindings::EmbedThreadRunner(void *arg) { void NodeBindings::EmbedThreadRunner(void *arg) {
NodeBindings* self = static_cast<NodeBindings*>(arg); NodeBindings* self = static_cast<NodeBindings*>(arg);
while (!self->embed_closed_) { while (true) {
// Wait for the main loop to deal with events. // Wait for the main loop to deal with events.
uv_sem_wait(&self->embed_sem_); uv_sem_wait(&self->embed_sem_);
if (self->embed_closed_)
break;
// Wait for something to happen in uv loop.
// Note that the PollEvents() is implemented by derived classes, so when
// this class is being destructed the PollEvents() would not be available
// anymore. Because of it we must make sure we only invoke PollEvents()
// when this class is alive.
self->PollEvents(); self->PollEvents();
if (self->embed_closed_)
break;
// Deal with event in main thread. // Deal with event in main thread.
self->WakeupMainThread(); self->WakeupMainThread();

View file

@ -6,6 +6,7 @@
#define ATOM_COMMON_NODE_BINDINGS_H_ #define ATOM_COMMON_NODE_BINDINGS_H_
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
#include "vendor/node/deps/uv/include/uv.h" #include "vendor/node/deps/uv/include/uv.h"
@ -37,6 +38,10 @@ class NodeBindings {
// Do message loop integration. // Do message loop integration.
virtual void RunMessageLoop(); virtual void RunMessageLoop();
// Gets/sets the environment to wrap uv loop.
void set_uv_env(node::Environment* env) { uv_env_ = env; }
node::Environment* uv_env() const { return uv_env_; }
protected: protected:
explicit NodeBindings(bool is_browser); explicit NodeBindings(bool is_browser);
@ -83,6 +88,11 @@ class NodeBindings {
// Semaphore to wait for main loop in the embed thread. // Semaphore to wait for main loop in the embed thread.
uv_sem_t embed_sem_; uv_sem_t embed_sem_;
// Environment that to wrap the uv loop.
node::Environment* uv_env_;
base::WeakPtrFactory<NodeBindings> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NodeBindings); DISALLOW_COPY_AND_ASSIGN(NodeBindings);
}; };

View file

@ -17,8 +17,9 @@
#include "common/swap_or_assign.h" #include "common/swap_or_assign.h"
#include "common/v8/scoped_persistent.h" #include "common/v8/scoped_persistent.h"
#include "common/v8/v8_value_converter.h" #include "common/v8/v8_value_converter.h"
#include "content/public/renderer/v8_value_converter.h" #include "ui/gfx/point.h"
#include "ui/gfx/rect.h" #include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "url/gurl.h" #include "url/gurl.h"
// Convert V8 value to arbitrary supported types. // Convert V8 value to arbitrary supported types.
@ -71,8 +72,9 @@ struct FromV8Value {
converter->FromV8Value(value_, v8::Context::GetCurrent())); converter->FromV8Value(value_, v8::Context::GetCurrent()));
} }
operator std::vector<std::string>() { template<class T>
std::vector<std::string> array; operator std::vector<T>() {
std::vector<T> array;
v8::Handle<v8::Array> v8_array = v8::Handle<v8::Array>::Cast(value_); v8::Handle<v8::Array> v8_array = v8::Handle<v8::Array>::Cast(value_);
for (uint32_t i = 0; i < v8_array->Length(); ++i) for (uint32_t i = 0; i < v8_array->Length(); ++i)
array.push_back(FromV8Value(v8_array->Get(i))); array.push_back(FromV8Value(v8_array->Get(i)));
@ -80,14 +82,15 @@ struct FromV8Value {
return array; return array;
} }
operator std::map<std::string, std::string>() { template<class K, class V>
std::map<std::string, std::string> dict; operator std::map<K, V>() {
std::map<K, V> dict;
v8::Handle<v8::Object> v8_dict = value_->ToObject(); v8::Handle<v8::Object> v8_dict = value_->ToObject();
v8::Handle<v8::Array> v8_keys = v8_dict->GetOwnPropertyNames(); v8::Handle<v8::Array> v8_keys = v8_dict->GetOwnPropertyNames();
for (uint32_t i = 0; i < v8_keys->Length(); ++i) { for (uint32_t i = 0; i < v8_keys->Length(); ++i) {
v8::Handle<v8::Value> v8_key = v8_keys->Get(i); v8::Handle<v8::Value> v8_key = v8_keys->Get(i);
std::string key = FromV8Value(v8_key); K key = FromV8Value(v8_key);
dict[key] = std::string(FromV8Value(v8_dict->Get(v8_key))); dict[key] = V(FromV8Value(v8_dict->Get(v8_key)));
} }
return dict; return dict;
@ -121,6 +124,14 @@ inline v8::Handle<v8::Value> ToV8Value(bool b) {
return v8::Boolean::New(b); return v8::Boolean::New(b);
} }
inline v8::Handle<v8::Value> ToV8Value(float f) {
return v8::Number::New(f);
}
inline v8::Handle<v8::Value> ToV8Value(double f) {
return v8::Number::New(f);
}
inline v8::Handle<v8::Value> ToV8Value(const char* s) { inline v8::Handle<v8::Value> ToV8Value(const char* s) {
return v8::String::New(s); return v8::String::New(s);
} }
@ -146,14 +157,37 @@ inline v8::Handle<v8::Value> ToV8Value(void* whatever) {
return v8::Undefined(); return v8::Undefined();
} }
inline template<class T> inline
v8::Handle<v8::Value> ToV8Value(const std::vector<base::FilePath>& paths) { v8::Handle<v8::Value> ToV8Value(const std::vector<T>& arr) {
v8::Handle<v8::Array> result = v8::Array::New(paths.size()); v8::Handle<v8::Array> result = v8::Array::New(arr.size());
for (size_t i = 0; i < paths.size(); ++i) for (size_t i = 0; i < arr.size(); ++i)
result->Set(i, ToV8Value(paths[i])); result->Set(i, ToV8Value(arr[i]));
return result; return result;
} }
inline v8::Handle<v8::Value> ToV8Value(const gfx::Point& point) {
v8::Handle<v8::Object> obj = v8::Object::New();
obj->Set(ToV8Value("x"), ToV8Value(point.x()));
obj->Set(ToV8Value("y"), ToV8Value(point.y()));
return obj;
}
inline v8::Handle<v8::Value> ToV8Value(const gfx::Rect& rect) {
v8::Handle<v8::Object> obj = v8::Object::New();
obj->Set(ToV8Value("x"), ToV8Value(rect.x()));
obj->Set(ToV8Value("y"), ToV8Value(rect.y()));
obj->Set(ToV8Value("width"), ToV8Value(rect.width()));
obj->Set(ToV8Value("height"), ToV8Value(rect.height()));
return obj;
}
inline v8::Handle<v8::Value> ToV8Value(const gfx::Size& size) {
v8::Handle<v8::Object> obj = v8::Object::New();
obj->Set(ToV8Value("width"), ToV8Value(size.width()));
obj->Set(ToV8Value("height"), ToV8Value(size.height()));
return obj;
}
// Check if a V8 Value is of specified type. // Check if a V8 Value is of specified type.
template<class T> inline template<class T> inline
bool V8ValueCanBeConvertedTo(v8::Handle<v8::Value> value) { bool V8ValueCanBeConvertedTo(v8::Handle<v8::Value> value) {

View file

@ -8,6 +8,8 @@
// Include common headers for using node APIs. // Include common headers for using node APIs.
#undef CHECK #undef CHECK
#undef CHECK_EQ
#undef CHECK_NE
#undef DISALLOW_COPY_AND_ASSIGN #undef DISALLOW_COPY_AND_ASSIGN
#include "vendor/node/src/env.h" #include "vendor/node/src/env.h"
#include "vendor/node/src/env-inl.h" #include "vendor/node/src/env-inl.h"

View file

@ -35,4 +35,5 @@ Common modules:
* [clipboard](api/common/clipboard.md) * [clipboard](api/common/clipboard.md)
* [crash-reporter](api/common/crash-reporter.md) * [crash-reporter](api/common/crash-reporter.md)
* [screen](api/common/screen.md)
* [shell](api/common/shell.md) * [shell](api/common/shell.md)

11
docs/api/common/screen.md Normal file
View file

@ -0,0 +1,11 @@
# screen
Gets various info about screen size, displays, cursor position, etc.
## screen.getCursorScreenPoint()
Returns the current absolute position of the mouse pointer.
## screen.getPrimaryDisplay()
Returns the primary display.

View file

@ -1,14 +1,17 @@
{ {
"name": "atom-shell", "name": "atom-shell",
"version": "0.8.1", "version": "0.8.5",
"devDependencies": { "devDependencies": {
"coffee-script": "~1.6.3", "coffee-script": "~1.6.3",
"coffeelint": "~0.6.1", "coffeelint": "~0.6.1",
"mocha": "~1.13.0", "mocha": "~1.13.0",
"pathwatcher": "0.14.0",
"q": "0.9.7",
"walkdir": "~0.0.7", "walkdir": "~0.0.7",
"runas": "0.3.0", "runas": "0.3.0",
"formidable": "~1.0.14" "formidable": "~1.0.14",
"temp": "~0.6.0"
}, },
"private": true, "private": true,

View file

@ -4,6 +4,8 @@
#include "renderer/atom_renderer_client.h" #include "renderer/atom_renderer_client.h"
#include <algorithm>
#include "common/node_bindings.h" #include "common/node_bindings.h"
#include "renderer/api/atom_renderer_bindings.h" #include "renderer/api/atom_renderer_bindings.h"
#include "renderer/atom_render_view_observer.h" #include "renderer/atom_render_view_observer.h"
@ -51,10 +53,17 @@ void AtomRendererClient::DidCreateScriptContext(WebKit::WebFrame* frame,
node_bindings_->RunMessageLoop(); node_bindings_->RunMessageLoop();
// Setup node environment for each window. // Setup node environment for each window.
node_bindings_->CreateEnvironment(context); node::Environment* env = node_bindings_->CreateEnvironment(context);
// Add atom-shell extended APIs. // Add atom-shell extended APIs.
atom_bindings_->BindToFrame(frame); atom_bindings_->BindToFrame(frame);
// Store the created environment.
web_page_envs_.push_back(env);
// Make uv loop being wrapped by window context.
if (node_bindings_->uv_env() == NULL)
node_bindings_->set_uv_env(env);
} }
void AtomRendererClient::WillReleaseScriptContext( void AtomRendererClient::WillReleaseScriptContext(
@ -67,7 +76,36 @@ void AtomRendererClient::WillReleaseScriptContext(
return; return;
} }
env->Dispose(); // Clear the environment.
web_page_envs_.erase(
std::remove(web_page_envs_.begin(), web_page_envs_.end(), env),
web_page_envs_.end());
// Notice that we are not disposing the environment object here, because there
// may still be pending uv operations in the uv loop, and when they got done
// they would be needing the original environment.
// So we are leaking the environment object here, just like Chrome leaking the
// memory :) . Since it's only leaked when refreshing or unloading, so as long
// as we make sure renderer process is restared then the memory would not be
// leaked.
// env->Dispose();
// Wrap the uv loop with another environment.
if (env == node_bindings_->uv_env()) {
node::Environment* env = web_page_envs_.size() > 0 ? web_page_envs_[0] :
NULL;
node_bindings_->set_uv_env(env);
}
}
bool AtomRendererClient::ShouldFork(WebKit::WebFrame* frame,
const GURL& url,
const std::string& http_method,
bool is_initial_navigation,
bool is_server_redirect,
bool* send_referrer) {
// Handle all the navigations and reloads in browser.
return true;
} }
} // namespace atom } // namespace atom

View file

@ -5,8 +5,14 @@
#ifndef ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_ #ifndef ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_
#define ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_ #define ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_
#include <vector>
#include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/content_renderer_client.h"
namespace node {
class Environment;
}
namespace atom { namespace atom {
class AtomRendererBindings; class AtomRendererBindings;
@ -29,6 +35,14 @@ class AtomRendererClient : public content::ContentRendererClient {
virtual void WillReleaseScriptContext(WebKit::WebFrame* frame, virtual void WillReleaseScriptContext(WebKit::WebFrame* frame,
v8::Handle<v8::Context>, v8::Handle<v8::Context>,
int world_id) OVERRIDE; int world_id) OVERRIDE;
virtual bool ShouldFork(WebKit::WebFrame* frame,
const GURL& url,
const std::string& http_method,
bool is_initial_navigation,
bool is_server_redirect,
bool* send_referrer);
std::vector<node::Environment*> web_page_envs_;
scoped_ptr<NodeBindings> node_bindings_; scoped_ptr<NodeBindings> node_bindings_;
scoped_ptr<AtomRendererBindings> atom_bindings_; scoped_ptr<AtomRendererBindings> atom_bindings_;

View file

@ -1,5 +1,4 @@
path = require 'path' path = require 'path'
timers = require 'timers'
Module = require 'module' Module = require 'module'
# Expose information of current process. # Expose information of current process.
@ -14,29 +13,16 @@ process.argv.splice 1, 1
# of Atom's built-in libraries. # of Atom's built-in libraries.
globalPaths = Module.globalPaths globalPaths = Module.globalPaths
globalPaths.push path.join(process.resourcesPath, 'renderer', 'api', 'lib') globalPaths.push path.join(process.resourcesPath, 'renderer', 'api', 'lib')
# And also common/api/lib.
globalPaths.push path.join(process.resourcesPath, 'common', 'api', 'lib')
# And also app. # And also app.
globalPaths.push path.join(process.resourcesPath, 'app') globalPaths.push path.join(process.resourcesPath, 'app')
# Import common settings.
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init.js')
# Expose global variables. # Expose global variables.
global.require = require global.require = require
global.module = module global.module = module
# setImmediate and process.nextTick makes use of uv_check and uv_prepare to
# run the callbacks, however since we only run uv loop on requests, the
# callbacks wouldn't be called until something else activated the uv loop,
# which would delay the callbacks for arbitrary long time. So we should
# initiatively activate the uv loop once setImmediate and process.nextTick is
# called.
wrapWithActivateUvLoop = (func) ->
->
process.activateUvLoop()
func.apply this, arguments
process.nextTick = wrapWithActivateUvLoop process.nextTick
global.setImmediate = wrapWithActivateUvLoop timers.setImmediate
global.clearImmediate = timers.clearImmediate
# Set the __filename to the path of html file if it's file:// protocol. # Set the __filename to the path of html file if it's file:// protocol.
if window.location.protocol is 'file:' if window.location.protocol is 'file:'
global.__filename = global.__filename =
@ -46,6 +32,9 @@ if window.location.protocol is 'file:'
window.location.pathname window.location.pathname
global.__dirname = path.dirname global.__filename global.__dirname = path.dirname global.__filename
# Set module's filename so relative require can work as expected.
module.filename = global.__filename
# Also search for module under the html file. # Also search for module under the html file.
module.paths = module.paths.concat Module._nodeModulePaths(global.__dirname) module.paths = module.paths.concat Module._nodeModulePaths(global.__dirname)
else else

View file

@ -12,7 +12,7 @@ from lib.util import scoped_cwd, rm_rf, get_atom_shell_version, make_zip, \
ATOM_SHELL_VRESION = get_atom_shell_version() ATOM_SHELL_VRESION = get_atom_shell_version()
NODE_VERSION = 'v0.11.9' NODE_VERSION = 'v0.11.10'
BASE_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' BASE_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent'
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))

View file

@ -21,7 +21,7 @@ TARGET_PLATFORM = {
ATOM_SHELL_REPO = 'atom/atom-shell' ATOM_SHELL_REPO = 'atom/atom-shell'
ATOM_SHELL_VRESION = get_atom_shell_version() ATOM_SHELL_VRESION = get_atom_shell_version()
NODE_VERSION = 'v0.11.9' NODE_VERSION = 'v0.11.10'
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
OUT_DIR = os.path.join(SOURCE_ROOT, 'out', 'Release') OUT_DIR = os.path.join(SOURCE_ROOT, 'out', 'Release')

View file

@ -0,0 +1,16 @@
assert = require 'assert'
screen = require 'screen'
describe 'screen module', ->
describe 'screen.getCursorScreenPoint()', ->
it 'returns a point object', ->
point = screen.getCursorScreenPoint()
assert.equal typeof(point.x), 'number'
assert.equal typeof(point.y), 'number'
describe 'screen.getPrimaryDisplay()', ->
it 'returns a display object', ->
display = screen.getPrimaryDisplay()
assert.equal typeof(display.scaleFactor), 'number'
assert display.size.width > 0
assert display.size.height > 0

View file

@ -1,9 +1,11 @@
assert = require 'assert' assert = require 'assert'
fs = require 'fs' fs = require 'fs'
path = require 'path' path = require 'path'
temp = require 'temp'
describe 'third-party module', -> describe 'third-party module', ->
fixtures = path.join __dirname, 'fixtures' fixtures = path.join __dirname, 'fixtures'
temp.track()
describe 'runas', -> describe 'runas', ->
it 'can be required in renderer', -> it 'can be required in renderer', ->
@ -15,3 +17,25 @@ describe 'third-party module', ->
child.on 'message', (msg) -> child.on 'message', (msg) ->
assert.equal msg, 'ok' assert.equal msg, 'ok'
done() done()
describe 'pathwatcher', ->
it 'emits file events correctly', (done) ->
pathwatcher = require 'pathwatcher'
temp.mkdir 'dir', (err, dir) ->
assert err == null
file = path.join dir, 'file'
fs.writeFileSync file, 'content'
watcher = pathwatcher.watch file, (event) ->
assert.equal event, 'change'
watcher.close()
done()
fs.writeFileSync file, 'content2'
describe 'q', ->
Q = require 'q'
describe 'Q.when', ->
it 'emits the fullfil callback', (done) ->
Q(true).then (val) ->
assert.equal val, true
done()

View file

@ -37,6 +37,11 @@ describe 'node feature', ->
fs.readFile __filename, -> fs.readFile __filename, ->
setTimeout done, 0 setTimeout done, 0
describe 'setTimeout in pure uv callback', ->
it 'does not crash', (done) ->
process.scheduleCallback ->
setTimeout done, 0
describe 'throw error in node context', -> describe 'throw error in node context', ->
it 'gets caught', (done) -> it 'gets caught', (done) ->
error = new Error('boo!') error = new Error('boo!')

2
vendor/apm vendored

@ -1 +1 @@
Subproject commit 89f678cc34850ffa0163c4ac485336d40c72bb86 Subproject commit 35edbb07fb4abba49dd97d12a1ad8c4adb71625f

2
vendor/node vendored

@ -1 +1 @@
Subproject commit b5bbfb6a7d66750c21bf654e973f47f1178adced Subproject commit 184a341c2b959a092f64b168e3d55b11d13583bf