Merge remote-tracking branch 'electron/master' into certificate-addition-windows
This commit is contained in:
commit
253a4b0114
21 changed files with 240 additions and 91 deletions
|
@ -655,6 +655,14 @@ void App::OnGpuProcessCrashed(base::TerminationStatus status) {
|
|||
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
|
||||
}
|
||||
|
||||
base::FilePath App::GetAppPath() const {
|
||||
return app_path_;
|
||||
}
|
||||
|
||||
void App::SetAppPath(const base::FilePath& app_path) {
|
||||
app_path_ = app_path;
|
||||
}
|
||||
|
||||
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
|
||||
bool succeed = false;
|
||||
base::FilePath path;
|
||||
|
@ -959,6 +967,8 @@ void App::BuildPrototype(
|
|||
.SetMethod("isUnityRunning",
|
||||
base::Bind(&Browser::IsUnityRunning, browser))
|
||||
#endif
|
||||
.SetMethod("setAppPath", &App::SetAppPath)
|
||||
.SetMethod("getAppPath", &App::GetAppPath)
|
||||
.SetMethod("setPath", &App::SetPath)
|
||||
.SetMethod("getPath", &App::GetPath)
|
||||
.SetMethod("setDesktopName", &App::SetDesktopName)
|
||||
|
|
|
@ -70,6 +70,8 @@ class App : public AtomBrowserClient::Delegate,
|
|||
std::unique_ptr<CertificateManagerModel> model);
|
||||
#endif
|
||||
|
||||
base::FilePath GetAppPath() const;
|
||||
|
||||
protected:
|
||||
explicit App(v8::Isolate* isolate);
|
||||
~App() override;
|
||||
|
@ -115,6 +117,8 @@ class App : public AtomBrowserClient::Delegate,
|
|||
void OnGpuProcessCrashed(base::TerminationStatus status) override;
|
||||
|
||||
private:
|
||||
void SetAppPath(const base::FilePath& app_path);
|
||||
|
||||
// Get/Set the pre-defined path in PathService.
|
||||
base::FilePath GetPath(mate::Arguments* args, const std::string& name);
|
||||
void SetPath(mate::Arguments* args,
|
||||
|
@ -154,6 +158,8 @@ class App : public AtomBrowserClient::Delegate,
|
|||
// Tracks tasks requesting file icons.
|
||||
base::CancelableTaskTracker cancelable_task_tracker_;
|
||||
|
||||
base::FilePath app_path_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(App);
|
||||
};
|
||||
|
||||
|
|
|
@ -263,6 +263,14 @@ void Window::OnWindowSwipe(const std::string& direction) {
|
|||
Emit("swipe", direction);
|
||||
}
|
||||
|
||||
void Window::OnWindowSheetBegin() {
|
||||
Emit("sheet-begin");
|
||||
}
|
||||
|
||||
void Window::OnWindowSheetEnd() {
|
||||
Emit("sheet-end");
|
||||
}
|
||||
|
||||
void Window::OnWindowEnterHtmlFullScreen() {
|
||||
Emit("enter-html-full-screen");
|
||||
}
|
||||
|
|
|
@ -79,6 +79,8 @@ class Window : public mate::TrackableObject<Window>,
|
|||
void OnWindowScrollTouchEnd() override;
|
||||
void OnWindowScrollTouchEdge() override;
|
||||
void OnWindowSwipe(const std::string& direction) override;
|
||||
void OnWindowSheetBegin() override;
|
||||
void OnWindowSheetEnd() override;
|
||||
void OnWindowEnterFullScreen() override;
|
||||
void OnWindowLeaveFullScreen() override;
|
||||
void OnWindowEnterHtmlFullScreen() override;
|
||||
|
|
|
@ -235,6 +235,11 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
|||
}
|
||||
#endif
|
||||
|
||||
if (delegate_) {
|
||||
auto app_path = static_cast<api::App*>(delegate_)->GetAppPath();
|
||||
command_line->AppendSwitchPath(switches::kAppPath, app_path);
|
||||
}
|
||||
|
||||
content::WebContents* web_contents = GetWebContentsFromProcessID(process_id);
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
|
|
@ -554,6 +554,16 @@ void NativeWindow::NotifyWindowSwipe(const std::string& direction) {
|
|||
observer.OnWindowSwipe(direction);
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowSheetBegin() {
|
||||
for (NativeWindowObserver& observer : observers_)
|
||||
observer.OnWindowSheetBegin();
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowSheetEnd() {
|
||||
for (NativeWindowObserver& observer : observers_)
|
||||
observer.OnWindowSheetEnd();
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowLeaveFullScreen() {
|
||||
for (NativeWindowObserver& observer : observers_)
|
||||
observer.OnWindowLeaveFullScreen();
|
||||
|
|
|
@ -233,6 +233,8 @@ class NativeWindow : public base::SupportsUserData,
|
|||
void NotifyWindowScrollTouchEnd();
|
||||
void NotifyWindowScrollTouchEdge();
|
||||
void NotifyWindowSwipe(const std::string& direction);
|
||||
void NotifyWindowSheetBegin();
|
||||
void NotifyWindowSheetEnd();
|
||||
void NotifyWindowEnterFullScreen();
|
||||
void NotifyWindowLeaveFullScreen();
|
||||
void NotifyWindowEnterHtmlFullScreen();
|
||||
|
|
|
@ -313,6 +313,14 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
return rect;
|
||||
}
|
||||
|
||||
- (void)windowWillBeginSheet:(NSNotification *)notification {
|
||||
shell_->NotifyWindowSheetBegin();
|
||||
}
|
||||
|
||||
- (void)windowDidEndSheet:(NSNotification *)notification {
|
||||
shell_->NotifyWindowSheetEnd();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface AtomPreviewItem : NSObject <QLPreviewItem>
|
||||
|
|
|
@ -67,6 +67,8 @@ class NativeWindowObserver {
|
|||
virtual void OnWindowScrollTouchEnd() {}
|
||||
virtual void OnWindowScrollTouchEdge() {}
|
||||
virtual void OnWindowSwipe(const std::string& direction) {}
|
||||
virtual void OnWindowSheetBegin() {}
|
||||
virtual void OnWindowSheetEnd() {}
|
||||
virtual void OnWindowEnterFullScreen() {}
|
||||
virtual void OnWindowLeaveFullScreen() {}
|
||||
virtual void OnWindowEnterHtmlFullScreen() {}
|
||||
|
|
|
@ -159,6 +159,9 @@ const char kSecureSchemes[] = "secure-schemes";
|
|||
// The browser process app model ID
|
||||
const char kAppUserModelId[] = "app-user-model-id";
|
||||
|
||||
// The application path
|
||||
const char kAppPath[] = "app-path";
|
||||
|
||||
// The command line switch versions of the options.
|
||||
const char kBackgroundColor[] = "background-color";
|
||||
const char kPreloadScript[] = "preload";
|
||||
|
|
|
@ -81,6 +81,7 @@ extern const char kStandardSchemes[];
|
|||
extern const char kRegisterServiceWorkerSchemes[];
|
||||
extern const char kSecureSchemes[];
|
||||
extern const char kAppUserModelId[];
|
||||
extern const char kAppPath[];
|
||||
|
||||
extern const char kBackgroundColor[];
|
||||
extern const char kPreloadScript[];
|
||||
|
|
|
@ -498,6 +498,14 @@ Returns:
|
|||
|
||||
Emitted on 3-finger swipe. Possible directions are `up`, `right`, `down`, `left`.
|
||||
|
||||
#### Event: 'sheet-begin' _macOS_
|
||||
|
||||
Emitted when the window opens a sheet.
|
||||
|
||||
#### Event: 'sheet-end' _macOS_
|
||||
|
||||
Emitted when the window has closed a sheet.
|
||||
|
||||
### Static Methods
|
||||
|
||||
The `BrowserWindow` class has the following static methods:
|
||||
|
|
|
@ -28,6 +28,10 @@ effect on macOS.
|
|||
|
||||
Returns `Menu` - The application menu, if set, or `null`, if not set.
|
||||
|
||||
**Note:** The returned `Menu` instance doesn't support dynamic addition or
|
||||
removal of menu items. [Instance properties](#instance-properties) can still
|
||||
be dynamically modified.
|
||||
|
||||
#### `Menu.sendActionToFirstResponder(action)` _macOS_
|
||||
|
||||
* `action` String
|
||||
|
|
|
@ -12,7 +12,8 @@ rendered.
|
|||
Unlike an `iframe`, the `webview` runs in a separate process than your
|
||||
app. It doesn't have the same permissions as your web page and all interactions
|
||||
between your app and embedded content will be asynchronous. This keeps your app
|
||||
safe from the embedded content.
|
||||
safe from the embedded content. **Note:** Most methods called on the
|
||||
webview from the host page require a syncronous call to the main process.
|
||||
|
||||
For security purposes, `webview` can only be used in `BrowserWindow`s that have
|
||||
`nodeIntegration` enabled.
|
||||
|
|
|
@ -10,6 +10,9 @@ Follow the guidelines below for building Electron on Windows.
|
|||
* [Python 2.7](http://www.python.org/download/releases/2.7/)
|
||||
* [Node.js](http://nodejs.org/download/)
|
||||
* [Git](http://git-scm.com)
|
||||
* [Debugging Tools for Windows](https://msdn.microsoft.com/en-us/library/windows/hardware/ff551063.aspx)
|
||||
if you plan on creating a full distribution since `symstore.exe` is used for
|
||||
creating a symbol store from `.pdb` files.
|
||||
|
||||
If you don't currently have a Windows installation,
|
||||
[dev.microsoftedge.com](https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/)
|
||||
|
|
|
@ -12,11 +12,7 @@ const {EventEmitter} = require('events')
|
|||
|
||||
Object.setPrototypeOf(App.prototype, EventEmitter.prototype)
|
||||
|
||||
let appPath = null
|
||||
|
||||
Object.assign(app, {
|
||||
getAppPath () { return appPath },
|
||||
setAppPath (path) { appPath = path },
|
||||
setApplicationMenu (menu) {
|
||||
return Menu.setApplicationMenu(menu)
|
||||
},
|
||||
|
|
|
@ -56,6 +56,7 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (ev
|
|||
let nodeIntegration = 'false'
|
||||
let preloadScript = null
|
||||
let isBackgroundPage = false
|
||||
let appPath = null
|
||||
for (let arg of process.argv) {
|
||||
if (arg.indexOf('--guest-instance-id=') === 0) {
|
||||
// This is a guest web view.
|
||||
|
@ -69,6 +70,8 @@ for (let arg of process.argv) {
|
|||
preloadScript = arg.substr(arg.indexOf('=') + 1)
|
||||
} else if (arg === '--background-page') {
|
||||
isBackgroundPage = true
|
||||
} else if (arg.indexOf('--app-path=') === 0) {
|
||||
appPath = arg.substr(arg.indexOf('=') + 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,6 +119,11 @@ if (nodeIntegration === 'true') {
|
|||
} else {
|
||||
global.__filename = __filename
|
||||
global.__dirname = __dirname
|
||||
|
||||
if (appPath) {
|
||||
// Search for module under the app directory
|
||||
module.paths = module.paths.concat(Module._nodeModulePaths(appPath))
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect window.onerror to uncaughtException.
|
||||
|
|
|
@ -86,8 +86,6 @@ def main():
|
|||
run_script('create-dist.py')
|
||||
run_script('upload.py')
|
||||
else:
|
||||
if PLATFORM == 'win32':
|
||||
os.environ['OUTPUT_TO_FILE'] = 'output.log'
|
||||
run_script('build.py', ['-c', 'D'])
|
||||
if PLATFORM == 'win32' or target_arch == 'x64':
|
||||
run_script('test.py', ['--ci'])
|
||||
|
|
|
@ -1191,6 +1191,54 @@ describe('BrowserWindow module', function () {
|
|||
})
|
||||
})
|
||||
|
||||
describe('sheet-begin event', function () {
|
||||
if (process.platform !== 'darwin') {
|
||||
return
|
||||
}
|
||||
|
||||
let sheet = null
|
||||
|
||||
afterEach(function () {
|
||||
return closeWindow(sheet, {assertSingleWindow: false}).then(function () { sheet = null })
|
||||
})
|
||||
|
||||
it('emits when window opens a sheet', function (done) {
|
||||
w.show()
|
||||
w.once('sheet-begin', function () {
|
||||
sheet.close()
|
||||
done()
|
||||
})
|
||||
sheet = new BrowserWindow({
|
||||
modal: true,
|
||||
parent: w
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('sheet-end event', function () {
|
||||
if (process.platform !== 'darwin') {
|
||||
return
|
||||
}
|
||||
|
||||
let sheet = null
|
||||
|
||||
afterEach(function () {
|
||||
return closeWindow(sheet, {assertSingleWindow: false}).then(function () { sheet = null })
|
||||
})
|
||||
|
||||
it('emits when window has closed a sheet', function (done) {
|
||||
w.show()
|
||||
sheet = new BrowserWindow({
|
||||
modal: true,
|
||||
parent: w
|
||||
})
|
||||
w.once('sheet-end', function () {
|
||||
done()
|
||||
})
|
||||
sheet.close()
|
||||
})
|
||||
})
|
||||
|
||||
describe('beginFrameSubscription method', function () {
|
||||
// This test is too slow, only test it on CI.
|
||||
if (!isCI) return
|
||||
|
|
|
@ -1,60 +1,63 @@
|
|||
const assert = require('assert')
|
||||
const Module = require('module')
|
||||
const path = require('path')
|
||||
const temp = require('temp')
|
||||
const {remote} = require('electron')
|
||||
const {BrowserWindow} = remote
|
||||
const {closeWindow} = require('./window-helpers')
|
||||
|
||||
describe('third-party module', function () {
|
||||
describe('modules support', function () {
|
||||
var fixtures = path.join(__dirname, 'fixtures')
|
||||
temp.track()
|
||||
|
||||
if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) {
|
||||
describe('runas', function () {
|
||||
it('can be required in renderer', function () {
|
||||
require('runas')
|
||||
describe('third-party module', function () {
|
||||
if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) {
|
||||
describe('runas', function () {
|
||||
it('can be required in renderer', function () {
|
||||
require('runas')
|
||||
})
|
||||
|
||||
it('can be required in node binary', function (done) {
|
||||
var runas = path.join(fixtures, 'module', 'runas.js')
|
||||
var child = require('child_process').fork(runas)
|
||||
child.on('message', function (msg) {
|
||||
assert.equal(msg, 'ok')
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('can be required in node binary', function (done) {
|
||||
var runas = path.join(fixtures, 'module', 'runas.js')
|
||||
var child = require('child_process').fork(runas)
|
||||
child.on('message', function (msg) {
|
||||
assert.equal(msg, 'ok')
|
||||
done()
|
||||
describe('ffi', function () {
|
||||
if (process.platform === 'win32') return
|
||||
|
||||
it('does not crash', function () {
|
||||
var ffi = require('ffi')
|
||||
var libm = ffi.Library('libm', {
|
||||
ceil: ['double', ['double']]
|
||||
})
|
||||
assert.equal(libm.ceil(1.5), 2)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe('q', function () {
|
||||
var Q = require('q')
|
||||
describe('Q.when', function () {
|
||||
it('emits the fullfil callback', function (done) {
|
||||
Q(true).then(function (val) {
|
||||
assert.equal(val, true)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('ffi', function () {
|
||||
if (process.platform === 'win32') return
|
||||
|
||||
it('does not crash', function () {
|
||||
var ffi = require('ffi')
|
||||
var libm = ffi.Library('libm', {
|
||||
ceil: ['double', ['double']]
|
||||
describe('coffee-script', function () {
|
||||
it('can be registered and used to require .coffee files', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
require('coffee-script').register()
|
||||
})
|
||||
assert.equal(libm.ceil(1.5), 2)
|
||||
assert.strictEqual(require('./fixtures/module/test.coffee'), true)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe('q', function () {
|
||||
var Q = require('q')
|
||||
describe('Q.when', function () {
|
||||
it('emits the fullfil callback', function (done) {
|
||||
Q(true).then(function (val) {
|
||||
assert.equal(val, true)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('coffee-script', function () {
|
||||
it('can be registered and used to require .coffee files', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
require('coffee-script').register()
|
||||
})
|
||||
assert.strictEqual(require('./fixtures/module/test.coffee'), true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('global variables', function () {
|
||||
|
@ -76,56 +79,79 @@ describe('third-party module', function () {
|
|||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Module._nodeModulePaths', function () {
|
||||
describe('when the path is inside the resources path', function () {
|
||||
it('does not include paths outside of the resources path', function () {
|
||||
let modulePath = process.resourcesPath
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
describe('Module._nodeModulePaths', function () {
|
||||
describe('when the path is inside the resources path', function () {
|
||||
it('does not include paths outside of the resources path', function () {
|
||||
let modulePath = process.resourcesPath
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
|
||||
modulePath = process.resourcesPath + '-foo'
|
||||
let nodeModulePaths = Module._nodeModulePaths(modulePath)
|
||||
assert(nodeModulePaths.includes(path.join(modulePath, 'node_modules')))
|
||||
assert(nodeModulePaths.includes(path.join(modulePath, '..', 'node_modules')))
|
||||
modulePath = process.resourcesPath + '-foo'
|
||||
let nodeModulePaths = Module._nodeModulePaths(modulePath)
|
||||
assert(nodeModulePaths.includes(path.join(modulePath, 'node_modules')))
|
||||
assert(nodeModulePaths.includes(path.join(modulePath, '..', 'node_modules')))
|
||||
|
||||
modulePath = path.join(process.resourcesPath, 'foo')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'foo', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
modulePath = path.join(process.resourcesPath, 'foo')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'foo', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
|
||||
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
|
||||
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'bar')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'bar', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'bar')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'bar', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
|
||||
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
|
||||
path.join(process.resourcesPath, 'node_modules')
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the path is outside the resources path', function () {
|
||||
it('includes paths outside of the resources path', function () {
|
||||
let modulePath = path.resolve('/foo')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(modulePath, 'node_modules'),
|
||||
path.resolve('/node_modules')
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the path is outside the resources path', function () {
|
||||
it('includes paths outside of the resources path', function () {
|
||||
let modulePath = path.resolve('/foo')
|
||||
assert.deepEqual(Module._nodeModulePaths(modulePath), [
|
||||
path.join(modulePath, 'node_modules'),
|
||||
path.resolve('/node_modules')
|
||||
])
|
||||
describe('require', () => {
|
||||
describe('when loaded URL is not file: protocol', () => {
|
||||
let w
|
||||
|
||||
beforeEach(() => {
|
||||
w = new BrowserWindow({
|
||||
show: false
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await closeWindow(w)
|
||||
w = null
|
||||
})
|
||||
|
||||
it('searches for module under app directory', async () => {
|
||||
w.loadURL('about:blank')
|
||||
const result = await w.webContents.executeJavaScript('typeof require("q").when')
|
||||
assert.equal(result, 'function')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -85,7 +85,7 @@ describe('node feature', function () {
|
|||
child.stdout.on('data', (chunk) => {
|
||||
data += String(chunk)
|
||||
})
|
||||
child.on('exit', (code) => {
|
||||
child.on('close', (code) => {
|
||||
assert.equal(code, 0)
|
||||
assert.equal(data, 'pipes stdio')
|
||||
done()
|
||||
|
|
Loading…
Reference in a new issue