Merge branch 'devel' into release-1.4.3.x

This commit is contained in:
Ben Newman
2017-03-16 11:28:35 -04:00
25 changed files with 563 additions and 278 deletions

View File

@@ -209,6 +209,10 @@ We have found that writing software to meet both these standards at the
same time is hard but
incredibly rewarding. We hope you come to feel the same way.
### Understanding the core
For more information about how to work with Meteor core, take a look at the [Development](Development.md) document which explains many important details, including how to [run from a checkout](Development.md#running-from-a-git-checkout), [run tests](Development.md#tests), and more.
### Proposing your change
You'll have the best chance of getting a change into core if you can build consensus in the community for it. Start by creating a well specified feature request as a Github issue.
@@ -237,9 +241,10 @@ these guidelines:
* Include tests that prove your code works.
* Follow the
[MDG style guide](https://guide.meteor.com/code-style.html#javascript)
for code and commit messages.
* Follow appropriate style for
[code contributions](Development.md#code-style)
and
[commit messages](Development.md#commit-messages)
* Be sure your author field in git is properly filled out with your full name
and email address so we can credit you.

View File

@@ -1,6 +1,6 @@
## v.NEXT
## v1.4.3.2, TBD
## v1.4.3.2, 2017-03-14
* Node has been upgraded to version 4.8.0.

View File

@@ -707,8 +707,8 @@
"from": "source-map@>=0.5.0 <0.6.0"
},
"source-map-support": {
"version": "0.4.12",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.12.tgz",
"version": "0.4.13",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.13.tgz",
"from": "source-map-support@>=0.4.2 <0.5.0"
},
"strip-ansi": {

View File

@@ -29,5 +29,11 @@ Babel = {
setCacheDir: function (cacheDir) {
Npm.require('meteor-babel').setCacheDir(cacheDir);
},
minify: function(source, options) {
var meteorBabel = Npm.require('meteor-babel');
var options = options || meteorBabel.getMinifierOptions();
return meteorBabel.minify(source, options);
}
};

View File

@@ -0,0 +1,254 @@
{
"dependencies": {
"arr-diff": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
"from": "arr-diff@>=2.0.0 <3.0.0"
},
"arr-flatten": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz",
"from": "arr-flatten@>=1.0.1 <2.0.0"
},
"arr-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz",
"from": "arr-map@>=2.0.0 <3.0.0"
},
"array-unique": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
"from": "array-unique@>=0.2.1 <0.3.0"
},
"braces": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
"from": "braces@>=1.8.2 <2.0.0"
},
"commander": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
"from": "commander@>=2.8.1 <3.0.0"
},
"debug": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz",
"from": "debug@>=2.2.0 <3.0.0"
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"from": "deep-equal@>=1.0.1 <2.0.0"
},
"expand-brackets": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
"from": "expand-brackets@>=0.1.4 <0.2.0"
},
"expand-range": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"from": "expand-range@>=1.8.1 <2.0.0"
},
"extglob": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
"from": "extglob@>=0.3.1 <0.4.0"
},
"filename-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz",
"from": "filename-regex@>=2.0.0 <3.0.0"
},
"fill-range": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
"from": "fill-range@>=2.1.0 <3.0.0"
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
"from": "for-in@>=1.0.1 <2.0.0"
},
"for-own": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
"from": "for-own@>=0.1.4 <0.2.0"
},
"forwarded-http": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/forwarded-http/-/forwarded-http-0.3.0.tgz",
"from": "forwarded-http@0.3.0"
},
"glob-base": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
"from": "glob-base@>=0.3.0 <0.4.0"
},
"glob-parent": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
"from": "glob-parent@>=2.0.0 <3.0.0"
},
"graceful-readlink": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
"from": "graceful-readlink@>=1.0.0"
},
"ip": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/ip/-/ip-0.3.3.tgz",
"from": "ip@>=0.3.2 <0.4.0"
},
"ip-filter": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/ip-filter/-/ip-filter-1.0.2.tgz",
"from": "ip-filter@>=1.0.0 <2.0.0"
},
"ip-port-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/ip-port-regex/-/ip-port-regex-1.0.0.tgz",
"from": "ip-port-regex@>=1.0.0 <2.0.0"
},
"ip-regex": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz",
"from": "ip-regex@>=1.0.3 <2.0.0"
},
"is-arguments": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.2.tgz",
"from": "is-arguments@>=1.0.2 <2.0.0"
},
"is-buffer": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz",
"from": "is-buffer@>=1.0.2 <2.0.0"
},
"is-dotfile": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz",
"from": "is-dotfile@>=1.0.0 <2.0.0"
},
"is-equal-shallow": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
"from": "is-equal-shallow@>=0.1.3 <0.2.0"
},
"is-extendable": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
"from": "is-extendable@>=0.1.1 <0.2.0"
},
"is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"from": "is-extglob@>=1.0.0 <2.0.0"
},
"is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"from": "is-glob@>=2.0.1 <3.0.0"
},
"is-match": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/is-match/-/is-match-0.4.1.tgz",
"from": "is-match@>=0.4.0 <0.5.0"
},
"is-number": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
"from": "is-number@>=2.1.0 <3.0.0"
},
"is-posix-bracket": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
"from": "is-posix-bracket@>=0.1.0 <0.2.0"
},
"is-primitive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
"from": "is-primitive@>=2.0.0 <3.0.0"
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"from": "isarray@1.0.0"
},
"isobject": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
"from": "isobject@>=2.0.0 <3.0.0"
},
"kind-of": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.1.0.tgz",
"from": "kind-of@>=3.0.2 <4.0.0"
},
"lazy-cache": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
"from": "lazy-cache@>=1.0.3 <2.0.0"
},
"make-iterator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz",
"from": "make-iterator@>=1.0.0 <2.0.0"
},
"micromatch": {
"version": "2.3.11",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
"from": "micromatch@>=2.3.7 <3.0.0"
},
"ms": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
"from": "ms@0.7.2"
},
"normalize-path": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz",
"from": "normalize-path@>=2.0.1 <3.0.0"
},
"object.omit": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
"from": "object.omit@>=2.0.0 <3.0.0"
},
"parse-glob": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
"from": "parse-glob@>=3.0.4 <4.0.0"
},
"preserve": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
"from": "preserve@>=0.2.0 <0.3.0"
},
"randomatic": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz",
"from": "randomatic@>=1.1.3 <2.0.0"
},
"regex-cache": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz",
"from": "regex-cache@>=0.4.2 <0.5.0"
},
"repeat-element": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
"from": "repeat-element@>=1.1.2 <2.0.0"
},
"repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"from": "repeat-string@>=1.5.2 <2.0.0"
},
"to-file-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/to-file-path/-/to-file-path-1.0.0.tgz",
"from": "to-file-path@>=1.0.0 <2.0.0"
}
}
}

