Skip to content

Commit f485929

Browse files
Liatshemsedinov
authored andcommitted
Pass context to function instead of global sandbox
Closes: #150 PR-URL: #154
1 parent 278c307 commit f485929

4 files changed

Lines changed: 23 additions & 47 deletions

File tree

api/introspection.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
(application.introspection);
1+
(application.introspect);

lib/application.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const { path, events, vm, fs, fsp } = api;
55
const security = require('./security.js');
66

77
const SCRIPT_OPTIONS = { timeout: 5000 };
8+
const EMPTY_CONTEXT = Object.freeze({});
89
const DIRS = ['static', 'domain', 'api'];
910

1011
class Application extends events.EventEmitter {
@@ -17,6 +18,7 @@ class Application extends events.EventEmitter {
1718
}
1819

1920
async init() {
21+
this.createSandbox();
2022
for (const name of DIRS) {
2123
this[name] = new Map();
2224
await this.loadPlace(name, path.join(this.path, name));
@@ -29,17 +31,15 @@ class Application extends events.EventEmitter {
2931
}
3032

3133
createSandbox() {
32-
const introspection = async () => [...this.api.keys()];
33-
const context = Object.freeze({});
34-
const application = { security, context, introspection };
34+
const introspect = async () => [...this.api.keys()];
35+
const application = { security, introspect };
3536
for (const name of this.namespaces) application[name] = this[name];
3637
const sandbox = {
3738
console: this.logger, Buffer, application, api,
3839
setTimeout, setImmediate, setInterval,
3940
clearTimeout, clearImmediate, clearInterval,
4041
};
41-
sandbox.global = sandbox;
42-
return vm.createContext(sandbox);
42+
this.sandbox = vm.createContext(sandbox);
4343
}
4444

4545
sandboxInject(name, module) {
@@ -49,21 +49,21 @@ class Application extends events.EventEmitter {
4949

5050
async createScript(fileName) {
5151
const code = await fsp.readFile(fileName, 'utf8');
52-
const src = '\'use strict\';\n' + code;
52+
const src = '\'use strict\';\ncontext => ' + code;
5353
const options = { filename: fileName, lineOffset: -1 };
5454
try {
55-
return new vm.Script(src, options);
55+
const script = new vm.Script(src, options);
56+
return script.runInContext(this.sandbox, SCRIPT_OPTIONS);
5657
} catch (err) {
5758
this.logger.error(err.stack);
5859
return null;
5960
}
6061
}
6162

6263
runScript(methodName, session) {
63-
const { sandbox } = session || this;
6464
const script = this.api.get(methodName);
6565
if (!script) return null;
66-
const exp = script.runInContext(sandbox, SCRIPT_OPTIONS);
66+
const exp = script(session ? session.context : EMPTY_CONTEXT);
6767
return typeof exp !== 'object' ? { access: 'logged', method: exp } : exp;
6868
}
6969

@@ -89,11 +89,10 @@ class Application extends events.EventEmitter {
8989
}
9090
if (place === 'domain') {
9191
const config = this.config.sections[name];
92-
const sandbox = this.domainSandbox;
93-
sandbox.application[name] = { config };
94-
const exp = script.runInContext(sandbox, SCRIPT_OPTIONS);
92+
this.sandbox.application[name] = { config };
93+
const exp = script(EMPTY_CONTEXT);
9594
if (config) exp.config = config;
96-
sandbox.application[name] = exp;
95+
this.sandbox.application[name] = exp;
9796
this.sandboxInject(name, exp);
9897
if (exp.start) exp.start();
9998
} else {

lib/auth.js

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@ const FUTURE = 'Fri, 01 Jan 2100 00:00:00 GMT';
1616
const LOCATION = 'Path=/; Domain';
1717
const COOKIE_DELETE = `${TOKEN}=deleted; Expires=${EPOCH}; ${LOCATION}=`;
1818
const COOKIE_HOST = `Expires=${FUTURE}; ${LOCATION}`;
19-
const SANDBOX_POOL = 20;
2019

2120
const sessions = new Map();
2221
const cache = new WeakMap();
23-
const pool = [];
2422

2523
const generateToken = () => {
2624
const base = ALPHA_DIGIT.length;
@@ -46,45 +44,29 @@ const parseCookies = cookie => {
4644
};
4745

4846
module.exports = () => {
49-
let timer = null;
5047
const { db } = application;
5148

52-
const fillPool = () => {
53-
const need = SANDBOX_POOL - pool.length;
54-
for (let i = 0; i < need; i++) {
55-
pool.push(application.createSandbox());
56-
}
57-
};
58-
59-
const getSandbox = () => {
60-
if (timer === null) {
61-
timer = setTimeout(() => {
62-
fillPool();
63-
timer = null;
64-
}, 0);
65-
}
66-
if (pool.length > 0) return pool.pop();
67-
return application.createSandbox();
68-
};
69-
7049
const save = (token, context) => {
7150
const data = JSON.stringify(context);
7251
db.update('Session', { data }, { token });
7352
};
7453

7554
class Session {
76-
constructor(token, sandbox, contextData = { token }) {
55+
constructor(token, contextData = { token }) {
7756
const contextHandler = {
57+
get: (data, key) => {
58+
if (key === 'token') return this.token;
59+
return Reflect.get(data, key);
60+
},
7861
set: (data, key, value) => {
7962
const res = Reflect.set(data, key, value);
8063
save(token, this.data);
8164
return res;
8265
}
8366
};
8467
this.token = token;
85-
this.sandbox = sandbox;
8668
this.data = contextData;
87-
sandbox.context = new Proxy(contextData, contextHandler);
69+
this.context = new Proxy(contextData, contextHandler);
8870
}
8971
}
9072

@@ -93,8 +75,7 @@ module.exports = () => {
9375
const host = common.parseHost(client.req.headers.host);
9476
const ip = client.req.connection.remoteAddress;
9577
const cookie = `${TOKEN}=${token}; ${COOKIE_HOST}=${host}; HttpOnly`;
96-
const sandbox = getSandbox();
97-
const session = new Session(token, sandbox);
78+
const session = new Session(token);
9879
sessions.set(token, session);
9980
cache.set(client.req, session);
10081
const data = JSON.stringify(session.data);
@@ -109,15 +90,14 @@ module.exports = () => {
10990
const { cookie } = client.req.headers;
11091
if (!cookie) return null;
11192
const cookies = parseCookies(cookie);
112-
const token = cookies.token;
93+
const { token } = cookies;
11394
if (!token) return null;
11495
let session = sessions.get(token);
11596
if (!session) {
11697
const [record] = await db.select('Session', ['Data'], { token });
11798
if (record && record.data) {
11899
const data = JSON.parse(record.data);
119-
const sandbox = getSandbox();
120-
session = new Session(token, sandbox, data);
100+
session = new Session(token, data);
121101
sessions.set(token, session);
122102
}
123103
}
@@ -141,5 +121,5 @@ module.exports = () => {
141121
.select('SystemUser', ['Id', 'Password'], { login })
142122
.then(([user]) => user);
143123

144-
return { fillPool, start, restore, remove, save, registerUser, getUser };
124+
return Object.freeze({ start, restore, remove, save, registerUser, getUser });
145125
};

lib/worker.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ const initAuth = require('./auth.js');
2727
application.server = new Server(config.sections.server);
2828
application.auth = initAuth();
2929
application.sandboxInject('auth', application.auth);
30-
application.sandbox = application.createSandbox();
31-
application.domainSandbox = application.createSandbox();
3230
await application.init();
33-
application.auth.fillPool();
3431
logger.log(`Application started in worker ${worker.threadId}`);
3532

3633
worker.parentPort.on('message', async message => {

0 commit comments

Comments
 (0)