Merge branch 'master' into native-window-open
This commit is contained in:
commit
6f9dbd4e04
50 changed files with 517 additions and 102 deletions
|
@ -14,6 +14,7 @@
|
|||
#include "atom/browser/javascript_environment.h"
|
||||
#include "atom/browser/node_debugger.h"
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/asar/asar_util.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/command_line.h"
|
||||
|
@ -60,8 +61,8 @@ AtomBrowserMainParts::AtomBrowserMainParts()
|
|||
: fake_browser_process_(new BrowserProcess),
|
||||
exit_code_(nullptr),
|
||||
browser_(new Browser),
|
||||
node_bindings_(NodeBindings::Create(true)),
|
||||
atom_bindings_(new AtomBindings),
|
||||
node_bindings_(NodeBindings::Create(NodeBindings::BROWSER)),
|
||||
atom_bindings_(new AtomBindings(uv_default_loop())),
|
||||
gc_timer_(true, true) {
|
||||
DCHECK(!self_) << "Cannot have two AtomBrowserMainParts";
|
||||
self_ = this;
|
||||
|
@ -71,6 +72,7 @@ AtomBrowserMainParts::AtomBrowserMainParts()
|
|||
}
|
||||
|
||||
AtomBrowserMainParts::~AtomBrowserMainParts() {
|
||||
asar::ClearArchives();
|
||||
// Leak the JavascriptEnvironment on exit.
|
||||
// This is to work around the bug that V8 would be waiting for background
|
||||
// tasks to finish on exit, while somehow it waits forever in Electron, more
|
||||
|
|
|
@ -80,9 +80,9 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
|
||||
std::unique_ptr<Browser> browser_;
|
||||
std::unique_ptr<JavascriptEnvironment> js_env_;
|
||||
std::unique_ptr<NodeEnvironment> node_env_;
|
||||
std::unique_ptr<NodeBindings> node_bindings_;
|
||||
std::unique_ptr<AtomBindings> atom_bindings_;
|
||||
std::unique_ptr<NodeEnvironment> node_env_;
|
||||
std::unique_ptr<NodeDebugger> node_debugger_;
|
||||
|
||||
base::Timer gc_timer_;
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
<key>CFBundleIconFile</key>
|
||||
<string>electron.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.6.3</string>
|
||||
<string>1.6.4</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.6.3</string>
|
||||
<string>1.6.4</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
|
|
@ -56,8 +56,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,6,3,0
|
||||
PRODUCTVERSION 1,6,3,0
|
||||
FILEVERSION 1,6,4,0
|
||||
PRODUCTVERSION 1,6,4,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -74,12 +74,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "1.6.3"
|
||||
VALUE "FileVersion", "1.6.4"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "1.6.3"
|
||||
VALUE "ProductVersion", "1.6.4"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
|
|
@ -97,6 +97,10 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches(
|
|||
command_line->AppendSwitchASCII(switches::kNodeIntegration,
|
||||
node_integration ? "true" : "false");
|
||||
|
||||
// Whether to enable node integration in Worker.
|
||||
if (web_preferences.GetBoolean(options::kNodeIntegrationInWorker, &b) && b)
|
||||
command_line->AppendSwitch(switches::kNodeIntegrationInWorker);
|
||||
|
||||
// If the `sandbox` option was passed to the BrowserWindow's webPreferences,
|
||||
// pass `--enable-sandbox` to the renderer so it won't have any node.js
|
||||
// integration.
|
||||
|
|
|
@ -141,15 +141,16 @@ void InitAsarSupport(v8::Isolate* isolate,
|
|||
v8::Local<v8::Value> result = asar_init->Run();
|
||||
|
||||
// Initialize asar support.
|
||||
base::Callback<void(v8::Local<v8::Value>,
|
||||
v8::Local<v8::Value>,
|
||||
std::string)> init;
|
||||
if (mate::ConvertFromV8(isolate, result, &init)) {
|
||||
if (result->IsFunction()) {
|
||||
const char* asar_native = reinterpret_cast<const char*>(
|
||||
static_cast<const unsigned char*>(node::asar_data));
|
||||
init.Run(process,
|
||||
require,
|
||||
std::string(asar_native, sizeof(node::asar_data) - 1));
|
||||
base::StringPiece asar_data(asar_native, sizeof(node::asar_data) - 1);
|
||||
v8::Local<v8::Value> args[] = {
|
||||
process,
|
||||
require,
|
||||
mate::ConvertToV8(isolate, asar_data),
|
||||
};
|
||||
result.As<v8::Function>()->Call(result, 3, args);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,8 +78,8 @@ void FatalErrorCallback(const char* location, const char* message) {
|
|||
} // namespace
|
||||
|
||||
|
||||
AtomBindings::AtomBindings() {
|
||||
uv_async_init(uv_default_loop(), &call_next_tick_async_, OnCallNextTick);
|
||||
AtomBindings::AtomBindings(uv_loop_t* loop) {
|
||||
uv_async_init(loop, &call_next_tick_async_, OnCallNextTick);
|
||||
call_next_tick_async_.data = this;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace atom {
|
|||
|
||||
class AtomBindings {
|
||||
public:
|
||||
AtomBindings();
|
||||
explicit AtomBindings(uv_loop_t* loop);
|
||||
virtual ~AtomBindings();
|
||||
|
||||
// Add process.atomBinding function, which behaves like process.binding but
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "base/files/file_util.h"
|
||||
#include "base/lazy_instance.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "base/threading/thread_local.h"
|
||||
|
||||
namespace asar {
|
||||
|
||||
|
@ -19,14 +20,17 @@ namespace {
|
|||
|
||||
// The global instance of ArchiveMap, will be destroyed on exit.
|
||||
typedef std::map<base::FilePath, std::shared_ptr<Archive>> ArchiveMap;
|
||||
static base::LazyInstance<ArchiveMap> g_archive_map = LAZY_INSTANCE_INITIALIZER;
|
||||
base::LazyInstance<base::ThreadLocalPointer<ArchiveMap>>::Leaky
|
||||
g_archive_map_tls = LAZY_INSTANCE_INITIALIZER;
|
||||
|
||||
const base::FilePath::CharType kAsarExtension[] = FILE_PATH_LITERAL(".asar");
|
||||
|
||||
} // namespace
|
||||
|
||||
std::shared_ptr<Archive> GetOrCreateAsarArchive(const base::FilePath& path) {
|
||||
ArchiveMap& archive_map = *g_archive_map.Pointer();
|
||||
if (!g_archive_map_tls.Pointer()->Get())
|
||||
g_archive_map_tls.Pointer()->Set(new ArchiveMap);
|
||||
ArchiveMap& archive_map = *g_archive_map_tls.Pointer()->Get();
|
||||
if (!ContainsKey(archive_map, path)) {
|
||||
std::shared_ptr<Archive> archive(new Archive(path));
|
||||
if (!archive->Init())
|
||||
|
@ -36,6 +40,11 @@ std::shared_ptr<Archive> GetOrCreateAsarArchive(const base::FilePath& path) {
|
|||
return archive_map[path];
|
||||
}
|
||||
|
||||
void ClearArchives() {
|
||||
if (g_archive_map_tls.Pointer()->Get())
|
||||
delete g_archive_map_tls.Pointer()->Get();
|
||||
}
|
||||
|
||||
bool GetAsarArchivePath(const base::FilePath& full_path,
|
||||
base::FilePath* asar_path,
|
||||
base::FilePath* relative_path) {
|
||||
|
|
|
@ -19,6 +19,9 @@ class Archive;
|
|||
// Gets or creates a new Archive from the path.
|
||||
std::shared_ptr<Archive> GetOrCreateAsarArchive(const base::FilePath& path);
|
||||
|
||||
// Destroy cached Archive objects.
|
||||
void ClearArchives();
|
||||
|
||||
// Separates the path to Archive out.
|
||||
bool GetAsarArchivePath(const base::FilePath& full_path,
|
||||
base::FilePath* asar_path,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#define ATOM_MAJOR_VERSION 1
|
||||
#define ATOM_MINOR_VERSION 6
|
||||
#define ATOM_PATCH_VERSION 3
|
||||
#define ATOM_PATCH_VERSION 4
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace mate {
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "base/bind.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "native_mate/function_template.h"
|
||||
#include "native_mate/scoped_persistent.h"
|
||||
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
// Force all builtin modules to be referenced so they can actually run their
|
||||
// DSO constructors, see http://git.io/DRIqCg.
|
||||
#define REFERENCE_MODULE(name) \
|
||||
|
@ -98,9 +96,9 @@ base::FilePath GetResourcesPath(bool is_browser) {
|
|||
|
||||
} // namespace
|
||||
|
||||
NodeBindings::NodeBindings(bool is_browser)
|
||||
: is_browser_(is_browser),
|
||||
uv_loop_(uv_default_loop()),
|
||||
NodeBindings::NodeBindings(BrowserEnvironment browser_env)
|
||||
: browser_env_(browser_env),
|
||||
uv_loop_(browser_env == WORKER ? uv_loop_new() : uv_default_loop()),
|
||||
embed_closed_(false),
|
||||
uv_env_(nullptr),
|
||||
weak_factory_(this) {
|
||||
|
@ -118,16 +116,20 @@ NodeBindings::~NodeBindings() {
|
|||
// Clear uv.
|
||||
uv_sem_destroy(&embed_sem_);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&dummy_uv_handle_), nullptr);
|
||||
|
||||
// Destroy loop.
|
||||
if (uv_loop_ != uv_default_loop())
|
||||
uv_loop_delete(uv_loop_);
|
||||
}
|
||||
|
||||
void NodeBindings::Initialize() {
|
||||
// Open node's error reporting system for browser process.
|
||||
node::g_standalone_mode = is_browser_;
|
||||
node::g_standalone_mode = browser_env_ == BROWSER;
|
||||
node::g_upstream_node_mode = false;
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
// Get real command line in renderer process forked by zygote.
|
||||
if (!is_browser_)
|
||||
if (browser_env_ != BROWSER)
|
||||
AtomCommandLine::InitializeFromCommandLine();
|
||||
#endif
|
||||
|
||||
|
@ -139,7 +141,7 @@ void NodeBindings::Initialize() {
|
|||
// uv_init overrides error mode to suppress the default crash dialog, bring
|
||||
// it back if user wants to show it.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (is_browser_ || env->HasVar("ELECTRON_DEFAULT_ERROR_MODE"))
|
||||
if (browser_env_ == BROWSER || env->HasVar("ELECTRON_DEFAULT_ERROR_MODE"))
|
||||
SetErrorMode(GetErrorMode() & ~SEM_NOGPFAULTERRORBOX);
|
||||
#endif
|
||||
}
|
||||
|
@ -149,9 +151,19 @@ node::Environment* NodeBindings::CreateEnvironment(
|
|||
auto args = AtomCommandLine::argv();
|
||||
|
||||
// Feed node the path to initialization script.
|
||||
base::FilePath::StringType process_type = is_browser_ ?
|
||||
FILE_PATH_LITERAL("browser") : FILE_PATH_LITERAL("renderer");
|
||||
base::FilePath resources_path = GetResourcesPath(is_browser_);
|
||||
base::FilePath::StringType process_type;
|
||||
switch (browser_env_) {
|
||||
case BROWSER:
|
||||
process_type = FILE_PATH_LITERAL("browser");
|
||||
break;
|
||||
case RENDERER:
|
||||
process_type = FILE_PATH_LITERAL("renderer");
|
||||
break;
|
||||
case WORKER:
|
||||
process_type = FILE_PATH_LITERAL("worker");
|
||||
break;
|
||||
}
|
||||
base::FilePath resources_path = GetResourcesPath(browser_env_ == BROWSER);
|
||||
base::FilePath script_path =
|
||||
resources_path.Append(FILE_PATH_LITERAL("electron.asar"))
|
||||
.Append(process_type)
|
||||
|
@ -161,10 +173,10 @@ node::Environment* NodeBindings::CreateEnvironment(
|
|||
|
||||
std::unique_ptr<const char*[]> c_argv = StringVectorToArgArray(args);
|
||||
node::Environment* env = node::CreateEnvironment(
|
||||
new node::IsolateData(context->GetIsolate(), uv_default_loop()), context,
|
||||
new node::IsolateData(context->GetIsolate(), uv_loop_), context,
|
||||
args.size(), c_argv.get(), 0, nullptr);
|
||||
|
||||
if (is_browser_) {
|
||||
if (browser_env_ == BROWSER) {
|
||||
// SetAutorunMicrotasks is no longer called in node::CreateEnvironment
|
||||
// so instead call it here to match expected node behavior
|
||||
context->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
|
||||
|
@ -178,7 +190,7 @@ node::Environment* NodeBindings::CreateEnvironment(
|
|||
process.Set("type", process_type);
|
||||
process.Set("resourcesPath", resources_path);
|
||||
// Do not set DOM globals for renderer process.
|
||||
if (!is_browser_)
|
||||
if (browser_env_ != BROWSER)
|
||||
process.Set("_noBrowserGlobals", resources_path);
|
||||
// The path to helper app.
|
||||
base::FilePath helper_exec_path;
|
||||
|
@ -187,7 +199,7 @@ node::Environment* NodeBindings::CreateEnvironment(
|
|||
|
||||
// Set process._debugWaitConnect if --debug-brk was specified to stop
|
||||
// the debugger on the first line
|
||||
if (is_browser_ &&
|
||||
if (browser_env_ == BROWSER &&
|
||||
base::CommandLine::ForCurrentProcess()->HasSwitch("debug-brk"))
|
||||
process.Set("_debugWaitConnect", true);
|
||||
|
||||
|
@ -200,8 +212,6 @@ void NodeBindings::LoadEnvironment(node::Environment* env) {
|
|||
}
|
||||
|
||||
void NodeBindings::PrepareMessageLoop() {
|
||||
DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
|
||||
// Add dummy handle for libuv, otherwise libuv would quit when there is
|
||||
// nothing to do.
|
||||
uv_async_init(uv_loop_, &dummy_uv_handle_, nullptr);
|
||||
|
@ -212,8 +222,6 @@ void NodeBindings::PrepareMessageLoop() {
|
|||
}
|
||||
|
||||
void NodeBindings::RunMessageLoop() {
|
||||
DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
|
||||
// The MessageLoop should have been created, remember the one in main thread.
|
||||
task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
||||
|
||||
|
@ -222,8 +230,6 @@ void NodeBindings::RunMessageLoop() {
|
|||
}
|
||||
|
||||
void NodeBindings::UvRunOnce() {
|
||||
DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
|
||||
node::Environment* env = uv_env();
|
||||
|
||||
// Use Locker in browser process.
|
||||
|
@ -237,13 +243,13 @@ void NodeBindings::UvRunOnce() {
|
|||
v8::MicrotasksScope script_scope(env->isolate(),
|
||||
v8::MicrotasksScope::kRunMicrotasks);
|
||||
|
||||
if (!is_browser_)
|
||||
if (browser_env_ != BROWSER)
|
||||
TRACE_EVENT_BEGIN0("devtools.timeline", "FunctionCall");
|
||||
|
||||
// Deal with uv events.
|
||||
int r = uv_run(uv_loop_, UV_RUN_NOWAIT);
|
||||
|
||||
if (!is_browser_)
|
||||
if (browser_env_ != BROWSER)
|
||||
TRACE_EVENT_END0("devtools.timeline", "FunctionCall");
|
||||
|
||||
if (r == 0)
|
||||
|
|
|
@ -23,7 +23,13 @@ namespace atom {
|
|||
|
||||
class NodeBindings {
|
||||
public:
|
||||
static NodeBindings* Create(bool is_browser);
|
||||
enum BrowserEnvironment {
|
||||
BROWSER,
|
||||
RENDERER,
|
||||
WORKER,
|
||||
};
|
||||
|
||||
static NodeBindings* Create(BrowserEnvironment browser_env);
|
||||
|
||||
virtual ~NodeBindings();
|
||||
|
||||
|
@ -46,8 +52,10 @@ class NodeBindings {
|
|||
void set_uv_env(node::Environment* env) { uv_env_ = env; }
|
||||
node::Environment* uv_env() const { return uv_env_; }
|
||||
|
||||
uv_loop_t* uv_loop() const { return uv_loop_; }
|
||||
|
||||
protected:
|
||||
explicit NodeBindings(bool is_browser);
|
||||
explicit NodeBindings(BrowserEnvironment browser_env);
|
||||
|
||||
// Called to poll events in new thread.
|
||||
virtual void PollEvents() = 0;
|
||||
|
@ -61,13 +69,13 @@ class NodeBindings {
|
|||
// Interrupt the PollEvents.
|
||||
void WakeupEmbedThread();
|
||||
|
||||
// Are we running in browser.
|
||||
bool is_browser_;
|
||||
// Which environment we are running.
|
||||
BrowserEnvironment browser_env_;
|
||||
|
||||
// Main thread's MessageLoop.
|
||||
// Current thread's MessageLoop.
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
// Main thread's libuv loop.
|
||||
// Current thread's libuv loop.
|
||||
uv_loop_t* uv_loop_;
|
||||
|
||||
private:
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
NodeBindingsLinux::NodeBindingsLinux(bool is_browser)
|
||||
: NodeBindings(is_browser),
|
||||
NodeBindingsLinux::NodeBindingsLinux(BrowserEnvironment browser_env)
|
||||
: NodeBindings(browser_env),
|
||||
epoll_(epoll_create(1)) {
|
||||
int backend_fd = uv_backend_fd(uv_loop_);
|
||||
struct epoll_event ev = { 0 };
|
||||
|
@ -50,8 +50,8 @@ void NodeBindingsLinux::PollEvents() {
|
|||
}
|
||||
|
||||
// static
|
||||
NodeBindings* NodeBindings::Create(bool is_browser) {
|
||||
return new NodeBindingsLinux(is_browser);
|
||||
NodeBindings* NodeBindings::Create(BrowserEnvironment browser_env) {
|
||||
return new NodeBindingsLinux(browser_env);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace atom {
|
|||
|
||||
class NodeBindingsLinux : public NodeBindings {
|
||||
public:
|
||||
explicit NodeBindingsLinux(bool is_browser);
|
||||
explicit NodeBindingsLinux(BrowserEnvironment browser_env);
|
||||
virtual ~NodeBindingsLinux();
|
||||
|
||||
void RunMessageLoop() override;
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
NodeBindingsMac::NodeBindingsMac(bool is_browser)
|
||||
: NodeBindings(is_browser) {
|
||||
NodeBindingsMac::NodeBindingsMac(BrowserEnvironment browser_env)
|
||||
: NodeBindings(browser_env) {
|
||||
}
|
||||
|
||||
NodeBindingsMac::~NodeBindingsMac() {
|
||||
|
@ -60,8 +60,8 @@ void NodeBindingsMac::PollEvents() {
|
|||
}
|
||||
|
||||
// static
|
||||
NodeBindings* NodeBindings::Create(bool is_browser) {
|
||||
return new NodeBindingsMac(is_browser);
|
||||
NodeBindings* NodeBindings::Create(BrowserEnvironment browser_env) {
|
||||
return new NodeBindingsMac(browser_env);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace atom {
|
|||
|
||||
class NodeBindingsMac : public NodeBindings {
|
||||
public:
|
||||
explicit NodeBindingsMac(bool is_browser);
|
||||
explicit NodeBindingsMac(BrowserEnvironment browser_env);
|
||||
virtual ~NodeBindingsMac();
|
||||
|
||||
void RunMessageLoop() override;
|
||||
|
|
|
@ -14,8 +14,8 @@ extern "C" {
|
|||
|
||||
namespace atom {
|
||||
|
||||
NodeBindingsWin::NodeBindingsWin(bool is_browser)
|
||||
: NodeBindings(is_browser) {
|
||||
NodeBindingsWin::NodeBindingsWin(BrowserEnvironment browser_env)
|
||||
: NodeBindings(browser_env) {
|
||||
}
|
||||
|
||||
NodeBindingsWin::~NodeBindingsWin() {
|
||||
|
@ -45,8 +45,8 @@ void NodeBindingsWin::PollEvents() {
|
|||
}
|
||||
|
||||
// static
|
||||
NodeBindings* NodeBindings::Create(bool is_browser) {
|
||||
return new NodeBindingsWin(is_browser);
|
||||
NodeBindings* NodeBindings::Create(BrowserEnvironment browser_env) {
|
||||
return new NodeBindingsWin(browser_env);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace atom {
|
|||
|
||||
class NodeBindingsWin : public NodeBindings {
|
||||
public:
|
||||
explicit NodeBindingsWin(bool is_browser);
|
||||
explicit NodeBindingsWin(BrowserEnvironment browser_env);
|
||||
virtual ~NodeBindingsWin();
|
||||
|
||||
private:
|
||||
|
|
|
@ -122,6 +122,9 @@ const char kBlinkFeatures[] = "blinkFeatures";
|
|||
// Disable blink features.
|
||||
const char kDisableBlinkFeatures[] = "disableBlinkFeatures";
|
||||
|
||||
// Enable the node integration in WebWorker.
|
||||
const char kNodeIntegrationInWorker[] = "nodeIntegrationInWorker";
|
||||
|
||||
} // namespace options
|
||||
|
||||
namespace switches {
|
||||
|
@ -165,6 +168,9 @@ const char kScrollBounce[] = "scroll-bounce";
|
|||
const char kHiddenPage[] = "hidden-page";
|
||||
const char kNativeWindowOpen[] = "native-window-open";
|
||||
|
||||
// Command switch passed to renderer process to control nodeIntegration.
|
||||
const char kNodeIntegrationInWorker[] = "node-integration-in-worker";
|
||||
|
||||
// Widevine options
|
||||
// Path to Widevine CDM binaries.
|
||||
const char kWidevineCdmPath[] = "widevine-cdm-path";
|
||||
|
|
|
@ -62,6 +62,7 @@ extern const char kOpenerID[];
|
|||
extern const char kScrollBounce[];
|
||||
extern const char kBlinkFeatures[];
|
||||
extern const char kDisableBlinkFeatures[];
|
||||
extern const char kNodeIntegrationInWorker[];
|
||||
|
||||
} // namespace options
|
||||
|
||||
|
@ -90,6 +91,7 @@ extern const char kOpenerID[];
|
|||
extern const char kScrollBounce[];
|
||||
extern const char kHiddenPage[];
|
||||
extern const char kNativeWindowOpen[];
|
||||
extern const char kNodeIntegrationInWorker[];
|
||||
|
||||
extern const char kWidevineCdmPath[];
|
||||
extern const char kWidevineCdmVersion[];
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
#include "atom/common/asar/asar_util.h"
|
||||
#include "atom/common/atom_constants.h"
|
||||
#include "atom/common/color_util.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
|
@ -23,6 +24,7 @@
|
|||
#include "atom/renderer/guest_view_container.h"
|
||||
#include "atom/renderer/node_array_buffer_bridge.h"
|
||||
#include "atom/renderer/preferences_manager.h"
|
||||
#include "atom/renderer/web_worker_observer.h"
|
||||
#include "base/command_line.h"
|
||||
#include "chrome/renderer/media/chrome_key_systems.h"
|
||||
#include "chrome/renderer/pepper/pepper_helper.h"
|
||||
|
@ -215,8 +217,8 @@ std::vector<std::string> ParseSchemesCLISwitch(const char* switch_name) {
|
|||
|
||||
AtomRendererClient::AtomRendererClient()
|
||||
: node_integration_initialized_(false),
|
||||
node_bindings_(NodeBindings::Create(false)),
|
||||
atom_bindings_(new AtomBindings) {
|
||||
node_bindings_(NodeBindings::Create(NodeBindings::RENDERER)),
|
||||
atom_bindings_(new AtomBindings(uv_default_loop())) {
|
||||
isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kContextIsolation);
|
||||
// Parse --standard-schemes=scheme1,scheme2
|
||||
|
@ -227,6 +229,7 @@ AtomRendererClient::AtomRendererClient()
|
|||
}
|
||||
|
||||
AtomRendererClient::~AtomRendererClient() {
|
||||
asar::ClearArchives();
|
||||
}
|
||||
|
||||
void AtomRendererClient::RenderThreadStarted() {
|
||||
|
@ -436,6 +439,22 @@ void AtomRendererClient::AddSupportedKeySystems(
|
|||
AddChromeKeySystems(key_systems);
|
||||
}
|
||||
|
||||
void AtomRendererClient::DidInitializeWorkerContextOnWorkerThread(
|
||||
v8::Local<v8::Context> context) {
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kNodeIntegrationInWorker)) {
|
||||
WebWorkerObserver::GetCurrent()->ContextCreated(context);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomRendererClient::WillDestroyWorkerContextOnWorkerThread(
|
||||
v8::Local<v8::Context> context) {
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kNodeIntegrationInWorker)) {
|
||||
WebWorkerObserver::GetCurrent()->ContextWillDestroy(context);
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Context> AtomRendererClient::GetContext(
|
||||
blink::WebFrame* frame, v8::Isolate* isolate) {
|
||||
if (isolated_world())
|
||||
|
|
|
@ -65,6 +65,10 @@ class AtomRendererClient : public content::ContentRendererClient {
|
|||
void AddSupportedKeySystems(
|
||||
std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems)
|
||||
override;
|
||||
void DidInitializeWorkerContextOnWorkerThread(
|
||||
v8::Local<v8::Context> context) override;
|
||||
void WillDestroyWorkerContextOnWorkerThread(
|
||||
v8::Local<v8::Context> context) override;
|
||||
|
||||
// Whether the node integration has been initialized.
|
||||
bool node_integration_initialized_;
|
||||
|
|
73
atom/renderer/web_worker_observer.cc
Normal file
73
atom/renderer/web_worker_observer.cc
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/renderer/web_worker_observer.h"
|
||||
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
#include "atom/common/asar/asar_util.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "base/lazy_instance.h"
|
||||
#include "base/threading/thread_local.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
static base::LazyInstance<base::ThreadLocalPointer<WebWorkerObserver>>
|
||||
lazy_tls = LAZY_INSTANCE_INITIALIZER;
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
WebWorkerObserver* WebWorkerObserver::GetCurrent() {
|
||||
WebWorkerObserver* self = lazy_tls.Pointer()->Get();
|
||||
return self ? self : new WebWorkerObserver;
|
||||
}
|
||||
|
||||
WebWorkerObserver::WebWorkerObserver()
|
||||
: node_bindings_(NodeBindings::Create(NodeBindings::WORKER)),
|
||||
atom_bindings_(new AtomBindings(node_bindings_->uv_loop())) {
|
||||
lazy_tls.Pointer()->Set(this);
|
||||
}
|
||||
|
||||
WebWorkerObserver::~WebWorkerObserver() {
|
||||
lazy_tls.Pointer()->Set(nullptr);
|
||||
node::FreeEnvironment(node_bindings_->uv_env());
|
||||
asar::ClearArchives();
|
||||
}
|
||||
|
||||
void WebWorkerObserver::ContextCreated(v8::Local<v8::Context> context) {
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
// Start the embed thread.
|
||||
node_bindings_->PrepareMessageLoop();
|
||||
|
||||
// Setup node environment for each window.
|
||||
node::Environment* env = node_bindings_->CreateEnvironment(context);
|
||||
|
||||
// Add Electron extended APIs.
|
||||
atom_bindings_->BindTo(env->isolate(), env->process_object());
|
||||
|
||||
// Load everything.
|
||||
node_bindings_->LoadEnvironment(env);
|
||||
|
||||
// Make uv loop being wrapped by window context.
|
||||
node_bindings_->set_uv_env(env);
|
||||
|
||||
// Give the node loop a run to make sure everything is ready.
|
||||
node_bindings_->RunMessageLoop();
|
||||
}
|
||||
|
||||
void WebWorkerObserver::ContextWillDestroy(v8::Local<v8::Context> context) {
|
||||
node::Environment* env = node::Environment::GetCurrent(context);
|
||||
if (env)
|
||||
mate::EmitEvent(env->isolate(), env->process_object(), "exit");
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
} // namespace atom
|
37
atom/renderer/web_worker_observer.h
Normal file
37
atom/renderer/web_worker_observer.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_RENDERER_WEB_WORKER_OBSERVER_H_
|
||||
#define ATOM_RENDERER_WEB_WORKER_OBSERVER_H_
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBindings;
|
||||
class NodeBindings;
|
||||
|
||||
// Watches for WebWorker and insert node integration to it.
|
||||
class WebWorkerObserver {
|
||||
public:
|
||||
// Returns the WebWorkerObserver for current worker thread.
|
||||
static WebWorkerObserver* GetCurrent();
|
||||
|
||||
void ContextCreated(v8::Local<v8::Context> context);
|
||||
void ContextWillDestroy(v8::Local<v8::Context> context);
|
||||
|
||||
private:
|
||||
WebWorkerObserver();
|
||||
~WebWorkerObserver();
|
||||
|
||||
std::unique_ptr<NodeBindings> node_bindings_;
|
||||
std::unique_ptr<AtomBindings> atom_bindings_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebWorkerObserver);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_RENDERER_WEB_WORKER_OBSERVER_H_
|
|
@ -15,6 +15,9 @@ exports.load = (appUrl) => {
|
|||
height: 600,
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor: '#FFFFFF',
|
||||
webPreferences: {
|
||||
nodeIntegrationInWorker: true
|
||||
},
|
||||
useContentSize: true
|
||||
}
|
||||
if (process.platform === 'linux') {
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
[![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev)
|
||||
[![Join the Electron Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/)
|
||||
|
||||
:memo: Traducciones disponibles: [Koreano](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Chino Simplificado](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Portugues Brasileño](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Chino Tradicional](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md)
|
||||
:memo: Traducciones disponibles: [Koreano](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Chino Simplificado](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Portugués Brasileño](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Chino Tradicional](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md)
|
||||
|
||||
Electron es framework que permite escribir aplicaciones de escritorio multiplataforma
|
||||
usando JavaScript, HTML y CSS. Está basado en [Node.js](https://nodejs.org/) con
|
||||
[Chromium](http://www.chromium.org). Es usado por [Atom
|
||||
Electron es un framework que permite escribir aplicaciones de escritorio multiplataforma
|
||||
usando JavaScript, HTML y CSS. Está basado en [Node.js](https://nodejs.org/) con
|
||||
[Chromium](http://www.chromium.org). Es usado por [Atom
|
||||
editor](https://github.com/atom/atom) y muchas otras [aplicaciones](https://electron.atom.io/apps).
|
||||
|
||||
Sigue a [@ElectronJS](https://twitter.com/electronjs) en Twitter para estar informado de anuncios
|
||||
importantes.
|
||||
|
||||
Este projecto se adhiere a [Código de Conducta convenido para Contribuyentes](CODE_OF_CONDUCT.md).
|
||||
Este proyecto se adhiere al [Código de Conducta convenido para Colaboradores](CODE_OF_CONDUCT.md).
|
||||
Si desea participar, debes seguir este código de conducta. Por favor reporta un comportamiento
|
||||
no aceptado a electron@github.com.
|
||||
no aceptado a electron@github.com.
|
||||
|
||||
## Downloads
|
||||
|
||||
|
@ -33,7 +33,7 @@ npm install electron -g
|
|||
```
|
||||
|
||||
Mira la [página de lanzamientos](https://github.com/electron/electron/releases) para
|
||||
los prebuilt binaries, debug symbols, and more.
|
||||
los prebuilt binaries, debug symbols, y más.
|
||||
|
||||
### Mirrors
|
||||
|
||||
|
@ -41,13 +41,13 @@ los prebuilt binaries, debug symbols, and more.
|
|||
|
||||
## Documentación
|
||||
|
||||
Las guias y API de referencia están disponibles en el directorio
|
||||
Las guías y API de referencia están disponibles en el directorio
|
||||
[docs](https://github.com/electron/electron/tree/master/docs). Ahí también
|
||||
puedes encontrar documentos que describen como construir y contribuir a Electron.
|
||||
puedes encontrar documentos que describen cómo construir y contribuir en Electron.
|
||||
|
||||
## Traducciones de la Documentación
|
||||
|
||||
- [Portugues Brasileño](https://github.com/electron/electron/tree/master/docs-translations/pt-BR)
|
||||
- [Portugués Brasileño](https://github.com/electron/electron/tree/master/docs-translations/pt-BR)
|
||||
- [Koreano](https://github.com/electron/electron/tree/master/docs-translations/ko-KR)
|
||||
- [Japonés](https://github.com/electron/electron/tree/master/docs-translations/jp)
|
||||
- [Español](https://github.com/electron/electron/tree/master/docs-translations/es)
|
||||
|
@ -57,12 +57,12 @@ puedes encontrar documentos que describen como construir y contribuir a Electron
|
|||
- [Thai](https://github.com/electron/electron/tree/master/docs-Translations/th-TH)
|
||||
- [Ucraniano](https://github.com/electron/electron/tree/master/docs-translations/uk-UA)
|
||||
- [Ruso](https://github.com/electron/electron/tree/master/docs-translations/ru-RU)
|
||||
- [Frances](https://github.com/electron/electron/tree/master/docs-translations/fr-FR)
|
||||
- [Francés](https://github.com/electron/electron/tree/master/docs-translations/fr-FR)
|
||||
|
||||
## Inicio rápido
|
||||
|
||||
Clona y ejecuta el repositorio [`electron/electron-quick-start`](https://github.com/electron/electron-quick-start)
|
||||
para ver una aplicación minima en acción.
|
||||
para ver una aplicación mínima en acción.
|
||||
|
||||
## Comunidad
|
||||
|
||||
|
@ -71,7 +71,7 @@ Puedes preguntar y interactuar con la comunidad en los siguientes lugares:
|
|||
Atom.
|
||||
- `#atom-shell` canal de IRC en Freenode
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) canales en Slack
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Portugues Brasileño)*
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Portugués Brasileño)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Koreano)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japonés)*
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turco)*
|
||||
|
@ -84,4 +84,4 @@ donde la comunidad mantiene una lista útil de ejemplos de aplicaciones, herrami
|
|||
|
||||
[MIT](https://github.com/electron/electron/blob/master/LICENSE)
|
||||
|
||||
Si usas los logos de Electron ó GitHub, asegurate de seguir las [GitHub logo guidelines](https://github.com/logos).
|
||||
Si usas los logos de Electron ó GitHub, asegúrate de seguir las [GitHub logo guidelines](https://github.com/logos).
|
||||
|
|
|
@ -35,9 +35,9 @@ without visual flash, there are two solutions for different situations.
|
|||
|
||||
### Using `ready-to-show` event
|
||||
|
||||
While loading the page, the `ready-to-show` event will be emitted when renderer
|
||||
process has done drawing for the first time, showing window after this event
|
||||
will have no visual flash:
|
||||
While loading the page, the `ready-to-show` event will be emitted when the renderer
|
||||
process has rendered the page for the first time if the window has not been shown yet. Showing
|
||||
the window after this event will have no visual flash:
|
||||
|
||||
```javascript
|
||||
const {BrowserWindow} = require('electron')
|
||||
|
@ -215,6 +215,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
|||
* `devTools` Boolean (optional) - Whether to enable DevTools. If it is set to `false`, can not use `BrowserWindow.webContents.openDevTools()` to open DevTools. Default is `true`.
|
||||
* `nodeIntegration` Boolean (optional) - Whether node integration is enabled. Default
|
||||
is `true`.
|
||||
* `nodeIntegrationInWorker` Boolean (optional) - Whether node integration is
|
||||
enabled in web workers. Default is `false`. More about this can be found
|
||||
in [Multithreading](../tutorial/multithreading.md).
|
||||
* `preload` String (optional) - Specifies a script that will be loaded before other
|
||||
scripts run in the page. This script will always have access to node APIs
|
||||
no matter whether node integration is turned on or off. The value should
|
||||
|
@ -391,7 +394,7 @@ Emitted when the window is hidden.
|
|||
|
||||
#### Event: 'ready-to-show'
|
||||
|
||||
Emitted when the web page has been rendered and window can be displayed without
|
||||
Emitted when the web page has been rendered (while not being shown) and window can be displayed without
|
||||
a visual flash.
|
||||
|
||||
#### Event: 'maximize'
|
||||
|
@ -633,7 +636,8 @@ Returns `Boolean` - Whether current window is a modal window.
|
|||
|
||||
#### `win.maximize()`
|
||||
|
||||
Maximizes the window.
|
||||
Maximizes the window. This will also show (but not focus) the window if it
|
||||
isn't being displayed already.
|
||||
|
||||
#### `win.unmaximize()`
|
||||
|
||||
|
|
|
@ -117,6 +117,14 @@ To clean the build files:
|
|||
$ npm run clean
|
||||
```
|
||||
|
||||
To clean only `out` and `dist` directories:
|
||||
|
||||
```bash
|
||||
$ npm run clean-build
|
||||
```
|
||||
|
||||
**Note:** Both clean commands require running `bootstrap` again before building.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error While Loading Shared Libraries: libtinfo.so.5
|
||||
|
|
|
@ -85,6 +85,14 @@ To clean the build files:
|
|||
$ npm run clean
|
||||
```
|
||||
|
||||
To clean only `out` and `dist` directories:
|
||||
|
||||
```bash
|
||||
$ npm run clean-build
|
||||
```
|
||||
|
||||
**Note:** Both clean commands require running `bootstrap` again before building.
|
||||
|
||||
## Tests
|
||||
|
||||
See [Build System Overview: Tests](build-system-overview.md#tests)
|
||||
|
|
|
@ -83,6 +83,14 @@ To clean the build files:
|
|||
$ npm run clean
|
||||
```
|
||||
|
||||
To clean only `out` and `dist` directories:
|
||||
|
||||
```bash
|
||||
$ npm run clean-build
|
||||
```
|
||||
|
||||
**Note:** Both clean commands require running `bootstrap` again before building.
|
||||
|
||||
## Tests
|
||||
|
||||
See [Build System Overview: Tests](build-system-overview.md#tests)
|
||||
|
|
50
docs/tutorial/multithreading.md
Normal file
50
docs/tutorial/multithreading.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
# Multithreading
|
||||
|
||||
With [Web Workers][web-workers], it is possible to run JavaScript in OS-level
|
||||
threads.
|
||||
|
||||
## Multi-threaded Node.js
|
||||
|
||||
It is possible to use Node.js features in Electron's Web Workers, to do
|
||||
so the `nodeIntegrationInWorker` option should be set to `true` in
|
||||
`webPreferences`.
|
||||
|
||||
```javascript
|
||||
let win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegrationInWorker: true
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `nodeIntegrationInWorker` can be used independent of `nodeIntegration`, but
|
||||
`sandbox` must not be set to `true`.
|
||||
|
||||
## Available APIs
|
||||
|
||||
All built-in modules of Node.js are supported in Web Workers, and `asar`
|
||||
archives can still be read with Node.js APIs. However none of Electron's
|
||||
built-in modules can be used in a multi-threaded environment.
|
||||
|
||||
## Native Node.js modules
|
||||
|
||||
Any native Node.js module can be loaded directly in Web Workers, but it is
|
||||
strongly recommended not to do so. Most existing native modules have been
|
||||
written assuming single-threaded environment, using them in Web Workers will
|
||||
lead to crashes and memory corruptions.
|
||||
|
||||
Note that even if a native Node.js module is thread-safe it's still not safe to
|
||||
load it in a Web Worker because the `process.dlopen` function is not thread
|
||||
safe.
|
||||
|
||||
The only way to load a native module safely for now, is to make sure the app
|
||||
loads no native modules after the Web Workers get started.
|
||||
|
||||
```javascript
|
||||
process.dlopen = () => {
|
||||
throw new Error('Load native module is not safe')
|
||||
}
|
||||
let worker = new Worker('script.js')
|
||||
```
|
||||
|
||||
[web-workers]: https://developer.mozilla.org/en/docs/Web/API/Web_Workers_API/Using_web_workers
|
|
@ -4,7 +4,7 @@
|
|||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '1.6.3',
|
||||
'version%': '1.6.4',
|
||||
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
|
||||
},
|
||||
'includes': [
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
'lib/renderer/extensions/i18n.js',
|
||||
'lib/renderer/extensions/storage.js',
|
||||
'lib/renderer/extensions/web-navigation.js',
|
||||
'lib/worker/init.js',
|
||||
],
|
||||
'js2c_sources': [
|
||||
'lib/common/asar.js',
|
||||
|
@ -479,6 +480,8 @@
|
|||
'atom/renderer/node_array_buffer_bridge.h',
|
||||
'atom/renderer/preferences_manager.cc',
|
||||
'atom/renderer/preferences_manager.h',
|
||||
'atom/renderer/web_worker_observer.cc',
|
||||
'atom/renderer/web_worker_observer.h',
|
||||
'atom/utility/atom_content_utility_client.cc',
|
||||
'atom/utility/atom_content_utility_client.h',
|
||||
'chromium_src/chrome/browser/browser_process.cc',
|
||||
|
|
|
@ -144,7 +144,7 @@ Menu.prototype._init = function () {
|
|||
}
|
||||
|
||||
Menu.prototype.popup = function (window, x, y, positioningItem) {
|
||||
let asyncPopup = false
|
||||
let asyncPopup
|
||||
|
||||
// menu.popup(x, y, positioningItem)
|
||||
if (window != null && (typeof window !== 'object' || window.constructor !== BrowserWindow)) {
|
||||
|
@ -174,6 +174,9 @@ Menu.prototype.popup = function (window, x, y, positioningItem) {
|
|||
// Default to not highlighting any item.
|
||||
if (typeof positioningItem !== 'number') positioningItem = -1
|
||||
|
||||
// Default to synchronous for backwards compatibility.
|
||||
if (typeof asyncPopup !== 'boolean') asyncPopup = false
|
||||
|
||||
this.popupAt(window, x, y, positioningItem, asyncPopup)
|
||||
}
|
||||
|
||||
|
|
|
@ -179,7 +179,15 @@ const proxyFunctionProperties = function (remoteMemberFunction, metaId, name) {
|
|||
},
|
||||
get: (target, property, receiver) => {
|
||||
if (!target.hasOwnProperty(property)) loadRemoteProperties()
|
||||
return target[property]
|
||||
const value = target[property]
|
||||
|
||||
// Bind toString to target if it is a function to avoid
|
||||
// Function.prototype.toString is not generic errors
|
||||
if (property === 'toString' && typeof value === 'function') {
|
||||
return value.bind(target)
|
||||
}
|
||||
|
||||
return value
|
||||
},
|
||||
ownKeys: (target) => {
|
||||
loadRemoteProperties()
|
||||
|
|
|
@ -6,7 +6,7 @@ const Module = require('module')
|
|||
const resolvePromise = Promise.resolve.bind(Promise)
|
||||
|
||||
// We modified the original process.argv to let node.js load the
|
||||
// atom-renderer.js, we need to restore it here.
|
||||
// init.js, we need to restore it here.
|
||||
process.argv.splice(1, 1)
|
||||
|
||||
// Clear search paths.
|
||||
|
|
37
lib/worker/init.js
Normal file
37
lib/worker/init.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const Module = require('module')
|
||||
|
||||
// We modified the original process.argv to let node.js load the
|
||||
// init.js, we need to restore it here.
|
||||
process.argv.splice(1, 1)
|
||||
|
||||
// Clear search paths.
|
||||
require('../common/reset-search-paths')
|
||||
|
||||
// Import common settings.
|
||||
require('../common/init')
|
||||
|
||||
// Expose public APIs.
|
||||
Module.globalPaths.push(path.join(__dirname, 'api', 'exports'))
|
||||
|
||||
// Export node bindings to global.
|
||||
global.require = require
|
||||
global.module = module
|
||||
|
||||
// Set the __filename to the path of html file if it is file: protocol.
|
||||
if (self.location.protocol === 'file:') {
|
||||
let pathname = process.platform === 'win32' && self.location.pathname[0] === '/' ? self.location.pathname.substr(1) : self.location.pathname
|
||||
global.__filename = path.normalize(decodeURIComponent(pathname))
|
||||
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.
|
||||
module.paths = module.paths.concat(Module._nodeModulePaths(global.__dirname))
|
||||
} else {
|
||||
global.__filename = __filename
|
||||
global.__dirname = __dirname
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "electron",
|
||||
"version": "1.6.3",
|
||||
"version": "1.6.4",
|
||||
"devDependencies": {
|
||||
"asar": "^0.11.0",
|
||||
"browserify": "^13.1.0",
|
||||
|
@ -30,6 +30,7 @@
|
|||
"bump-version": "./script/bump-version.py",
|
||||
"build": "python ./script/build.py -c D",
|
||||
"clean": "python ./script/clean.py",
|
||||
"clean-build": "python ./script/clean.py --build",
|
||||
"coverage": "npm run instrument-code-coverage && npm test -- --use-instrumented-asar",
|
||||
"instrument-code-coverage": "electabul instrument --input-path ./lib --output-path ./out/coverage/electron.asar",
|
||||
"lint": "npm run lint-js && npm run lint-cpp && npm run lint-py && npm run lint-api-docs-js && npm run lint-api-docs",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
@ -11,13 +12,34 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
|||
|
||||
def main():
|
||||
os.chdir(SOURCE_ROOT)
|
||||
rm_rf('node_modules')
|
||||
rm_rf('dist')
|
||||
rm_rf('out')
|
||||
rm_rf('spec/node_modules')
|
||||
rm_rf('vendor/brightray/vendor/download/libchromiumcontent')
|
||||
rm_rf('vendor/brightray/vendor/libchromiumcontent/src')
|
||||
rm_rf(os.path.expanduser('~/.node-gyp'))
|
||||
|
||||
args = parse_args()
|
||||
|
||||
remove_directory('dist')
|
||||
remove_directory('out')
|
||||
|
||||
if not args.build:
|
||||
remove_directory('node_modules')
|
||||
remove_directory('spec/node_modules')
|
||||
|
||||
remove_directory('vendor/brightray/vendor/download/libchromiumcontent')
|
||||
remove_directory('vendor/brightray/vendor/libchromiumcontent/src')
|
||||
|
||||
remove_directory(os.path.expanduser('~/.node-gyp'))
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description='Remove generated and' \
|
||||
'downloaded build files')
|
||||
parser.add_argument('-b', '--build',
|
||||
help='Only remove out and dist directories',
|
||||
action='store_true')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def remove_directory(directory):
|
||||
print 'Removing %s' % directory
|
||||
rm_rf(directory)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -161,6 +161,14 @@ describe('ipc module', function () {
|
|||
assert.equal(typeof remote.clipboard.readText, 'function')
|
||||
assert.equal(typeof remote.shell.openExternal, 'function')
|
||||
})
|
||||
|
||||
it('returns toString() of original function via toString()', function () {
|
||||
const {readText} = remote.clipboard
|
||||
assert(readText.toString().startsWith('function'))
|
||||
|
||||
var {functionWithToStringProperty} = remote.require(path.join(fixtures, 'module', 'to-string-non-function.js'))
|
||||
assert.equal(functionWithToStringProperty.toString, 'hello')
|
||||
})
|
||||
})
|
||||
|
||||
describe('remote object in renderer', function () {
|
||||
|
|
|
@ -590,6 +590,27 @@ describe('chromium feature', function () {
|
|||
worker.postMessage(message)
|
||||
})
|
||||
|
||||
it('Worker has no node integration by default', function (done) {
|
||||
let worker = new Worker('../fixtures/workers/worker_node.js')
|
||||
worker.onmessage = function (event) {
|
||||
assert.equal(event.data, 'undefined undefined undefined undefined')
|
||||
worker.terminate()
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
||||
it('Worker has node integration with nodeIntegrationInWorker', function (done) {
|
||||
let webview = new WebView()
|
||||
webview.addEventListener('ipc-message', function (e) {
|
||||
assert.equal(e.channel, 'object function object function')
|
||||
webview.remove()
|
||||
done()
|
||||
})
|
||||
webview.src = 'file://' + fixtures + '/pages/worker.html'
|
||||
webview.setAttribute('webpreferences', 'nodeIntegration, nodeIntegrationInWorker')
|
||||
document.body.appendChild(webview)
|
||||
})
|
||||
|
||||
it('SharedWorker can work', function (done) {
|
||||
var worker = new SharedWorker('../fixtures/workers/shared_worker.js')
|
||||
var message = 'ping'
|
||||
|
@ -599,6 +620,29 @@ describe('chromium feature', function () {
|
|||
}
|
||||
worker.port.postMessage(message)
|
||||
})
|
||||
|
||||
it('SharedWorker has no node integration by default', function (done) {
|
||||
let worker = new SharedWorker('../fixtures/workers/shared_worker_node.js')
|
||||
worker.port.onmessage = function (event) {
|
||||
assert.equal(event.data, 'undefined undefined undefined undefined')
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
||||
it('SharedWorker has node integration with nodeIntegrationInWorker', function (done) {
|
||||
let webview = new WebView()
|
||||
webview.addEventListener('console-message', function (e) {
|
||||
console.log(e)
|
||||
})
|
||||
webview.addEventListener('ipc-message', function (e) {
|
||||
assert.equal(e.channel, 'object function object function')
|
||||
webview.remove()
|
||||
done()
|
||||
})
|
||||
webview.src = 'file://' + fixtures + '/pages/shared_worker.html'
|
||||
webview.setAttribute('webpreferences', 'nodeIntegration, nodeIntegrationInWorker')
|
||||
document.body.appendChild(webview)
|
||||
})
|
||||
})
|
||||
|
||||
describe('iframe', function () {
|
||||
|
|
4
spec/fixtures/module/to-string-non-function.js
vendored
Normal file
4
spec/fixtures/module/to-string-non-function.js
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
function hello () {
|
||||
}
|
||||
hello.toString = 'hello'
|
||||
module.exports = {functionWithToStringProperty: hello}
|
12
spec/fixtures/pages/shared_worker.html
vendored
Normal file
12
spec/fixtures/pages/shared_worker.html
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
const {ipcRenderer} = require('electron')
|
||||
// Pass a random parameter to create independent worker.
|
||||
let worker = new SharedWorker(`../workers/shared_worker_node.js?a={Math.random()}`)
|
||||
worker.port.onmessage = function (event) {
|
||||
ipcRenderer.sendToHost(event.data)
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
12
spec/fixtures/pages/worker.html
vendored
Normal file
12
spec/fixtures/pages/worker.html
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
const {ipcRenderer} = require('electron')
|
||||
let worker = new Worker(`../workers/worker_node.js`)
|
||||
worker.onmessage = function (event) {
|
||||
ipcRenderer.sendToHost(event.data)
|
||||
worker.terminate()
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
5
spec/fixtures/workers/shared_worker_node.js
vendored
Normal file
5
spec/fixtures/workers/shared_worker_node.js
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
self.onconnect = function (event) {
|
||||
let port = event.ports[0]
|
||||
port.start()
|
||||
port.postMessage([typeof process, typeof setImmediate, typeof global, typeof Buffer].join(' '))
|
||||
}
|
1
spec/fixtures/workers/worker_node.js
vendored
Normal file
1
spec/fixtures/workers/worker_node.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
self.postMessage([typeof process, typeof setImmediate, typeof global, typeof Buffer].join(' '))
|
2
vendor/native_mate
vendored
2
vendor/native_mate
vendored
|
@ -1 +1 @@
|
|||
Subproject commit ad0fd825663932ee3fa29ff935dfec99933bdd8c
|
||||
Subproject commit fd0e7dc4ab778f0d1ccda6c9640464ea06ee771e
|
Loading…
Reference in a new issue