View File

@@ -0,0 +1,5 @@
# force-ssl-common
[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/force-ssl-common) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/force-ssl-common)
***
This is an internal Meteor package.

View File

@@ -0,0 +1,32 @@
import forwarded from 'forwarded-http';
// Determine if the connection is only over localhost. Both we
// received it on localhost, and all proxies involved received on
// localhost (supports "forwarded" and "x-forwarded-for").
const isLocalConnection = (req) => {
const localhostRegexp = /^\s*(127\.0\.0\.1|\[?::1\]?)\s*$/;
const request = Object.create(req);
request.connection = Object.assign(
{},
req.connection,
{ remoteAddress: req.connection.remoteAddress || req.socket.remoteAddress }
);
const forwardedParams = forwarded(request);
let isLocal = true;
Object.keys(forwardedParams.for).forEach((forKey) => {
if (!localhostRegexp.test(forKey)) {
isLocal = false;
}
});
return isLocal;
};
// Determine if the connection was over SSL at any point. Either we
// received it as SSL, or a proxy did and translated it for us.
const isSslConnection = (req) => {
const forwardedParams = forwarded(req);
return req.connection.pair
|| forwardedParams.proto && forwardedParams.proto.indexOf('https') !== -1;
};
export { isLocalConnection, isSslConnection };

View File

