Skip to content

Commit b729687

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 2d8e3f7 + b2297b4 commit b729687

45 files changed

Lines changed: 84693 additions & 373 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
npm-debug.log
33
tmp*
44
dist/
5+
yarn.lock

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ language: node_js
22
node_js:
33
- "stable"
44
- "4"
5-
- "0.12"
5+
- "6"
66

77
env:
88
- CXX=g++-4.8 WORKER_COUNT=2

Brocfile.js

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

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# FastBoot Changelog
22

3+
### 1.0.0-rc.3
4+
5+
* Remove Node 0.12 support.
6+
37
### 1.0.0-rc.2
48

59
* Set the entry point to the built cjs

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# FastBoot
22

3+
[![npm version](https://badge.fury.io/js/fastboot.svg)](https://badge.fury.io/js/fastboot)
34
[![Build Status](https://travis-ci.org/ember-fastboot/fastboot.svg?branch=master)](https://travis-ci.org/ember-fastboot/ember-fastboot-server)
45

56
FastBoot is a library for rendering Ember.js applications in Node.js.

package.json

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
{
22
"name": "fastboot",
3-
"version": "1.0.0-rc.2",
3+
"version": "1.0.0-rc.7",
44
"description": "Library for rendering Ember apps in node.js",
5-
"main": "dist/cjs/index.js",
5+
"main": "src/index.js",
66
"scripts": {
77
"test": "mocha",
8-
"prebuild": "rimraf dist",
9-
"build": "broccoli build dist",
108
"preversion": "npm test",
11-
"prepublish": "npm run build",
12-
"postinstall": "broccoli-module-alchemist-install",
139
"postversion": "git push origin master --tags"
1410
},
1511
"repository": {
1612
"type": "git",
1713
"url": "git+https://github.com/ember-fastboot/fastboot.git"
1814
},
15+
"engines": {
16+
"node": ">= 4.0.0"
17+
},
1918
"keywords": [
2019
"ember",
2120
"fastboot"
@@ -27,26 +26,19 @@
2726
},
2827
"homepage": "https://github.com/ember-fastboot/fastboot#readme",
2928
"dependencies": {
30-
"broccoli-module-alchemist-install": "^0.1.1",
3129
"chalk": "^0.5.1",
3230
"cookie": "^0.2.3",
3331
"debug": "^2.1.0",
3432
"exists-sync": "0.0.3",
3533
"express": "^4.13.3",
3634
"express-cluster": "0.0.4",
37-
"glob": "^4.0.5",
3835
"minimist": "^1.2.0",
39-
"najax": "^1.0.0",
36+
"najax": "^1.0.2",
4037
"rsvp": "^3.0.16",
4138
"simple-dom": "^0.3.0",
4239
"source-map-support": "^0.4.0"
4340
},
4441
"devDependencies": {
45-
"babel-core": "^6.10.4",
46-
"babel-preset-es2015": "^6.9.0",
47-
"broccoli": "^0.16.9",
48-
"broccoli-cli": "^1.0.0",
49-
"broccoli-module-alchemist": "^0.2.0",
5042
"chai": "^3.5.0",
5143
"chai-as-promised": "^5.2.0",
5244
"fs-promise": "^0.5.0",

src/ember-app.js

Lines changed: 55 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const fs = require('fs');
44
const path = require('path');
5-
const RSVP = require('rsvp');
5+
const chalk = require('chalk');
66

77
const najax = require('najax');
88
const SimpleDOM = require('simple-dom');
@@ -11,6 +11,7 @@ const debug = require('debug')('fastboot:ember-app');
1111

1212
const FastBootInfo = require('./fastboot-info');
1313
const Result = require('./result');
14+
const FastBootSchemaVersions = require('./fastboot-schema-versions');
1415

1516
/**
1617
* @private
@@ -58,7 +59,6 @@ class EmberApp {
5859
* @param {Object} [sandboxGlobals={}] any additional variables to expose in the sandbox or override existing in the sandbox
5960
*/
6061
buildSandbox(distPath, sandboxClass, sandboxGlobals) {
61-
let Sandbox = sandboxClass || require('./vm-sandbox');
6262
let sandboxRequire = this.buildWhitelistedRequire(this.moduleWhitelist, distPath);
6363
let config = this.appConfig;
6464
function appConfig() {
@@ -67,21 +67,16 @@ class EmberApp {
6767

6868
// add any additional user provided variables or override the default globals in the sandbox
6969
let globals = {
70-
najax: najax,
70+
najax,
7171
FastBoot: {
7272
require: sandboxRequire,
7373
config: appConfig
7474
}
7575
};
76-
for (let key in sandboxGlobals) {
77-
if (sandboxGlobals.hasOwnProperty(key)) {
78-
globals[key] = sandboxGlobals[key];
79-
}
80-
}
8176

82-
return new Sandbox({
83-
globals: globals
84-
});
77+
globals = Object.assign(globals, sandboxGlobals);
78+
79+
return new sandboxClass({ globals });
8580
}
8681

8782
/**
@@ -220,6 +215,10 @@ class EmberApp {
220215
* the app instance and then visits the given route and destroys the app instance
221216
* when the route is finished its render cycle.
222217
*
218+
* Ember apps can manually defer rendering in FastBoot mode if they're waiting
219+
* on something async the router doesn't know about. This function fetches
220+
* that promise for deferred rendering from the app.
221+
*
223222
* @param {string} path the URL path to render, like `/photos/1`
224223
* @param {Object} fastbootInfo An object holding per request info
225224
* @param {Object} bootOptions An object containing the boot options that are used by
@@ -238,18 +237,15 @@ class EmberApp {
238237

239238
return instance.boot(bootOptions);
240239
})
241-
.then(() => result.instanceBooted = true)
242240
.then(() => instance.visit(path, bootOptions))
243-
.then(() => waitForApp(instance))
244-
.then(() => {
245-
return instance;
246-
});
241+
.then(() => fastbootInfo.deferredPromise)
242+
.then(() => instance);
247243
}
248244

249245
/**
250246
* Creates a new application instance and renders the instance at a specific
251247
* URL, returning a promise that resolves to a {@link Result}. The `Result`
252-
* givesg you access to the rendered HTML as well as metadata about the
248+
* gives you access to the rendered HTML as well as metadata about the
253249
* request such as the HTTP status code.
254250
*
255251
* If this call to `visit()` is to service an incoming HTTP request, you may
@@ -273,7 +269,7 @@ class EmberApp {
273269
let res = options.response;
274270
let html = options.html || this.html;
275271
let disableShoebox = options.disableShoebox || false;
276-
let destroyAppInstanceInMs = options.destroyAppInstanceInMs;
272+
let destroyAppInstanceInMs = parseInt(options.destroyAppInstanceInMs, 10);
277273

278274
let shouldRender = (options.shouldRender !== undefined) ? options.shouldRender : true;
279275
let bootOptions = buildBootOptions(shouldRender);
@@ -292,23 +288,17 @@ class EmberApp {
292288
});
293289

294290
let destroyAppInstanceTimer;
295-
if (parseInt(destroyAppInstanceInMs, 10) > 0) {
291+
if (destroyAppInstanceInMs > 0) {
296292
// start a timer to destroy the appInstance forcefully in the given ms.
297293
// This is a failure mechanism so that node process doesn't get wedged if the `visit` never completes.
298294
destroyAppInstanceTimer = setTimeout(function() {
299-
if (instance && !result.instanceDestroyed) {
300-
result.instanceDestroyed = true;
295+
if (result._destroyAppInstance()) {
301296
result.error = new Error('App instance was forcefully destroyed in ' + destroyAppInstanceInMs + 'ms');
302-
instance.destroy();
303297
}
304298
}, destroyAppInstanceInMs);
305299
}
306300

307-
let instance;
308301
return this.visitRoute(path, fastbootInfo, bootOptions, result)
309-
.then(appInstance => {
310-
instance = appInstance;
311-
})
312302
.then(() => {
313303
if (!disableShoebox) {
314304
// if shoebox is not disabled, then create the shoebox and send API data
@@ -318,10 +308,7 @@ class EmberApp {
318308
.catch(error => result.error = error)
319309
.then(() => result._finalize())
320310
.finally(() => {
321-
if (instance && !result.instanceDestroyed) {
322-
result.instanceDestroyed = true;
323-
instance.destroy();
324-
311+
if (result._destroyAppInstance()) {
325312
if (destroyAppInstanceTimer) {
326313
clearTimeout(destroyAppInstanceTimer);
327314
}
@@ -344,48 +331,61 @@ class EmberApp {
344331
}
345332

346333
let manifest;
334+
let schemaVersion;
347335
let pkg;
348336

349337
try {
350338
pkg = JSON.parse(file);
351339
manifest = pkg.fastboot.manifest;
340+
schemaVersion = pkg.fastboot.schemaVersion;
352341
} catch (e) {
353342
throw new Error(`${pkgPath} was malformed or did not contain a manifest. Ensure that you have a compatible version of ember-cli-fastboot.`);
354343
}
355344

356-
var appFiles = [];
357-
if (manifest.appFiles) {
358-
debug("reading array of app file paths from manifest");
359-
manifest.appFiles.forEach(function(appFile) {
360-
appFiles.push(path.join(distPath, appFile));
361-
});
362-
} else if (manifest.appFile) {
363-
// TODO : remove after Fastboot 1.0
364-
debug("reading app file path from manifest");
365-
appFiles = [path.join(distPath, manifest.appFile)];
345+
const currentSchemaVersion = FastBootSchemaVersions.latest;
346+
// set schema version to 1 if not defined
347+
schemaVersion = schemaVersion || FastBootSchemaVersions.base;
348+
debug('Current schemaVersion from `ember-cli-fastboot` is %s while latest schema version is %s', (schemaVersion, currentSchemaVersion));
349+
350+
if (schemaVersion > currentSchemaVersion) {
351+
let errorMsg = chalk.bold.red('An incompatible version between `ember-cli-fastboot` and `fastboot` was found. Please update the version of fastboot library that is compatible with ember-cli-fastboot.');
352+
throw new Error(errorMsg);
366353
}
367354

368-
var vendorFiles = [];
369-
if (manifest.vendorFiles) {
370-
debug("reading array of vendor file paths from manifest");
371-
manifest.vendorFiles.forEach(function(vendorFile) {
372-
vendorFiles.push(path.join(distPath, vendorFile));
373-
});
374-
} else if (manifest.vendorFile) {
375-
// TODO : remove after Fastboot 1.0
376-
debug("reading vendor file path from manifest");
377-
vendorFiles = [path.join(distPath, manifest.vendorFile)];
355+
if (schemaVersion < FastBootSchemaVersions.manifestFileArrays) {
356+
// transform app and vendor file to array of files
357+
manifest = this.transformManifestFiles(manifest);
378358
}
379359

360+
debug("reading array of app file paths from manifest");
361+
var appFiles = manifest.appFiles.map(function(appFile) {
362+
return path.join(distPath, appFile);
363+
});
364+
365+
debug("reading array of vendor file paths from manifest");
366+
var vendorFiles = manifest.vendorFiles.map(function(vendorFile) {
367+
return path.join(distPath, vendorFile);
368+
});
369+
380370
return {
381-
appFiles: appFiles,
371+
appFiles: appFiles,
382372
vendorFiles: vendorFiles,
383373
htmlFile: path.join(distPath, manifest.htmlFile),
384374
moduleWhitelist: pkg.fastboot.moduleWhitelist,
385375
hostWhitelist: pkg.fastboot.hostWhitelist,
386376
appConfig: pkg.fastboot.appConfig
387377
};
388378
}
379+
380+
/**
381+
* Function to transform the manifest app and vendor files to an array.
382+
*/
383+
transformManifestFiles(manifest) {
384+
manifest.appFiles = [manifest.appFile];
385+
manifest.vendorFiles = [manifest.vendorFile];
386+
387+
return manifest;
388+
}
389389
}
390390

391391
/*
@@ -404,19 +404,6 @@ function buildBootOptions(shouldRender) {
404404
};
405405
}
406406

407-
/*
408-
* Ember apps can manually defer rendering in FastBoot mode if they're waiting
409-
* on something async the router doesn't know about. This function fetches
410-
* that promise for deferred rendering from the app.
411-
*/
412-
function waitForApp(instance) {
413-
let fastbootInfo = instance.lookup('info:-fastboot');
414-
415-
return fastbootInfo.deferredPromise.then(function() {
416-
return instance;
417-
});
418-
}
419-
420407
/*
421408
* Writes the shoebox into the DOM for the browser rendered app to consume.
422409
* Uses a script tag with custom type so that the browser will treat as plain
@@ -425,13 +412,14 @@ function waitForApp(instance) {
425412
* parse the specific item at the time it is needed instead of everything
426413
* all at once.
427414
*/
415+
const hasOwnProperty = Object.prototype.hasOwnProperty; // jshint ignore:line
416+
428417
function createShoebox(doc, fastbootInfo) {
429418
let shoebox = fastbootInfo.shoebox;
430-
if (!shoebox) { return RSVP.resolve(); }
419+
if (!shoebox) { return; }
431420

432421
for (let key in shoebox) {
433-
if (!shoebox.hasOwnProperty(key)) { continue; }
434-
422+
if (!hasOwnProperty.call(shoebox, key)) { continue; } // TODO: remove this later #144, ember-fastboot/ember-cli-fastboot/pull/417
435423
let value = shoebox[key];
436424
let textValue = JSON.stringify(value);
437425
textValue = escapeJSONString(textValue);
@@ -444,8 +432,6 @@ function createShoebox(doc, fastbootInfo) {
444432
scriptEl.appendChild(scriptText);
445433
doc.body.appendChild(scriptEl);
446434
}
447-
448-
return RSVP.resolve();
449435
}
450436

451437
const JSON_ESCAPE = {

0 commit comments

Comments
 (0)