Skip to content
This repository was archived by the owner on Jul 3, 2020. It is now read-only.

Commit 6278e61

Browse files
committed
Merge pull request #93 from runtimejs/node-support
Node support - Work In Progress
2 parents d9be22d + 749b11b commit 6278e61

15 files changed

+615
-19
lines changed

js/__loader.js

+36-2
Original file line numberDiff line numberDiff line change
@@ -265,15 +265,19 @@
265265
events: 'events',
266266
buffer: 'buffer',
267267
process: './modules/process.js',
268+
console: './modules/console.js',
268269
constants: 'constants-browserify',
269270
fs: './modules/fs.js',
270271
os: './modules/os.js',
272+
__errors__: './modules/errors.js',
273+
net: './modules/net.js',
274+
dns: './modules/dns.js',
271275
punycode: 'punycode',
272276
querystring: 'querystring-es3',
273277
string_decoder: 'string_decoder',
274278
path: 'path-browserify',
275279
url: 'url',
276-
stream: 'stream-browserify',
280+
stream: './modules/stream.js',
277281
inherits: './modules/inherits.js',
278282
sys: 'util/util.js',
279283
util: 'util/util.js'
@@ -284,6 +288,36 @@
284288

285289
global.process = loader.require('process');
286290
global.Buffer = loader.require('buffer').Buffer;
291+
const stream = loader.require('stream');
292+
class StdoutStream extends stream.Writable {
293+
_write(chunk, encoding, callback) {
294+
__SYSCALL.write(String(chunk));
295+
callback();
296+
}
297+
}
298+
class StderrStream extends stream.Writable {
299+
_write(chunk, encoding, callback) {
300+
__SYSCALL.write(String(chunk));
301+
callback();
302+
}
303+
}
304+
class TermoutStream extends stream.Writable {
305+
_write(chunk, encoding, callback) {
306+
runtime.stdio.defaultStdio.write(String(chunk));
307+
callback();
308+
}
309+
}
310+
class TermerrStream extends stream.Writable {
311+
_write(chunk, encoding, callback) {
312+
runtime.stdio.defaultStdio.writeError(String(chunk));
313+
callback();
314+
}
315+
}
316+
process.stdout = new StdoutStream();
317+
process.stderr = new StderrStream();
318+
process.termout = new TermoutStream();
319+
process.termerr = new TermerrStream();
320+
loader.require('console');
321+
Object.assign(global, loader.require('__errors__'));
287322
loader.require('/');
288323
})();
289-

js/component/dns-client/dns-packet.js

+17-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,19 @@ var isDomain = require('./is-domain');
1818
var PacketReader = require('./packet-reader');
1919
var randomId = 0x3322;
2020