@@ -0,0 +1,112 @@
import { isLocalConnection, isSslConnection } from './force_ssl_common';
import http from 'http';
Tinytest.add('force-ssl - check for a local connection', function (test) {
const req = new http.IncomingMessage();
req.connection = { remoteAddress: null };
req.socket = { remoteAddress: null };
// Remote address check (connection)
['127.0.0.1', '::1'].forEach((ip) => {
req.connection.remoteAddress = ip;
test.isTrue(isLocalConnection(req), 'Is a local connection');
});
['1.2.3.4', '2001:0db8:0000:0042:0000:8a2e:0370:7334'].forEach((ip) => {
req.connection.remoteAddress = ip;
test.isFalse(isLocalConnection(req), 'Not a local connection');
});
// Remote address check (socket)
['127.0.0.1', '::1'].forEach((ip) => {
req.connection = {};
req.socket.remoteAddress = ip;
test.isTrue(isLocalConnection(req), 'Is a local connection');
});
['1.2.3.4', '2001:0db8:0000:0042:0000:8a2e:0370:7334'].forEach((ip) => {
req.connection = {};
req.socket.remoteAddress = ip;
test.isFalse(isLocalConnection(req), 'Not a local connection');
});
// Header check
const localHeaders = [
{
name: 'forwarded',
value: 'for=127.0.0.1; proto=http',
ip: '127.0.0.1',
},
{
name: 'forwarded',
value: 'for="[::1]"; proto=http',
ip: '::1',
},
{
name: 'x-forwarded-for',
value: '127.0.0.1',
ip: '127.0.0.1',
},
];
localHeaders.forEach((header) => {
req.connection.remoteAddress = header.ip;
req.headers[header.name] = header.value;
test.isTrue(isLocalConnection(req), 'Is a local connection');
});
const remoteHeaders = [
{
name: 'forwarded',
value: 'for=1.2.3.4; proto=http',
ip: '1.2.3.4',
},
{
name: 'forwarded',
value: 'for=1.2.3.4; proto=http',
ip: '127.0.0.1',
},
{
name: 'forwarded',
value: 'for="[2001:0db8:0000:0042:0000:8a2e:0370:7334]"; proto=http',
ip: '2001:0db8:0000:0042:0000:8a2e:0370:7334',
},
{
name: 'x-forwarded-for',
value: '1.2.3.4',
ip: '1.2.3.4',
},
{
name: 'x-forwarded-for',
value: '2001:0db8:0000:0042:0000:8a2e:0370:7334',
ip: '2001:0db8:0000:0042:0000:8a2e:0370:7334',
},
];
remoteHeaders.forEach((header) => {
req.connection.remoteAddress = header.ip;
req.headers[header.name] = header.value;
test.isFalse(isLocalConnection(req), 'Not a local connection');
});
});
Tinytest.add('force-ssl - check for an SSL based connection', function (test) {
const req = new http.IncomingMessage();
req.connection = { pair: {} };
test.isTrue(isSslConnection(req), 'Is an SSL based connection');
req.connection = {};
req.headers = { forwarded: 'for=127.0.0.1; proto=https' };
test.isTrue(isSslConnection(req), 'Is an SSL based connection');
req.headers = { 'x-forwarded-proto': 'https' };
test.isTrue(isSslConnection(req), 'Is an SSL based connection');
req.headers = { forwarded: 'for=127.0.0.1; proto=http' };
test.isFalse(isSslConnection(req), 'Is not an SSL based connection');
req.headers = { 'x-forwarded-proto': 'http' };
test.isFalse(isSslConnection(req), 'Is not an SSL based connection');
});

View File

@@ -0,0 +1,19 @@
Package.describe({
summary: 'Internal force-ssl common code.',
version: '1.0.14'
});
Npm.depends({
'forwarded-http': '0.3.0'
});
Package.onUse(function (api) {
api.use('ecmascript');
api.mainModule('force_ssl_common.js', 'server');
});
Package.onTest(function (api) {
api.use('ecmascript');
api.use('tinytest');
api.mainModule('force_ssl_tests.js', 'server');
});

View File

