mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4af646b760 | ||
|
|
5720d4f802 | ||
|
|
80824b13c6 | ||
|
|
33ad68f7a7 | ||
|
|
4af802f215 | ||
|
|
3b4a45ac65 | ||
|
|
a0548530e7 | ||
|
|
8d6764e0a0 | ||
|
|
36ecb35cb1 | ||
|
|
9ad3b7939f | ||
|
|
8493975840 | ||
|
|
ec880d64bf | ||
|
|
113d644615 | ||
|
|
6c0621fe05 | ||
|
|
baa6d9730c | ||
|
|
d5ffa4dc77 | ||
|
|
01dd5638d0 | ||
|
|
ec5cd2fb1c | ||
|
|
44c0dc9104 | ||
|
|
7324f0468b | ||
|
|
64e3a6b437 | ||
|
|
690ab7d4ae | ||
|
|
48a0ac9a96 | ||
|
|
7212fa1056 | ||
|
|
8d710609fd | ||
|
|
7dcbd11863 | ||
|
|
e075a8b49e | ||
|
|
d1dc041aaf | ||
|
|
85243edf4e | ||
|
|
faeea88b16 | ||
|
|
139d581e5b | ||
|
|
64b2d0da36 | ||
|
|
dc1a8b644a | ||
|
|
8bb3b53833 | ||
|
|
8112fe741e | ||
|
|
60f24eb22b | ||
|
|
fd20050fc9 | ||
|
|
c5946bf977 | ||
|
|
618d0c6397 | ||
|
|
362bb6e68b | ||
|
|
b88168c0d2 | ||
|
|
df919a4be8 | ||
|
|
45f864d2b4 | ||
|
|
602f02b867 | ||
|
|
5cf61c9ab4 | ||
|
|
49a7954824 | ||
|
|
198b52bf40 | ||
|
|
cb31140d3a | ||
|
|
f2c1d8f4b2 | ||
|
|
3ddba90d94 | ||
|
|
887a2a3c00 | ||
|
|
585777e62d | ||
|
|
640f45a5b3 | ||
|
|
8bcb545119 |
@@ -2,29 +2,46 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "app/atom_main.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "content/public/app/content_main.h"
|
||||
#if defined(OS_WIN)
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include "app/atom_main_delegate.h"
|
||||
#include "base/environment.h"
|
||||
#include "content/public/app/startup_helper_win.h"
|
||||
#include "sandbox/win/src/sandbox_types.h"
|
||||
#else // defined(OS_WIN)
|
||||
#include "app/atom_library_main.h"
|
||||
#endif // defined(OS_MACOSX) || defined(OS_LINUX)
|
||||
|
||||
// Declaration of node::Start.
|
||||
namespace node {
|
||||
int Start(int argc, char *argv[]);
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
#include <windows.h> // NOLINT
|
||||
#include <shellapi.h> // NOLINT
|
||||
|
||||
#include "app/atom_main_delegate.h"
|
||||
#include "base/environment.h"
|
||||
#include "content/public/app/startup_helper_win.h"
|
||||
#include "sandbox/win/src/sandbox_types.h"
|
||||
|
||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
int argc = 0;
|
||||
wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||
|
||||
// Attach to the parent console if we've got one so that stdio works
|
||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
|
||||
FILE* dontcare;
|
||||
freopen_s(&dontcare, "CON", "w", stdout);
|
||||
freopen_s(&dontcare, "CON", "w", stderr);
|
||||
freopen_s(&dontcare, "CON", "r", stdin);
|
||||
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
std::string node_indicator;
|
||||
if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) &&
|
||||
@@ -74,8 +91,6 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
|
||||
#else // defined(OS_WIN)
|
||||
|
||||
#include "app/atom_library_main.h"
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
|
||||
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0)
|
||||
@@ -84,4 +99,4 @@ int main(int argc, const char* argv[]) {
|
||||
return AtomMain(argc, argv);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // defined(OS_MACOSX) || defined(OS_LINUX)
|
||||
|
||||
5
app/atom_main.h
Normal file
5
app/atom_main.h
Normal file
@@ -0,0 +1,5 @@
|
||||
// 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 "content/public/app/content_main.h"
|
||||
BIN
app/win/atom.ico
Normal file
BIN
app/win/atom.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 345 KiB |
BIN
app/win/atom.rc
BIN
app/win/atom.rc
Binary file not shown.
@@ -1,9 +1,10 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by brightray_example.rc
|
||||
|
||||
#define IDR_MAINFRAME 1
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
|
||||
2
atom.gyp
2
atom.gyp
@@ -4,6 +4,7 @@
|
||||
'product_name': 'Atom',
|
||||
'app_sources': [
|
||||
'app/atom_main.cc',
|
||||
'app/atom_main.h',
|
||||
],
|
||||
'bundle_sources': [
|
||||
'browser/mac/atom.icns',
|
||||
@@ -175,6 +176,7 @@
|
||||
['OS=="win"', {
|
||||
'app_sources': [
|
||||
'app/win/resource.h',
|
||||
'app/win/atom.ico',
|
||||
'app/win/atom.rc',
|
||||
'<(libchromiumcontent_src_dir)/content/app/startup_helper_win.cc',
|
||||
],
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "ui/gfx/point.h"
|
||||
#include "ui/gfx/rect.h"
|
||||
#include "ui/gfx/size.h"
|
||||
#include "vendor/node/src/node_buffer.h"
|
||||
|
||||
using content::V8ValueConverter;
|
||||
using content::NavigationController;
|
||||
@@ -82,6 +83,20 @@ void Window::OnRendererCrashed() {
|
||||
Emit("crashed");
|
||||
}
|
||||
|
||||
void Window::OnCapturePageDone(v8::Persistent<v8::Function> callback,
|
||||
const std::vector<unsigned char>& data) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// TODO(zcbenz): Use new Buffer API when we updated to node v0.12.x.
|
||||
node::Buffer* buffer = node::Buffer::New(
|
||||
reinterpret_cast<const char*>(data.data()),
|
||||
data.size());
|
||||
|
||||
v8::Handle<v8::Value> arg = buffer->handle_;
|
||||
callback->Call(v8::Context::GetCurrent()->Global(), 1, &arg);
|
||||
callback.Dispose(v8::Isolate::GetCurrent());
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Handle<v8::Value> Window::New(const v8::Arguments &args) {
|
||||
v8::HandleScope scope;
|
||||
@@ -428,6 +443,12 @@ v8::Handle<v8::Value> Window::CloseDevTools(const v8::Arguments &args) {
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Handle<v8::Value> Window::IsDevToolsOpened(const v8::Arguments& args) {
|
||||
UNWRAP_WINDOW_AND_CHECK;
|
||||
return ToV8Value(self->window_->IsDevToolsOpened());
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Handle<v8::Value> Window::InspectElement(const v8::Arguments& args) {
|
||||
UNWRAP_WINDOW_AND_CHECK;
|
||||
@@ -474,6 +495,23 @@ v8::Handle<v8::Value> Window::RestartHangMonitorTimeout(
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Handle<v8::Value> Window::CapturePage(const v8::Arguments& args) {
|
||||
UNWRAP_WINDOW_AND_CHECK;
|
||||
|
||||
gfx::Rect rect;
|
||||
v8::Persistent<v8::Function> callback;
|
||||
if (!FromV8Arguments(args, &rect, &callback) &&
|
||||
!FromV8Arguments(args, &callback))
|
||||
return node::ThrowTypeError("Bad argument");
|
||||
|
||||
self->window_->CapturePage(rect, base::Bind(&Window::OnCapturePageDone,
|
||||
base::Unretained(self),
|
||||
callback));
|
||||
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Handle<v8::Value> Window::GetPageTitle(const v8::Arguments &args) {
|
||||
UNWRAP_WINDOW_AND_CHECK;
|
||||
@@ -707,6 +745,7 @@ void Window::Initialize(v8::Handle<v8::Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "isKiosk", IsKiosk);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "openDevTools", OpenDevTools);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "closeDevTools", CloseDevTools);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "isDevToolsOpened", IsDevToolsOpened);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "inspectElement", InspectElement);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "focusOnWebView", FocusOnWebView);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "blurWebView", BlurWebView);
|
||||
@@ -714,6 +753,7 @@ void Window::Initialize(v8::Handle<v8::Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(t,
|
||||
"restartHangMonitorTimeout",
|
||||
RestartHangMonitorTimeout);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "capturePage", CapturePage);
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "getPageTitle", GetPageTitle);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "isLoading", IsLoading);
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_WINDOW_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_WINDOW_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "browser/api/atom_api_event_emitter.h"
|
||||
#include "browser/native_window_observer.h"
|
||||
@@ -80,12 +82,14 @@ class Window : public EventEmitter,
|
||||
static v8::Handle<v8::Value> IsKiosk(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> OpenDevTools(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> CloseDevTools(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> IsDevToolsOpened(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> InspectElement(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> FocusOnWebView(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> BlurWebView(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> IsWebViewFocused(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> RestartHangMonitorTimeout(
|
||||
const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> CapturePage(const v8::Arguments& args);
|
||||
|
||||
// APIs for WebContents.
|
||||
static v8::Handle<v8::Value> GetPageTitle(const v8::Arguments &args);
|
||||
@@ -109,6 +113,10 @@ class Window : public EventEmitter,
|
||||
static v8::Handle<v8::Value> Reload(const v8::Arguments &args);
|
||||
static v8::Handle<v8::Value> ReloadIgnoringCache(const v8::Arguments &args);
|
||||
|
||||
// Called when capturePage is done.
|
||||
void OnCapturePageDone(v8::Persistent<v8::Function> callback,
|
||||
const std::vector<unsigned char>& data);
|
||||
|
||||
scoped_ptr<NativeWindow> window_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Window);
|
||||
|
||||
@@ -12,13 +12,7 @@ BrowserWindow::_init = ->
|
||||
@setMenu menu if menu?
|
||||
|
||||
BrowserWindow::toggleDevTools = ->
|
||||
opened = v8Util.getHiddenValue this, 'devtoolsOpened'
|
||||
if opened
|
||||
@closeDevTools()
|
||||
v8Util.setHiddenValue this, 'devtoolsOpened', false
|
||||
else
|
||||
@openDevTools()
|
||||
v8Util.setHiddenValue this, 'devtoolsOpened', true
|
||||
if @isDevToolsOpened() then @closeDevTools() else @openDevTools()
|
||||
|
||||
BrowserWindow::restart = ->
|
||||
@loadUrl(@getUrl())
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<string>0.6.12</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/file_util.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/utf_string_conversions.h"
|
||||
#include "base/values.h"
|
||||
@@ -28,9 +29,11 @@
|
||||
#include "common/api/api_messages.h"
|
||||
#include "common/options_switches.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "ui/gfx/codec/png_codec.h"
|
||||
#include "ui/gfx/point.h"
|
||||
#include "ui/gfx/rect.h"
|
||||
#include "ui/gfx/size.h"
|
||||
#include "webkit/glue/image_decoder.h"
|
||||
|
||||
using content::NavigationEntry;
|
||||
|
||||
@@ -46,6 +49,12 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
|
||||
brightray::InspectableWebContents::Create(web_contents)) {
|
||||
options->GetBoolean(switches::kFrame, &has_frame_);
|
||||
|
||||
std::string icon;
|
||||
if (options->GetString(switches::kIcon, &icon)) {
|
||||
if (!SetIcon(icon))
|
||||
LOG(ERROR) << "Failed to set icon to " << icon;
|
||||
}
|
||||
|
||||
web_contents->SetDelegate(this);
|
||||
|
||||
WindowList::AddWindow(this);
|
||||
@@ -141,6 +150,10 @@ void NativeWindow::CloseDevTools() {
|
||||
inspectable_web_contents()->GetView()->CloseDevTools();
|
||||
}
|
||||
|
||||
bool NativeWindow::IsDevToolsOpened() {
|
||||
return inspectable_web_contents()->IsDevToolsOpened();
|
||||
}
|
||||
|
||||
void NativeWindow::InspectElement(int x, int y) {
|
||||
OpenDevTools();
|
||||
content::RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
|
||||
@@ -165,6 +178,37 @@ void NativeWindow::RestartHangMonitorTimeout() {
|
||||
GetWebContents()->GetRenderViewHost()->RestartHangMonitorTimeout();
|
||||
}
|
||||
|
||||
bool NativeWindow::SetIcon(const std::string& str_path) {
|
||||
base::FilePath path = base::FilePath::FromUTF8Unsafe(str_path);
|
||||
|
||||
// Read the file from disk.
|
||||
std::string file_contents;
|
||||
if (path.empty() || !file_util::ReadFileToString(path, &file_contents))
|
||||
return false;
|
||||
|
||||
// Decode the bitmap using WebKit's image decoder.
|
||||
const unsigned char* data =
|
||||
reinterpret_cast<const unsigned char*>(file_contents.data());
|
||||
webkit_glue::ImageDecoder decoder;
|
||||
scoped_ptr<SkBitmap> decoded(new SkBitmap());
|
||||
*decoded = decoder.Decode(data, file_contents.length());
|
||||
if (decoded->empty())
|
||||
return false; // Unable to decode.
|
||||
|
||||
icon_ = gfx::Image::CreateFrom1xBitmap(*decoded.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeWindow::CapturePage(const gfx::Rect& rect,
|
||||
const CapturePageCallback& callback) {
|
||||
GetWebContents()->GetRenderViewHost()->CopyFromBackingStore(
|
||||
rect,
|
||||
gfx::Size(),
|
||||
base::Bind(&NativeWindow::OnCapturePageDone,
|
||||
base::Unretained(this),
|
||||
callback));
|
||||
}
|
||||
|
||||
void NativeWindow::CloseWebContents() {
|
||||
bool prevent_default = false;
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver,
|
||||
@@ -341,6 +385,15 @@ void NativeWindow::Observe(int type,
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback,
|
||||
bool succeed,
|
||||
const SkBitmap& bitmap) {
|
||||
std::vector<unsigned char> data;
|
||||
if (succeed)
|
||||
gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &data);
|
||||
callback.Run(data);
|
||||
}
|
||||
|
||||
void NativeWindow::OnRendererMessage(const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessage(
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "content/public/browser/notification_registrar.h"
|
||||
#include "content/public/browser/notification_observer.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
#include "vendor/brightray/browser/default_web_contents_delegate.h"
|
||||
|
||||
namespace base {
|
||||
@@ -48,6 +49,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
public content::WebContentsObserver,
|
||||
public content::NotificationObserver {
|
||||
public:
|
||||
typedef base::Callback<void(const std::vector<unsigned char>& buffer)>
|
||||
CapturePageCallback;
|
||||
|
||||
virtual ~NativeWindow();
|
||||
|
||||
// Create window with existing WebContents.
|
||||
@@ -99,11 +103,18 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
virtual bool IsClosed() const { return is_closed_; }
|
||||
virtual void OpenDevTools();
|
||||
virtual void CloseDevTools();
|
||||
virtual bool IsDevToolsOpened();
|
||||
virtual void InspectElement(int x, int y);
|
||||
virtual void FocusOnWebView();
|
||||
virtual void BlurWebView();
|
||||
virtual bool IsWebViewFocused();
|
||||
virtual void RestartHangMonitorTimeout();
|
||||
virtual bool SetIcon(const std::string& path);
|
||||
|
||||
// Captures the page with |rect|, |callback| would be called when capturing is
|
||||
// done.
|
||||
virtual void CapturePage(const gfx::Rect& rect,
|
||||
const CapturePageCallback& callback);
|
||||
|
||||
// The same with closing a tab in a real browser.
|
||||
//
|
||||
@@ -175,9 +186,17 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
// Whether window has standard frame.
|
||||
bool has_frame_;
|
||||
|
||||
// Window icon.
|
||||
gfx::Image icon_;
|
||||
|
||||
private:
|
||||
void RendererUnresponsiveDelayed();
|
||||
|
||||
// Called when CapturePage has done.
|
||||
void OnCapturePageDone(const CapturePageCallback& callback,
|
||||
bool succeed,
|
||||
const SkBitmap& bitmap);
|
||||
|
||||
void OnRendererMessage(const string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
|
||||
@@ -217,6 +217,8 @@ NativeWindowWin::NativeWindowWin(content::WebContents* web_contents,
|
||||
gfx::Size size(width, height);
|
||||
window_->CenterWindow(size);
|
||||
|
||||
window_->UpdateWindowIcon();
|
||||
|
||||
web_view_->SetWebContents(web_contents);
|
||||
OnViewWasResized();
|
||||
}
|
||||
@@ -463,8 +465,15 @@ bool NativeWindowWin::ShouldHandleSystemCommands() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NativeWindowWin::ShouldShowWindowIcon() const {
|
||||
return true;
|
||||
gfx::ImageSkia NativeWindowWin::GetWindowAppIcon() {
|
||||
if (icon_.IsEmpty())
|
||||
return gfx::ImageSkia();
|
||||
else
|
||||
return *icon_.ToImageSkia();
|
||||
}
|
||||
|
||||
gfx::ImageSkia NativeWindowWin::GetWindowIcon() {
|
||||
return GetWindowAppIcon();
|
||||
}
|
||||
|
||||
views::Widget* NativeWindowWin::GetWidget() {
|
||||
|
||||
@@ -98,7 +98,8 @@ class NativeWindowWin : public NativeWindow,
|
||||
virtual bool CanMaximize() const OVERRIDE;
|
||||
virtual string16 GetWindowTitle() const OVERRIDE;
|
||||
virtual bool ShouldHandleSystemCommands() const OVERRIDE;
|
||||
virtual bool ShouldShowWindowIcon() const OVERRIDE;
|
||||
virtual gfx::ImageSkia GetWindowAppIcon() OVERRIDE;
|
||||
virtual gfx::ImageSkia GetWindowIcon() OVERRIDE;
|
||||
virtual views::Widget* GetWidget() OVERRIDE;
|
||||
virtual const views::Widget* GetWidget() const OVERRIDE;
|
||||
virtual views::ClientView* CreateClientView(views::Widget* widget) OVERRIDE;
|
||||
|
||||
@@ -30,8 +30,8 @@ void AdapterRequestJob::Start() {
|
||||
}
|
||||
|
||||
void AdapterRequestJob::Kill() {
|
||||
DCHECK(real_job_);
|
||||
real_job_->Kill();
|
||||
if (real_job_) // Kill could happen when real_job_ is created.
|
||||
real_job_->Kill();
|
||||
}
|
||||
|
||||
bool AdapterRequestJob::ReadRawData(net::IOBuffer* buf,
|
||||
|
||||
@@ -93,10 +93,6 @@ bool StringToAccelerator(const std::string& description,
|
||||
|
||||
std::vector<std::string> tokens;
|
||||
base::SplitString(shortcut, '+', &tokens);
|
||||
if (tokens.size() < 2 || tokens.size() > 4) {
|
||||
LOG(WARNING) << "Invalid accelerator description: " << description;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now, parse it into an accelerator.
|
||||
int modifiers = ui::EF_NONE;
|
||||
@@ -112,13 +108,7 @@ bool StringToAccelerator(const std::string& description,
|
||||
} else if (tokens[i] == "ctrl") {
|
||||
modifiers |= ui::EF_CONTROL_DOWN;
|
||||
} else if (tokens[i] == "command") {
|
||||
// The "Command" would be translated to "Ctrl" on platforms other than
|
||||
// OS X.
|
||||
#if defined(OS_MACOSX)
|
||||
modifiers |= ui::EF_COMMAND_DOWN;
|
||||
#else
|
||||
modifiers |= ui::EF_CONTROL_DOWN;
|
||||
#endif
|
||||
} else if (tokens[i] == "alt") {
|
||||
modifiers |= ui::EF_ALT_DOWN;
|
||||
} else if (tokens[i] == "shift") {
|
||||
|
||||
54
common.gypi
54
common.gypi
@@ -4,7 +4,12 @@
|
||||
'conditions': [
|
||||
['OS=="mac"', {
|
||||
'clang': 1,
|
||||
'mac_sdk%': '<!(python tools/mac/find_sdk.py 10.8)',
|
||||
}],
|
||||
['OS=="win" and (MSVS_VERSION=="2012e" or MSVS_VERSION=="2010e")', {
|
||||
'msvs_express': 1,
|
||||
'windows_driver_kit_path%': 'C:/WinDDK/7600.16385.1',
|
||||
},{
|
||||
'msvs_express': 0,
|
||||
}],
|
||||
],
|
||||
# Reflects node's config.gypi.
|
||||
@@ -57,6 +62,16 @@
|
||||
'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO'
|
||||
},
|
||||
}],
|
||||
['_target_name=="libuv"', {
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
# Expose libuv's symbols.
|
||||
'defines': [
|
||||
'BUILDING_UV_SHARED=1',
|
||||
],
|
||||
}], # OS=="win"
|
||||
],
|
||||
}],
|
||||
],
|
||||
'msvs_cygwin_shell': 0, # Strangely setting it to 1 would make building under cygwin fail.
|
||||
'msvs_disabled_warnings': [
|
||||
@@ -67,6 +82,12 @@
|
||||
4819, # The file contains a character that cannot be represented in the current code page
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
# Programs that use the Standard C++ library must be compiled with C++
|
||||
# exception handling enabled.
|
||||
# http://support.microsoft.com/kb/154419
|
||||
'ExceptionHandling': 1,
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'AdditionalOptions': [
|
||||
# ATL 8.0 included in WDK 7.1 makes the linker to generate following
|
||||
@@ -112,23 +133,36 @@
|
||||
'-fcolor-diagnostics',
|
||||
],
|
||||
|
||||
'SDKROOT': 'macosx<(mac_sdk)', # -isysroot
|
||||
'GCC_C_LANGUAGE_STANDARD': 'c99', # -std=c99
|
||||
},
|
||||
},
|
||||
}], # clang==1
|
||||
# Windows specific settings.
|
||||
['OS=="win"', {
|
||||
# Using Visual Studio Express.
|
||||
['msvs_express==1', {
|
||||
'target_defaults': {
|
||||
'defines!': [
|
||||
'_SECURE_ATL',
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
# Programs that use the Standard C++ library must be compiled with C++
|
||||
# exception handling enabled.
|
||||
# http://support.microsoft.com/kb/154419
|
||||
'ExceptionHandling': 1,
|
||||
'VCLibrarianTool': {
|
||||
'AdditionalLibraryDirectories': [
|
||||
'<(windows_driver_kit_path)/lib/ATL/i386',
|
||||
],
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'AdditionalLibraryDirectories': [
|
||||
'<(windows_driver_kit_path)/lib/ATL/i386',
|
||||
],
|
||||
'AdditionalDependencies': [
|
||||
'atlthunk.lib',
|
||||
],
|
||||
},
|
||||
},
|
||||
'msvs_system_include_dirs': [
|
||||
'<(windows_driver_kit_path)/inc/atl71',
|
||||
'<(windows_driver_kit_path)/inc/mfc42',
|
||||
],
|
||||
},
|
||||
}], # OS=="win"
|
||||
}], # msvs_express==1
|
||||
],
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 6
|
||||
#define ATOM_PATCH_VERSION 2
|
||||
#define ATOM_PATCH_VERSION 12
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
||||
@@ -39,10 +39,16 @@ NodeBindings::NodeBindings(bool is_browser)
|
||||
}
|
||||
|
||||
NodeBindings::~NodeBindings() {
|
||||
// Clear uv.
|
||||
// Quit the embed thread.
|
||||
embed_closed_ = true;
|
||||
uv_sem_post(&embed_sem_);
|
||||
WakeupEmbedThread();
|
||||
|
||||
// Wait for everything to be done.
|
||||
uv_thread_join(&embed_thread_);
|
||||
message_loop_->RunUntilIdle();
|
||||
|
||||
// Clear uv.
|
||||
uv_sem_destroy(&embed_sem_);
|
||||
uv_timer_stop(&idle_timer_);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/string16.h"
|
||||
#include "browser/api/atom_api_window.h"
|
||||
#include "ui/gfx/rect.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
// Convert V8 value to arbitrary supported types.
|
||||
@@ -38,6 +39,20 @@ struct FromV8Value {
|
||||
return base::FilePath::FromUTF8Unsafe(FromV8Value(value_));
|
||||
}
|
||||
|
||||
operator gfx::Rect() {
|
||||
v8::Handle<v8::Object> rect = value_->ToObject();
|
||||
v8::Handle<v8::Value> x = rect->Get(v8::String::New("x"));
|
||||
v8::Handle<v8::Value> y = rect->Get(v8::String::New("y"));
|
||||
v8::Handle<v8::Value> width = rect->Get(v8::String::New("width"));
|
||||
v8::Handle<v8::Value> height = rect->Get(v8::String::New("height"));
|
||||
if (!x->IsNumber() || !y->IsNumber() ||
|
||||
!width->IsNumber() || !height->IsNumber())
|
||||
return gfx::Rect();
|
||||
else
|
||||
return gfx::Rect(x->IntegerValue(), y->IntegerValue(),
|
||||
width->IntegerValue(), height->IntegerValue());
|
||||
}
|
||||
|
||||
operator std::vector<std::string>() {
|
||||
std::vector<std::string> array;
|
||||
v8::Handle<v8::Array> v8_array = v8::Handle<v8::Array>::Cast(value_);
|
||||
@@ -58,11 +73,9 @@ struct FromV8Value {
|
||||
}
|
||||
|
||||
operator v8::Persistent<v8::Function>() {
|
||||
return value_->IsFunction() ?
|
||||
v8::Persistent<v8::Function>::New(
|
||||
node::node_isolate,
|
||||
v8::Handle<v8::Function>::Cast(value_)) :
|
||||
v8::Persistent<v8::Function>();
|
||||
return v8::Persistent<v8::Function>::New(
|
||||
node::node_isolate,
|
||||
v8::Handle<v8::Function>::Cast(value_));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> value_;
|
||||
@@ -137,6 +150,11 @@ bool V8ValueCanBeConvertedTo<base::FilePath>(v8::Handle<v8::Value> value) {
|
||||
return V8ValueCanBeConvertedTo<std::string>(value);
|
||||
}
|
||||
|
||||
template<> inline
|
||||
bool V8ValueCanBeConvertedTo<gfx::Rect>(v8::Handle<v8::Value> value) {
|
||||
return value->IsObject();
|
||||
}
|
||||
|
||||
template<> inline
|
||||
bool V8ValueCanBeConvertedTo<std::vector<std::string>>(
|
||||
v8::Handle<v8::Value> value) {
|
||||
|
||||
@@ -290,6 +290,23 @@ Starts inspecting element at position (`x`, `y`).
|
||||
|
||||
### BrowserWindow.restartHangMonitorTimeout()
|
||||
|
||||
### BrowserWindow.capturePage([rect, ]callback)
|
||||
|
||||
* `rect` Object - The area of page to be captured
|
||||
* `x`
|
||||
* `y`
|
||||
* `width`
|
||||
* `height`
|
||||
* `callback` Function
|
||||
|
||||
Captures the snapshot of page within `rect`, upon completion `callback` would be
|
||||
called with `callback(image)`, the `image` is a `Buffer` that stores the PNG
|
||||
encoded data of the snapshot. Omitting the `rect` would capture the whole
|
||||
visible page.
|
||||
|
||||
You can write received `image` directly to a `.png` file, or you can base64
|
||||
encode it and use data URL to embed the image in HTML.
|
||||
|
||||
### BrowserWindow.getPageTitle()
|
||||
|
||||
Returns the title of web page.
|
||||
|
||||
@@ -23,5 +23,4 @@
|
||||
|
||||
## Notes on accelerator
|
||||
|
||||
On Linux and Windows, the `Command` would be translated to `Ctrl`, so usually
|
||||
you can use `Command` for most of the commands.
|
||||
On Linux and Windows, the `Command` key would not have any effect.
|
||||
|
||||
@@ -3,11 +3,21 @@
|
||||
## Prerequisites
|
||||
|
||||
* Windows 7 or later
|
||||
* Visual Studio 2010 Express or higher
|
||||
* Visual Studio 2010 Express or Profissional
|
||||
* Make sure "X64 Compilers and Tools" are installed if you use the
|
||||
Profissional edition.
|
||||
* [Python 2.7](http://www.python.org/download/releases/2.7/)
|
||||
* [node.js](http://nodejs.org/)
|
||||
* [git](http://git-scm.com)
|
||||
|
||||
If you are using Visual Studio 2010 __Express__ then you also need following
|
||||
softwares:
|
||||
|
||||
* [WDK](http://www.microsoft.com/en-us/download/details.aspx?id=11800)
|
||||
* `Build Environments` is required.
|
||||
* [Windows 7 SDK](http://www.microsoft.com/en-us/download/details.aspx?id=8279)
|
||||
* `Windows Headers` and `Visual C++ Compilers` are required.
|
||||
|
||||
The instructions bellow are executed under [cygwin](http://www.cygwin.com),
|
||||
but it's not a requirement, you can also build atom-shell under Windows's
|
||||
console or other terminals.
|
||||
@@ -18,7 +28,7 @@ not use Visual Studio for the development. Support of building with Visual
|
||||
Studio will come in future.
|
||||
|
||||
**Note:** Even though Visual Studio is not used for building, it's still
|
||||
**required because we need the build toolchains it provided.
|
||||
**required** because we need the build toolchains it provided.
|
||||
|
||||
## Getting the code
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "atom-shell",
|
||||
"version" : "0.6.2",
|
||||
"name": "atom-shell",
|
||||
"version": "0.6.12",
|
||||
|
||||
"devDependencies": {
|
||||
"coffee-script": "~1.6.3",
|
||||
@@ -16,6 +16,6 @@
|
||||
"private": true,
|
||||
|
||||
"scripts": {
|
||||
"preinstall": "true"
|
||||
"preinstall": "node -e 'process.exit(0)'"
|
||||
}
|
||||
}
|
||||
|
||||
116
script/bump-version.py
Executable file
116
script/bump-version.py
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print 'Usage: bump-version.py version'
|
||||
return 1
|
||||
|
||||
version = sys.argv[1]
|
||||
if version[0] == 'v':
|
||||
version = version[1:]
|
||||
versions = parse_version(version)
|
||||
|
||||
os.chdir(SOURCE_ROOT)
|
||||
update_package_json(version)
|
||||
update_win_rc(version, versions)
|
||||
update_version_h(versions)
|
||||
update_info_plist(version)
|
||||
tag_version(version)
|
||||
|
||||
|
||||
def parse_version(version):
|
||||
vs = version.split('.')
|
||||
if len(vs) > 4:
|
||||
return vs[0:4]
|
||||
else:
|
||||
return vs + [0] * (4 - len(vs))
|
||||
|
||||
|
||||
def update_package_json(version):
|
||||
pattern = re.compile(' *"version" *: *"[0-9.]+"')
|
||||
with open('package.json', 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
for i in range(0, len(lines)):
|
||||
if pattern.match(lines[i]):
|
||||
lines[i] = ' "version": "{0}",\n'.format(version)
|
||||
with open('package.json', 'w') as f:
|
||||
f.write(''.join(lines))
|
||||
return
|
||||
|
||||
|
||||
def update_win_rc(version, versions):
|
||||
pattern_fv = re.compile(' FILEVERSION [0-9,]+')
|
||||
pattern_pv = re.compile(' PRODUCTVERSION [0-9,]+')
|
||||
pattern_fvs = re.compile(' *VALUE "FileVersion", "[0-9.]+"')
|
||||
pattern_pvs = re.compile(' *VALUE "ProductVersion", "[0-9.]+"')
|
||||
|
||||
win_rc = os.path.join('app', 'win', 'atom.rc')
|
||||
with open(win_rc, 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
versions = [str(v) for v in versions]
|
||||
for i in range(0, len(lines)):
|
||||
line = lines[i]
|
||||
if pattern_fv.match(line):
|
||||
lines[i] = ' FILEVERSION {0}\r\n'.format(','.join(versions))
|
||||
elif pattern_pv.match(line):
|
||||
lines[i] = ' PRODUCTVERSION {0}\r\n'.format(','.join(versions))
|
||||
elif pattern_fvs.match(line):
|
||||
lines[i] = ' VALUE "FileVersion", "{0}"\r\n'.format(version)
|
||||
elif pattern_pvs.match(line):
|
||||
lines[i] = ' VALUE "ProductVersion", "{0}"\r\n'.format(version)
|
||||
|
||||
with open(win_rc, 'w') as f:
|
||||
f.write(''.join(lines))
|
||||
|
||||
|
||||
def update_version_h(versions):
|
||||
version_h = os.path.join('common', 'atom_version.h')
|
||||
with open(version_h, 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
for i in range(0, len(lines)):
|
||||
line = lines[i]
|
||||
if 'ATOM_MAJOR_VERSION' in line:
|
||||
lines[i] = '#define ATOM_MAJOR_VERSION {0}\n'.format(versions[0])
|
||||
lines[i + 1] = '#define ATOM_MINOR_VERSION {0}\n'.format(versions[1])
|
||||
lines[i + 2] = '#define ATOM_PATCH_VERSION {0}\n'.format(versions[2])
|
||||
|
||||
with open(version_h, 'w') as f:
|
||||
f.write(''.join(lines))
|
||||
return
|
||||
|
||||
|
||||
def update_info_plist(version):
|
||||
info_plist = os.path.join('browser', 'mac', 'Info.plist')
|
||||
with open(info_plist, 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
for i in range(0, len(lines)):
|
||||
line = lines[i]
|
||||
if 'CFBundleVersion' in line:
|
||||
lines[i + 1] = ' <string>{0}</string>\n'.format(version)
|
||||
|
||||
with open(info_plist, 'w') as f:
|
||||
f.write(''.join(lines))
|
||||
return
|
||||
|
||||
|
||||
def tag_version(version):
|
||||
subprocess.check_call(['git', 'commit', '-a', '-m',
|
||||
'Bump v{0}.'.format(version)])
|
||||
subprocess.check_call(['git', 'tag', 'v{0}'.format(version)])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -31,6 +31,7 @@ TARGET_BINARIES = {
|
||||
],
|
||||
'win32': [
|
||||
'atom.exe',
|
||||
'atom.exe.pdb',
|
||||
'chromiumcontent.dll',
|
||||
'content_shell.pak',
|
||||
'ffmpegsumo.dll',
|
||||
@@ -136,10 +137,9 @@ def create_zip():
|
||||
zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
|
||||
|
||||
with scoped_cwd(DIST_DIR):
|
||||
files = TARGET_BINARIES[TARGET_PLATFORM] + \
|
||||
TARGET_DIRECTORIES[TARGET_PLATFORM] + \
|
||||
['LICENSE', 'version']
|
||||
make_zip(zip_file, files)
|
||||
files = TARGET_BINARIES[TARGET_PLATFORM] + ['LICENSE', 'version']
|
||||
dirs = TARGET_DIRECTORIES[TARGET_PLATFORM]
|
||||
make_zip(zip_file, files, dirs)
|
||||
|
||||
|
||||
def create_header_tarball():
|
||||
|
||||
@@ -64,14 +64,19 @@ def extract_zip(zip_path, destination):
|
||||
with zipfile.ZipFile(zip_path) as z:
|
||||
z.extractall(destination)
|
||||
|
||||
def make_zip(zip_file_path, files):
|
||||
def make_zip(zip_file_path, files, dirs):
|
||||
safe_unlink(zip_file_path)
|
||||
if sys.platform == 'darwin':
|
||||
files += dirs
|
||||
subprocess.check_call(['zip', '-r', '-y', zip_file_path] + files)
|
||||
else:
|
||||
zip_file = zipfile.ZipFile(zip_file_path, "w")
|
||||
zip_file = zipfile.ZipFile(zip_file_path, "w", zipfile.ZIP_DEFLATED)
|
||||
for filename in files:
|
||||
zip_file.write(filename, filename)
|
||||
for dirname in dirs:
|
||||
for root, _, filenames in os.walk(dirname):
|
||||
for f in filenames:
|
||||
zip_file.write(os.path.join(root, f))
|
||||
zip_file.close()
|
||||
|
||||
|
||||
|
||||
@@ -75,6 +75,13 @@ describe 'window module', ->
|
||||
assert.equal w.isVisible(), false
|
||||
w.close()
|
||||
|
||||
describe 'BrowserWindow.capturePage(rect, callback)', ->
|
||||
it 'calls the callback with a Buffer', ->
|
||||
w = new BrowserWindow(show: false)
|
||||
w.capturePage {x: 0, y: 0, width: 100, height: 100}, (image) ->
|
||||
assert.equal image.constructor.name, 'SlowBuffer'
|
||||
w.close()
|
||||
|
||||
describe 'beforeunload handler', ->
|
||||
it 'returning true would not prevent close', (done) ->
|
||||
w = new BrowserWindow(show: false)
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
"""Prints the lowest locally available SDK version greater than or equal to a
|
||||
given minimum sdk version to standard output.
|
||||
|
||||
Usage:
|
||||
python find_sdk.py 10.6 # Ignores SDKs < 10.6
|
||||
"""
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
|
||||
def parse_version(version_str):
|
||||
"""'10.6' => [10, 6]"""
|
||||
return map(int, re.findall(r'(\d+)', version_str))
|
||||
|
||||
|
||||
def main():
|
||||
parser = OptionParser()
|
||||
parser.add_option("--verify",
|
||||
action="store_true", dest="verify", default=False,
|
||||
help="return the sdk argument and warn if it doesn't exist")
|
||||
parser.add_option("--sdk_path",
|
||||
action="store", type="string", dest="sdk_path", default="",
|
||||
help="user-specified SDK path; bypasses verification")
|
||||
(options, args) = parser.parse_args()
|
||||
min_sdk_version = args[0]
|
||||
|
||||
job = subprocess.Popen(['xcode-select', '-print-path'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
out, err = job.communicate()
|
||||
if job.returncode != 0:
|
||||
print >>sys.stderr, out
|
||||
print >>sys.stderr, err
|
||||
raise Exception(('Error %d running xcode-select, you might have to run '
|
||||
'|sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer| '
|
||||
'if you are using Xcode 4.') % job.returncode)
|
||||
# The Developer folder moved in Xcode 4.3.
|
||||
xcode43_sdk_path = os.path.join(
|
||||
out.rstrip(), 'Platforms/MacOSX.platform/Developer/SDKs')
|
||||
if os.path.isdir(xcode43_sdk_path):
|
||||
sdk_dir = xcode43_sdk_path
|
||||
else:
|
||||
sdk_dir = os.path.join(out.rstrip(), 'SDKs')
|
||||
sdks = [re.findall('^MacOSX(10\.\d+)\.sdk$', s) for s in os.listdir(sdk_dir)]
|
||||
sdks = [s[0] for s in sdks if s] # [['10.5'], ['10.6']] => ['10.5', '10.6']
|
||||
sdks = [s for s in sdks # ['10.5', '10.6'] => ['10.6']
|
||||
if parse_version(s) >= parse_version(min_sdk_version)]
|
||||
if not sdks:
|
||||
raise Exception('No %s+ SDK found' % min_sdk_version)
|
||||
best_sdk = sorted(sdks, key=parse_version)[0]
|
||||
|
||||
if options.verify and best_sdk != min_sdk_version and not options.sdk_path:
|
||||
print >>sys.stderr, ''
|
||||
print >>sys.stderr, ' vvvvvvv'
|
||||
print >>sys.stderr, ''
|
||||
print >>sys.stderr, \
|
||||
'This build requires the %s SDK, but it was not found on your system.' \
|
||||
% min_sdk_version
|
||||
print >>sys.stderr, \
|
||||
'Either install it, or explicitly set mac_sdk in your GYP_DEFINES.'
|
||||
print >>sys.stderr, ''
|
||||
print >>sys.stderr, ' ^^^^^^^'
|
||||
print >>sys.stderr, ''
|
||||
return min_sdk_version
|
||||
|
||||
return best_sdk
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.platform != 'darwin':
|
||||
raise Exception("This script only runs on Mac")
|
||||
print main()
|
||||
2
vendor/apm
vendored
2
vendor/apm
vendored
Submodule vendor/apm updated: 952b3221bb...65aafcd8e6
2
vendor/brightray
vendored
2
vendor/brightray
vendored
Submodule vendor/brightray updated: b207f0e5be...2f84310fe4
2
vendor/node
vendored
2
vendor/node
vendored
Submodule vendor/node updated: 7f44fac0fd...24c11bdc79
Reference in New Issue
Block a user