Skip to content

Commit 1ff2b24

Browse files
Robert Jacksonkrisselden
andcommitted
Share script bytecode across vm contexts.
Avoid reevaluating the app files and vendor files from scratch for each visit request. Co-authored-by: Kris Selden <[email protected]>
1 parent 8789fc5 commit 1ff2b24

5 files changed

Lines changed: 62 additions & 53 deletions

File tree

src/ember-app.js

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const fs = require('fs');
4+
const vm = require('vm');
45
const path = require('path');
56
const chalk = require('chalk');
67

@@ -37,8 +38,6 @@ class EmberApp {
3738
let distPath = (this.distPath = path.resolve(options.distPath));
3839
let config = this.readPackageJSON(distPath);
3940

40-
this.appFilePaths = config.appFiles;
41-
this.vendorFilePaths = config.vendorFiles;
4241
this.moduleWhitelist = config.moduleWhitelist;
4342
this.hostWhitelist = config.hostWhitelist;
4443
this.config = config.config;
@@ -61,6 +60,11 @@ class EmberApp {
6160
this.html = fs.readFileSync(config.htmlFile, 'utf8');
6261

6362
this.sandboxRequire = this.buildWhitelistedRequire(this.moduleWhitelist, distPath);
63+
let filePaths = [require.resolve('./scripts/install-source-map-support')].concat(
64+
config.vendorFiles,
65+
config.appFiles
66+
);
67+
this.scripts = buildScripts(filePaths);
6468
}
6569

6670
/**
@@ -176,35 +180,6 @@ class EmberApp {
176180
};
177181
}
178182

179-
/**
180-
* @private
181-
*
182-
* Loads the app and vendor files in the sandbox (Node vm).
183-
*
184-
*/
185-
loadAppFiles(sandbox) {
186-
let appFilePaths = this.appFilePaths;
187-
let vendorFilePaths = this.vendorFilePaths;
188-
189-
sandbox.eval('sourceMapSupport.install(Error);');
190-
191-
debug('evaluating app and vendor files');
192-
193-
vendorFilePaths.forEach(function(vendorFilePath) {
194-
debug('evaluating vendor file %s', vendorFilePath);
195-
let vendorFile = fs.readFileSync(vendorFilePath, 'utf8');
196-
sandbox.eval(vendorFile, vendorFilePath);
197-
});
198-
debug('vendor file evaluated');
199-
200-
appFilePaths.forEach(function(appFilePath) {
201-
debug('evaluating app file %s', appFilePath);
202-
let appFile = fs.readFileSync(appFilePath, 'utf8');
203-
sandbox.eval(appFile, appFilePath);
204-
});
205-
debug('app files evaluated');
206-
}
207-
208183
/**
209184
* @private
210185
*
@@ -247,7 +222,14 @@ class EmberApp {
247222
async buildAppInstance() {
248223
let sandbox = this.buildSandbox();
249224

250-
this.loadAppFiles(sandbox);
225+
debug('adding files to sandbox');
226+
227+
for (let script of this.scripts) {
228+
debug('evaluating file %s', script);
229+
sandbox.runScript(script);
230+
}
231+
232+
debug('files evaluated');
251233

252234
let app = await this.createEmberApp(sandbox).boot();
253235

@@ -525,4 +507,11 @@ function registerFastBootInfo(info, instance) {
525507
info.register(instance);
526508
}
527509

510+
function buildScripts(filePaths) {
511+
return filePaths.filter(Boolean).map(filePath => {
512+
let source = fs.readFileSync(filePath, { encoding: 'utf8' });
513+
514+
return new vm.Script(source, { filename: filePath });
515+
});
516+
}
528517
module.exports = EmberApp;

src/install-source-map-support.js

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/sandbox.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
const chalk = require('chalk');
44
const vm = require('vm');
5+
const sourceMapSupport = require('source-map-support');
6+
57

68
module.exports = class Sandbox {
79
constructor(globals) {
@@ -13,7 +15,6 @@ module.exports = class Sandbox {
1315

1416
buildSandbox() {
1517
let console = this.buildWrappedConsole();
16-
let sourceMapSupport = require('./install-source-map-support');
1718
let URL = require('url');
1819
let globals = this.globals;
1920

@@ -53,6 +54,10 @@ module.exports = class Sandbox {
5354
return wrappedConsole;
5455
}
5556

57+
runScript(script) {
58+
script.runInContext(this.context);
59+
}
60+
5661
eval(source, filePath) {
5762
var fileScript = new vm.Script(source, { filename: filePath });
5863
fileScript.runInContext(this.context);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
/* globals sourceMapSupport */
3+
4+
Error.prepareStackTrace = function prepareStackTrace(error, stack) {
5+
return error + stack.map(frame => '\n at ' + sourceMapSupport.wrapCallSite(frame)).join('');
6+
};
7+
Error.stackTraceLimit = Infinity;
8+
9+
sourceMapSupport.install({
10+
environment: 'node',
11+
handleUncaughtExceptions: false,
12+
});

test/fastboot-test.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,29 @@ describe('FastBoot', function() {
6565
});
6666
});
6767

68+
it('can run multiple visits', async function() {
69+
this.timeout(3000);
70+
71+
var fastboot = new FastBoot({
72+
distPath: fixture('basic-app'),
73+
});
74+
75+
let result = await fastboot.visit('/');
76+
let html = await result.html();
77+
78+
expect(html).to.match(/Welcome to Ember/);
79+
80+
result = await fastboot.visit('/');
81+
html = await result.html();
82+
83+
expect(html).to.match(/Welcome to Ember/);
84+
85+
result = await fastboot.visit('/');
86+
html = await result.html();
87+
88+
expect(html).to.match(/Welcome to Ember/);
89+
});
90+
6891
it('can render HTML with array of app files defined in package.json', function() {
6992
var fastboot = new FastBoot({
7093
distPath: fixture('multiple-app-files'),

0 commit comments

Comments
 (0)