@@ -9,12 +9,14 @@ is always encrypted to protect users from active spoofing attacks.
Meteor bundles (i.e. `meteor build`) do not include an HTTPS server or
certificate. A proxy server that terminates SSL in front of a Meteor
bundle must set the standard `x-forwarded-proto` header for this package to work.
bundle must set the `x-forwarded-proto` or `forwarded`
([RFC 7239](https://tools.ietf.org/html/rfc7239)) header for this package to
work.
The `x-forwarded-proto` header is used to determine if the connection arrived
over HTTPS and a heuristic is used to guess if it's running in development. To
simplify development, unencrypted connections from `localhost` are always
accepted over HTTP.
The `x-forwarded-proto` or `forwarded` header is used to determine if the
connection arrived over HTTPS and a heuristic is used to guess if it's running
in development. To simplify development, unencrypted connections from
`localhost` are always accepted over HTTP.
We recommend this package only for deployment platforms that do not have their
own ability to force SSL. If you're deploying with

View File

@@ -0,0 +1 @@
Object.assign(Meteor.absoluteUrl.defaultOptions, { secure: true });

View File

@@ -1 +0,0 @@
_.extend(Meteor.absoluteUrl.defaultOptions, {secure: true});

View File

@@ -1,4 +1,5 @@
var url = Npm.require("url");
import { isLocalConnection, isSslConnection } from 'meteor/force-ssl-common';
// Unfortunately we can't use a connect middleware here since
// sockjs installs itself prior to all existing listeners
@@ -16,29 +17,10 @@ httpServer.addListener('request', function (req, res) {
// localhost (development mode).
//
// Note: someone could trick us into serving over non-ssl by setting
// x-forwarded-for or x-forwarded-proto. Not much we can do there if
// we still want to operate behind proxies.
// x-forwarded-for, x-forwarded-proto, forwarded, etc. Not much we can do
// there if we still want to operate behind proxies.
var remoteAddress =
req.connection.remoteAddress || req.socket.remoteAddress;
// Determine if the connection is only over localhost. Both we
// received it on localhost, and all proxies involved received on
// localhost.
var localhostRegexp = /^\s*(127\.0\.0\.1|::1)\s*$/;
var isLocal = (
localhostRegexp.test(remoteAddress) &&
(!req.headers['x-forwarded-for'] ||
_.all(req.headers['x-forwarded-for'].split(','), function (x) {
return localhostRegexp.test(x);
})));
// Determine if the connection was over SSL at any point. Either we
// received it as SSL, or a proxy did and translated it for us.
var isSsl = req.connection.pair ||
(req.headers['x-forwarded-proto'] &&
req.headers['x-forwarded-proto'].indexOf('https') !== -1);
if (!isLocal && !isSsl) {
if (!isLocalConnection(req) && !isSslConnection(req)) {
// connection is not cool. send a 302 redirect!
var host = url.parse(Meteor.absoluteUrl()).hostname;
@@ -57,7 +39,7 @@ httpServer.addListener('request', function (req, res) {
// connection is OK. Proceed normally.
var args = arguments;
_.each(oldHttpServerListeners, function(oldListener) {
oldHttpServerListeners.forEach((oldListener) => {
oldListener.apply(httpServer, args);
});
});
@@ -67,8 +49,8 @@ httpServer.addListener('request', function (req, res) {
//
// Websockets come in via the 'upgrade' request. We can override this,
// however the problem is we're not sure if the websocket is actually
// encrypted. We don't get x-forwarded-for or x-forwarded-proto on
// websockets. It's possible the 'sec-websocket-origin' header does
// encrypted. We don't get x-forwarded-for, x-forwarded-proto, forwarded, etc.
// on websockets. It's possible the 'sec-websocket-origin' header does
// what we want, but that's not clear.
//
// For now, this package allows raw unencrypted DDP connections over

View File

@@ -1,18 +1,19 @@
Package.describe({
summary: "Require this application to use HTTPS",
version: "1.0.13",
version: "1.0.14",
prodOnly: true
});
Package.onUse(function (api) {
api.use('ecmascript');
api.use('webapp', 'server');
api.use('underscore');
// make sure we come after livedata, so we load after the sockjs
// server has been instantiated.
api.use('ddp', 'server');
api.use('force-ssl-common', 'server');
api.addFiles('force_ssl_common.js', ['client', 'server']);
api.addFiles('force_ssl_server.js', 'server');
api.mainModule('force_ssl_both.js', ['client', 'server']);
api.mainModule('force_ssl_server.js', 'server');
// Another thing we could do is add a force_ssl_client.js file that
// makes sure document.location.protocol is 'https'. If it detected

View File

@@ -1,94 +0,0 @@
{
"dependencies": {
"align-text": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
"from": "align-text@>=0.1.3 <0.2.0"
},
"async": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
"from": "async@>=0.2.6 <0.3.0"
},
"camelcase": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
"from": "camelcase@>=1.0.2 <2.0.0"
},
"center-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
"from": "center-align@>=0.1.1 <0.2.0"
},
"cliui": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
"from": "cliui@>=2.1.0 <3.0.0"
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"from": "decamelize@>=1.0.0 <2.0.0"
},
"is-buffer": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz",
"from": "is-buffer@>=1.0.2 <2.0.0"
},
"kind-of": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz",
"from": "kind-of@>=3.0.2 <4.0.0"
},
"lazy-cache": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
"from": "lazy-cache@>=1.0.3 <2.0.0"
},
"longest": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
"from": "longest@>=1.0.1 <2.0.0"
},
"repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"from": "repeat-string@>=1.5.2 <2.0.0"
},
"right-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
"from": "right-align@>=0.1.1 <0.2.0"
},
"source-map": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
"from": "source-map@>=0.5.1 <0.6.0"
},
"uglify-js": {
"version": "2.7.5",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz",
"from": "uglify-js@2.7.5"
},
"uglify-to-browserify": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
"from": "uglify-to-browserify@>=1.0.0 <1.1.0"
},
"window-size": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
"from": "window-size@0.1.0"
},
"wordwrap": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
"from": "wordwrap@0.0.2"
},
"yargs": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
"from": "yargs@>=3.10.0 <3.11.0"
}
}
}