21-
exports.getQuery = function(domain) {
21+
var queries = {
22+
'A': 0x01,
23+
'NS': 0x02,
24+
'CNAME': 0x05,
25+
'PTR': 0x0C,
26+
'MX': 0x0F,
27+
'SRV': 0x21,
28+
'SOA': 0x06,
29+
'TXT': 0x0A
30+
}
31+
32+
exports.getQuery = function(domain, query) {
33+
// query isn't used (for now)
2234
assert(isDomain(domain));
2335

2436
var bufferLength = 17;
@@ -51,9 +63,9 @@ exports.getQuery = function(domain) {
5163
view.setUint8(offset++, label.charCodeAt(j));
5264
}
5365
}
54-
view.setUint8(offset++, 0);
66+
view.setUint8(offset++, 0); // null terminator
5567

56-
view.setUint16(offset + 0, 1, false); // Type A query (host address)
68+
view.setUint16(offset + 0, queries[query], false); // Type A query (host address)
5769
view.setUint16(offset + 2, 1, false); // Query IN (Internet address)
5870
return u8;
5971
};
@@ -129,15 +141,15 @@ exports.parseResponse = function(u8) {
129141
var bytes = [];
130142

131143
switch (recordType) {
132-
case 1: // A record
144+
case queries.A: // A record
133145
if (4 !== rdLen) {
134146
return null;
135147
}
136148

137149
results.push({hostname: host, record: 'A', address: [reader.readUint8(), reader.readUint8(),
138150
reader.readUint8(), reader.readUint8()], ttl: ttl });
139151
break;
140-
case 5: // CNAME record
152+
case queries.CNAME: // CNAME record
141153
results.push({hostname: host, record: 'CNAME', name: readHostname(reader).join('.')});
142154
break;
143155
default:

js/component/dns-client/index.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ function DNSClient(serverIP, serverPort) {
7272
}
7373

7474
if (req.retry > 0) {
75-
self._sendQuery(req.domain);
75+
self._sendQuery(req.domain, req.opts.query || 'A');
7676
--req.retry;
7777
} else {
7878
req.cb(new Error('E_FAILED'));
@@ -85,8 +85,8 @@ function DNSClient(serverIP, serverPort) {
8585
}, 1000);
8686
}
8787

88-
DNSClient.prototype._sendQuery = function(domain) {
89-
var query = dnsPacket.getQuery(domain);
88+
DNSClient.prototype._sendQuery = function(domain, type) {
89+
var query = dnsPacket.getQuery(domain, type);
9090
this._socket.send(this._serverIP, this._serverPort, query);
9191
};
9292

@@ -95,7 +95,7 @@ DNSClient.prototype.resolve = function(domain, opts, cb) {
9595
assert(typeutils.isString(domain));
9696
assert(typeutils.isFunction(cb));
9797

98-
this._sendQuery(domain);
98+
this._sendQuery(domain, opts.query || 'A');
9999
this._requests.push({
100100
domain: domain,
101101
retry: 3,

js/core/net/interfaces.js

+4
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,7 @@ exports.getByName = function(intfName) {
3737
exports.forEach = function(fn) {
3838
intfs.forEach(fn);
3939
};
40+
41+
exports.getAll = function() {
42+
return intfs;
43+
}

js/modules/console.js

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2015-present runtime.js project authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
'use strict';
15+
16+
const util = require('util');
17+
18+
class Console {
19+
constructor(stdout, stderr) {
20+
if (!stdout) throw new Error('Console: Must provide a stdout stream to the constructor.');
21+
this._stdout = stdout;
22+
if (stderr) this._stderr = stderr;
23+
this._labels = {};
24+
}
25+
assert(val, ...data) {
26+
if (!val) throw new Error(util.format(...data));
27+
}
28+
dir(obj, opts) {
29+
opts = opts || {};
30+
opts.customInspect = true;
31+
this._stdout.write(util.inspect(obj, opts));
32+
}
33+
error(...data) {
34+
const out = this._stderr || this._stdout;
35+
out.write(`${util.format(...data)}\n`);
36+
}
37+
log(...data) {
38+
this._stdout.write(`${util.format(...data)}\n`);
39+
}
40+
time(label) {
41+
if (!label) label = 'undefined';
42+
this._labels[label] = Date.now();
43+
}
44+
timeEnd(label) {
45+
if (!label) label = 'undefined'
46+
if (!this._labels[label]) throw new Error('Console.timeEnd: Label does not exist.');
47+
this._stdout.write(`${label}: ${Date.now()-this._labels[label]}ms\n`);
48+
}
49+
trace(...data) {
50+
let trace = (new Error()).stack;
51+
let arr = trace.split('\n');
52+
arr[0] = 'Trace';
53+
if (data.length > 0) arr[0] += `: ${util.format(...data)}`;
54+
trace = arr.join('\n');
55+
this._stdout.write(`${trace}\n`);
56+
}
57+
info(...data) {
58+
this.log(...data);
59+
}
60+
warn(...data) {
61+
this.error(...data);
62+
}
63+
}
64+
65+
module.exports = Console;
66+
global.console = new Console(process.stdout, process.stderr);

js/modules/dns.js

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright 2015-present runtime.js project authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
'use strict';
15+
16+
Object.assign(exports, {
17+
NODATA: 'ENODATA',
18+
BADFAMILY: 'EBADFAMILY',
19+
FORMERR: 'EFORMERR',
20+
SERVFAIL: 'ESERVFAIL',
21+
NOTFOUND: 'ENOTFOUND',
22+
NOTIMP: 'ENOTIMP',
23+
REFUSED: 'EREFUSED',
24+
BADQUERY: 'EBADQUERY',
25+
BADNAME: 'EBADNAME',
26+
BADRESP: 'EBADRESP',
27+
CONNREFUSED: 'ECONNREFUSED',
28+
TIMEOUT: 'ETIMEOUT',
29+
EOF: 'EEOF',
30+
FILE: 'EFILE',
31+
NOMEM: 'ENOMEM',
32+
DESTRUCTION: 'EDESTRUCTION',
33+
BADSTR: 'EBADSTR',
34+
BADFLAGS: 'EBADFLAGS',
35+
NONAME: 'ENONAME',
36+
BADHINTS: 'EBADHINTS',
37+
NOTINITIALIZED: 'ENOTINITIALIZED',
38+
LOADIPHLPAPI: 'ELOADIPHLPAPI',
39+
ADDRGETNETWORKPARAMS: 'EADDRGETNETWORKPARAMS',
40+
CANCELLED: 'ECANCELLED'
41+
});
42+
43+
let servers = [
44+
'8.8.8.8'
45+
];
46+
47+
function lookup(hostname, opts, cb) {
48+
if (opts.family && opts.family === 6) return throwIPv6Err(cb);
49+
opts.query = opts.query || 'A';
50+
if (hostname === 'localhost' && opts.query === 'A') {
51+
if (!opts.all) {
52+
if (cb) cb(null, '127.0.0.1', 4);
53+
} else {
54+
if (opts.addrOnly) {
55+
if (cb) cb(null, ['127.0.0.1']);
56+
} else {
57+
if (cb) cb(null, [{address: '127.0.0.1', family: 4}]);
58+
}
59+
}
60+
return;
61+
}
62+
runtime.dns.resolve(hostname, {
63+
query: opts.query
64+
}, function(err, data) {
65+
if (err) {
66+
if (cb) cb(err, null, null);
67+
return;
68+
}
69+
var res;
70+
var ret = [];
71+
for (var i = 0; i < data.results.length; i++) {
72+
res = data.results[i];
73+
if (!opts.all && i === 0) {
74+
var addr = res.address.join('.');
75+
if (cb) cb(null, addr, 4);
76+
break;
77+
} else {
78+
switch (res.record) {
79+
case 'A':
80+
if (opts.addrOnly) {
81+
ret.push(res.address.join('.'));
82+
} else {
83+
ret.push({
84+
address: res.address.join('.'),
85+
family: 4
86+
});
87+
}
88+
break;
89+
}
90+
}
91+
}
92+
if (ret.length === 0) {
93+
if (cb) cb(new SystemError('dns query failed', exports.NODATA, 'runtime.dns.resolve'), null);
94+
return;
95+
}
96+
if (cb) cb(null, ret);
97+
});
98+
}
99+
100+
function throwIPv6Err(cb) {
101+
var err = new SystemError('runtime doesn\'t support IPv6', exports.BADFAMILY);
102+
if (cb) return cb(err);
103+
throw err;
104+
}
105+
106+
exports.getServers = function() {
107+
return servers;
108+
}
109+
110+
exports.lookup = function(hostname, opts, cb) {
111+
if (typeof opts === 'function') {
112+
cb = opts;
113+
opts = null;
114+
}
115+
if (typeof opts === 'undefined' || opts === null) opts = {};
116+
if (typeof opts === 'number' || opts instanceof Number) {
117+
opts = {
118+
family: opts
119+
};
120+
}
121+
122+
return lookup(hostname, opts, cb);
123+
}
124+
125+
exports.resolve4 = function(hostname, cb) {
126+
return lookup(hostname, {
127+
all: true,
128+
addrOnly: true
129+
}, cb);
130+
}
131+
132+
exports.resolve6 = function(hostname, cb) {
133+
throwIPv6Err(cb);
134+
}
135+
136+
exports.resolve = function(hostname, rrtype, cb) {
137+
if (typeof rrtype === 'function') {
138+
cb = rrtype;
139+
rrtype = null;
140+
}
141+
if (typeof rrtype === 'undefined' || rrtype === null) rrtype = 'A';
142+
switch (rrtype) {
143+
case 'A':
144+
return exports.resolve4(hostname, cb);
145+
break;
146+
case 'AAAA':
147+
return exports.resolve6(hostname, cb);
148+
break;
149+
}
150+
}

js/modules/errors.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2015-present runtime.js project authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
'use strict';
15+
16+
exports.Error = Error;
17+
18+
class SystemError {
19+
constructor(message, errcode, call) {
20+
var msg = '';
21+
if (errcode) msg += `${errcode}: `;
22+
if (message) msg += message;
23+
if (call) msg += `, ${call}`;
24+
var err = new Error(msg);
25+
err.code = errcode || '';
26+
err.syscall = call || '';
27+
return err;
28+
}
29+
}
30+
31+
exports.SystemError = SystemError;

0 commit comments

Comments
 (0)