diff --git a/Contributing.md b/Contributing.md index a7bb33399c..c4db02a8a4 100644 --- a/Contributing.md +++ b/Contributing.md @@ -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. diff --git a/History.md b/History.md index 2e80891038..a7ae881960 100644 --- a/History.md +++ b/History.md @@ -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. diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index 6dcea7f5c3..b99616ca62 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -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": { diff --git a/packages/babel-compiler/babel.js b/packages/babel-compiler/babel.js index fc20af1d6e..ac518d1034 100644 --- a/packages/babel-compiler/babel.js +++ b/packages/babel-compiler/babel.js @@ -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); } }; diff --git a/packages/minifier-js/.npm/package/.gitignore b/packages/force-ssl-common/.npm/package/.gitignore similarity index 100% rename from packages/minifier-js/.npm/package/.gitignore rename to packages/force-ssl-common/.npm/package/.gitignore diff --git a/packages/minifier-js/.npm/package/README b/packages/force-ssl-common/.npm/package/README similarity index 100% rename from packages/minifier-js/.npm/package/README rename to packages/force-ssl-common/.npm/package/README diff --git a/packages/force-ssl-common/.npm/package/npm-shrinkwrap.json b/packages/force-ssl-common/.npm/package/npm-shrinkwrap.json new file mode 100644 index 0000000000..c38d2816a4 --- /dev/null +++ b/packages/force-ssl-common/.npm/package/npm-shrinkwrap.json @@ -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" + } + } +} diff --git a/packages/force-ssl-common/README.md b/packages/force-ssl-common/README.md new file mode 100644 index 0000000000..a0309c3510 --- /dev/null +++ b/packages/force-ssl-common/README.md @@ -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. diff --git a/packages/force-ssl-common/force_ssl_common.js b/packages/force-ssl-common/force_ssl_common.js new file mode 100644 index 0000000000..e01afd099a --- /dev/null +++ b/packages/force-ssl-common/force_ssl_common.js @@ -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 }; diff --git a/packages/force-ssl-common/force_ssl_tests.js b/packages/force-ssl-common/force_ssl_tests.js new file mode 100644 index 0000000000..256400e393 --- /dev/null +++ b/packages/force-ssl-common/force_ssl_tests.js @@ -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'); +}); diff --git a/packages/force-ssl-common/package.js b/packages/force-ssl-common/package.js new file mode 100644 index 0000000000..fda41c4f54 --- /dev/null +++ b/packages/force-ssl-common/package.js @@ -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'); +}); diff --git a/packages/force-ssl/README.md b/packages/force-ssl/README.md index 723f509afc..144ecd9edf 100644 --- a/packages/force-ssl/README.md +++ b/packages/force-ssl/README.md @@ -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 diff --git a/packages/force-ssl/force_ssl_both.js b/packages/force-ssl/force_ssl_both.js new file mode 100644 index 0000000000..86e1bd0714 --- /dev/null +++ b/packages/force-ssl/force_ssl_both.js @@ -0,0 +1 @@ +Object.assign(Meteor.absoluteUrl.defaultOptions, { secure: true }); diff --git a/packages/force-ssl/force_ssl_common.js b/packages/force-ssl/force_ssl_common.js deleted file mode 100644 index 00b121f8b4..0000000000 --- a/packages/force-ssl/force_ssl_common.js +++ /dev/null @@ -1 +0,0 @@ -_.extend(Meteor.absoluteUrl.defaultOptions, {secure: true}); diff --git a/packages/force-ssl/force_ssl_server.js b/packages/force-ssl/force_ssl_server.js index b050a172fc..6c31cc6217 100644 --- a/packages/force-ssl/force_ssl_server.js +++ b/packages/force-ssl/force_ssl_server.js @@ -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 diff --git a/packages/force-ssl/package.js b/packages/force-ssl/package.js index 76f2e6a095..bc9c4bf6ed 100644 --- a/packages/force-ssl/package.js +++ b/packages/force-ssl/package.js @@ -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 diff --git a/packages/minifier-js/.npm/package/npm-shrinkwrap.json b/packages/minifier-js/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index e5204dc869..0000000000 --- a/packages/minifier-js/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -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" - } - } -} diff --git a/packages/minifier-js/beautify-tests.js b/packages/minifier-js/beautify-tests.js deleted file mode 100644 index 05eca60ddb..0000000000 --- a/packages/minifier-js/beautify-tests.js +++ /dev/null @@ -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 and - // 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' + - '};'); -}); diff --git a/packages/minifier-js/minifier.js b/packages/minifier-js/minifier.js index 942d6126ae..2fc7f565bf 100644 --- a/packages/minifier-js/minifier.js +++ b/packages/minifier-js/minifier.js @@ -1,2 +1 @@ -UglifyJS = Npm.require('uglify-js'); -UglifyJSMinify = UglifyJS.minify; \ No newline at end of file +meteorBabelMinify = Babel.minify; \ No newline at end of file diff --git a/packages/minifier-js/package.js b/packages/minifier-js/package.js index b741592858..4abf7fef00 100644 --- a/packages/minifier-js/package.js +++ b/packages/minifier-js/package.js @@ -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'); -}); diff --git a/packages/non-core/blaze b/packages/non-core/blaze index 637dac5914..0ded311a13 160000 --- a/packages/non-core/blaze +++ b/packages/non-core/blaze @@ -1 +1 @@ -Subproject commit 637dac59146e74e2d384e8ea15b4cb7a8cb67896 +Subproject commit 0ded311a13bd0cf0fbf8e19574156cdb7e5ed220 diff --git a/packages/standard-minifier-js/package.js b/packages/standard-minifier-js/package.js index 8c0f4ad725..227cdf2a1f 100644 --- a/packages/standard-minifier-js/package.js +++ b/packages/standard-minifier-js/package.js @@ -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) { -}); diff --git a/packages/standard-minifier-js/plugin/minify-js.js b/packages/standard-minifier-js/plugin/minify-js.js index c1ff32c96b..c1d699c6b2 100644 --- a/packages/standard-minifier-js/plugin/minify-js.js +++ b/packages/standard-minifier-js/plugin/minify-js.js @@ -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 }); diff --git a/tools/tests/apps/modules/.meteor/packages b/tools/tests/apps/modules/.meteor/packages index de346a8de7..0713ff4409 100644 --- a/tools/tests/apps/modules/.meteor/packages +++ b/tools/tests/apps/modules/.meteor/packages @@ -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 diff --git a/tools/tests/apps/modules/.meteor/versions b/tools/tests/apps/modules/.meteor/versions index 07fcfdc84e..a3a570fa9b 100644 --- a/tools/tests/apps/modules/.meteor/versions +++ b/tools/tests/apps/modules/.meteor/versions @@ -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