View File

@@ -1,16 +0,0 @@
// The UglifyJSMinify API can also be used for beautification. Test that it
// behaves as expected.
Tinytest.add('minifier-js - uglify beautify', function (test) {
// See <https://github.com/mishoo/UglifyJS2#the-simple-way> and
// <http://lisperator.net/uglifyjs/codegen> for the API we're calling.
test.equal(UglifyJSMinify('one = function () { return 1; };',
{ fromString: true,
output: { beautify: true,
indent_level: 2,
width: 80 } }).code,
'one = function() {\n' +
' return 1;\n' +
'};');
});

View File

@@ -1,2 +1 @@
UglifyJS = Npm.require('uglify-js');
UglifyJSMinify = UglifyJS.minify;
meteorBabelMinify = Babel.minify;

View File

@@ -1,26 +1,10 @@
Package.describe({
summary: "JavaScript minifier",
version: "1.2.18"
});
Npm.depends({
"uglify-js": "2.7.5"
});
Npm.strip({
"uglify-js": ["test/"]
version: "2.0.0"
});
Package.onUse(function (api) {
api.export(['UglifyJSMinify', 'UglifyJS']);
api.use('babel-compiler');
api.export(['meteorBabelMinify']);
api.addFiles(['minifier.js'], 'server');
});
Package.onTest(function (api) {
api.use('minifier-js', 'server');
api.use('tinytest');
api.addFiles([
'beautify-tests.js',
], 'server');
});

View File

@@ -1,23 +1,20 @@
Package.describe({
name: 'standard-minifier-js',
version: '1.2.3',
version: '2.0.0',
summary: 'Standard javascript minifiers used with Meteor apps by default.',
documentation: 'README.md'
documentation: 'README.md',
});
Package.registerBuildPlugin({
name: "minifyStdJS",
use: [
'minifier-js'
'minifier-js@2.0.0',
],
sources: [
'plugin/minify-js.js'
]
'plugin/minify-js.js',
],
});
Package.onUse(function(api) {
api.use('isobuild:minifier-plugin@1.0.0');
});
Package.onTest(function(api) {
});

View File

