Documentation ¶
Index ¶
- Constants
- Variables
- func Initialize(m *plugin.Manager) (plugin.Plugin, error)
- type Process
- func (p *Process) CloseInput() error
- func (p *Process) Done() bool
- func (p *Process) Error() string
- func (p *Process) ExitCode() int
- func (p *Process) Input(input string) error
- func (p *Process) Kill() error
- func (p *Process) Output() string
- func (p *Process) PID() (int, error)
- func (p *Process) Result() (*os.ProcessState, error)
- func (p *Process) Run()
- func (p *Process) Start()
Constants ¶
View Source
const PluginName = "node_compat"
Variables ¶
View Source
var ChildProcess = &vm.Module{
Name: "child_process",
Main: "index",
Path: "child_process",
Body: `
import EventEmitter from 'events';
const runCommand = async (proc) => {
proc.Run();
await proc.Result();
return proc;
}
export const spawn = (command, args, opts) => {
if(typeof(exec) === 'undefined') {
throw new Error("node_compat: cannot start child process: exec must be enabled");
}
let child = new class extends EventEmitter {
constructor() {
super();
this.proc = exec.Command(command, ...(args || []));
this.stdout = new EventEmitter();
this.stderr = new EventEmitter();
this.stdin = {
write: (input) => {
this.proc.Input(input);
},
end: () => {
return this.proc.CloseInput();
},
};
}
};
setTimeout(() => {
runCommand(child.proc).catch((e) => {
console.log('error running child_process', e);
}).finally(res => {
child.stdout.emit('data', child.proc.Output());
child.stderr.emit('data', child.proc.Error());
child.emit('close', child.proc.ExitCode());
});
}, 10);
return child;
};
`,
}
ChildProcess is a polyfill for the child_process node module.
View Source
var Crypto = &vm.Module{
Name: "crypto",
Main: "index",
Path: "crypto",
Body: `
import {Buffer} from 'buffer';
class Sha1 {
constructor() {
this.data = Buffer.alloc(0);
}
update(data) {
this.data.write(data);
return this;
}
digest(kind) {
switch(kind) {
case 'hex':
return sha1.Sum(this.data.toString());
default:
throw new Error('unsupported digest format: '+kind);
}
}
}
export const createHash = (kind) => {
switch(kind) {
case 'sha1':
return new Sha1();
default:
throw new Error('unsupported hash algo: '+kind);
}
};`,
}
Crypto is a polyfill providing some functionality from the node crypto module.
View Source
var EventEmitter = &vm.Module{
Name: "events",
Main: "index",
Path: "events",
Body: `/* Polyfill EventEmitter. */
var EventEmitter = function () {
this.events = {};
};
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype.on = function (event, listener) {
if (typeof this.events[event] !== 'object') {
this.events[event] = [];
}
this.events[event].push(listener);
};
EventEmitter.prototype.removeListener = function (event, listener) {
var idx;
if (typeof this.events[event] === 'object') {
idx = this.events[event].indexOf(listener);
if (idx > -1) {
this.events[event].splice(idx, 1);
}
}
};
EventEmitter.prototype.emit = function (event) {
var i, listeners, length, args = [].slice.call(arguments, 1);
if (typeof this.events[event] === 'object') {
listeners = this.events[event].slice();
length = listeners.length;
for (i = 0; i < length; i++) {
listeners[i].apply(this, args);
}
}
};
EventEmitter.prototype.once = function (event, listener) {
this.on(event, function g () {
this.removeListener(event, g);
listener.apply(this, arguments);
});
};
EventEmitter.prototype.listenerCount = function (event) {
if(!this.events[event]) {
return 0;
}
return this.events[event].length;
};
module.exports = EventEmitter;`,
}
EventEmitter is a polyfill for the node events module. See https://gist.github.com/mudge/5830382 Modified to add listenerCount instance method.
View Source
var Http = &vm.Module{
Name: "http",
Main: "index",
Path: "http",
Body: `
import EventEmitter from 'events';
import {Server as NetServer} from 'net';
export class Server extends NetServer {
constructor(options, requestListener) {}
setTimeout(timeout, callback = null) {}
get maxHeadersCount() {}
get timeout() {}
get headersTimeout() {}
get keepAliveTimeout() {}
}
export class OutgoingMessage {
get upgrading() {}
get chunkedEncoding() {}
get shouldKeepAlive() {}
get useChunkedEncodingByDefault() {}
get sendDate() {}
get finished() {}
get headersSent() {}
get connection() {}
constructor() {}
setTimeout(timeout, callback = null) {}
setHeader(name, value) {}
getHeader(name) {}
getHeaders() {}
getHeaderNames() {}
hasHeader(name) {}
removeHeader(name) {}
addTrailers(headers) {}
flushHeaders() {}
}
export class ServerResponse extends OutgoingMessage {
get statusCode() {}
get statusMessage() {}
constructor(req) {}
assignSocket(socket) {}
detachSocket(socket) {}
writeContinue(callback) {}
writeHead(statusCode, reasonPhrase, headers = null) {}
}
export class ClientRequest extends OutgoingMessage {
get connection() {}
get socket() {}
get aborted() {}
constructor(uri, callback = null) {}
get path() {}
abort() {}
onSocket(socket) {}
setTimeout(timeout, callback = null) {}
setNoDelay(noDelay) {}
setSocketKeepAlive(enable, initialDelay = null) {}
}
class IncomingMessage {
constructor(socket) {}
get httpVersion() {}
get httpVersionMajor() {}
get httpVersionMinor() {}
get connection() {}
get headers() {}
get rawHeaders() {}
get trailers() {}
get rawTrailers() {}
setTimeout(timeout, callback = null) {}
get method() {}
get url() {}
get statusCode() {}
get statusMessage() {}
get socket() {}
destroy() {}
}
class Agent {
get maxFreeSockets() {
}
get maxSockets() {}
get sockets() {}
get requests() {}
constructor(options) {}
destroy() {}
}
export const METHODS = [];
export const STATUS_CODES = {};
export function createServer(options, requestListener) {}
export function request(options, callback) {}
export function get(options, callback) {}
export let globalAgent;
export const maxHeaderSize;
`,
}
Http is a polyfill for the node http module.
View Source
var Net = &vm.Module{
Name: "net",
Main: "index",
Path: "net",
Body: `
import {Duplex} from 'stream';
import {Buffer} from 'buffer';
import {EventEmitter} from 'events';
const goAddrToNode = addr => {
// todo: support ipv6 addresses, udp, ipc, etc
let parts = addr.String().split(':');
return {
host: parts[0],
port: parseInt(parts[1]),
family: addr.Network(),
};
};
export class Socket extends Duplex {
constructor(options = {}) {
super(options);
this.options = options || {};
this._connection = null;
this._local = null;
this._remote = null;
this._connecting = false;
this.on('ready', () => {
this._connecting = false;
this._local = goAddrToNode(this._connection.LocalAddr());
this._remote = goAddrToNode(this._connection.RemoteAddr());
});
}
_read(size = null) {
if(!this._connection) {
return;
}
let result = this._connection.Read(size);
let wait = 1;
let check = () => {
if(result.Ready()) {
let data = result.Value();
if(data !== null && data.length) {
this.push(data);
} else {
this.push(null);
}
} else {
if(wait < 64) {
wait *= 2;
}
setTimeout(check, wait);
}
};
check();
}
_write(buffer, encoding, callback) {
if(!this._connection) {
callback(Error('not connected'));
return;
}
let err = null;
try {
this._connection.Write(buffer);
} catch(e) {
err = e;
} finally {
callback(err);
}
}
async connect(options, listener = null) {
// todo: support ipc
// todo: udp is defined in Node's dgram module
if(listener !== null) {
this.once('connect', listener);
}
let host = options.host || 'localhost';
let port = options.port;
if(!port) {
throw new Error('ipc connections are unsupported');
}
console.log('dialing', host + ':' + port);
this._connecting = true;
this._connection = native.Dial('tcp', host + ':' + port);
this.emit('connect');
this.emit('ready');
}
setEncoding(encoding) {
this.encoding = encoding;
}
_destroy(callback) {
let err = null;
try {
this._connection.Close();
} catch(e) {
err = e;
console.log('error destroying', err.toString());
} finally {
this._connection = null;
if(callback) {
callback(err);
}
}
}
// setTimeout(timeout, callback = null) {}
// setNoDelay(noDelay) {}
// setKeepAlive(keepAlive) {}
// address() {}
// unref() {}
// ref() {}
//
// get bufferSize() {}
// get bytesRead() {}
// get bytesWritten() {}
get connecting() {
return this._connecting;
}
get localAddress() {
if(!this._connection) {
return null;
}
return this._local.host;
}
get localPort() {
if(!this._connection) {
return null;
}
return this._local.port;
}
get remoteAddress() {
if(!this._connection) {
return null;
}
return this._remote.host;
}
get remoteFamily() {
if(!this._connection) {
return null;
}
return this._remote.family;
}
get remotePort() {
if(!this._connection) {
return null;
}
return this._remote.port;
}
}
export class Server extends EventEmitter {
constructor(listener = null) {
super();
if(listener !== null) {
this.on('connection', listener);
}
this._server = null;
}
listen(port, hostname, listener = null) {
if(listener !== null) {
this.on('connection', listener);
}
let addr = hostname + ':' + port;
let accept = (conn) => {
let socket = new Socket();
socket._connection = conn;
socket.on('end', () => {
console.log('server ended');
socket.destroy();
});
socket.emit('connect');
this.emit('connection', socket);
socket.emit('ready');
};
this._server = native.Listen(accept, 'tcp4', addr);
this.emit('listening');
}
close(callback = null) {
this._server.Close();
this.emit('close');
if(callback !== null) {
callback();
}
}
address() {
return goAddrToNode(this._server.Addr());
}
getConnections(callback) {}
ref() {}
unref() {}
get maxConnections() {}
get connections() {}
get listening() {}
}
//
// export function createServer(options = null, connectionListener = null) {}
//
// export function connect(options, connectionListener = null) {}
//
// export function createConnection(options, connectionListener = null) {}
//
// export function isIP(input) {}
//
// export function isIPv4(input) {}
//
// export function isIPv6(input) {}
`,
}
Net is a polyfill for the node net module.
View Source
var Stream = &vm.Module{
Name: "stream",
Main: "index.js",
Path: "stream",
Body: `// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
module.exports = Stream;
var EE = require('events').EventEmitter;
var inherits = require('inherits');
inherits(Stream, EE);
Stream.Readable = require('readable-stream/lib/_stream_readable.js');
Stream.Writable = require('readable-stream/lib/_stream_writable.js');
Stream.Duplex = require('readable-stream/lib/_stream_duplex.js');
Stream.Transform = require('readable-stream/lib/_stream_transform.js');
Stream.PassThrough = require('readable-stream/lib/_stream_passthrough.js');
Stream.finished = require('readable-stream/lib/internal/streams/end-of-Stream.js')
Stream.pipeline = require('readable-stream/lib/internal/streams/pipeline.js')
// Backwards-compat with node 0.4.x
Stream.Stream = Stream;
// old-style streams. Note that the pipe method (the only relevant
// part of this class) is overridden in the Readable class.
function Stream() {
EE.call(this);
}
Stream.prototype.pipe = function(dest, options) {
var source = this;
function ondata(chunk) {
if (dest.writable) {
if (false === dest.write(chunk) && source.pause) {
source.pause();
}
}
}
source.on('data', ondata);
function ondrain() {
if (source.readable && source.resume) {
source.resume();
}
}
dest.on('drain', ondrain);
// If the 'end' option is not supplied, dest.end() will be called when
// source gets the 'end' or 'close' events. Only dest.end() once.
if (!dest._isStdio && (!options || options.end !== false)) {
source.on('end', onend);
source.on('close', onclose);
}
var didOnEnd = false;
function onend() {
if (didOnEnd) return;
didOnEnd = true;
dest.end();
}
function onclose() {
if (didOnEnd) return;
didOnEnd = true;
if (typeof dest.destroy === 'function') dest.destroy();
}
// don't leave dangling pipes when there are errors.
function onerror(er) {
cleanup();
if (EE.listenerCount(this, 'error') === 0) {
throw er; // Unhandled Stream error in pipe.
}
}
source.on('error', onerror);
dest.on('error', onerror);
// remove all the event listeners that were added.
function cleanup() {
source.removeListener('data', ondata);
dest.removeListener('drain', ondrain);
source.removeListener('end', onend);
source.removeListener('close', onclose);
source.removeListener('error', onerror);
dest.removeListener('error', onerror);
source.removeListener('end', cleanup);
source.removeListener('close', cleanup);
dest.removeListener('close', cleanup);
}
source.on('end', cleanup);
source.on('close', cleanup);
dest.on('close', cleanup);
dest.emit('pipe', source);
// Allow for unix-like usage: A.pipe(B).pipe(C)
return dest;
};`,
}
Stream is based on stream-browserify and relies on readable-stream. See https://github.com/browserify/stream-browserify/blob/v3.0.0/index.js
Functions ¶
Types ¶
type Process ¶
type Process struct {
// contains filtered or unexported fields
}
func NewProcess ¶
func (*Process) CloseInput ¶
Source Files ¶
Click to show internal directories.
Click to hide internal directories.