From 4a6a7bbe1bd400c3fba1401a541e6f8a4fac2414 Mon Sep 17 00:00:00 2001 From: Kleak Date: Wed, 14 Sep 2016 21:48:16 +0200 Subject: [PATCH] first version on github for older version see the gitlab repos here https://gitlab.com/grimshield/nodejs.dart --- .analysis_options | 45 +++ .gitignore | 25 ++ AUTHORS | 7 + CHANGELOG.md | 15 + LICENSE | 24 ++ README.md | 7 + lib/nodejs.dart | 50 +++ lib/src/buffer.dart | 123 +++++++ lib/src/child_process.dart | 630 ++++++++++++++++++++++++++++++++ lib/src/errors/error.dart | 76 ++++ lib/src/errors/range_error.dart | 36 ++ lib/src/events.dart | 68 ++++ lib/src/fs.dart | 339 +++++++++++++++++ lib/src/module.dart | 35 ++ lib/src/object.dart | 107 ++++++ lib/src/process.dart | 196 ++++++++++ lib/src/stream.dart | 16 + lib/src/stream/duplex.dart | 98 +++++ lib/src/stream/readable.dart | 79 ++++ lib/src/stream/writable.dart | 76 ++++ lib/src/util.dart | 53 +++ lib/src/utils.dart | 10 + lib/transformer.dart | 57 +++ pubspec.yaml | 15 + test/node_dart_test.dart | 9 + 25 files changed, 2196 insertions(+) create mode 100644 .analysis_options create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 lib/nodejs.dart create mode 100644 lib/src/buffer.dart create mode 100644 lib/src/child_process.dart create mode 100644 lib/src/errors/error.dart create mode 100644 lib/src/errors/range_error.dart create mode 100644 lib/src/events.dart create mode 100644 lib/src/fs.dart create mode 100644 lib/src/module.dart create mode 100644 lib/src/object.dart create mode 100644 lib/src/process.dart create mode 100644 lib/src/stream.dart create mode 100644 lib/src/stream/duplex.dart create mode 100644 lib/src/stream/readable.dart create mode 100644 lib/src/stream/writable.dart create mode 100644 lib/src/util.dart create mode 100644 lib/src/utils.dart create mode 100644 lib/transformer.dart create mode 100644 pubspec.yaml create mode 100644 test/node_dart_test.dart diff --git a/.analysis_options b/.analysis_options new file mode 100644 index 0000000..a4f14e3 --- /dev/null +++ b/.analysis_options @@ -0,0 +1,45 @@ +# Supported lint rules and documentation: http://dart-lang.github.io/linter/lints/ +linter: + rules: + - always_declare_return_types + - always_specify_types + - annotate_overrides + # - avoid_as + - avoid_init_to_null + - avoid_empty_else + - avoid_return_types_on_setters + - await_only_futures + - camel_case_types + - comment_references + - constant_identifier_names + - control_flow_in_finally + - empty_constructor_bodies + - hash_and_equals + - implementation_imports + - iterable_contains_unrelated_type + - library_names + - library_prefixes + - non_constant_identifier_names + - one_member_abstracts + # - overridden_fields + - package_api_docs + - package_prefixed_library_names + - prefer_is_not_empty + # - public_member_api_docs + - slash_for_doc_comments + - sort_constructors_first + - sort_unnamed_constructors_first + - super_goes_last + - test_types_in_equals + - throw_in_finally + - type_annotate_public_apis + - type_init_formals + - unnecessary_brace_in_string_interp + - unnecessary_getters_setters + - unrelated_type_equality_checks + - package_names + +analyzer: + strong-mode: + implicit-casts: false + implicit-dynamic: false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa53169 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Files and directories created by pub +.packages +.pub/ +build/ +packages +pubspec.lock + +# Files created by dart2js +*.dart.js +*.part.js +*.js.deps +*.js.map +*.info.json + +# Directory created by dartdoc +doc/api/ + +# JetBrains IDEs +.idea/ +*.iml +*.ipr +*.iws + +# Atom +.atom diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..b60a85c --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +# Below is a list of people and organizations that have contributed +# to the nodejs.dart project. Names should be added to the list like so: +# +# Name/Organization + +GrimShield +Kevin Segaud diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..003abab --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +## 0.0.1 + +**Warning:** This is the first commit. + +This commit include a wrap of the class listed below: + - all `Readable` + - all `Writable` + - all `Duplex` + - all `File System` excluding `FSWatcher` + - all `Process` + - all `Child Process` + - all `Module` + - part of `Buffer` diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c7ac348 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2016, GrimShield. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of GrimShield nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL GrimShield BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b827a76 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# nodejs.dart + +nodejs.dart is a wrapper of the nodejs API in dart + +## Warning + +This is under development so if you have suggestion on the existing API or you find a bug don't hesitate to fill an issue :) diff --git a/lib/nodejs.dart b/lib/nodejs.dart new file mode 100644 index 0000000..3680107 --- /dev/null +++ b/lib/nodejs.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +@JS() +library nodejs; + +import "dart:async"; +import "dart:convert"; +import "dart:typed_data"; + +import "package:js/js.dart"; + +part "src/utils.dart"; +part "src/object.dart"; +part "src/module.dart"; + +part "src/util.dart"; + +part "src/buffer.dart"; + +part "src/errors/error.dart"; +part "src/errors/range_error.dart"; + +part "src/events.dart"; + +part "src/stream.dart"; +part "src/stream/readable.dart"; +part "src/stream/writable.dart"; +part "src/stream/duplex.dart"; + +part "src/process.dart"; + +part "src/child_process.dart"; + +part "src/fs.dart"; + +@JS('nodejs.filename') +external String get filename; + +@JS('nodejs.dirname') +external String get dirname; + +@JS('nodejs.require') +external dynamic require(String id); + +@JS('JSON.stringify') +external String stringify(NativeJsObject object); + +@JS('JSON.parse') +external NativeJsObject parse(String json); diff --git a/lib/src/buffer.dart b/lib/src/buffer.dart new file mode 100644 index 0000000..bc95d20 --- /dev/null +++ b/lib/src/buffer.dart @@ -0,0 +1,123 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS('setObjectValueAtIndex') +external void _setObjectValueAtIndex(dynamic object, int index, dynamic value); +@JS('getObjectValueAtIndex') +external void _getObjectValueAtIndex(dynamic object, int index); + +@JS('Buffer.compare') +external int _bufferCompare(NativeJsBuffer buffer1, NativeJsBuffer buffer2); + +@JS('Buffer') +class NativeJsBuffer { + external static NativeJsBuffer from(dynamic arg1, + [dynamic arg2, dynamic arg3]); + external static NativeJsBuffer alloc(int size, + [dynamic fill, String encoding]); + external static NativeJsBuffer allocUnsafe(int size); + + external static int byteLength(dynamic object, String encoding); + external static NativeJsBuffer concat(List buffers, + [int totalLength]); + external static bool isBuffer(dynamic object); + external static bool isEncoding(String encoding); + + external int compare(NativeJsBuffer otherBuffer); + external int copy(NativeJsBuffer targetBuffer, + [int targetStart, int sourceStart, int sourceEnd]); + external Iterator entries(); + + external int get length; + + @override + external String toString([String encoding = 'utf8', int start = 0, int end]); +} + +class BufferEncoding { + static const String ascii = 'ascii'; + static const String utf8 = 'utf8'; + static const String utf16le = 'utf16le'; + static const String binary = 'binary'; + static const String hex = 'hex'; +} + +class Buffer { + NativeJsBuffer _buffer; + + Buffer.alloc(int size, [dynamic fill = null, String encoding = 'utf8']) { + _buffer = NativeJsBuffer.alloc(size, fill, encoding); + } + + Buffer.allocUnsafe(int size) { + _buffer = NativeJsBuffer.allocUnsafe(size); + } + + Buffer.fromList(List list) { + _buffer = NativeJsBuffer.from(list); + } + + Buffer.fromArrayBuffer(ByteBuffer byteBuffer, + [int byteOffset = 0, int length]) { + if (length == null) length = byteBuffer.lengthInBytes - byteOffset; + _buffer = NativeJsBuffer.from(byteBuffer); + } + + Buffer.fromBuffer(Buffer buffer) { + _buffer = NativeJsBuffer.from(buffer._buffer); + } + + Buffer.fromStringWithEncoding(String str, [String encoding = 'utf8']) { + _buffer = NativeJsBuffer.from(str, encoding); + } + + Buffer.FromNativeJsBuffer(this._buffer); + + static int byteLength(dynamic object, [String encoding = 'utf8']) => + NativeJsBuffer.byteLength(object, encoding); + static int compareTwoBuffer(Buffer buffer1, Buffer buffer2) => + _bufferCompare(buffer1._buffer, buffer2._buffer); + static Buffer concat(List buffers, [int totalLength]) { + List jsBuffers = + buffers.map((Buffer buffer) => buffer._buffer); + return new Buffer.FromNativeJsBuffer( + NativeJsBuffer.concat(jsBuffers, totalLength)); + } + + static bool isBuffer(dynamic object) => NativeJsBuffer.isBuffer(object); + static bool isEncoding(String encoding) => + NativeJsBuffer.isEncoding(encoding); + + void operator []=(int index, dynamic value) { + _setObjectValueAtIndex(_buffer, index, value); + } + + dynamic operator [](int index) { + return _getObjectValueAtIndex(_buffer, index); + } + + int compare(Buffer otherBuffer) => _buffer.compare(otherBuffer._buffer); + + int copy(Buffer targetBuffer, + [int targetStart = 0, int sourceStart = 0, int sourceEnd]) { + if (sourceEnd == null) sourceEnd = length; + return _buffer.copy( + targetBuffer._buffer, targetStart, sourceStart, sourceEnd); + } + + Iterable entries() sync* { + for (int i = 0; i < length; i++) { + yield [i, this[i]]; + } + } + + int get length => _buffer.length; + + @override + String toString([String encoding = 'utf8', int start = 0, int end]) { + if (end == null) end = _buffer.length; + return _buffer.toString(encoding, start, end); + } +} diff --git a/lib/src/child_process.dart b/lib/src/child_process.dart new file mode 100644 index 0000000..4fa333d --- /dev/null +++ b/lib/src/child_process.dart @@ -0,0 +1,630 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS("_child_process") +external NativeJsObject get _childProcess; +@JS("_child_process") +external set _childProcess(NativeJsObject value); + +void _requireChildProcess() { + _requireEvents(); + if (_childProcess == null) { + _childProcess = require("child_process"); + } +} + +@JS() +@anonymous +class NativeJsChildProcessExecOptions { + external const factory NativeJsChildProcessExecOptions( + {String cwd, + NativeJsObject env, + String encoding: "utf8", + String shell: "/bin/sh", + int timeout: 0, + int maxBuffer: 204800, + String killSignal: "SIGTERM", + int uid, + int gid}); + + external String get cwd; + external NativeJsObject get env; + external String get encoding; + external String get shell; + external int get timeout; + external int get maxBuffer; + external String get killSignal; + external int get uid; + external int get gid; +} + +class ChildProcessExecOptions { + final NativeJsChildProcessExecOptions _options; + + ChildProcessExecOptions( + {String cwd, + DartJsObject env, + String encoding: "utf8", + String shell: "/bin/sh", + int timeout: 0, + int maxBuffer: 204800, + String killSignal: "SIGTERM", + int uid, + int gid}) + : _options = new NativeJsChildProcessExecOptions( + cwd: cwd, + env: env?.jsObject, + encoding: encoding, + shell: shell, + timeout: timeout, + maxBuffer: maxBuffer, + killSignal: killSignal, + uid: uid, + gid: gid); +} + +final ChildProcessExecOptions _defaultChildProcessExecOptions = + new ChildProcessExecOptions(); + +@JS('_child_process.exec') +external NativeJsChildProcess _exec(String command, + [NativeJsChildProcessExecOptions options, Function callback]); + +ChildProcess exec(String command, + {ChildProcessExecOptions options: null, Function callback: null}) { + _requireChildProcess(); + if (options == null) options = _defaultChildProcessExecOptions; + ChildProcess child; + if (callback == null) { + if (options == null) { + child = new ChildProcess.fromNativeJsChildProcess(_exec(command)); + } else { + child = new ChildProcess.fromNativeJsChildProcess( + _exec(command, options._options)); + } + } else { + child = new ChildProcess.fromNativeJsChildProcess( + _exec(command, options._options, allowInterop(callback))); + } + return child; +} + +@JS() +@anonymous +class NativeJsChildProcessExecFileOptions { + external const factory NativeJsChildProcessExecFileOptions( + {String cwd, + NativeJsObject env, + String encoding: 'utf8', + int timeout: 0, + int maxBuffer: 204800, + String killSignal: "SIGTERM", + int uid, + int gid}); + + external String get cwd; + external NativeJsObject get env; + external String get encoding; + external int get timeout; + external int get maxBuffer; + external String get killSignal; + external int get uid; + external int get gid; +} + +class ChildProcessExecFileOptions { + final NativeJsChildProcessExecFileOptions _options; + + ChildProcessExecFileOptions( + {String cwd, + DartJsObject env, + String encoding: "utf8", + String shell: "/bin/sh", + int timeout: 0, + int maxBuffer: 204800, + String killSignal: "SIGTERM", + int uid, + int gid}) + : _options = new NativeJsChildProcessExecFileOptions( + cwd: cwd, + env: env?.jsObject, + encoding: encoding, + timeout: timeout, + maxBuffer: maxBuffer, + killSignal: killSignal, + uid: uid, + gid: gid); +} + +final ChildProcessExecFileOptions _defaultChildProcessExecFileOptions = + new ChildProcessExecFileOptions(); + +@JS("_child_process.execFile") +external NativeJsChildProcess _execFile(String file, + [List args, + NativeJsChildProcessExecFileOptions options, + Function callback]); + +ChildProcess execFile(String file, + {List args: null, + ChildProcessExecFileOptions options: null, + Function callback: null}) { + _requireChildProcess(); + if (options == null) options = _defaultChildProcessExecFileOptions; + if (callback == null) { + return new ChildProcess.fromNativeJsChildProcess( + _execFile(file, args, options._options)); + } + return new ChildProcess.fromNativeJsChildProcess( + _execFile(file, args, options._options, allowInterop(callback))); +} + +@JS() +@anonymous +class NativeJsChildProcessForkOptions { + external factory NativeJsChildProcessForkOptions( + {String cwd, + NativeJsObject env, + String execPath, + List execArgv, + bool silent, + int uid, + int gid}); + + external String get cwd; + external NativeJsObject get env; + external String get execPath; + external List get execArgv; + external bool get silent; + external int get uid; + external int get gid; +} + +class ChildProcessForkOptions { + final NativeJsChildProcessForkOptions _options; + + ChildProcessForkOptions( + {String cwd, + DartJsObject env, + String execPath, + List execArgv, + bool silent, + int uid, + int gid}) + : _options = new NativeJsChildProcessForkOptions( + cwd: cwd, + env: env?.jsObject, + execPath: execPath, + execArgv: execArgv, + silent: silent, + uid: uid, + gid: gid); +} + +final ChildProcessForkOptions _defaultChildProcessForkOptions = + new ChildProcessForkOptions(); + +@JS('_child_process.fork') +external NativeJsChildProcess _fork(String modulePath, + [List args, NativeJsChildProcessForkOptions options]); + +ChildProcess fork(String modulePath, + {List args: null, ChildProcessForkOptions options: null}) { + _requireChildProcess(); + if (options == null) options = _defaultChildProcessForkOptions; + return new ChildProcess.fromNativeJsChildProcess( + _fork(modulePath, args, options._options)); +} + +@JS() +@anonymous +class NativeJsChildProcessSpawnOptions { + external factory NativeJsChildProcessSpawnOptions( + {String cwd, + NativeJsObject env, + dynamic stdio, + bool detached, + int uid, + int gid, + dynamic shell}); + + external String get cwd; + external NativeJsObject get env; + external dynamic get stdio; + external bool get detached; + external int get uid; + external int get gid; + external dynamic get shell; +} + +class ChildProcessSpawnOptions { + final NativeJsChildProcessSpawnOptions _options; + + ChildProcessSpawnOptions( + {String cwd, + DartJsObject env, + dynamic stdio, + bool detached, + int uid, + int gid, + dynamic shell: true}) + : _options = new NativeJsChildProcessSpawnOptions( + cwd: cwd, + env: env?.jsObject, + stdio: stdio, + detached: detached, + uid: uid, + gid: gid, + shell: shell); +} + +final ChildProcessSpawnOptions _defaultChildProcessSpawnOptions = + new ChildProcessSpawnOptions(); + +@JS("_child_process.spawn") +external NativeJsChildProcess _spawn(String command, + [List args, NativeJsChildProcessSpawnOptions options]); + +ChildProcess spawn(String command, + {List args: null, ChildProcessSpawnOptions options: null}) { + _requireChildProcess(); + if (options == null) options = _defaultChildProcessSpawnOptions; + return new ChildProcess.fromNativeJsChildProcess( + _spawn(command, args, options._options)); +} + +@JS() +@anonymous +class NativeJsChildProcessExecFileSyncOptions { + external factory NativeJsChildProcessExecFileSyncOptions( + {String cwd, + dynamic input, + dynamic stdio, + NativeJsObject env, + int uid, + int gid, + int timeout, + String killSignal, + int maxBuffer, + String encoding}); + + external String get cwd; + external dynamic get input; + external dynamic get stdio; + external NativeJsObject get env; + external int get uid; + external int get gid; + external int get timeout; + external String get killSignal; + external int get maxBuffer; + external String get encoding; +} + +class ChildProcessExecFileSyncOptions { + final NativeJsChildProcessExecFileSyncOptions _options; + + ChildProcessExecFileSyncOptions( + {String cwd, + dynamic input, + dynamic stdio: 'pipe', + DartJsObject env, + int uid, + int gid, + int timeout: null, + String killSignal: 'SIGTERM', + int maxBuffer, + String encoding}) + : _options = new NativeJsChildProcessExecFileSyncOptions( + cwd: cwd, + input: input, + stdio: stdio, + env: env?.jsObject, + uid: uid, + gid: gid, + timeout: timeout, + killSignal: killSignal, + encoding: encoding); +} + +final ChildProcessExecFileSyncOptions _defaultChildProcessExecFileSyncOptions = + new ChildProcessExecFileSyncOptions(); + +@JS('_child_process.execFileSync') +external dynamic _execFileSync(String file, + [List args, NativeJsChildProcessExecFileSyncOptions options]); + +dynamic execFileSync(String file, + {List args, ChildProcessExecFileSyncOptions options}) { + _requireChildProcess(); + if (options == null) options = _defaultChildProcessExecFileSyncOptions; + return _execFileSync(file, args, options._options); +} + +@JS() +@anonymous +class NativeJsChildProcessExecSyncOptions { + external factory NativeJsChildProcessExecSyncOptions( + {String cwd, + dynamic input, + dynamic stdio, + NativeJsObject env, + dynamic shell, + int uid, + int gid, + int timeout, + String killSignal, + int maxBuffer, + String encoding}); + + external String get cwd; + external dynamic get input; + external dynamic get stdio; + external NativeJsObject get env; + external dynamic get shell; + external int get uid; + external int get gid; + external int get timeout; + external String get killSignal; + external int get maxBuffer; + external String get encoding; +} + +class ChildProcessExecSyncOptions { + final NativeJsChildProcessExecSyncOptions _options; + + ChildProcessExecSyncOptions( + {String cwd, + dynamic input, + dynamic stdio: 'pipe', + DartJsObject env, + String shell: '/bin/sh', + int uid, + int gid, + int timeout: null, + String killSignal: "SIGTERM", + int maxBuffer, + String encoding}) + : _options = new NativeJsChildProcessExecSyncOptions( + cwd: cwd, + input: input, + stdio: stdio, + env: env?.jsObject, + shell: shell ?? false, + uid: uid, + gid: gid, + timeout: timeout, + killSignal: killSignal, + maxBuffer: maxBuffer, + encoding: encoding); +} + +final ChildProcessExecSyncOptions _defaultChildProcessExecSyncOptions = + new ChildProcessExecSyncOptions(); + +@JS("_child_process.execSync") +external dynamic _execSync(String command, + [List args, NativeJsChildProcessExecSyncOptions options]); + +dynamic execSync(String command, + {List args: null, ChildProcessExecSyncOptions options: null}) { + _requireChildProcess(); + if (options == null) options = _defaultChildProcessExecSyncOptions; + + return _execSync(command, args, options._options); +} + +@JS() +@anonymous +class NativeJsChildProcessSpawnSyncOptions { + external factory NativeJsChildProcessSpawnSyncOptions( + {String cwd, + dynamic input, + dynamic stdio, + NativeJsObject env, + int uid, + int gid, + int timeout, + String killSignal, + int maxBuffer, + String encoding, + dynamic shell}); + + external String get cwd; + external dynamic get input; + external dynamic get stdio; + external NativeJsObject get env; + external int get uid; + external int get gid; + external int get timeout; + external String get killSignal; + external int get maxBuffer; + external String get encoding; + external dynamic get shell; +} + +class ChildProcessSpawnSyncOptions { + final NativeJsChildProcessSpawnSyncOptions _options; + + ChildProcessSpawnSyncOptions( + {String cwd, + dynamic input, + dynamic stdio, + DartJsObject env, + int uid, + int gid, + int timeout: null, + String killSignal: "SIGTERM", + int maxBuffer, + String encoding, + dynamic shell: false}) + : _options = new NativeJsChildProcessSpawnSyncOptions( + cwd: cwd, + input: input, + stdio: stdio, + env: env?.jsObject, + uid: uid, + gid: gid, + timeout: timeout, + killSignal: killSignal, + encoding: encoding, + shell: shell); +} + +final ChildProcessSpawnSyncOptions _defaultChildProcessSpawnSyncOptions = + new ChildProcessSpawnSyncOptions(); + +@JS() +@anonymous +class NativeJsSpawnSyncResult { + external factory NativeJsSpawnSyncResult(); + + external int get pid; + external List get output; + external dynamic get stdout; + external dynamic get stderr; + external int get status; + external String get signal; + external NativeJsError get error; +} + +class SpawnSyncResult { + final NativeJsSpawnSyncResult _result; + + SpawnSyncResult.fromNativeJsSpawnSyncResult(this._result); + + int get pid => _result.pid; + List get output => _result.output; + dynamic get stdout => _result.stdout; + dynamic get stderr => _result.stderr; + int get status => _result.status; + String get signal => _result.signal; + Error get error => new Error.fromNativeJsError(_result.error); +} + +@JS('_child_process.spawnSync') +external dynamic _spawnSync(String file, + [List args, NativeJsChildProcessSpawnSyncOptions options]); + +dynamic spawnSync(String file, + {List args, ChildProcessSpawnSyncOptions options}) { + _requireChildProcess(); + if (args == null) args = []; + if (options == null) options = _defaultChildProcessSpawnSyncOptions; + return new SpawnSyncResult.fromNativeJsSpawnSyncResult( + _spawnSync(file, args, options._options)); +} + +@JS() +@anonymous +class ChildProcessSendOptions { + external factory ChildProcessSendOptions({bool keepOpen: false}); + + external bool get keepOpen; +} + +@JS("_child_process.ChildProcess") +class NativeJsChildProcess extends NativeJsEventEmitter { + external bool get connected; + external int get pid; + external NativeJsReadable get stderr; + external NativeJsWritable get stdin; + external List get stdio; + external NativeJsReadable get stdout; + + external void disconnect(); + external void kill([String signal]); + external bool send(NativeJsObject message, + [dynamic sendHandle, ChildProcessSendOptions options, Function callback]); +} + +class _ChildProcessEvent { + int code; + String signal; + + _ChildProcessEvent(this.code, this.signal); +} + +class ChildProcessCloseEvent extends _ChildProcessEvent { + ChildProcessCloseEvent(int code, String signal) : super(code, signal); +} + +class ChildProcessExitEvent extends _ChildProcessEvent { + ChildProcessExitEvent(int code, String signal) : super(code, signal); +} + +class ChildProcessMessageEvent { + dynamic message; + dynamic handler; + + ChildProcessMessageEvent(this.message, this.handler); +} + +class ChildProcess extends EventEmitter { + NativeJsChildProcess _childprocess; + + StreamController _close; + StreamController _disconnect; + StreamController _error; + StreamController _exit; + StreamController _message; + + ChildProcess.fromNativeJsChildProcess(NativeJsChildProcess _childProcess) + : super.fromNativeJsEventEmitter(_childProcess) { + _requireChildProcess(); + _childprocess = _childProcess; + _initAllStreamController(); + } + + bool get connected => _childprocess.connected; + int get pid => _childprocess.pid; + Readable get stderr => + new Readable.fromNativeJsReadable(_childprocess.stderr); + Writable get stdin => new Writable.fromNativeJsWritable(_childprocess.stdin); + List get stdio => _childprocess.stdio; + Readable get stdout => + new Readable.fromNativeJsReadable(_childprocess.stdout); + + Stream get onClose => _close.stream; + Stream get onDisconnect => _disconnect.stream; + Stream get onError => _error.stream; + Stream get onExit => _exit.stream; + Stream get onMessage => _message.stream; + + void disconnect() => _childprocess.disconnect(); + void kill([String signal = "SIGTERM"]) => _childprocess.kill(signal); + bool send(DartJsObject message, + [dynamic sendHandle, + ChildProcessSendOptions options, + Function callback]) { + if (callback != null) { + return _childprocess.send( + message.jsObject, sendHandle, options, allowInterop(callback)); + } + return _childprocess.send(message.jsObject, sendHandle, options); + } + + void _onClose(int code, String signal) => + _close.add(new ChildProcessCloseEvent(code, signal)); + void _onDisconnect() => _disconnect.add(null); + void _onError(NativeJsError error) => + _error.add(new Error.fromNativeJsError(error)); + void _onExit(int code, String signal) => + _exit.add(new ChildProcessExitEvent(code, signal)); + void _onMessage(dynamic message, dynamic handler) => + _message.add(new ChildProcessMessageEvent(message, handler)); + + void _initAllStreamController() { + _close = new StreamController(sync: true); + on('close', _onClose); + _disconnect = new StreamController(sync: true); + on('disconnect', _onDisconnect); + _error = new StreamController(sync: true); + on('error', _onError); + _exit = new StreamController(sync: true); + on('exit', _onExit); + _message = new StreamController(sync: true); + on('message', _onMessage); + } +} diff --git a/lib/src/errors/error.dart b/lib/src/errors/error.dart new file mode 100644 index 0000000..260ce69 --- /dev/null +++ b/lib/src/errors/error.dart @@ -0,0 +1,76 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS('Error') +class NativeJsError { + external NativeJsError([dynamic message]); + + external static int get stackTraceLimit; + external static set stackTraceLimit(dynamic value); + external static void captureStackTrace(dynamic object, + [dynamic constructorOpt]); + + external String get stack; + external set stack(String value); + external String get message; + external set message(String value); +} + +@JS() +@anonymous +class _Tracable { + _Tracable(); + + external set stack(dynamic value); + external String get stack; +} + +abstract class TracableStack { + _Tracable _tracable; + + TracableStack() { + _tracable = new _Tracable(); + } + + set stack(String value) { + _tracable.stack = value; + } + + String get stack => _tracable.stack; +} + +class Error extends TracableStack { + NativeJsError _error; + + Error([dynamic message = null]) { + if (message == null) { + _error = new NativeJsError(); + } else { + _error = new NativeJsError(message); + } + } + + Error.fromNativeJsError(this._error); + + static int get stackTraceLimit => NativeJsError.stackTraceLimit; + static set stackTraceLimit(int value) { + NativeJsError.stackTraceLimit = value; + } + + static void captureStackTrace(TracableStack object) => + NativeJsError.captureStackTrace(object._tracable); + + @override + String get stack => _error.stack; + @override + set stack(String value) { + _error.stack = value; + } + + String get message => _error.message; + set message(String value) { + _error.message = value; + } +} diff --git a/lib/src/errors/range_error.dart b/lib/src/errors/range_error.dart new file mode 100644 index 0000000..d8dd73d --- /dev/null +++ b/lib/src/errors/range_error.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS('RangeError') +class NativeJsRangeError extends NativeJsError { + external NativeJsRangeError([dynamic message]); +} + +class RangeError extends Error { + NativeJsRangeError _rangeError; + + RangeError([dynamic message = null]) { + _rangeError = new NativeJsRangeError(message); + _error = _rangeError; + } + + RangeError.fromJSRangeError(this._rangeError) { + _error = _rangeError; + } + + @override + String get stack => _rangeError.stack; + @override + set stack(String value) { + _rangeError.stack = value; + } + + @override + String get message => _rangeError.message; + @override + set message(String value) { + _rangeError.message = value; + } +} diff --git a/lib/src/events.dart b/lib/src/events.dart new file mode 100644 index 0000000..d35f0f5 --- /dev/null +++ b/lib/src/events.dart @@ -0,0 +1,68 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS() +external set _events(NativeJsObject value); +@JS() +external NativeJsObject get _events; + +void _requireEvents() { + if (_events == null) { + _events = require("events"); + } +} + +@JS('_events.EventEmitter') +class NativeJsEventEmitter { + external NativeJsEventEmitter(); + + external static int get defaultMaxListeners; + + external int getMaxListeners(); + external void setMaxListeners(int value); + external bool emit(String event, [dynamic arguments]); + external void on(String eventName, Function function); + external void once(String eventName, Function function); + external void listenerCount(String eventName); + external void listeners(String eventName); + external void removeAllListeners([String eventName]); + external void removeListener(String eventName, Function function); +} + +class EventEmitter { + NativeJsEventEmitter _eventEmitter; + + EventEmitter() { + _requireEvents(); + _eventEmitter = new NativeJsEventEmitter(); + } + + EventEmitter.fromNativeJsEventEmitter(NativeJsEventEmitter eventEmitter) { + _requireEvents(); + _eventEmitter = eventEmitter; + } + + static int get defaultMaxListeners => + NativeJsEventEmitter.defaultMaxListeners; + + int get getMaxListeners => _eventEmitter.getMaxListeners(); + set setMaxListeners(dynamic value) => _eventEmitter.setMaxListeners(value); + + bool emit(String eventName, [List arguments = null]) => + arguments == null + ? _eventEmitter.emit(eventName) + : _eventEmitter.emit(eventName, arguments); + void on(String eventName, Function function) => + _eventEmitter.on(eventName, allowInterop(function)); + void once(String eventName, Function function) => + _eventEmitter.once(eventName, allowInterop(function)); + void listenerCount(String eventName) => + _eventEmitter.listenerCount(eventName); + void listeners(String eventName) => _eventEmitter.listeners(eventName); + void removeAllListeners([String eventName]) => + _eventEmitter.removeAllListeners(eventName); + void removeListener(String eventName, Function function) => + _eventEmitter.removeListener(eventName, allowInterop(function)); +} diff --git a/lib/src/fs.dart b/lib/src/fs.dart new file mode 100644 index 0000000..cc50fc8 --- /dev/null +++ b/lib/src/fs.dart @@ -0,0 +1,339 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS() +external set _fs(NativeJsFs value); +@JS() +external NativeJsFs get _fs; + +void _requireFs() { + if (_fs == null) { + _fs = require("fs"); + } +} + +Fs fs = _getFs(); + +Fs _getFs() { + _requireFs(); + return new Fs.fromNativeJsFs(_fs); +} + +@JS() +@anonymous +class FsAppendFileOptions { + external factory FsAppendFileOptions( + {String encoding: 'utf8', int mode, String flag: 'a'}); + + external String get encoding; + external int get mode; + external String get flag; +} + +@JS('_fs.ReadStream') +class NativeJsReadStream extends NativeJsReadable { + external String get path; +} + +@JS('_fs.WriteStream') +class NativeJsWriteStream extends NativeJsWritable { + external int get bytesWritten; + external String get path; +} + +class ReadStream extends Readable { + NativeJsReadStream _readStream; + + StreamController _open; + + ReadStream.fromNativeJsReadStream(NativeJsReadStream readStream) + : super.fromNativeJsReadable(readStream) { + _requireStream(); + _readStream = readStream; + _initAllStreamController(); + } + + String get path => _readStream.path; + Stream get onOpen => _open.stream; + + void _onOpen(int fd) => _open.add(fd); + + @override + void _initAllStreamController() { + super._initAllStreamController(); + _open = new StreamController(sync: true); + on('open', _onOpen); + } +} + +class WriteStream extends Writable { + NativeJsWriteStream _writeStream; + + StreamController _open; + + WriteStream.fromNativeJsWriteStream(NativeJsWriteStream writeStream) + : super.fromNativeJsWritable(writeStream) { + _requireStream(); + _writeStream = writeStream; + _initAllStreamController(); + } + + String get path => _writeStream.path; + int get bytesWritten => _writeStream.bytesWritten; + Stream get onOpen => _open.stream; + + void _onOpen(int fd) => _open.add(fd); + + @override + void _initAllStreamController() { + super._initAllStreamController(); + _open = new StreamController(sync: true); + on('open', _onOpen); + } +} + +@JS() +@anonymous +class CreateStreamOptions { + external factory CreateStreamOptions( + {String flags: 'r', + String encoding: null, + int fd: null, + int mode: 438, + bool autoClose: true, + int start: null, + int end: null}); +} + +@JS('_fs') +class NativeJsFs { + external int get fOk; + external int get rOk; + external int get wOk; + external int get xOk; + + external void access(String path, int options, Function callback); + external void accessSync(String path, int options); + external void appendFile(dynamic file, dynamic data, + FsAppendFileOptions options, Function callback); + external void appendFileSync( + dynamic file, dynamic data, FsAppendFileOptions options); + external void chmod(String path, int mode, Function callback); + external void chmodSync(String path, int mode); + external void chown(String path, int uid, int gid, Function callback); + external void chownSync(String path, int uid, int gid); + external void close(int fd, Function callback); + external void closeSync(int fd); + external NativeJsReadStream createReadStream( + String path, CreateStreamOptions options); + external NativeJsWriteStream createWriteStream( + String path, CreateStreamOptions options); +} + +@JS() +@anonymous +class NativeJsFsError extends NativeJsError { + external factory NativeJsFsError({int errno, String code, String syscall}); + + external int get errno; + external String get code; + external String get syscall; +} + +class FsError extends Error { + String _description; + NativeJsFsError _fsError; + + FsError.fromNativeJsFsError(this._fsError) { + _description = ''; + if (_fsError.code == 'EACCES') { + _description = 'permission denied'; + } else if (_fsError.code == 'EBADF') { + _description = 'bad file descriptor'; + } + } + + @override + String toString() { + return 'FsError: ${_fsError.code}: $_description, ${_fsError.syscall}'; + } +} + +@JS() +@anonymous +class NativeJsFsAccessSyncError extends NativeJsFsError { + external factory NativeJsFsAccessSyncError( + {int errno, String code, String syscall, String path}); + + external String get path; +} + +class FsAccessSyncError extends FsError { + NativeJsFsAccessSyncError _jsAccessSyncError; + + FsAccessSyncError.fromNativeJsAccessSyncError( + NativeJsFsAccessSyncError jsAccessSyncError) + : super.fromNativeJsFsError(jsAccessSyncError) { + _jsAccessSyncError = jsAccessSyncError; + } + + @override + String toString() => super.toString() + " " + _jsAccessSyncError.path; +} + +class FileReference { + final String _path; + final int _fd; + + FileReference.path(String path) + : _path = path, + _fd = null; + FileReference.fd(int fd) + : _path = null, + _fd = fd; +} + +class Fs { + NativeJsFs _jsFs; + + Fs.fromNativeJsFs(this._jsFs); + + int get fOk => _jsFs.fOk; + int get rOk => _jsFs.rOk; + int get wOk => _jsFs.wOk; + int get xOk => _jsFs.xOk; + + Future _accessInternal(String path, int options) { + Completer completer = new Completer(); + _jsFs.access(path, options, allowInterop((NativeJsFsAccessSyncError error) { + if (error != null) { + completer + .complete(new FsAccessSyncError.fromNativeJsAccessSyncError(error)); + } else { + completer.complete(null); + } + })); + return completer.future; + } + + Future access(String path, [int options = 0]) => + _accessInternal(path, options); + + void accessSync(String path, [int options = 0]) { + try { + _jsFs.accessSync(path, options); + } on NativeJsFsAccessSyncError catch (error) { + throw new FsAccessSyncError.fromNativeJsAccessSyncError(error); + } + } + + Future _appendFileInternal( + dynamic file, dynamic data, dynamic options) { + Completer completer = new Completer(); + _jsFs.appendFile(file, data, options, allowInterop((NativeJsFsError error) { + if (error != null) { + completer.complete(new FsError.fromNativeJsFsError(error)); + } else { + completer.complete(null); + } + })); + return completer.future; + } + + Future appendFile(dynamic file, dynamic data, + [FsAppendFileOptions options]) { + if (options == null) options = new FsAppendFileOptions(); + return _appendFileInternal(file, data, options); + } + + void appendFileSync(dynamic file, dynamic data, + [FsAppendFileOptions options]) { + if (options == null) options = new FsAppendFileOptions(); + try { + _jsFs.appendFileSync(file, data, options); + } on NativeJsFsError catch (error) { + throw new FsError.fromNativeJsFsError(error); + } + } + + Future _chmodInternal(String path, int mode) { + Completer completer = new Completer(); + _jsFs.chmod(path, mode, allowInterop((NativeJsFsError error) { + if (error != null) { + completer.complete(new FsError.fromNativeJsFsError(error)); + } else { + completer.complete(null); + } + })); + return completer.future; + } + + Future chmod(String path, int mode) => _chmodInternal(path, mode); + + void chmodSync(String path, int mode) { + try { + _jsFs.chmodSync(path, mode); + } on NativeJsFsError catch (error) { + throw new FsError.fromNativeJsFsError(error); + } + } + + Future _chownInternal(String path, int uid, int gid) { + Completer completer = new Completer(); + _jsFs.chown(path, uid, gid, allowInterop((NativeJsFsError error) { + if (error != null) { + completer.complete(new FsError.fromNativeJsFsError(error)); + } else { + completer.complete(null); + } + })); + return completer.future; + } + + Future chown(String path, int uid, int gid) => + _chownInternal(path, uid, gid); + + void chownSync(String path, int uid, int gid) { + try { + _jsFs.chownSync(path, uid, gid); + } on NativeJsFsError catch (error) { + throw new FsError.fromNativeJsFsError(error); + } + } + + Future _closeInternal(int fd) { + Completer completer = new Completer(); + _jsFs.close(fd, allowInterop((NativeJsFsError error) { + if (error != null) { + completer.complete(new FsError.fromNativeJsFsError(error)); + } else { + completer.complete(null); + } + })); + return completer.future; + } + + Future close(int fd) => _closeInternal(fd); + + void closeSync(int fd) { + try { + _jsFs.closeSync(fd); + } on NativeJsFsError catch (error) { + throw new FsError.fromNativeJsFsError(error); + } + } + + ReadStream createReadStream(String path, CreateStreamOptions options) { + if (options == null) options = new CreateStreamOptions(); + return new ReadStream.fromNativeJsReadStream( + _jsFs.createReadStream(path, options)); + } + + WriteStream createWriteStream(String path, CreateStreamOptions options) { + if (options == null) options = new CreateStreamOptions(); + return new WriteStream.fromNativeJsWriteStream( + _jsFs.createWriteStream(path, options)); + } +} diff --git a/lib/src/module.dart b/lib/src/module.dart new file mode 100644 index 0000000..6c7df03 --- /dev/null +++ b/lib/src/module.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS('Module') +class NativeJsModule { + external factory NativeJsModule(); + + external String get id; + external NativeJsObject get exports; + external NativeJsModule get parent; + external String get filename; + external bool get loaded; + external List get children; + external List get paths; +} + +class Module { + NativeJsModule _module; + + Module.fromJSModule(this._module); + + String get id => _module.id; + DartJsObject get exports => + new DartJsObject.fromNativeJsObject(_module.exports); + Module get parent => new Module.fromJSModule(_module.parent); + String get filename => _module.filename; + bool get loaded => _module.loaded; + List get children => _module.children; + List get paths => _module.paths; + + @override + String toString() => id; +} diff --git a/lib/src/object.dart b/lib/src/object.dart new file mode 100644 index 0000000..442ea2f --- /dev/null +++ b/lib/src/object.dart @@ -0,0 +1,107 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS() +@anonymous +class NativeJsDescription { + external factory NativeJsDescription( + {dynamic value: null, + bool writable: false, + bool enumerable: false, + bool configurable: false, + Function set: null, + Function get: null}); + + external dynamic get value; + external bool get writable; + external bool get enumerable; + external bool get configurable; + external Function get set; + external Function get get; +} + +class Description { + NativeJsDescription _description; + + Description( + {dynamic value: null, + bool writable: true, + bool enumerable: true, + bool configurable: false, + Function set: null, + Function get: null}) { + if (value is Function) { + value = allowInterop(value); + } + if (get != null && set != null) { + _description = new NativeJsDescription( + value: value, + writable: writable, + enumerable: enumerable, + configurable: configurable, + set: allowInterop(set), + get: allowInterop(get)); + } else if (get == null && set != null) { + _description = new NativeJsDescription( + value: value, + writable: writable, + enumerable: enumerable, + configurable: configurable, + set: allowInterop(set)); + } else if (get != null && set == null) { + _description = new NativeJsDescription( + value: value, + writable: writable, + enumerable: enumerable, + configurable: configurable, + get: allowInterop(get)); + } else { + _description = new NativeJsDescription( + value: value, + writable: writable, + enumerable: enumerable, + configurable: configurable); + } + } +} + +@JS('Object') +class NativeJsObject { + external factory NativeJsObject([NativeJsObject fields]); + + external static void defineProperty( + NativeJsObject object, String key, NativeJsDescription description); + external static List keys(NativeJsObject object); +} + +class DartJsObject { + NativeJsObject jsObject; + Map _data; + + DartJsObject([Map fields]) { + jsObject = new NativeJsObject(convertMapToNativeJsObject(fields)); + _data = fields; + } + + DartJsObject.fromNativeJsObject(this.jsObject) { + _data = convertNativeJsObjectToMap(jsObject); + } + + static void defineProperty( + DartJsObject object, String key, Description description) { + NativeJsObject.defineProperty( + object.jsObject, key, description._description); + object._data[key] = description._description.value; + } + + static List keys(NativeJsObject object) => + NativeJsObject.keys(object); + + dynamic operator [](String key) => _data[key]; + void operator []=(String key, dynamic value) => + DartJsObject.defineProperty(this, key, new Description(value: value)); + + Map toMap() => _data; +} diff --git a/lib/src/process.dart b/lib/src/process.dart new file mode 100644 index 0000000..087e553 --- /dev/null +++ b/lib/src/process.dart @@ -0,0 +1,196 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +Process process = new Process.fromJSProcess(_jsProcess); + +@JS('process') +external NativeJsProcess get _jsProcess; + +@JS('process') +class NativeJsProcess extends NativeJsEventEmitter { + external static List get arch; + external static List get argv; + external static NativeJsObject get config; + external static bool get connected; + external static NativeJsObject get env; + external static List get execArgv; + external static int get exitCode; + external static NativeJsModule get mainModule; + external static int get pid; + external static String get platform; + external static NativeJsObject get release; + external static NativeJsWritable get stderr; + external static NativeJsReadable get stdin; + external static NativeJsWritable get stdout; + external static dynamic get title; + external static set title(dynamic value); + external static String get version; + external static NativeJsObject get versions; + + external static void abort(); + external static void chdir(String directory); + external static void cwd(); + external static void disconnect(); + external static void exit([int code = 0]); + external static int getegid(); + external static int geteuid(); + external static int getgid(); + external static void getgroups(); + external static int getuid(); + external static void hrtime(); + external static void initgroups(String user, dynamic extraGroup); + external static void kill([int pid]); + external static NativeJsObject memoryUsage(); + external static void nextTick(Function function, dynamic params); + external static void send( + dynamic message, dynamic handleObject, Function callback); + external static void setegid(int id); + external static void seteuid(int id); + external static void setgid(int id); + external static void setgroups(String groups); + external static void setuid(int id); + external static int umask([dynamic mask]); +} + +class ProcessMessage { + dynamic message; + dynamic sendHandle; + + ProcessMessage(this.message, this.sendHandle); +} + +class ProcessUnhandledRejection { + dynamic reason; + dynamic promise; + + ProcessUnhandledRejection(this.reason, this.promise); +} + +class Process extends EventEmitter { + StreamController _sigUsr1; + StreamController _sigPipe; + StreamController _sigHup; + StreamController _sigTerm; + StreamController _sigInt; + StreamController _sigBreak; + StreamController _sigWinch; + StreamController _beforeExit; + StreamController _exit; + StreamController _message; + StreamController _rejectionHandled; + StreamController _uncaughtException; + StreamController _unhandledRejection; + + Process.fromJSProcess(NativeJsProcess _process) + : super.fromNativeJsEventEmitter(_process) { + _initAllStreamController(); + } + + List get arch => NativeJsProcess.arch; + List get argv => NativeJsProcess.argv; + Map get config => + convertNativeJsObjectToMap(NativeJsProcess.config); + bool get connected => NativeJsProcess.connected; + Map get env => + convertNativeJsObjectToMap(NativeJsProcess.env); + List get execArgv => NativeJsProcess.execArgv; + int get exitCode => NativeJsProcess.exitCode; + Module get mainModule => new Module.fromJSModule(NativeJsProcess.mainModule); + int get pid => NativeJsProcess.pid; + String get platform => NativeJsProcess.platform; + Map get release => + convertNativeJsObjectToMap(NativeJsProcess.release); + Writable get stderr => + new Writable.fromNativeJsWritable(NativeJsProcess.stderr); + Readable get stdin => + new Readable.fromNativeJsReadable(NativeJsProcess.stdin); + Writable get stdout => + new Writable.fromNativeJsWritable(NativeJsProcess.stdout); + dynamic get title => NativeJsProcess.title; + set title(dynamic value) => NativeJsProcess.title(value); + String get version => NativeJsProcess.version; + DartJsObject get versions => + new DartJsObject.fromNativeJsObject(NativeJsProcess.versions); + Stream get sigUsr1 => _sigUsr1.stream; + Stream get sigPipe => _sigPipe.stream; + Stream get sigHup => _sigHup.stream; + Stream get sigTerm => _sigTerm.stream; + Stream get sigInt => _sigInt.stream; + Stream get sigBreak => _sigBreak.stream; + Stream get sigWinch => _sigWinch.stream; + + void abort() => NativeJsProcess.abort(); + void chdir(String directory) => NativeJsProcess.chdir(directory); + void cwd() => NativeJsProcess.cwd(); + void disconnect() => NativeJsProcess.disconnect(); + void exit([int code = 0]) => NativeJsProcess.exit(code); + int getegid() => NativeJsProcess.getegid(); + int geteuid() => NativeJsProcess.geteuid(); + int getgid() => NativeJsProcess.getgid(); + void getgroups() => NativeJsProcess.getgroups(); + int getuid() => NativeJsProcess.getuid(); + void hrtime() => NativeJsProcess.hrtime(); + void initgroups(String user, dynamic extraGroup) => + NativeJsProcess.initgroups(user, extraGroup); + void kill([int pid]) => NativeJsProcess.kill(pid); + DartJsObject memoryUsage() => + new DartJsObject.fromNativeJsObject(NativeJsProcess.memoryUsage()); + void nextTick(Function function, dynamic params) => + NativeJsProcess.nextTick(allowInterop(function), params); + void send(dynamic message, dynamic handleObject, Function function) => + NativeJsProcess.send(message, handleObject, allowInterop(function)); + void setegid(int id) => NativeJsProcess.setegid(id); + void seteuid(int id) => NativeJsProcess.seteuid(id); + void setgid(int id) => NativeJsProcess.setgid(id); + void setgroups(String groups) => NativeJsProcess.setgroups(groups); + void setuid(int id) => NativeJsProcess.setuid(id); + int umask([dynamic mask]) => NativeJsProcess.umask(mask); + + void _initAllStreamController() { + _sigUsr1 = new StreamController(sync: true); + on('SIGUSR1', _onSIGUSR1); + _sigPipe = new StreamController(sync: true); + on('SIGPIPE', _onSIGPIPE); + _sigHup = new StreamController(sync: true); + on('SIGHUP', _onSIGHUP); + _sigTerm = new StreamController(sync: true); + on('SIGTERM', _onSIGTERM); + _sigInt = new StreamController(sync: true); + on('SIGINT', _onSIGINT); + _sigBreak = new StreamController(sync: true); + on('SIGBREAK', _onSIGBREAK); + _sigWinch = new StreamController(sync: true); + on('SIGWINCH', _onSIGWINCH); + _beforeExit = new StreamController(sync: true); + on('beforeExit', _onBeforeExit); + _exit = new StreamController(sync: true); + on('exit', _onExit); + _message = new StreamController(sync: true); + on('message', _onMessage); + _rejectionHandled = new StreamController(sync: true); + on('rejectionHandled', _onRejectionHandled); + _uncaughtException = new StreamController(sync: true); + on('uncaughtException', _onUncaughtException); + _unhandledRejection = + new StreamController(sync: true); + on('unhandledRejection', _onUnhandledRejection); + } + + void _onSIGUSR1([dynamic event]) => _sigUsr1.add(null); + void _onSIGPIPE([dynamic event]) => _sigPipe.add(null); + void _onSIGHUP([dynamic event]) => _sigPipe.add(null); + void _onSIGTERM([dynamic event]) => _sigTerm.add(null); + void _onSIGINT([dynamic event]) => _sigInt.add(null); + void _onSIGBREAK([dynamic event]) => _sigBreak.add(null); + void _onSIGWINCH([dynamic event]) => _sigWinch.add(null); + void _onBeforeExit([dynamic event]) => _beforeExit.add(null); + void _onExit(dynamic code) => _exit.add(code); + void _onMessage(dynamic message, dynamic sendHandle) => + _message.add(new ProcessMessage(message, sendHandle)); + void _onRejectionHandled(dynamic promise) => _rejectionHandled.add(promise); + void _onUncaughtException(dynamic error) => _uncaughtException.add(error); + void _onUnhandledRejection(dynamic reason, dynamic promise) => + _unhandledRejection.add(new ProcessUnhandledRejection(reason, promise)); +} diff --git a/lib/src/stream.dart b/lib/src/stream.dart new file mode 100644 index 0000000..9106cd0 --- /dev/null +++ b/lib/src/stream.dart @@ -0,0 +1,16 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS() +external set _stream(NativeJsObject value); +@JS() +external NativeJsObject get _stream; + +void _requireStream() { + _requireEvents(); + if (_stream == null) { + _stream = require("stream"); + } +} diff --git a/lib/src/stream/duplex.dart b/lib/src/stream/duplex.dart new file mode 100644 index 0000000..8d6e378 --- /dev/null +++ b/lib/src/stream/duplex.dart @@ -0,0 +1,98 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS('_stream.Duplex') +class NativeJsDuplex extends NativeJsReadable implements NativeJsWritable { + external NativeJsDuplex(); + + @override + external void cork(); + @override + external void end([dynamic chunk, String encoding, Function callback]); + @override + external void setDefaultEncoding(String value); + @override + external void uncork(); + @override + external bool write(dynamic chunk, [String encoding, Function callback]); +} + +class Duplex extends Readable implements Writable { + NativeJsDuplex _duplex; + @override + NativeJsWritable _writable; + @override + StreamController _drain; + @override + StreamController _error; + @override + StreamController _finish; + @override + StreamController _pipe; + @override + StreamController _unpipe; + + Duplex() : super() { + _duplex = new NativeJsDuplex(); + _readable = _duplex; + _writable = _duplex; + _eventEmitter = _duplex; + _initAllStreamController(); + } + + Duplex.fromJSDuplex(NativeJsDuplex duplex) + : super.fromNativeJsReadable(duplex) { + _duplex = duplex; + _writable = _duplex; + _eventEmitter = _duplex; + _initAllStreamController(); + } + + @override + set defaultEncoding(String value) => _writable.setDefaultEncoding(value); + + @override + void cork() => _writable.cork(); + @override + void uncork() => _writable.uncork(); + + @override + Future end([dynamic chunk, String encoding]) { + Completer completer = new Completer(); + _writable.end(chunk, encoding, allowInterop(completer.complete)); + return completer.future; + } + + @override + Future write(dynamic chunk, [String encoding]) { + Completer completer = new Completer(); + _writable.write(chunk, encoding, allowInterop(completer.complete)); + return completer.future; + } + + @override + void _onDrainEvent([dynamic event = null]) => _drain.add(event); + @override + void _onErrorEvent([NativeJsError error = null]) => + _error.add(new Error.fromNativeJsError(error)); + @override + void _onFinishEvent([dynamic event = null]) => _finish.add(event); + @override + void _onPipeEvent(Readable readable) => _pipe.add(readable); + @override + void _onUnPipeEvent(Readable readable) => _unpipe.add(readable); + + @override + void _initAllStreamController() { + _drain = new StreamController(sync: true); + on('drain', _onDrainEvent); + _error = new StreamController(sync: true); + on('finish', _onFinishEvent); + _pipe = new StreamController(sync: true); + on('pipe', _onPipeEvent); + _unpipe = new StreamController(sync: true); + on('unpipe', _onUnPipeEvent); + } +} diff --git a/lib/src/stream/readable.dart b/lib/src/stream/readable.dart new file mode 100644 index 0000000..af2eb7b --- /dev/null +++ b/lib/src/stream/readable.dart @@ -0,0 +1,79 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS('_stream.Readable') +class NativeJsReadable extends NativeJsEventEmitter { + external NativeJsReadable(); + + external bool isPaused(); + external void pause(); + external void pipe(Writable destination, [dynamic options]); + external void read([int size]); + external void resume(); + external void setEncoding(String encoding); + external void unpipe([Writable destination]); + external void unshift(dynamic chunk); +} + +class Readable extends EventEmitter { + NativeJsReadable _readable; + + StreamController _onClose; + StreamController _onData; + StreamController _onEnd; + StreamController _onError; + StreamController _onReadable; + + Readable() { + _requireStream(); + _readable = new NativeJsReadable(); + _eventEmitter = _readable; + _initAllStreamController(); + } + + Readable.fromNativeJsReadable(NativeJsReadable readable) + : super.fromNativeJsEventEmitter(readable) { + _requireStream(); + _readable = readable; + _initAllStreamController(); + } + + set encoding(String encoding) => _readable.setEncoding(encoding); + + bool get isPaused => _readable.isPaused(); + Stream get onClose => _onClose.stream; + Stream get onData => _onData.stream; + Stream get onEnd => _onEnd.stream; + Stream get onError => _onError.stream; + Stream get onReadable => _onReadable.stream; + + void pause() => _readable.pause(); + void pipe(Writable destination, [dynamic options]) => + _readable.pipe(destination, options); + void read([int size]) => _readable.read(size); + void resume() => _readable.resume(); + void unpipe([Writable destination]) => _readable.unpipe(destination); + void unshift(dynamic chunk) => _readable.unshift(chunk); + + void _onCloseEvent([dynamic event = null]) => _onClose.add(event); + void _onDataEvent([dynamic data = null]) => _onData.add(data); + void _onEndEvent([dynamic event = null]) => _onEnd.add(event); + void _onErrorEvent([NativeJsError error = null]) => + _onError.add(new Error.fromNativeJsError(error)); + void _onReadableEvent([dynamic event = null]) => _onReadable.add(event); + + void _initAllStreamController() { + _onClose = new StreamController(sync: true); + on('close', _onCloseEvent); + _onData = new StreamController(sync: true); + on('data', _onDataEvent); + _onEnd = new StreamController(sync: true); + on('end', _onEndEvent); + _onError = new StreamController(sync: true); + on('error', _onErrorEvent); + _onReadable = new StreamController(sync: true); + on('readable', _onReadableEvent); + } +} diff --git a/lib/src/stream/writable.dart b/lib/src/stream/writable.dart new file mode 100644 index 0000000..4beb0e2 --- /dev/null +++ b/lib/src/stream/writable.dart @@ -0,0 +1,76 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS('_stream.Writable') +class NativeJsWritable extends NativeJsEventEmitter { + external NativeJsWritable(); + + external void cork(); + external void end([dynamic chunk, String encoding, Function callback]); + external void setDefaultEncoding(String value); + external void uncork(); + external bool write(dynamic chunk, [String encoding, Function callback]); +} + +class Writable extends EventEmitter { + NativeJsWritable _writable; + + StreamController _drain; + StreamController _error; + StreamController _finish; + StreamController _pipe; + StreamController _unpipe; + + Writable() { + _requireStream(); + _writable = new NativeJsWritable(); + _eventEmitter = _writable; + _initAllStreamController(); + } + + Writable.fromNativeJsWritable(NativeJsWritable writable) + : super.fromNativeJsEventEmitter(writable) { + _requireStream(); + _writable = writable; + _initAllStreamController(); + } + + set defaultEncoding(String value) => _writable.setDefaultEncoding(value); + + void cork() => _writable.cork(); + void uncork() => _writable.uncork(); + + Future end([dynamic chunk, String encoding]) { + Completer completer = new Completer(); + _writable.end(chunk, encoding, allowInterop(completer.complete)); + return completer.future; + } + + Future write(dynamic chunk, [String encoding]) { + Completer completer = new Completer(); + _writable.write(chunk, encoding, allowInterop(completer.complete)); + return completer.future; + } + + void _onDrainEvent([dynamic event = null]) => _drain.add(event); + void _onErrorEvent([NativeJsError error = null]) => + _error.add(new Error.fromNativeJsError(error)); + void _onFinishEvent([dynamic event = null]) => _finish.add(event); + void _onPipeEvent(Readable readable) => _pipe.add(readable); + void _onUnPipeEvent(Readable readable) => _unpipe.add(readable); + + void _initAllStreamController() { + _drain = new StreamController(sync: true); + on('drain', _onDrainEvent); + _error = new StreamController(sync: true); + on('error', _onErrorEvent); + _finish = new StreamController(sync: true); + on('finish', _onFinishEvent); + _pipe = new StreamController(sync: true); + on('pipe', _onPipeEvent); + _unpipe = new StreamController(sync: true); + on('unpipe', _onUnPipeEvent); + } +} diff --git a/lib/src/util.dart b/lib/src/util.dart new file mode 100644 index 0000000..669a17f --- /dev/null +++ b/lib/src/util.dart @@ -0,0 +1,53 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +@JS() +external set _util(NativeJsObject value); +@JS() +external NativeJsObject get _util; + +void _requireUtil() { + if (_util == null) { + _util = require("util"); + } +} + +@JS('util') +external NativeJsUtil get _jsUtil; + +Util util = new Util.fromNativeJsUtil(_jsUtil); + +@JS() +@anonymous +class InspectOptions { + external factory InspectOptions( + {bool showHidden: false, + int depth: 2, + bool colors: false, + bool customInspect: true}); + + external bool get showHidden; + external int get depth; + external bool get colors; + external bool get customInspect; +} + +@JS('util') +class NativeJsUtil { + external String inspect(NativeJsObject object, InspectOptions options); + external void log(String message); +} + +class Util { + NativeJsUtil _util; + + Util.fromNativeJsUtil(this._util) { + _requireUtil(); + } + + String inspect(DartJsObject object, InspectOptions options) => + _util.inspect(object.jsObject, options); + void log(String message) => _util.log(message); +} diff --git a/lib/src/utils.dart b/lib/src/utils.dart new file mode 100644 index 0000000..d242652 --- /dev/null +++ b/lib/src/utils.dart @@ -0,0 +1,10 @@ +// Copyright (c) 2016, GrimShield. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +part of nodejs; + +Map convertNativeJsObjectToMap(NativeJsObject object) => + JSON.decode(stringify(object)); + +NativeJsObject convertMapToNativeJsObject(Map map) => + parse(JSON.encode(map)); diff --git a/lib/transformer.dart b/lib/transformer.dart new file mode 100644 index 0000000..ed55e18 --- /dev/null +++ b/lib/transformer.dart @@ -0,0 +1,57 @@ +import 'dart:async'; +import 'package:barback/barback.dart'; + +class ElectronTransformer extends Transformer { + ElectronTransformer.asPlugin(); + + @override + String get allowedExtensions => ".dart.js"; + + @override + Future apply(Transform transform) async { + String content = await transform.primaryInput.readAsString(); + AssetId id = transform.primaryInput.id; + String newContent = pre + d8 + content; + transform.addOutput(new Asset.fromString(id, newContent)); + } +} + +const String pre = r''' +var GLOBAL; +try { + GLOBAL = global +} catch (e) { + GLOBAL = {}; +} +GLOBAL.nodejs = {}; +try { + GLOBAL.nodejs.dirname = __dirname; +} catch (e) {} +try { +GLOBAL.nodejs.filename = __filename; +} catch (e) {} +try { +GLOBAL.nodejs.module = module; +} catch (e) {} +try { +GLOBAL.nodejs.require = require; +} catch (e) {} +'''; + +/// From: $(DART_SDK)/lib/_internal/compiler/js_lib/preambles/d8.js +const String d8 = r''' +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// Javascript preamble, that lets the output of dart2js run on V8's d8 shell. +// Node wraps files and provides them with a different `this`. The global +// `this` can be accessed through `global`. +var self = this; +if (typeof global != "undefined") self = global; // Node.js. +global.setObjectValueAtIndex = (obj, index, value) =>{ + obj[index] = value; +}; +global.getObjectValueAtIndex = (obj, index) => { + return obj[index]; +}; +'''; diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..7b22b8a --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,15 @@ +name: nodejs +version: 0.0.1 +description: NodeJS wrapper for dart +author: GrimShield +homepage: https://gitlab.com/grimshield/nodejs.dart + +environment: + sdk: '>=1.0.0 <2.0.0' + +dependencies: + barback: '>=0.15.2 <0.16.0' + js: '>=0.6.0 <0.7.0' + +dev_dependencies: + test: '>=0.12.0 <0.13.0' diff --git a/test/node_dart_test.dart b/test/node_dart_test.dart new file mode 100644 index 0000000..483bd49 --- /dev/null +++ b/test/node_dart_test.dart @@ -0,0 +1,9 @@ +// Copyright (c) 2016, NodeDart Authors. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +library node_dart.test; + +// import 'package:node_dart/node_dart.dart'; +// import 'package:test/test.dart'; + +void main() {}