Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fastboot

Package Overview
Dependencies
Maintainers
5
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastboot - npm Package Compare versions

Comparing version 1.0.0-rc.6 to 1.0.0-rc.7

yarn.lock

5

package.json
{
"name": "fastboot",
"version": "1.0.0-rc.6",
"version": "1.0.0-rc.7",
"description": "Library for rendering Ember apps in node.js",

@@ -35,5 +35,4 @@ "main": "src/index.js",

"express-cluster": "0.0.4",
"glob": "^4.0.5",
"minimist": "^1.2.0",
"najax": "^1.0.1",
"najax": "^1.0.2",
"rsvp": "^3.0.16",

@@ -40,0 +39,0 @@ "simple-dom": "^0.3.0",

75

src/ember-app.js

@@ -5,3 +5,2 @@ 'use strict';

const path = require('path');
const RSVP = require('rsvp');
const chalk = require('chalk');

@@ -72,3 +71,3 @@

let globals = {
najax: najax,
najax,
FastBoot: {

@@ -79,11 +78,6 @@ require: sandboxRequire,

};
for (let key in sandboxGlobals) {
if (sandboxGlobals.hasOwnProperty(key)) {
globals[key] = sandboxGlobals[key];
}
}
return new sandboxClass({
globals: globals
});
globals = Object.assign(globals, sandboxGlobals);
return new sandboxClass({ globals });
}

@@ -227,2 +221,6 @@

*
* Ember apps can manually defer rendering in FastBoot mode if they're waiting
* on something async the router doesn't know about. This function fetches
* that promise for deferred rendering from the app.
*
* @param {string} path the URL path to render, like `/photos/1`

@@ -248,6 +246,4 @@ * @param {Object} fastbootInfo An object holding per request info

.then(() => instance.visit(path, bootOptions))
.then(() => waitForApp(instance))
.then(() => {
return instance;
});
.then(() => fastbootInfo.deferredPromise)
.then(() => instance);
}

@@ -282,3 +278,3 @@

let disableShoebox = options.disableShoebox || false;
let destroyAppInstanceInMs = options.destroyAppInstanceInMs;
let destroyAppInstanceInMs = parseInt(options.destroyAppInstanceInMs, 10);

@@ -302,10 +298,8 @@ let shouldRender = (options.shouldRender !== undefined) ? options.shouldRender : true;

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

@@ -315,7 +309,3 @@ }, destroyAppInstanceInMs);