@@ -1,14 +1,14 @@
Plugin.registerMinifier({
extensions: ["js"],
archMatching: "web"
extensions: ['js'],
archMatching: 'web'
}, function () {
var minifier = new UglifyJSMinifier();
var minifier = new MeteorBabelMinifier();
return minifier;
});
function UglifyJSMinifier () {};
function MeteorBabelMinifier () {};
UglifyJSMinifier.prototype.processFilesForBundle = function (files, options) {
MeteorBabelMinifier.prototype.processFilesForBundle = function(files, options) {
var mode = options.minifyMode;
// don't minify anything for development
@@ -17,96 +17,92 @@ UglifyJSMinifier.prototype.processFilesForBundle = function (files, options) {
file.addJavaScript({
data: file.getContentsAsBuffer(),
sourceMap: file.getSourceMap(),
path: file.getPathInBundle()
path: file.getPathInBundle(),
});
});
return;
}
var minifyOptions = {
fromString: true,
compress: {
drop_debugger: false,
unused: false,
dead_code: false
}
};
function maybeThrowMinifyErrorBySourceFile(error, file) {
var minifierErrorRegex = /\(line: (\d+), col: (\d+), pos: (\d+)\)/;
var parseError = minifierErrorRegex.exec(error.toString());
var minifierErrorRegex = /^(.*?)\s?\((\d+):(\d+)\)$/;
var parseError = minifierErrorRegex.exec(error.message);
if (parseError) {
var lineErrorMessage = parseError[0];
var lineErrorLineNumber = parseError[1];
if (!parseError) {
// If we were unable to parse it, just let the usual error handling work.
return;
}
var parseErrorContentIndex = lineErrorLineNumber - 1;
var lineErrorMessage = parseError[1];
var lineErrorLineNumber = parseError[2];
// Unlikely, since we have a multi-line fixed header in this file.
if (parseErrorContentIndex < 0) {
return;
}
var parseErrorContentIndex = lineErrorLineNumber - 1;
/*
// Unlikely, since we have a multi-line fixed header in this file.
if (parseErrorContentIndex < 0) {
return;
}
What we're parsing looks like this:
/*
/////////////////////////////////////////
// //
// path/to/file.js //
// //
/////////////////////////////////////////
// 1
var illegalECMAScript = true; // 2
// 3
/////////////////////////////////////////
What we're parsing looks like this:
Btw, the above code is intentionally not newer ECMAScript so
we don't break ourselves.
/////////////////////////////////////////
// //
// path/to/file.js //
// //
/////////////////////////////////////////
// 1
var illegalECMAScript = true; // 2
// 3
/////////////////////////////////////////
*/
Btw, the above code is intentionally not newer ECMAScript so
we don't break ourselves.
var contents = file.getContentsAsString().split(/\n/);
var lineContent = contents[parseErrorContentIndex];
*/
// Try to grab the line number, which sometimes doesn't exist on
// line, abnormally-long lines in a larger block.
var lineSrcLineParts = /^(.*?)(?:\s*\/\/ (\d+))?$/.exec(lineContent);
var contents = file.getContentsAsString().split(/\n/);
var lineContent = contents[parseErrorContentIndex];
// The line didn't match at all? Let's just not try.
if (!lineSrcLineParts) {
return;
}
// Try to grab the line number, which sometimes doesn't exist on
// line, abnormally-long lines in a larger block.
var lineSrcLineParts = /^(.*?)(?:\s*\/\/ (\d+))?$/.exec(lineContent);
var lineSrcLineContent = lineSrcLineParts[1];
var lineSrcLineNumber = lineSrcLineParts[2];
// The line didn't match at all? Let's just not try.
if (!lineSrcLineParts) {
return;
}
// Count backward from the failed line to find the filename.
for (var c = parseErrorContentIndex - 1; c >= 0; c--) {
var sourceLine = contents[c];
var lineSrcLineContent = lineSrcLineParts[1];
var lineSrcLineNumber = lineSrcLineParts[2];
// If the line is a boatload of slashes, we're in the right place.
if (/^\/\/\/{6,}$/.test(sourceLine)) {
// Count backward from the failed line to find the filename.
for (var c = parseErrorContentIndex - 1; c >= 0; c--) {
var sourceLine = contents[c];
// If 4 lines back is the same exact line, we've found the framing.
if (contents[c - 4] === sourceLine) {
// If the line is a boatload of slashes, we're in the right place.
if (/^\/\/\/{6,}$/.test(sourceLine)) {
// So in that case, 2 lines back is the file path.
var parseErrorPath = contents[c - 2]
.substring(3)
.replace(/\s+\/\//, "");
// If 4 lines back is the same exact line, we've found the framing.
if (contents[c - 4] === sourceLine) {
var minError = new Error(
"UglifyJS minification error: \n\n" +
error.message + " at " + parseErrorPath +
(lineSrcLineNumber ? " line " + lineSrcLineNumber + "\n\n" : "") +
" within " + file.getPathInBundle() + " " +
lineErrorMessage + ":\n\n" +
lineSrcLineContent + "\n"
);
// So in that case, 2 lines back is the file path.
var parseErrorPath = contents[c - 2]
.substring(3)
.replace(/\s+\/\//, "");
throw minError;
}
var minError = new Error(
"Babili minification error " +
"within " + file.getPathInBundle() + ":\n" +
parseErrorPath +
(lineSrcLineNumber ? ", line " + lineSrcLineNumber : "") + "\n" +
"\n" +
lineErrorMessage + ":\n" +
"\n" +
lineSrcLineContent + "\n"
);
throw minError;
}
}
}
@@ -114,32 +110,33 @@ UglifyJSMinifier.prototype.processFilesForBundle = function (files, options) {
var allJs = '';
files.forEach(function (file) {
// Don't reminify *.min.js.
if (/\.min\.js$/.test(file.getPathInBundle())) {
allJs += file.getContentsAsString();
} else {
var minified;
try {
minified = UglifyJSMinify(file.getContentsAsString(), minifyOptions);
if (!(minified && typeof minified.code === "string")) {
throw new Error();
// Don't reminify *.min.js.
if (/\.min\.js$/.test(file.getPathInBundle())) {
allJs += file.getContentsAsString();
} else {
var minified;
try {
minified = meteorBabelMinify(file.getContentsAsString());
if (!(minified && typeof minified.code === "string")) {
throw new Error();
}
} catch (err) {
var filePath = file.getPathInBundle();
maybeThrowMinifyErrorBySourceFile(err, file);
err.message += " while minifying " + filePath;
throw err;
}
} catch (err) {
var filePath = file.getPathInBundle();
// Try to catch the ugly Uglify error.
maybeThrowMinifyErrorBySourceFile(err, file);
err.message += " while minifying " + filePath;
throw err;
allJs += minified.code;
}
allJs += '\n\n';
allJs += minified.code;
}
allJs += '\n\n';
Plugin.nudge();
});
Plugin.nudge();
});
if (files.length) {
files[0].addJavaScript({ data: allJs });

View File

@@ -20,7 +20,7 @@ modules-test-package
dispatch:mocha-phantomjs
dispatch:mocha-browser
standard-minifier-css@1.3.3
standard-minifier-js@1.2.2
standard-minifier-js@2.0.0
client-only-ecmascript
modules-test-plugin
shell-server@0.2.2

View File

@@ -1,6 +1,6 @@
allow-deny@1.0.5
autoupdate@1.3.12
babel-compiler@6.14.1
babel-compiler@6.15.0
babel-runtime@1.0.1
base64@1.0.10
binary-heap@1.0.10
@@ -42,7 +42,7 @@ logging@1.1.17
meteor@1.6.1
meteor-base@1.0.4
minifier-css@1.2.16
minifier-js@1.2.17
minifier-js@2.0.0
minimongo@1.0.20
mobile-experience@1.0.4
mobile-status-bar@1.0.14
@@ -68,7 +68,7 @@ shell-server@0.2.2
spacebars@1.0.13
spacebars-compiler@1.1.0
standard-minifier-css@1.3.3
standard-minifier-js@1.2.2
standard-minifier-js@2.0.0
templating@1.3.0
templating-compiler@1.3.0
templating-runtime@1.3.0