-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathREPL.js
99 lines (85 loc) · 2.62 KB
/
REPL.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
'use strict';
// Need this to make ''socket.io-client' work
// http://browniefed.com/blog/2015/05/16/react-native-and-socket-dot-io/
if (!window.navigator.userAgent) {
window.navigator.userAgent = 'react-native';
}
const io = require('socket.io-client/socket.io');
const evalMap = {};
/*
* Register a context-bound evaluator. `contextName` is the name the context
* will be looked up by in `evalIn(...)` or `queueEvalIn(...)`. `evaluator`
* should be a function that evaluates its JavaScript code string argument in
* the desired context and returns the result. This is usually `(code) =>
* eval(code)` so that it closes over the desired context.
*/
const registerEval = (contextName, evaluator) => {
evalMap[contextName] = evaluator;
};
/*
* Evaluate the string of JavaScript code `code` in the context named
* `contextName`. The context should have been previously registered with
* `registerEval(...)`. This runs the code synchronously in the thread where
* `evalIn(...)` is called. Use `queueEvalIn` to run on next flush of queued
* evals (usually on the next `'TICK'`).
*/
const evalIn = (contextName, code) => {
if (!evalMap[contextName]) {
throw new Error(`Evaluator context '${contextName}' not registered ` +
` for evalIn(...)`);
}
return evalMap[contextName](code);
};
const evalInQueue = [];
/*
* Like `evalIn(...)`, except it queues the code for execution the next time the
* eval queue is flushed (usually on the next `'TICK'`).
*/
const queueEvalIn = (contextName, code) => {
evalInQueue.push({ contextName, code });
};
/*
* Flush the queued-up evals since the last flush or since the birth of the
* process. This runs all the evals in order queued, synchronously in the thread
* where the function is called. It logs the value of each eval to the console.
* Usually you want to call this once each `'TICK'`.
*/
const flushEvalInQueue = () => {
evalInQueue.forEach(({ module, code}) => {
console.log(window.evalIn(module, code));
});
evalInQueue.length = 0;
};
/*
* Connect to the REPL server.
*/
let socket;
const connect = (url = 'http://nikhileshs-air.local:5000') => {
socket = io(url, { jsonp: false });
socket.on('evalIn', ({ contextName, code }) => {
let result;
let error;
try {
result = evalIn(contextName, code);
} catch (ex) {
error = ex.toString();
}
socket.emit('evalResult', { result, error });
});
};
/*
* Log to the REPL server.
*/
const log = (obj) => {
socket.emit('log', obj);
};
const repl = {
evalIn,
queueEvalIn,
registerEval,
flushEvalInQueue,
connect,
log,
};
window.repl = repl;
export default repl;