let instance;
return this.visitRoute(path, fastbootInfo, bootOptions, result)
.then(appInstance => {
instance = appInstance;
})
.then(() => {

@@ -330,6 +320,3 @@ if (!disableShoebox) {

.finally(() => {
if (instance && !result.instanceDestroyed) {
result.instanceDestroyed = true;
instance.destroy();
if (result._destroyAppInstance()) {
if (destroyAppInstanceTimer) {

@@ -383,16 +370,14 @@ clearTimeout(destroyAppInstanceTimer);

var appFiles = [];
debug("reading array of app file paths from manifest");
manifest.appFiles.forEach(function(appFile) {
appFiles.push(path.join(distPath, appFile));
var appFiles = manifest.appFiles.map(function(appFile) {
return path.join(distPath, appFile);
});
var vendorFiles = [];
debug("reading array of vendor file paths from manifest");
manifest.vendorFiles.forEach(function(vendorFile) {
vendorFiles.push(path.join(distPath, vendorFile));
var vendorFiles = manifest.vendorFiles.map(function(vendorFile) {
return path.join(distPath, vendorFile);
});
return {
appFiles: appFiles,
appFiles: appFiles,
vendorFiles: vendorFiles,

@@ -434,15 +419,2 @@ htmlFile: path.join(distPath, manifest.htmlFile),

/*
* Ember apps can manually defer rendering in FastBoot mode if they're waiting
* on something async the router doesn't know about. This function fetches
* that promise for deferred rendering from the app.
*/
function waitForApp(instance) {
let fastbootInfo = instance.lookup('info:-fastboot');
return fastbootInfo.deferredPromise.then(function() {
return instance;
});
}
/*
* Writes the shoebox into the DOM for the browser rendered app to consume.

@@ -455,9 +427,10 @@ * Uses a script tag with custom type so that the browser will treat as plain

*/
const hasOwnProperty = Object.prototype.hasOwnProperty; // jshint ignore:line
function createShoebox(doc, fastbootInfo) {
let shoebox = fastbootInfo.shoebox;
if (!shoebox) { return RSVP.resolve(); }
if (!shoebox) { return; }
for (let key in shoebox) {
if (!shoebox.hasOwnProperty(key)) { continue; }
if (!hasOwnProperty.call(shoebox, key)) { continue; } // TODO: remove this later #144, ember-fastboot/ember-cli-fastboot/pull/417
let value = shoebox[key];

@@ -475,4 +448,2 @@ let textValue = JSON.stringify(value);

}
return RSVP.resolve();
}

@@ -479,0 +450,0 @@

@@ -5,90 +5,93 @@ 'use strict';

// https://developer.mozilla.org/en-US/docs/Web/API/Headers
function FastBootHeaders(headers) {
headers = headers || {};
this.headers = {};
class FastBootHeaders {
constructor(headers) {
headers = headers || {};
this.headers = {};
for (var header in headers) {
let value = headers[header];
for (var header in headers) {
let value = headers[header];
// Express gives us either a string
// or an array of strings if there are multiple values.
// We want to support the Header spec
// so we will coerce to an array always.
if (typeof value === 'string') {
value = [value];
// Express gives us either a string
// or an array of strings if there are multiple values.
// We want to support the Header spec
// so we will coerce to an array always.
if (typeof value === 'string') {
value = [value];
}
this.headers[header] = value;
}
}
this.headers[header] = value;
append(header, value) {
let _header = header.toLowerCase();
if (!this.has(_header)) {
this.headers[_header] = [];
}
this.headers[_header].push(value);
}
}
FastBootHeaders.prototype.append = function(header, value) {
header = header.toLowerCase();
if (!this.has(header)) {
this.headers[header] = [];
delete(header) {
delete this.headers[header.toLowerCase()];
}
this.headers[header].push(value);
};
entries() {
var entries = [];
FastBootHeaders.prototype.delete = function(header) {
delete this.headers[header.toLowerCase()];
};
for(var key in this.headers) {
var values = this.headers[key];
for(var index = 0; index < values.length; ++index ) {
entries.push([key, values[index]]);
}
}
FastBootHeaders.prototype.entries = function() {
var entries = [];
return entries[Symbol.iterator]();
}
for(var key in this.headers) {
var values = this.headers[key];
for(var index = 0; index < values.length; ++index ) {
entries.push([key, values[index]]);
}
get(header) {
return this.getAll(header)[0] || null;
}
return entries[Symbol.iterator]();
};
getAll(header) {
return this.headers[header.toLowerCase()] || [];
}
FastBootHeaders.prototype.get = function(header) {
return this.getAll(header)[0] || null;
};
has(header) {
return this.headers[header.toLowerCase()] !== undefined;
}
FastBootHeaders.prototype.getAll = function(header) {
return this.headers[header.toLowerCase()] || [];
};
keys() {
var entries = [];
FastBootHeaders.prototype.has = function(header) {
return this.headers[header.toLowerCase()] !== undefined;
};
for(var key in this.headers) {
var values = this.headers[key];
for(var index = 0; index < values.length; ++index ) {
entries.push(key);
}
}
FastBootHeaders.prototype.keys = function() {
var entries = [];
return entries[Symbol.iterator]();
}
for(var key in this.headers) {
var values = this.headers[key];
for(var index = 0; index < values.length; ++index ) {
entries.push(key);
}
set(header, value) {
header = header.toLowerCase();
this.headers[header] = [value];
}
return entries[Symbol.iterator]();
};
values() {
var entries = [];
FastBootHeaders.prototype.set = function(header, value) {
header = header.toLowerCase();
this.headers[header] = [value];
};
for(var key in this.headers) {
var values = this.headers[key];
for(var index = 0; index < values.length; ++index ) {
entries.push(values[index]);
}
}
FastBootHeaders.prototype.values = function() {
var entries = [];
for(var key in this.headers) {
var values = this.headers[key];
for(var index = 0; index < values.length; ++index ) {
entries.push(values[index]);
}
return entries[Symbol.iterator]();
}
}
return entries[Symbol.iterator]();
};
module.exports = FastBootHeaders;
'use strict';
var RSVP = require('rsvp');
var FastBootRequest = require('./fastboot-request');
var FastBootResponse = require('./fastboot-response');
const RSVP = require('rsvp');
const FastBootRequest = require('./fastboot-request');
const FastBootResponse = require('./fastboot-response');

@@ -18,31 +18,33 @@ /*

*/
function FastBootInfo(request, response, options) {
class FastBootInfo {
constructor(request, response, options) {
this.deferredPromise = RSVP.resolve();
let hostWhitelist = options.hostWhitelist;
let metadata = options.metadata;
if (request) {
this.request = new FastBootRequest(request, hostWhitelist);
}
this.deferredPromise = RSVP.resolve();
let hostWhitelist = options.hostWhitelist;
let metadata = options.metadata;
if (request) {
this.request = new FastBootRequest(request, hostWhitelist);
this.response = new FastBootResponse(response || {});
this.metadata = metadata;
}
this.response = new FastBootResponse(response || {});
this.metadata = metadata;
deferRendering(promise) {
this.deferredPromise = this.deferredPromise.then(function() {
return promise;
});
}
/*
* Registers this FastBootInfo instance in the registry of an Ember
* ApplicationInstance. It is configured to be injected into the FastBoot
* service, ensuring it is available inside instance initializers.
*/
register(instance) {
instance.register('info:-fastboot', this, { instantiate: false });
instance.inject('service:fastboot', '_fastbootInfo', 'info:-fastboot');
}
}
FastBootInfo.prototype.deferRendering = function(promise) {
this.deferredPromise = this.deferredPromise.then(function() {
return promise;
});
};
/*
* Registers this FastBootInfo instance in the registry of an Ember
* ApplicationInstance. It is configured to be injected into the FastBoot
* service, ensuring it is available inside instance initializers.
*/
FastBootInfo.prototype.register = function(instance) {
instance.register('info:-fastboot', this, { instantiate: false });
instance.inject('service:fastboot', '_fastbootInfo', 'info:-fastboot');
};
module.exports = FastBootInfo;

@@ -1,60 +0,62 @@

var cookie = require('cookie');
var FastBootHeaders = require('./fastboot-headers');
'use strict';
function FastBootRequest(request, hostWhitelist) {
this.hostWhitelist = hostWhitelist;
const cookie = require('cookie');
const FastBootHeaders = require('./fastboot-headers');
this.protocol = request.protocol;
this.headers = new FastBootHeaders(request.headers);
this.queryParams = request.query;
this.path = request.url;
this.method = request.method;
this.body = request.body;
class FastBootRequest {
constructor(request, hostWhitelist) {
this.hostWhitelist = hostWhitelist;
this.cookies = this.extractCookies(request);
}
this.protocol = request.protocol;
this.headers = new FastBootHeaders(request.headers);
this.queryParams = request.query;
this.path = request.url;
this.method = request.method;
this.body = request.body;
FastBootRequest.prototype.host = function() {
if (!this.hostWhitelist) {
throw new Error('You must provide a hostWhitelist to retrieve the host');
this.cookies = this.extractCookies(request);
}
var host = this.headers.get('host');
host() {
if (!this.hostWhitelist) {
throw new Error('You must provide a hostWhitelist to retrieve the host');
}
var matchFound = this.hostWhitelist.reduce(function(previous, currentEntry) {
if (currentEntry[0] === '/' &&
currentEntry.slice(-1) === '/') {
// RegExp as string
var regexp = new RegExp(currentEntry.slice(1, -1));
var host = this.headers.get('host');
var matchFound = this.hostWhitelist.some(function(entry) {
if (entry[0] === '/' && entry.slice(-1) === '/') {
var regexp = new RegExp(entry.slice(1, -1));
return regexp.test(host);
} else {
return entry === host;
}
});
return previous || regexp.test(host);
} else {
return previous || currentEntry === host;
if (!matchFound) {
throw new Error(`The host header did not match a hostWhitelist entry. Host header: ${host}`);
}
}, false);
if (!matchFound) {
throw new Error(`The host header did not match a hostWhitelist entry. Host header: ${host}`);
return host;
}
return host;
};
extractCookies(request) {
// If cookie-parser middleware has already parsed the cookies,
// just use that.
if (request.cookies) {
return request.cookies;
}
FastBootRequest.prototype.extractCookies = function(request) {
// If cookie-parser middleware has already parsed the cookies,
// just use that.
if (request.cookies) {
return request.cookies;
}
// Otherwise, try to parse the cookies ourselves, if they exist.
var cookies = request.headers.cookie;
if (cookies) {
return cookie.parse(cookies);
}
// Otherwise, try to parse the cookies ourselves, if they exist.
var cookies = request.headers.cookie;
if (cookies) {
return cookie.parse(cookies);
// Return an empty object instead of undefined if no cookies are present.
return {};
}
// Return an empty object instead of undefined if no cookies are present.
return {};
};
}
module.exports = FastBootRequest;

@@ -1,8 +0,12 @@

var FastBootHeaders = require('./fastboot-headers');
'use strict';
function FastbootResponse(response) {
this.headers = new FastBootHeaders(response._headers);
this.statusCode = 200;
const FastBootHeaders = require('./fastboot-headers');
class FastbootResponse {
constructor(response) {
this.headers = new FastBootHeaders(response._headers);
this.statusCode = 200;
}
}
module.exports = FastbootResponse;

@@ -1,2 +0,2 @@

var sourceMapSupport = require('source-map-support');
const sourceMapSupport = require('source-map-support');

@@ -3,0 +3,0 @@ function prepareStackTrace(error, stack) {

@@ -14,3 +14,3 @@ 'use strict';

this.instanceBooted = false;
this.instanceDestroyed = false;
this._instanceDestroyed = false;
this._doc = options.doc;

@@ -47,3 +47,3 @@ this._html = options.html;

return Promise.resolve(insertIntoIndexHTML(this._html, this._head, this._body));
return insertIntoIndexHTML(this._html, this._head, this._body);
}

@@ -102,2 +102,11 @@

_destroyAppInstance() {
if (this.instance && !this._instanceDestroyed) {
this._instanceDestroyed = true;
this.instance.destroy();
return true;
}
return false;
}
_finalizeHTML() {

@@ -118,20 +127,32 @@ let head = this._doc.head;

/**
* `String.replace()` converts '$$' to '$', so we must escape each '$' as '$$';
* but because we’re using `String.replace()` to do it, we must use '$$$'!
*/
function escapeForStringReplace(string) {
return string.replace(/\$/g, '$$$');
function missingTag(tag) {
return Promise.reject(new Error(`Fastboot was not able to find ${tag} in base HTML. It could not replace the contents.`));
}
function insertIntoIndexHTML(html, head, body) {
html = html.replace("<!-- EMBER_CLI_FASTBOOT_BODY -->", escapeForStringReplace(body));
if (!html) { return Promise.resolve(html); }
let isBodyReplaced = false;
let isHeadReplaced = false;
if (head) {
html = html.replace("<!-- EMBER_CLI_FASTBOOT_HEAD -->", escapeForStringReplace(head));
html = html.replace(/<\!-- EMBER_CLI_FASTBOOT_(HEAD|BODY) -->/g, function(match, tag) {
if (tag === 'HEAD' && head && !isHeadReplaced) {
isHeadReplaced = true;
return head;
} else if (tag === 'BODY' && body && !isBodyReplaced) {
isBodyReplaced = true;
return body;
}
return '';
});
if (head && !isHeadReplaced) {
return missingTag('<!--EMBER_CLI_FASTBOOT_HEAD-->');
}
if (body && !isBodyReplaced) {
return missingTag('<!--EMBER_CLI_FASTBOOT_BODY-->');
}
return html;
return Promise.resolve(html);
}
module.exports = Result;

@@ -1,50 +0,52 @@

var chalk = require('chalk');
'use strict';
function Sandbox() {
}
const chalk = require('chalk');
Sandbox.prototype.init = function(options) {
this.globals = options.globals;
this.sandbox = this.buildSandbox();
};
class Sandbox {
Sandbox.prototype.buildSandbox = function() {
var console = this.buildWrappedConsole();
var sourceMapSupport = require('./install-source-map-support');
var URL = require('url');
var globals = this.globals;
constructor(options) {
this.globals = options.globals;
this.sandbox = this.buildSandbox();
}
var sandbox = {
sourceMapSupport: sourceMapSupport,
console: console,
setTimeout: setTimeout,
clearTimeout: clearTimeout,
URL: URL,
buildSandbox() {
var console = this.buildWrappedConsole();
var sourceMapSupport = require('./install-source-map-support');
var URL = require('url');
var globals = this.globals;
// Convince jQuery not to assume it's in a browser
module: { exports: {} }
};
var sandbox = {
sourceMapSupport: sourceMapSupport,
console: console,
setTimeout: setTimeout,
clearTimeout: clearTimeout,
URL: URL,
for (var key in globals) {
sandbox[key] = globals[key];
}
// Convince jQuery not to assume it's in a browser
module: { exports: {} }
};
// Set the global as `window`.
sandbox.window = sandbox;
sandbox.window.self = sandbox;
for (var key in globals) {
sandbox[key] = globals[key];
}
return sandbox;
};
// Set the global as `window`.
sandbox.window = sandbox;
sandbox.window.self = sandbox;
Sandbox.prototype.buildWrappedConsole = function() {
var wrappedConsole = Object.create(console);
wrappedConsole.error = function() {
console.error.apply(console, Array.prototype.map.call(arguments, function(a) {
return typeof a === 'string' ? chalk.red(a) : a;
}));
};
return sandbox;
}
return wrappedConsole;
};
buildWrappedConsole() {
var wrappedConsole = Object.create(console);
wrappedConsole.error = function() {
console.error.apply(console, Array.prototype.map.call(arguments, function(a) {
return typeof a === 'string' ? chalk.red(a) : a;
}));
};
return wrappedConsole;
}
}
module.exports = Sandbox;

@@ -1,21 +0,23 @@

var vm = require('vm');
var Sandbox = require('./sandbox');
'use strict';
function VMSandbox(options) {
this.init(options);
vm.createContext(this.sandbox);
}
const vm = require('vm');
const Sandbox = require('./sandbox');
VMSandbox.prototype = Object.create(Sandbox.prototype);
VMSandbox.prototype.constructor = Sandbox;
class VMSandbox extends Sandbox {
constructor(options) {
super(options);
vm.createContext(this.sandbox);
}
VMSandbox.prototype.eval = function(source, filePath) {
var fileScript = new vm.Script(source, { filename: filePath });
fileScript.runInContext(this.sandbox);
};
eval(source, filePath) {
var fileScript = new vm.Script(source, { filename: filePath });
fileScript.runInContext(this.sandbox);
}
VMSandbox.prototype.run = function(cb) {
return cb.call(this.sandbox, this.sandbox);
};
run(cb) {
return cb.call(this.sandbox, this.sandbox);
}
}
module.exports = VMSandbox;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc