Merge branch 'master' into linux
Conflicts: vendor/apm
This commit is contained in:
commit
2f798c5116
43 changed files with 478 additions and 75 deletions
|
@ -50,8 +50,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,8,1,0
|
||||
PRODUCTVERSION 0,8,1,0
|
||||
FILEVERSION 0,8,5,0
|
||||
PRODUCTVERSION 0,8,5,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -68,12 +68,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Atom-Shell"
|
||||
VALUE "FileVersion", "0.8.1"
|
||||
VALUE "FileVersion", "0.8.5"
|
||||
VALUE "InternalName", "atom.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2013 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "atom.exe"
|
||||
VALUE "ProductName", "Atom-Shell"
|
||||
VALUE "ProductVersion", "0.8.1"
|
||||
VALUE "ProductVersion", "0.8.5"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
9
atom.gyp
9
atom.gyp
|
@ -12,6 +12,7 @@
|
|||
],
|
||||
'coffee_sources': [
|
||||
'browser/api/lib/app.coffee',
|
||||
'browser/api/lib/atom-delegate.coffee',
|
||||
'browser/api/lib/auto-updater.coffee',
|
||||
'browser/api/lib/browser-window.coffee',
|
||||
'browser/api/lib/dialog.coffee',
|
||||
|
@ -27,7 +28,9 @@
|
|||
'common/api/lib/clipboard.coffee',
|
||||
'common/api/lib/crash-reporter.coffee',
|
||||
'common/api/lib/id-weak-map.coffee',
|
||||
'common/api/lib/screen.coffee',
|
||||
'common/api/lib/shell.coffee',
|
||||
'common/lib/init.coffee',
|
||||
'renderer/lib/init.coffee',
|
||||
'renderer/api/lib/ipc.coffee',
|
||||
'renderer/api/lib/remote.coffee',
|
||||
|
@ -46,8 +49,6 @@
|
|||
'browser/api/atom_api_dialog.h',
|
||||
'browser/api/atom_api_event.cc',
|
||||
'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.h',
|
||||
'browser/api/atom_api_menu_mac.h',
|
||||
|
@ -133,8 +134,12 @@
|
|||
'common/api/atom_api_clipboard.h',
|
||||
'common/api/atom_api_crash_reporter.cc',
|
||||
'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.h',
|
||||
'common/api/atom_api_screen.cc',
|
||||
'common/api/atom_api_screen.h',
|
||||
'common/api/atom_api_shell.cc',
|
||||
'common/api/atom_api_shell.h',
|
||||
'common/api/atom_api_v8_util.cc',
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#define ATOM_BROWSER_API_ATOM_API_APP_H_
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "browser/api/atom_api_event_emitter.h"
|
||||
#include "browser/browser_observer.h"
|
||||
#include "common/api/atom_api_event_emitter.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "browser/api/atom_api_event_emitter.h"
|
||||
#include "browser/auto_updater_delegate.h"
|
||||
#include "common/api/atom_api_event_emitter.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace {
|
|||
|
||||
template<typename T>
|
||||
void CallV8Function(const RefCountedV8Function& callback, T arg) {
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
v8::Handle<v8::Value> value = ToV8Value(arg);
|
||||
callback->NewHandle(node_isolate)->Call(
|
||||
v8::Context::GetCurrent()->Global(), 1, &value);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#define ATOM_BROWSER_API_ATOM_API_MENU_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"
|
||||
|
||||
namespace atom {
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
#ifndef 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/power_monitor/power_observer.h"
|
||||
#include "common/api/atom_api_event_emitter.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
#include <vector>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "browser/api/atom_api_event_emitter.h"
|
||||
#include "browser/native_window_observer.h"
|
||||
#include "common/api/atom_api_event_emitter.h"
|
||||
#include "common/v8/scoped_persistent.h"
|
||||
|
||||
namespace base {
|
||||
|
|
6
browser/api/lib/atom-delegate.coffee
Normal file
6
browser/api/lib/atom-delegate.coffee
Normal file
|
@ -0,0 +1,6 @@
|
|||
module.exports =
|
||||
browserMainParts:
|
||||
preMainMessageLoopRun: ->
|
||||
|
||||
setImmediate ->
|
||||
module.exports.browserMainParts.preMainMessageLoopRun()
|
|
@ -50,8 +50,8 @@ bool AtomBrowserClient::ShouldSwapProcessesForNavigation(
|
|||
content::SiteInstance* site_instance,
|
||||
const GURL& current_url,
|
||||
const GURL& new_url) {
|
||||
// Restart renderer process if navigating to the same url.
|
||||
return current_url == new_url;
|
||||
// Restart renderer process for all navigations.
|
||||
return true;
|
||||
}
|
||||
|
||||
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
fs = require 'fs'
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
|
||||
# Expose information of current process.
|
||||
|
@ -14,12 +14,12 @@ process.argv.splice 1, 1
|
|||
globalPaths = require('module').globalPaths
|
||||
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
|
||||
# native bindings can work.
|
||||
setImmediate ->
|
||||
# Import common settings.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init.js')
|
||||
|
||||
if process.platform is 'win32'
|
||||
# Redirect node's console to use our own implementations, since node can not
|
||||
# handle console output when running as GUI program.
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.8.1</string>
|
||||
<string>0.8.5</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
|
|
@ -283,6 +283,30 @@ void NativeWindow::NotifyWindowBlur() {
|
|||
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() {
|
||||
if (!dialog_manager_)
|
||||
dialog_manager_.reset(new AtomJavaScriptDialogManager);
|
||||
|
|
|
@ -157,6 +157,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
|||
const std::vector<DraggableRegion>& regions) = 0;
|
||||
|
||||
// Implementations of content::WebContentsDelegate.
|
||||
virtual content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) OVERRIDE;
|
||||
virtual content::JavaScriptDialogManager*
|
||||
GetJavaScriptDialogManager() OVERRIDE;
|
||||
virtual void BeforeUnloadFired(content::WebContents* tab,
|
||||
|
|
|
@ -142,7 +142,7 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
|
|||
: NativeWindow(web_contents, options),
|
||||
is_kiosk_(false),
|
||||
attention_request_id_(0) {
|
||||
int width, height;
|
||||
int width = 800, height = 600;
|
||||
options->GetInteger(switches::kWidth, &width);
|
||||
options->GetInteger(switches::kHeight, &height);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
# Settings to compile node under Windows.
|
||||
'target_defaults': {
|
||||
'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': [
|
||||
4013, # 'free' undefined; assuming extern returning int
|
||||
4054, #
|
||||
|
@ -49,13 +49,14 @@
|
|||
4204, # non-constant aggregate initializer
|
||||
4214, # bit field types other than int
|
||||
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
|
||||
4389, # '==' : signed/unsigned mismatch
|
||||
4505, # unreferenced local function has been removed
|
||||
4701, # potentially uninitialized local variable 'sizew' used
|
||||
4706, # assignment within conditional expression
|
||||
4804, # unsafe use of type 'bool' in operation
|
||||
4996, #
|
||||
4804, # unsafe use of type 'bool' in operation
|
||||
4996, # this function or variable may be unsafe.
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "browser/api/atom_api_event_emitter.h"
|
||||
#include "common/api/atom_api_event_emitter.h"
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_EVENT_EMITTER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_EVENT_EMITTER_H_
|
||||
#ifndef ATOM_COMMON_API_ATOM_API_EVENT_EMITTER_H_
|
||||
#define ATOM_COMMON_API_ATOM_API_EVENT_EMITTER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -40,4 +40,4 @@ class EventEmitter : public node::ObjectWrap {
|
|||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_EVENT_EMITTER_H_
|
||||
#endif // ATOM_COMMON_API_ATOM_API_EVENT_EMITTER_H_
|
86
common/api/atom_api_screen.cc
Normal file
86
common/api/atom_api_screen.cc
Normal 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)
|
44
common/api/atom_api_screen.h
Normal file
44
common/api/atom_api_screen.h
Normal 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_
|
|
@ -16,11 +16,41 @@ namespace {
|
|||
|
||||
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; };
|
||||
|
||||
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) {
|
||||
|
@ -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);
|
||||
|
||||
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() {
|
||||
|
@ -58,6 +89,7 @@ void AtomBindings::BindTo(v8::Handle<v8::Object> process) {
|
|||
NODE_SET_METHOD(process, "activateUvLoop", ActivateUVLoop);
|
||||
NODE_SET_METHOD(process, "log", Log);
|
||||
NODE_SET_METHOD(process, "getCurrentStackTrace", GetCurrentStackTrace);
|
||||
NODE_SET_METHOD(process, "scheduleCallback", ScheduleCallback);
|
||||
|
||||
process->Get(v8::String::New("versions"))->ToObject()->
|
||||
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
|
||||
void AtomBindings::ActivateUVLoop(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
uv_async_send(&dummy_uv_handle);
|
||||
uv_async_send(&g_next_tick_uv_handle);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -146,4 +178,12 @@ void AtomBindings::GetCurrentStackTrace(
|
|||
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
|
||||
|
|
|
@ -26,6 +26,7 @@ class AtomBindings {
|
|||
static void Log(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetCurrentStackTrace(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ScheduleCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBindings);
|
||||
};
|
||||
|
|
|
@ -27,6 +27,7 @@ NODE_EXT_LIST_ITEM(atom_renderer_ipc)
|
|||
NODE_EXT_LIST_ITEM(atom_common_clipboard)
|
||||
NODE_EXT_LIST_ITEM(atom_common_crash_reporter)
|
||||
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_v8_util)
|
||||
|
||||
|
|
3
common/api/lib/screen.coffee
Normal file
3
common/api/lib/screen.coffee
Normal file
|
@ -0,0 +1,3 @@
|
|||
{Screen} = process.atomBinding 'screen'
|
||||
|
||||
module.exports = new Screen
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 8
|
||||
#define ATOM_PATCH_VERSION 1
|
||||
#define ATOM_PATCH_VERSION 5
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
|
28
common/lib/init.coffee
Normal file
28
common/lib/init.coffee
Normal 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
|
|
@ -65,7 +65,9 @@ NodeBindings::NodeBindings(bool is_browser)
|
|||
: is_browser_(is_browser),
|
||||
message_loop_(NULL),
|
||||
uv_loop_(uv_default_loop()),
|
||||
embed_closed_(false) {
|
||||
embed_closed_(false),
|
||||
uv_env_(NULL),
|
||||
weak_factory_(this) {
|
||||
}
|
||||
|
||||
NodeBindings::~NodeBindings() {
|
||||
|
@ -76,7 +78,6 @@ NodeBindings::~NodeBindings() {
|
|||
|
||||
// Wait for everything to be done.
|
||||
uv_thread_join(&embed_thread_);
|
||||
message_loop_->RunUntilIdle();
|
||||
|
||||
// Clear uv.
|
||||
uv_sem_destroy(&embed_sem_);
|
||||
|
@ -193,9 +194,13 @@ void NodeBindings::RunMessageLoop() {
|
|||
void NodeBindings::UvRunOnce() {
|
||||
DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
|
||||
// Enter node context while dealing with uv events.
|
||||
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.
|
||||
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() {
|
||||
DCHECK(message_loop_);
|
||||
message_loop_->PostTask(FROM_HERE, base::Bind(&NodeBindings::UvRunOnce,
|
||||
base::Unretained(this)));
|
||||
weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
void NodeBindings::WakeupEmbedThread() {
|
||||
|
@ -220,11 +225,20 @@ void NodeBindings::WakeupEmbedThread() {
|
|||
void NodeBindings::EmbedThreadRunner(void *arg) {
|
||||
NodeBindings* self = static_cast<NodeBindings*>(arg);
|
||||
|
||||
while (!self->embed_closed_) {
|
||||
while (true) {
|
||||
// Wait for the main loop to deal with events.
|
||||
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();
|
||||
if (self->embed_closed_)
|
||||
break;
|
||||
|
||||
// Deal with event in main thread.
|
||||
self->WakeupMainThread();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define ATOM_COMMON_NODE_BINDINGS_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "v8/include/v8.h"
|
||||
#include "vendor/node/deps/uv/include/uv.h"
|
||||
|
||||
|
@ -37,6 +38,10 @@ class NodeBindings {
|
|||
// Do message loop integration.
|
||||
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:
|
||||
explicit NodeBindings(bool is_browser);
|
||||
|
||||
|
@ -83,6 +88,11 @@ class NodeBindings {
|
|||
// Semaphore to wait for main loop in the embed thread.
|
||||
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);
|
||||
};
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
#include "common/swap_or_assign.h"
|
||||
#include "common/v8/scoped_persistent.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/size.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
// Convert V8 value to arbitrary supported types.
|
||||
|
@ -71,8 +72,9 @@ struct FromV8Value {
|
|||
converter->FromV8Value(value_, v8::Context::GetCurrent()));
|
||||
}
|
||||
|
||||
operator std::vector<std::string>() {
|
||||
std::vector<std::string> array;
|
||||
template<class T>
|
||||
operator std::vector<T>() {
|
||||
std::vector<T> array;
|
||||
v8::Handle<v8::Array> v8_array = v8::Handle<v8::Array>::Cast(value_);
|
||||
for (uint32_t i = 0; i < v8_array->Length(); ++i)
|
||||
array.push_back(FromV8Value(v8_array->Get(i)));
|
||||
|
@ -80,14 +82,15 @@ struct FromV8Value {
|
|||
return array;
|
||||
}
|
||||
|
||||
operator std::map<std::string, std::string>() {
|
||||
std::map<std::string, std::string> dict;
|
||||
template<class K, class V>
|
||||
operator std::map<K, V>() {
|
||||
std::map<K, V> dict;
|
||||
v8::Handle<v8::Object> v8_dict = value_->ToObject();
|
||||
v8::Handle<v8::Array> v8_keys = v8_dict->GetOwnPropertyNames();
|
||||
for (uint32_t i = 0; i < v8_keys->Length(); ++i) {
|
||||
v8::Handle<v8::Value> v8_key = v8_keys->Get(i);
|
||||
std::string key = FromV8Value(v8_key);
|
||||
dict[key] = std::string(FromV8Value(v8_dict->Get(v8_key)));
|
||||
K key = FromV8Value(v8_key);
|
||||
dict[key] = V(FromV8Value(v8_dict->Get(v8_key)));
|
||||
}
|
||||
|
||||
return dict;
|
||||
|
@ -121,6 +124,14 @@ inline v8::Handle<v8::Value> ToV8Value(bool 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) {
|
||||
return v8::String::New(s);
|
||||
}
|
||||
|
@ -146,14 +157,37 @@ inline v8::Handle<v8::Value> ToV8Value(void* whatever) {
|
|||
return v8::Undefined();
|
||||
}
|
||||
|
||||
inline
|
||||
v8::Handle<v8::Value> ToV8Value(const std::vector<base::FilePath>& paths) {
|
||||
v8::Handle<v8::Array> result = v8::Array::New(paths.size());
|
||||
for (size_t i = 0; i < paths.size(); ++i)
|
||||
result->Set(i, ToV8Value(paths[i]));
|
||||
template<class T> inline
|
||||
v8::Handle<v8::Value> ToV8Value(const std::vector<T>& arr) {
|
||||
v8::Handle<v8::Array> result = v8::Array::New(arr.size());
|
||||
for (size_t i = 0; i < arr.size(); ++i)
|
||||
result->Set(i, ToV8Value(arr[i]));
|
||||
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.
|
||||
template<class T> inline
|
||||
bool V8ValueCanBeConvertedTo(v8::Handle<v8::Value> value) {
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
// Include common headers for using node APIs.
|
||||
|
||||
#undef CHECK
|
||||
#undef CHECK_EQ
|
||||
#undef CHECK_NE
|
||||
#undef DISALLOW_COPY_AND_ASSIGN
|
||||
#include "vendor/node/src/env.h"
|
||||
#include "vendor/node/src/env-inl.h"
|
||||
|
|
|
@ -35,4 +35,5 @@ Common modules:
|
|||
|
||||
* [clipboard](api/common/clipboard.md)
|
||||
* [crash-reporter](api/common/crash-reporter.md)
|
||||
* [screen](api/common/screen.md)
|
||||
* [shell](api/common/shell.md)
|
||||
|
|
11
docs/api/common/screen.md
Normal file
11
docs/api/common/screen.md
Normal 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.
|
|
@ -1,14 +1,17 @@
|
|||
{
|
||||
"name": "atom-shell",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.5",
|
||||
|
||||
"devDependencies": {
|
||||
"coffee-script": "~1.6.3",
|
||||
"coffeelint": "~0.6.1",
|
||||
"mocha": "~1.13.0",
|
||||
"pathwatcher": "0.14.0",
|
||||
"q": "0.9.7",
|
||||
"walkdir": "~0.0.7",
|
||||
"runas": "0.3.0",
|
||||
"formidable": "~1.0.14"
|
||||
"formidable": "~1.0.14",
|
||||
"temp": "~0.6.0"
|
||||
},
|
||||
|
||||
"private": true,
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "renderer/atom_renderer_client.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/node_bindings.h"
|
||||
#include "renderer/api/atom_renderer_bindings.h"
|
||||
#include "renderer/atom_render_view_observer.h"
|
||||
|
@ -51,10 +53,17 @@ void AtomRendererClient::DidCreateScriptContext(WebKit::WebFrame* frame,
|
|||
node_bindings_->RunMessageLoop();
|
||||
|
||||
// Setup node environment for each window.
|
||||
node_bindings_->CreateEnvironment(context);
|
||||
node::Environment* env = node_bindings_->CreateEnvironment(context);
|
||||
|
||||
// Add atom-shell extended APIs.
|
||||
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(
|
||||
|
@ -67,7 +76,36 @@ void AtomRendererClient::WillReleaseScriptContext(
|
|||
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
|
||||
|
|
|
@ -5,8 +5,14 @@
|
|||
#ifndef ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_
|
||||
#define ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "content/public/renderer/content_renderer_client.h"
|
||||
|
||||
namespace node {
|
||||
class Environment;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomRendererBindings;
|
||||
|
@ -29,6 +35,14 @@ class AtomRendererClient : public content::ContentRendererClient {
|
|||
virtual void WillReleaseScriptContext(WebKit::WebFrame* frame,
|
||||
v8::Handle<v8::Context>,
|
||||
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<AtomRendererBindings> atom_bindings_;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
path = require 'path'
|
||||
timers = require 'timers'
|
||||
Module = require 'module'
|
||||
|
||||
# Expose information of current process.
|
||||
|
@ -14,29 +13,16 @@ process.argv.splice 1, 1
|
|||
# of Atom's built-in libraries.
|
||||
globalPaths = Module.globalPaths
|
||||
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.
|
||||
globalPaths.push path.join(process.resourcesPath, 'app')
|
||||
|
||||
# Import common settings.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init.js')
|
||||
|
||||
# Expose global variables.
|
||||
global.require = require
|
||||
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.
|
||||
if window.location.protocol is 'file:'
|
||||
global.__filename =
|
||||
|
@ -46,6 +32,9 @@ if window.location.protocol is 'file:'
|
|||
window.location.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
|
||||
|
|
|
@ -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()
|
||||
NODE_VERSION = 'v0.11.9'
|
||||
NODE_VERSION = 'v0.11.10'
|
||||
BASE_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent'
|
||||
|
||||
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
|
|
@ -21,7 +21,7 @@ TARGET_PLATFORM = {
|
|||
|
||||
ATOM_SHELL_REPO = 'atom/atom-shell'
|
||||
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__)))
|
||||
OUT_DIR = os.path.join(SOURCE_ROOT, 'out', 'Release')
|
||||
|
|
16
spec/api-screen-spec.coffee
Normal file
16
spec/api-screen-spec.coffee
Normal 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
|
|
@ -1,9 +1,11 @@
|
|||
assert = require 'assert'
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
temp = require 'temp'
|
||||
|
||||
describe 'third-party module', ->
|
||||
fixtures = path.join __dirname, 'fixtures'
|
||||
temp.track()
|
||||
|
||||
describe 'runas', ->
|
||||
it 'can be required in renderer', ->
|
||||
|
@ -15,3 +17,25 @@ describe 'third-party module', ->
|
|||
child.on 'message', (msg) ->
|
||||
assert.equal msg, 'ok'
|
||||
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()
|
||||
|
|
|
@ -37,6 +37,11 @@ describe 'node feature', ->
|
|||
fs.readFile __filename, ->
|
||||
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', ->
|
||||
it 'gets caught', (done) ->
|
||||
error = new Error('boo!')
|
||||
|
|
2
vendor/apm
vendored
2
vendor/apm
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 89f678cc34850ffa0163c4ac485336d40c72bb86
|
||||
Subproject commit 35edbb07fb4abba49dd97d12a1ad8c4adb71625f
|
2
vendor/node
vendored
2
vendor/node
vendored
|
@ -1 +1 @@
|
|||
Subproject commit b5bbfb6a7d66750c21bf654e973f47f1178adced
|
||||
Subproject commit 184a341c2b959a092f64b168e3d55b11d13583bf
|
Loading…
Reference in a new issue