From 02a544f7927bea221548d6c2a0195ebe0c9ebe14 Mon Sep 17 00:00:00 2001 From: Sudhanshu Date: Tue, 28 Mar 2017 15:35:46 +0530 Subject: [PATCH 001/125] Add the field name in the error When Minimongo throws an error, most of the times, the field names are not present, making it a bit difficult to debug. Updated the error messages to include the field name for which it threw the error. --- packages/minimongo/modify.js | 60 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/minimongo/modify.js b/packages/minimongo/modify.js index e5a81ba8f6..e595d82cab 100644 --- a/packages/minimongo/modify.js +++ b/packages/minimongo/modify.js @@ -185,20 +185,20 @@ var MODIFIERS = { $currentDate: function (target, field, arg) { if (typeof arg === "object" && arg.hasOwnProperty("$type")) { if (arg.$type !== "date") { - throw MinimongoError("Minimongo does currently only support the date type in $currentDate modifiers"); + throw MinimongoError("Minimongo does currently only support the date type in $currentDate modifiers: " + field); } } else if (arg !== true) { - throw MinimongoError("Invalid $currentDate modifier"); + throw MinimongoError("Invalid $currentDate modifier: " + field); } target[field] = new Date(); }, $min: function (target, field, arg) { if (typeof arg !== "number") { - throw MinimongoError("Modifier $min allowed for numbers only"); + throw MinimongoError("Modifier $min allowed for numbers only: " + field); } if (field in target) { if (typeof target[field] !== "number") { - throw MinimongoError("Cannot apply $min modifier to non-number"); + throw MinimongoError("Cannot apply $min modifier to non-number: " + field); } if (target[field] > arg) { target[field] = arg; @@ -209,11 +209,11 @@ var MODIFIERS = { }, $max: function (target, field, arg) { if (typeof arg !== "number") { - throw MinimongoError("Modifier $max allowed for numbers only"); + throw MinimongoError("Modifier $max allowed for numbers only: " + field); } if (field in target) { if (typeof target[field] !== "number") { - throw MinimongoError("Cannot apply $max modifier to non-number"); + throw MinimongoError("Cannot apply $max modifier to non-number: " + field); } if (target[field] < arg) { target[field] = arg; @@ -224,10 +224,10 @@ var MODIFIERS = { }, $inc: function (target, field, arg) { if (typeof arg !== "number") - throw MinimongoError("Modifier $inc allowed for numbers only"); + throw MinimongoError("Modifier $inc allowed for numbers only: " + field); if (field in target) { if (typeof target[field] !== "number") - throw MinimongoError("Cannot apply $inc modifier to non-number"); + throw MinimongoError("Cannot apply $inc modifier to non-number: " + field); target[field] += arg; } else { target[field] = arg; @@ -235,12 +235,12 @@ var MODIFIERS = { }, $set: function (target, field, arg) { if (!_.isObject(target)) { // not an array or an object - var e = MinimongoError("Cannot set property on non-object field"); + var e = MinimongoError("Cannot set property on non-object field: " + field); e.setPropertyError = true; throw e; } if (target === null) { - var e = MinimongoError("Cannot set property on null"); + var e = MinimongoError("Cannot set property on null: " + field); e.setPropertyError = true; throw e; } @@ -267,7 +267,7 @@ var MODIFIERS = { if (target[field] === undefined) target[field] = []; if (!(target[field] instanceof Array)) - throw MinimongoError("Cannot apply $push modifier to non-array"); + throw MinimongoError("Cannot apply $push modifier to non-array: " + field); if (!(arg && arg.$each)) { // Simple mode: not $each @@ -278,16 +278,16 @@ var MODIFIERS = { // Fancy mode: $each (and maybe $slice and $sort and $position) var toPush = arg.$each; if (!(toPush instanceof Array)) - throw MinimongoError("$each must be an array"); + throw MinimongoError("$each must be an array: " + field); // Parse $position var position = undefined; if ('$position' in arg) { if (typeof arg.$position !== "number") - throw MinimongoError("$position must be a numeric value"); + throw MinimongoError("$position must be a numeric value: " + field); // XXX should check to make sure integer if (arg.$position < 0) - throw MinimongoError("$position in $push must be zero or positive"); + throw MinimongoError("$position in $push must be zero or positive: " + field); position = arg.$position; } @@ -295,10 +295,10 @@ var MODIFIERS = { var slice = undefined; if ('$slice' in arg) { if (typeof arg.$slice !== "number") - throw MinimongoError("$slice must be a numeric value"); + throw MinimongoError("$slice must be a numeric value: " + field); // XXX should check to make sure integer if (arg.$slice > 0) - throw MinimongoError("$slice in $push must be zero or negative"); + throw MinimongoError("$slice in $push must be zero or negative: " + field); slice = arg.$slice; } @@ -306,7 +306,7 @@ var MODIFIERS = { var sortFunction = undefined; if (arg.$sort) { if (slice === undefined) - throw MinimongoError("$sort requires $slice to be present"); + throw MinimongoError("$sort requires $slice to be present: " + field); // XXX this allows us to use a $sort whose value is an array, but that's // actually an extension of the Node driver, so it won't work // server-side. Could be confusing! @@ -315,7 +315,7 @@ var MODIFIERS = { for (var i = 0; i < toPush.length; i++) { if (LocalCollection._f._type(toPush[i]) !== 3) { throw MinimongoError("$push like modifiers using $sort " + - "require all elements to be objects"); + "require all elements to be objects: " + field); } } } @@ -350,7 +350,7 @@ var MODIFIERS = { if (x === undefined) target[field] = arg; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pushAll modifier to non-array"); + throw MinimongoError("Cannot apply $pushAll modifier to non-array: " + field); else { for (var i = 0; i < arg.length; i++) x.push(arg[i]); @@ -371,7 +371,7 @@ var MODIFIERS = { if (x === undefined) target[field] = values; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $addToSet modifier to non-array"); + throw MinimongoError("Cannot apply $addToSet modifier to non-array: " + field); else { _.each(values, function (value) { for (var i = 0; i < x.length; i++) @@ -388,7 +388,7 @@ var MODIFIERS = { if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pop modifier to non-array"); + throw MinimongoError("Cannot apply $pop modifier to non-array: " + field); else { if (typeof arg === 'number' && arg < 0) x.splice(0, 1); @@ -403,7 +403,7 @@ var MODIFIERS = { if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array"); + throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array: " + field); else { var out = []; if (arg != null && typeof arg === "object" && !(arg instanceof Array)) { @@ -430,14 +430,14 @@ var MODIFIERS = { }, $pullAll: function (target, field, arg) { if (!(typeof arg === "object" && arg instanceof Array)) - throw MinimongoError("Modifier $pushAll/pullAll allowed for arrays only"); + throw MinimongoError("Modifier $pushAll/pullAll allowed for arrays only: " + field); if (target === undefined) return; var x = target[field]; if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array"); + throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array: " + field); else { var out = []; for (var i = 0; i < x.length; i++) { @@ -457,15 +457,15 @@ var MODIFIERS = { $rename: function (target, field, arg, keypath, doc) { if (keypath === arg) // no idea why mongo has this restriction.. - throw MinimongoError("$rename source must differ from target"); + throw MinimongoError("$rename source must differ from target: " + field); if (target === null) - throw MinimongoError("$rename source field invalid"); + throw MinimongoError("$rename source field invalid: " + field); if (typeof arg !== "string") - throw MinimongoError("$rename target must be a string"); + throw MinimongoError("$rename target must be a string: " + field); if (arg.indexOf('\0') > -1) { // Null bytes are not allowed in Mongo field names // https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names - throw MinimongoError("The 'to' field for $rename cannot contain an embedded null byte"); + throw MinimongoError("The 'to' field for $rename cannot contain an embedded null byte: " + field); } if (target === undefined) return; @@ -475,13 +475,13 @@ var MODIFIERS = { var keyparts = arg.split('.'); var target2 = findModTarget(doc, keyparts, {forbidArray: true}); if (target2 === null) - throw MinimongoError("$rename target field invalid"); + throw MinimongoError("$rename target field invalid: " + field); var field2 = keyparts.pop(); target2[field2] = v; }, $bit: function (target, field, arg) { // XXX mongo only supports $bit on integers, and we only support // native javascript numbers (doubles) so far, so we can't support $bit - throw MinimongoError("$bit is not supported"); + throw MinimongoError("$bit is not supported: " + field); } }; From 7594b749e944bc79de09ceab1f3e88e34d452539 Mon Sep 17 00:00:00 2001 From: Akarshit Date: Thu, 6 Apr 2017 22:43:47 +0530 Subject: [PATCH 002/125] Index creation in the file using the query --- packages/accounts-base/accounts_server.js | 2 ++ packages/accounts-password/password_server.js | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/accounts-base/accounts_server.js b/packages/accounts-base/accounts_server.js index 57ea4eb6e0..34ba671f66 100644 --- a/packages/accounts-base/accounts_server.js +++ b/packages/accounts-base/accounts_server.js @@ -1500,6 +1500,8 @@ function setupUsersCollection(users) { { sparse: 1 }); // For expiring login tokens users._ensureIndex("services.resume.loginTokens.when", { sparse: 1 }); + // For expiring password tokens + users._ensureIndex('services.password.reset.when', { sparse: 1 }); } /// diff --git a/packages/accounts-password/password_server.js b/packages/accounts-password/password_server.js index 5bc154917b..7333493c73 100644 --- a/packages/accounts-password/password_server.js +++ b/packages/accounts-password/password_server.js @@ -1085,5 +1085,3 @@ Meteor.users._ensureIndex('services.email.verificationTokens.token', {unique: 1, sparse: 1}); Meteor.users._ensureIndex('services.password.reset.token', {unique: 1, sparse: 1}); -Meteor.users._ensureIndex('services.password.reset.when', - {sparse: 1}); From ddfa7083e73077b2415b90ef737cf1f064548feb Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Fri, 7 Apr 2017 17:06:13 +0300 Subject: [PATCH 003/125] Change `MinimongoError` to accept `field` in a new `options` parameter. This allows the field name to be dynamically introduced into the error message. Follows-up on meteor/meteor#8529. --- packages/minimongo/minimongo.js | 6 ++- packages/minimongo/minimongo_tests.js | 16 ++++++ packages/minimongo/modify.js | 78 ++++++++++++++++----------- packages/minimongo/package.js | 1 + 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js index f79f2d4bc1..312c9e4581 100644 --- a/packages/minimongo/minimongo.js +++ b/packages/minimongo/minimongo.js @@ -40,7 +40,11 @@ Minimongo = {}; // Use it to export private functions to test in Tinytest. MinimongoTest = {}; -MinimongoError = function (message) { +MinimongoError = function (message, options={}) { + if (typeof message === "string" && options.field) { + message += ` for field '${options.field}'`; + } + var e = new Error(message); e.name = "MinimongoError"; return e; diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 69e728448e..9edc47c52e 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -163,6 +163,22 @@ Tinytest.add("minimongo - basics", function (test) { }); +Tinytest.add("minimongo - error - no options", function (test) { + try { + throw MinimongoError("Not fun to have errors"); + } catch (e) { + test.equal(e.message, "Not fun to have errors"); + } +}); + +Tinytest.add("minimongo - error - with field", function (test) { + try { + throw MinimongoError("Cats are no fun", { field: "mice" }); + } catch (e) { + test.equal(e.message, "Cats are no fun for field 'mice'"); + } +}); + Tinytest.add("minimongo - cursors", function (test) { var c = new LocalCollection(); var res; diff --git a/packages/minimongo/modify.js b/packages/minimongo/modify.js index e595d82cab..7074482ee6 100644 --- a/packages/minimongo/modify.js +++ b/packages/minimongo/modify.js @@ -185,20 +185,24 @@ var MODIFIERS = { $currentDate: function (target, field, arg) { if (typeof arg === "object" && arg.hasOwnProperty("$type")) { if (arg.$type !== "date") { - throw MinimongoError("Minimongo does currently only support the date type in $currentDate modifiers: " + field); + throw MinimongoError( + "Minimongo does currently only support the date type " + + "in $currentDate modifiers", + { field }); } } else if (arg !== true) { - throw MinimongoError("Invalid $currentDate modifier: " + field); + throw MinimongoError("Invalid $currentDate modifier", { field }); } target[field] = new Date(); }, $min: function (target, field, arg) { if (typeof arg !== "number") { - throw MinimongoError("Modifier $min allowed for numbers only: " + field); + throw MinimongoError("Modifier $min allowed for numbers only", { field }); } if (field in target) { if (typeof target[field] !== "number") { - throw MinimongoError("Cannot apply $min modifier to non-number: " + field); + throw MinimongoError( + "Cannot apply $min modifier to non-number", { field }); } if (target[field] > arg) { target[field] = arg; @@ -209,11 +213,12 @@ var MODIFIERS = { }, $max: function (target, field, arg) { if (typeof arg !== "number") { - throw MinimongoError("Modifier $max allowed for numbers only: " + field); + throw MinimongoError("Modifier $max allowed for numbers only", { field }); } if (field in target) { if (typeof target[field] !== "number") { - throw MinimongoError("Cannot apply $max modifier to non-number: " + field); + throw MinimongoError( + "Cannot apply $max modifier to non-number", { field }); } if (target[field] < arg) { target[field] = arg; @@ -224,10 +229,11 @@ var MODIFIERS = { }, $inc: function (target, field, arg) { if (typeof arg !== "number") - throw MinimongoError("Modifier $inc allowed for numbers only: " + field); + throw MinimongoError("Modifier $inc allowed for numbers only", { field }); if (field in target) { if (typeof target[field] !== "number") - throw MinimongoError("Cannot apply $inc modifier to non-number: " + field); + throw MinimongoError( + "Cannot apply $inc modifier to non-number", { field }); target[field] += arg; } else { target[field] = arg; @@ -235,12 +241,13 @@ var MODIFIERS = { }, $set: function (target, field, arg) { if (!_.isObject(target)) { // not an array or an object - var e = MinimongoError("Cannot set property on non-object field: " + field); + var e = MinimongoError( + "Cannot set property on non-object field", { field }); e.setPropertyError = true; throw e; } if (target === null) { - var e = MinimongoError("Cannot set property on null: " + field); + var e = MinimongoError("Cannot set property on null", { field }); e.setPropertyError = true; throw e; } @@ -267,7 +274,8 @@ var MODIFIERS = { if (target[field] === undefined) target[field] = []; if (!(target[field] instanceof Array)) - throw MinimongoError("Cannot apply $push modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $push modifier to non-array", { field }); if (!(arg && arg.$each)) { // Simple mode: not $each @@ -278,16 +286,17 @@ var MODIFIERS = { // Fancy mode: $each (and maybe $slice and $sort and $position) var toPush = arg.$each; if (!(toPush instanceof Array)) - throw MinimongoError("$each must be an array: " + field); + throw MinimongoError("$each must be an array", { field }); // Parse $position var position = undefined; if ('$position' in arg) { if (typeof arg.$position !== "number") - throw MinimongoError("$position must be a numeric value: " + field); + throw MinimongoError("$position must be a numeric value", { field }); // XXX should check to make sure integer if (arg.$position < 0) - throw MinimongoError("$position in $push must be zero or positive: " + field); + throw MinimongoError( + "$position in $push must be zero or positive", { field }); position = arg.$position; } @@ -295,10 +304,11 @@ var MODIFIERS = { var slice = undefined; if ('$slice' in arg) { if (typeof arg.$slice !== "number") - throw MinimongoError("$slice must be a numeric value: " + field); + throw MinimongoError("$slice must be a numeric value", { field }); // XXX should check to make sure integer if (arg.$slice > 0) - throw MinimongoError("$slice in $push must be zero or negative: " + field); + throw MinimongoError( + "$slice in $push must be zero or negative", { field }); slice = arg.$slice; } @@ -306,7 +316,7 @@ var MODIFIERS = { var sortFunction = undefined; if (arg.$sort) { if (slice === undefined) - throw MinimongoError("$sort requires $slice to be present: " + field); + throw MinimongoError("$sort requires $slice to be present", { field }); // XXX this allows us to use a $sort whose value is an array, but that's // actually an extension of the Node driver, so it won't work // server-side. Could be confusing! @@ -315,7 +325,7 @@ var MODIFIERS = { for (var i = 0; i < toPush.length; i++) { if (LocalCollection._f._type(toPush[i]) !== 3) { throw MinimongoError("$push like modifiers using $sort " + - "require all elements to be objects: " + field); + "require all elements to be objects", { field }); } } } @@ -350,7 +360,8 @@ var MODIFIERS = { if (x === undefined) target[field] = arg; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pushAll modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $pushAll modifier to non-array", { field }); else { for (var i = 0; i < arg.length; i++) x.push(arg[i]); @@ -371,7 +382,8 @@ var MODIFIERS = { if (x === undefined) target[field] = values; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $addToSet modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $addToSet modifier to non-array", { field }); else { _.each(values, function (value) { for (var i = 0; i < x.length; i++) @@ -388,7 +400,8 @@ var MODIFIERS = { if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pop modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $pop modifier to non-array", { field }); else { if (typeof arg === 'number' && arg < 0) x.splice(0, 1); @@ -403,7 +416,8 @@ var MODIFIERS = { if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $pull/pullAll modifier to non-array", { field }); else { var out = []; if (arg != null && typeof arg === "object" && !(arg instanceof Array)) { @@ -430,14 +444,16 @@ var MODIFIERS = { }, $pullAll: function (target, field, arg) { if (!(typeof arg === "object" && arg instanceof Array)) - throw MinimongoError("Modifier $pushAll/pullAll allowed for arrays only: " + field); + throw MinimongoError( + "Modifier $pushAll/pullAll allowed for arrays only", { field }); if (target === undefined) return; var x = target[field]; if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $pull/pullAll modifier to non-array", { field }); else { var out = []; for (var i = 0; i < x.length; i++) { @@ -457,15 +473,17 @@ var MODIFIERS = { $rename: function (target, field, arg, keypath, doc) { if (keypath === arg) // no idea why mongo has this restriction.. - throw MinimongoError("$rename source must differ from target: " + field); + throw MinimongoError("$rename source must differ from target", { field }); if (target === null) - throw MinimongoError("$rename source field invalid: " + field); + throw MinimongoError("$rename source field invalid", { field }); if (typeof arg !== "string") - throw MinimongoError("$rename target must be a string: " + field); + throw MinimongoError("$rename target must be a string", { field }); if (arg.indexOf('\0') > -1) { // Null bytes are not allowed in Mongo field names // https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names - throw MinimongoError("The 'to' field for $rename cannot contain an embedded null byte: " + field); + throw MinimongoError( + "The 'to' field for $rename cannot contain an embedded null byte", + { field }); } if (target === undefined) return; @@ -475,13 +493,13 @@ var MODIFIERS = { var keyparts = arg.split('.'); var target2 = findModTarget(doc, keyparts, {forbidArray: true}); if (target2 === null) - throw MinimongoError("$rename target field invalid: " + field); + throw MinimongoError("$rename target field invalid", { field }); var field2 = keyparts.pop(); target2[field2] = v; }, $bit: function (target, field, arg) { // XXX mongo only supports $bit on integers, and we only support // native javascript numbers (doubles) so far, so we can't support $bit - throw MinimongoError("$bit is not supported: " + field); + throw MinimongoError("$bit is not supported", { field }); } }; diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index e4353c687a..d490228a29 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -7,6 +7,7 @@ Package.onUse(function (api) { api.export('LocalCollection'); api.export('Minimongo'); api.export('MinimongoTest', { testOnly: true }); + api.export('MinimongoError', { testOnly: true }); api.use([ 'underscore', 'ejson', From fde92c9d7985e52ce118f9714a448202367e605b Mon Sep 17 00:00:00 2001 From: Tomas Brambora Date: Wed, 12 Apr 2017 21:51:35 +1000 Subject: [PATCH 004/125] Fixed Google OAuth user data fetching. --- packages/google-oauth/google_server.js | 47 +++++++++++--------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/packages/google-oauth/google_server.js b/packages/google-oauth/google_server.js index 4b647a37d5..6b9b3f00e5 100644 --- a/packages/google-oauth/google_server.js +++ b/packages/google-oauth/google_server.js @@ -5,34 +5,7 @@ var Accounts = require("meteor/accounts-base").Accounts; Google.whitelistedFields = ['id', 'email', 'verified_email', 'name', 'given_name', 'family_name', 'picture', 'locale', 'timezone', 'gender']; -Accounts.registerLoginHandler(function (request) { - if (request.googleSignIn !== true) { - return; - } - - var res = HTTP.get( - "https://www.googleapis.com/oauth2/v3/tokeninfo", - { headers: { "User-Agent": "Meteor/1.0" }, - params: { id_token: request.idToken }} - ); - - if (res.error) { - throw res.error; - } - - if (res.statusCode === 200 && - res.data.sub === request.userId) { - return Accounts.updateOrCreateUserFromExternalService("google", { - id: request.userId, - idToken: request.idToken, - accessToken: request.accessToken, - email: request.email, - picture: request.imageUrl - }); - } -}); - -OAuth.registerService('google', 2, null, function(query) { +function getServiceData(query) { var response = getTokens(query); var expiresAt = (+new Date) + (1000 * parseInt(response.expiresIn, 10)); var accessToken = response.accessToken; @@ -60,8 +33,26 @@ OAuth.registerService('google', 2, null, function(query) { serviceData: serviceData, options: {profile: {name: identity.name}} }; +} + +Accounts.registerLoginHandler(function (request) { + if (request.googleSignIn !== true) { + return; + } + + const res = getServiceData({code: request.serverAuthCode}); + + return Accounts.updateOrCreateUserFromExternalService("google", _.extend({ + id: request.userId, + idToken: request.idToken, + accessToken: request.accessToken, + email: request.email, + picture: request.imageUrl + }, res.serviceData)); }); +OAuth.registerService('google', 2, null, getServiceData); + // returns an object containing: // - accessToken // - expiresIn: lifetime of token in seconds From 27b2a04f6f92a83f3ee05a5b23dc82ec97e61a94 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Wed, 12 Apr 2017 09:58:16 -0700 Subject: [PATCH 005/125] Remove experimental trailing comma to avoid problems with `jsdoc`. The comma in question: a trailing comma a rest-parameter, within a function argument's parameter de-structuring: function a({ a = false, ...b, }) { // ... } Espree, the parser used by `jsdoc` (used in Meteor docs) previously allowed this with `experimentalObjectRestSpread` enabled but now throws an error with the addition of https://github.com/eslint/espree/commit/652990a7bfeb9eca2041e8cbb696de671522d420. It might have been argued at one point that the trailing-comma could allow for the easy, future addition of another parameter, ala: function a({ a = false, ...b, c = true, }) { // ... } Having the rest-parameter in the last position is certainly more clear (it is the "rest", after-all, and there can be only one) but I'm not going to have that discussion at the cost of docs not deploying! --- tools/isobuild/bundler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index 526b5e1eed..3bbc8cacb4 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -353,7 +353,7 @@ export class NodeModulesDirectory { // Options consumed by readDirsFromJSON are listed above. Any other // options will be passed on to NodeModulesDirectory constructor via // this callerInfo object: - ...callerInfo, + ...callerInfo }) { assert.strictEqual(typeof callerInfo.sourceRoot, "string"); From c67540cf56a0678f423e1cd603195470091985e7 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 12 Apr 2017 14:20:06 -0400 Subject: [PATCH 006/125] Remove underscore dependency from google-oauth package. --- packages/google-oauth/google_client.js | 41 ++++++++++++++++--------- packages/google-oauth/google_server.js | 40 ++++++++++++++++-------- packages/google-oauth/google_sign-in.js | 14 +++++---- packages/google-oauth/package.js | 5 ++- 4 files changed, 63 insertions(+), 37 deletions(-) diff --git a/packages/google-oauth/google_client.js b/packages/google-oauth/google_client.js index c7b54dccfb..a45c080011 100644 --- a/packages/google-oauth/google_client.js +++ b/packages/google-oauth/google_client.js @@ -1,5 +1,13 @@ var Google = require("./namespace.js"); +var ILLEGAL_PARAMETERS = { + 'response_type': 1, + 'client_id': 1, + 'scope': 1, + 'redirect_uri': 1, + 'state': 1 +}; + // Request Google credentials for the user // @param options {optional} // @param credentialRequestCompleteCallback {Function} Callback function to call on @@ -24,24 +32,26 @@ Google.requestCredential = function (options, credentialRequestCompleteCallback) var credentialToken = Random.secret(); // we need the email scope to get user id from google. - var requiredScope = ['email']; - var scope = ['profile']; - if (options.requestPermissions) - scope = options.requestPermissions; - scope = _.union(scope, requiredScope); + var requiredScopes = { 'email': 1 }; + var scopes = options.requestPermissions || ['profile']; + scopes.forEach(function (scope) { + requiredScopes[scope] = 1; + }); + scopes = Object.keys(requiredScopes); var loginUrlParameters = {}; if (config.loginUrlParameters){ - _.extend(loginUrlParameters, config.loginUrlParameters) + Object.assign(loginUrlParameters, config.loginUrlParameters); } if (options.loginUrlParameters){ - _.extend(loginUrlParameters, options.loginUrlParameters) + Object.assign(loginUrlParameters, options.loginUrlParameters); } - var ILLEGAL_PARAMETERS = ['response_type', 'client_id', 'scope', 'redirect_uri', 'state']; - // validate options keys - _.each(_.keys(loginUrlParameters), function (key) { - if (_.contains(ILLEGAL_PARAMETERS, key)) + + // validate options keys + Object.keys(loginUrlParameters).forEach(function (key) { + if (ILLEGAL_PARAMETERS.hasOwnProperty(key)) { throw new Error("Google.requestCredential: Invalid loginUrlParameter: " + key); + } }); // backwards compatible options @@ -60,16 +70,17 @@ Google.requestCredential = function (options, credentialRequestCompleteCallback) var loginStyle = OAuth._loginStyle('google', config, options); // https://developers.google.com/accounts/docs/OAuth2WebServer#formingtheurl - _.extend(loginUrlParameters, { + Object.assign(loginUrlParameters, { "response_type": "code", "client_id": config.clientId, - "scope": scope.join(' '), // space delimited + "scope": scopes.join(' '), // space delimited "redirect_uri": OAuth._redirectUri('google', config), "state": OAuth._stateParam(loginStyle, credentialToken, options.redirectUrl) }); var loginUrl = 'https://accounts.google.com/o/oauth2/auth?' + - _.map(loginUrlParameters, function(value, param){ - return encodeURIComponent(param) + '=' + encodeURIComponent(value); + Object.keys(loginUrlParameters).map(function (param) { + return encodeURIComponent(param) + '=' + + encodeURIComponent(loginUrlParameters[param]); }).join("&"); OAuth.launchLogin({ diff --git a/packages/google-oauth/google_server.js b/packages/google-oauth/google_server.js index 6b9b3f00e5..c430bd5637 100644 --- a/packages/google-oauth/google_server.js +++ b/packages/google-oauth/google_server.js @@ -1,5 +1,6 @@ var Google = require("./namespace.js"); var Accounts = require("meteor/accounts-base").Accounts; +var hasOwn = Object.prototype.hasOwnProperty; // https://developers.google.com/accounts/docs/OAuth2Login#userinfocall Google.whitelistedFields = ['id', 'email', 'verified_email', 'name', 'given_name', @@ -20,8 +21,14 @@ function getServiceData(query) { scope: scopes }; - var fields = _.pick(identity, Google.whitelistedFields); - _.extend(serviceData, fields); + var fields = Object.create(null); + Google.whitelistedFields.forEach(function (name) { + if (hasOwn.call(identity, name)) { + fields[name] = identity[name]; + } + }); + + Object.assign(serviceData, fields); // only set the token in serviceData if it's there. this ensures // that we don't lose old ones (since we only get this on the first @@ -40,15 +47,16 @@ Accounts.registerLoginHandler(function (request) { return; } - const res = getServiceData({code: request.serverAuthCode}); - - return Accounts.updateOrCreateUserFromExternalService("google", _.extend({ + return Accounts.updateOrCreateUserFromExternalService("google", { id: request.userId, idToken: request.idToken, accessToken: request.accessToken, email: request.email, - picture: request.imageUrl - }, res.serviceData)); + picture: request.imageUrl, + ...getServiceData({ + code: request.serverAuthCode + }).serviceData, + }); }); OAuth.registerService('google', 2, null, getServiceData); @@ -73,8 +81,10 @@ var getTokens = function (query) { grant_type: 'authorization_code' }}); } catch (err) { - throw _.extend(new Error("Failed to complete OAuth handshake with Google. " + err.message), - {response: err.response}); + throw Object.assign( + new Error("Failed to complete OAuth handshake with Google. " + err.message), + { response: err.response } + ); } if (response.data.error) { // if the http response was a json object with an error attribute @@ -95,8 +105,10 @@ var getIdentity = function (accessToken) { "https://www.googleapis.com/oauth2/v1/userinfo", {params: {access_token: accessToken}}).data; } catch (err) { - throw _.extend(new Error("Failed to fetch identity from Google. " + err.message), - {response: err.response}); + throw Object.assign( + new Error("Failed to fetch identity from Google. " + err.message), + { response: err.response } + ); } }; @@ -106,8 +118,10 @@ var getScopes = function (accessToken) { "https://www.googleapis.com/oauth2/v1/tokeninfo", {params: {access_token: accessToken}}).data.scope.split(' '); } catch (err) { - throw _.extend(new Error("Failed to fetch tokeninfo from Google. " + err.message), - {response: err.response}); + throw Object.assign( + new Error("Failed to fetch tokeninfo from Google. " + err.message), + { response: err.response } + ); } }; diff --git a/packages/google-oauth/google_sign-in.js b/packages/google-oauth/google_sign-in.js index 4d21403264..3ba3a54ea8 100644 --- a/packages/google-oauth/google_sign-in.js +++ b/packages/google-oauth/google_sign-in.js @@ -59,12 +59,14 @@ exports.signIn = Google.signIn = function (options, callback) { function getScopes(options) { // we need the email scope to get user id from google. - var requiredScopes = ['email']; - var scopes = ['profile']; - if (options && options.requestPermissions) { - scopes = options.requestPermissions; - } - return _.union(scopes, requiredScopes); + var requiredScopes = { 'email': 1 }; + var scopes = options.requestPermissions || ['profile']; + + scopes.forEach(function (scope) { + requiredScopes[scope] = 1; + }); + + return Object.keys(requiredScopes); } exports.signOut = Google.signOut = function () { diff --git a/packages/google-oauth/package.js b/packages/google-oauth/package.js index d977bb6d16..4432aff495 100644 --- a/packages/google-oauth/package.js +++ b/packages/google-oauth/package.js @@ -14,12 +14,11 @@ Cordova.depends({ }); Package.onUse(function(api) { - api.use("modules"); - api.use("promise"); + api.use("ecmascript"); api.use('oauth2', ['client', 'server']); api.use('oauth', ['client', 'server']); api.use('http', ['server']); - api.use(['underscore', 'service-configuration'], ['client', 'server']); + api.use('service-configuration'); api.use('random', 'client'); api.addFiles('google_server.js', 'server'); From c41a65ce59d97f8854ff0beeb715482e13fdadb1 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 12 Apr 2017 15:20:43 -0400 Subject: [PATCH 007/125] Bump google-oauth package version to 1.2.2. --- packages/google-oauth/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-oauth/package.js b/packages/google-oauth/package.js index 4432aff495..ea533526fa 100644 --- a/packages/google-oauth/package.js +++ b/packages/google-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Google OAuth flow", - version: "1.2.1" + version: "1.2.2" }); var cordovaPluginGooglePlusURL = From 18870317334912a5ba47529a434dc5b9a8c8d497 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 12 Apr 2017 15:25:12 -0400 Subject: [PATCH 008/125] Bump minimongo package version to 1.0.22. --- packages/minimongo/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index d490228a29..d89b5f03df 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.0.21' + version: '1.0.22' }); Package.onUse(function (api) { From 895321e35f19d083e15ba721b42231dd8abd1fed Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 02:35:01 -0400 Subject: [PATCH 009/125] Upgrade meteor-babel and reify to fix #8595. (#8599) * Upgrade meteor-babel to version 0.20.1 and reify to 0.7.4. * Bump $BUNDLE_VERSION to 4.7.25 before rebuilding dev bundle. --- History.md | 4 + meteor | 2 +- .../.npm/package/npm-shrinkwrap.json | 202 +++++++++--------- packages/babel-compiler/package.js | 4 +- .../modules/.npm/package/npm-shrinkwrap.json | 22 +- packages/modules/package.js | 4 +- scripts/dev-bundle-tool-package.js | 2 +- 7 files changed, 112 insertions(+), 128 deletions(-) diff --git a/History.md b/History.md index c422428108..210c44c613 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,9 @@ ## v.NEXT +* The `meteor-babel` npm package has been upgraded to version 0.20.1, and + the `reify` npm package has been upgraded to version 0.7.4, fixing + [issue #8595](https://github.com/meteor/meteor/issues/8595). + ## v1.4.4.1, 2017-04-07 * A change in Meteor 1.4.4 to remove "garbage" directories asynchronously diff --git a/meteor b/meteor index 886256dfb7..cc0116c16a 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.7.23 +BUNDLE_VERSION=4.7.25 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index 214f819c77..7bd00f4cd2 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "acorn": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz", - "from": "acorn@>=4.0.5 <4.1.0" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "from": "acorn@>=5.0.0 <5.1.0" }, "ansi-regex": { "version": "2.1.1", @@ -21,29 +21,29 @@ "from": "babel-code-frame@>=6.22.0 <7.0.0" }, "babel-core": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.1.tgz", "from": "babel-core@>=6.22.1 <7.0.0" }, "babel-generator": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.0.tgz", - "from": "babel-generator@>=6.24.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.1.tgz", + "from": "babel-generator@>=6.24.1 <7.0.0" }, "babel-helper-builder-react-jsx": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.23.0.tgz", - "from": "babel-helper-builder-react-jsx@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz", + "from": "babel-helper-builder-react-jsx@>=6.24.1 <7.0.0" }, "babel-helper-call-delegate": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz", - "from": "babel-helper-call-delegate@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "from": "babel-helper-call-delegate@>=6.24.1 <7.0.0" }, "babel-helper-define-map": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.23.0.tgz", - "from": "babel-helper-define-map@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz", + "from": "babel-helper-define-map@>=6.24.1 <7.0.0" }, "babel-helper-evaluate-path": { "version": "0.0.3", @@ -56,19 +56,19 @@ "from": "babel-helper-flip-expressions@>=0.0.2 <0.0.3" }, "babel-helper-function-name": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz", - "from": "babel-helper-function-name@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "from": "babel-helper-function-name@>=6.24.1 <7.0.0" }, "babel-helper-get-function-arity": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz", - "from": "babel-helper-get-function-arity@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "from": "babel-helper-get-function-arity@>=6.24.1 <7.0.0" }, "babel-helper-hoist-variables": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.22.0.tgz", - "from": "babel-helper-hoist-variables@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "from": "babel-helper-hoist-variables@>=6.24.1 <7.0.0" }, "babel-helper-is-nodes-equiv": { "version": "0.0.1", @@ -86,14 +86,14 @@ "from": "babel-helper-mark-eval-scopes@>=0.0.3 <0.0.4" }, "babel-helper-optimise-call-expression": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.23.0.tgz", - "from": "babel-helper-optimise-call-expression@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "from": "babel-helper-optimise-call-expression@>=6.24.1 <7.0.0" }, "babel-helper-regex": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.22.0.tgz", - "from": "babel-helper-regex@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz", + "from": "babel-helper-regex@>=6.24.1 <7.0.0" }, "babel-helper-remove-or-void": { "version": "0.0.1", @@ -101,9 +101,9 @@ "from": "babel-helper-remove-or-void@>=0.0.1 <0.0.2" }, "babel-helper-replace-supers": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.23.0.tgz", - "from": "babel-helper-replace-supers@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "from": "babel-helper-replace-supers@>=6.24.1 <7.0.0" }, "babel-helper-to-multiple-sequence-expressions": { "version": "0.0.3", @@ -111,9 +111,9 @@ "from": "babel-helper-to-multiple-sequence-expressions@>=0.0.3 <0.0.4" }, "babel-helpers": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.23.0.tgz", - "from": "babel-helpers@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "from": "babel-helpers@>=6.24.1 <7.0.0" }, "babel-messages": { "version": "6.23.0", @@ -131,8 +131,8 @@ "from": "babel-plugin-minify-constant-folding@>=0.0.4 <0.0.5", "dependencies": { "jsesc": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.4.0.tgz", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.0.tgz", "from": "jsesc@>=2.4.0 <3.0.0" } } @@ -235,18 +235,18 @@ "from": "babel-plugin-transform-es2015-block-scoped-functions@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-block-scoping": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz", "from": "babel-plugin-transform-es2015-block-scoping@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-classes": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "from": "babel-plugin-transform-es2015-classes@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-computed-properties": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "from": "babel-plugin-transform-es2015-computed-properties@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-destructuring": { @@ -265,28 +265,28 @@ "from": "babel-plugin-transform-es2015-literals@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz", "from": "babel-plugin-transform-es2015-modules-commonjs@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-modules-reify": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.6.2.tgz", - "from": "babel-plugin-transform-es2015-modules-reify@>=0.6.0 <0.7.0" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.7.0.tgz", + "from": "babel-plugin-transform-es2015-modules-reify@>=0.7.0 <0.8.0" }, "babel-plugin-transform-es2015-object-super": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "from": "babel-plugin-transform-es2015-object-super@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-parameters": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "from": "babel-plugin-transform-es2015-parameters@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "from": "babel-plugin-transform-es2015-shorthand-properties@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-spread": { @@ -295,8 +295,8 @@ "from": "babel-plugin-transform-es2015-spread@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "from": "babel-plugin-transform-es2015-sticky-regex@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-template-literals": { @@ -310,8 +310,8 @@ "from": "babel-plugin-transform-es2015-typeof-symbol@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "from": "babel-plugin-transform-es2015-unicode-regex@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es3-property-literals": { @@ -360,9 +360,9 @@ "from": "babel-plugin-transform-react-display-name@>=6.23.0 <7.0.0" }, "babel-plugin-transform-react-jsx": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.23.0.tgz", - "from": "babel-plugin-transform-react-jsx@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "from": "babel-plugin-transform-react-jsx@>=6.24.1 <7.0.0" }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", @@ -375,8 +375,8 @@ "from": "babel-plugin-transform-react-jsx-source@>=6.22.0 <7.0.0" }, "babel-plugin-transform-regenerator": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz", "from": "babel-plugin-transform-regenerator@>=6.22.0 <7.0.0" }, "babel-plugin-transform-regexp-constructors": { @@ -410,9 +410,9 @@ "from": "babel-plugin-transform-simplify-comparison-operators@>=6.8.1 <7.0.0" }, "babel-plugin-transform-strict-mode": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.22.0.tgz", - "from": "babel-plugin-transform-strict-mode@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "from": "babel-plugin-transform-strict-mode@>=6.24.1 <7.0.0" }, "babel-plugin-transform-undefined-to-void": { "version": "6.8.0", @@ -430,19 +430,19 @@ "from": "babel-preset-flow@>=6.23.0 <7.0.0" }, "babel-preset-meteor": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-6.25.0.tgz", - "from": "babel-preset-meteor@6.25.0" + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-6.26.0.tgz", + "from": "babel-preset-meteor@6.26.0" }, "babel-preset-react": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "from": "babel-preset-react@>=6.22.0 <7.0.0" }, "babel-register": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.0.tgz", - "from": "babel-register@>=6.24.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", + "from": "babel-register@>=6.24.1 <7.0.0" }, "babel-runtime": { "version": "6.23.0", @@ -450,18 +450,18 @@ "from": "babel-runtime@>=6.22.0 <7.0.0" }, "babel-template": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", "from": "babel-template@>=6.22.0 <7.0.0" }, "babel-traverse": { - "version": "6.23.1", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.23.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", "from": "babel-traverse@>=6.22.1 <7.0.0" }, "babel-types": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", "from": "babel-types@>=6.22.0 <7.0.0" }, "babylon": { @@ -475,8 +475,8 @@ "from": "balanced-match@>=0.4.1 <0.5.0" }, "brace-expansion": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", "from": "brace-expansion@>=1.0.0 <2.0.0" }, "chalk": { @@ -490,8 +490,8 @@ "from": "concat-map@0.0.1" }, "convert-source-map": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.4.0.tgz", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", "from": "convert-source-map@>=1.3.0 <2.0.0" }, "core-js": { @@ -579,15 +579,10 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", "from": "loose-envify@>=1.0.0 <2.0.0" }, - "magic-string": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.19.0.tgz", - "from": "magic-string@>=0.19.0 <0.20.0" - }, "meteor-babel": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.19.1.tgz", - "from": "meteor-babel@0.19.1" + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.0.tgz", + "from": "meteor-babel@0.20.0" }, "meteor-babel-helpers": { "version": "0.0.3", @@ -650,9 +645,9 @@ "from": "regenerator-runtime@>=0.10.0 <0.11.0" }, "regenerator-transform": { - "version": "0.9.8", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.8.tgz", - "from": "regenerator-transform@0.9.8" + "version": "0.9.11", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.11.tgz", + "from": "regenerator-transform@0.9.11" }, "regexpu-core": { "version": "2.0.0", @@ -677,9 +672,9 @@ } }, "reify": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.6.6.tgz", - "from": "reify@>=0.6.2 <0.7.0" + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz", + "from": "reify@>=0.7.2 <0.8.0" }, "repeating": { "version": "2.0.1", @@ -720,11 +715,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "from": "trim-right@>=1.0.1 <2.0.0" - }, - "vlq": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.1.tgz", - "from": "vlq@>=0.2.1 <0.3.0" } } } diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index 44bc595b9c..dbd098e545 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,11 +6,11 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.18.1' + version: '6.18.2' }); Npm.depends({ - 'meteor-babel': '0.19.1' + 'meteor-babel': '0.20.1' }); Package.onUse(function (api) { diff --git a/packages/modules/.npm/package/npm-shrinkwrap.json b/packages/modules/.npm/package/npm-shrinkwrap.json index 0ec396bdbd..20c76d7a1d 100644 --- a/packages/modules/.npm/package/npm-shrinkwrap.json +++ b/packages/modules/.npm/package/npm-shrinkwrap.json @@ -1,24 +1,14 @@ { "dependencies": { "acorn": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz", - "from": "acorn@>=4.0.5 <4.1.0" - }, - "magic-string": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.19.0.tgz", - "from": "magic-string@>=0.19.0 <0.20.0" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "from": "acorn@>=5.0.0 <5.1.0" }, "reify": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.6.6.tgz", - "from": "reify@0.6.6" - }, - "vlq": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.1.tgz", - "from": "vlq@>=0.2.1 <0.3.0" + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz", + "from": "reify@0.7.4" } } } diff --git a/packages/modules/package.js b/packages/modules/package.js index 1153f2f9cb..49e7a97eae 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,12 +1,12 @@ Package.describe({ name: "modules", - version: "0.8.1", + version: "0.8.2", summary: "CommonJS module system", documentation: "README.md" }); Npm.depends({ - reify: "0.6.6" + reify: "0.7.4" }); Package.onUse(function(api) { diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index f7d2ed362e..9d8d0ec578 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -14,7 +14,7 @@ var packageJson = { npm: "4.4.4", "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", - "meteor-babel": "0.19.1", + "meteor-babel": "0.20.1", "meteor-promise": "0.8.0", fibers: "1.0.15", promise: "7.1.1", From d8fa46b5aa6198a7a208a5550db7828972613f91 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 02:36:37 -0400 Subject: [PATCH 010/125] Update npm-shrinkwrap.json for babel-compiler package. --- packages/babel-compiler/.npm/package/npm-shrinkwrap.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index 7bd00f4cd2..f297b0adf2 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -580,9 +580,9 @@ "from": "loose-envify@>=1.0.0 <2.0.0" }, "meteor-babel": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.0.tgz", - "from": "meteor-babel@0.20.0" + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.1.tgz", + "from": "meteor-babel@0.20.1" }, "meteor-babel-helpers": { "version": "0.0.3", From 353bea75b776ecb71bba7f125465abe112fa82d1 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 02:38:20 -0400 Subject: [PATCH 011/125] Bump ecmascript package version to 0.7.3. Bumping this version is necessary after upgrading babel-compiler since ecmascript registers a compiler plugin that uses babel-compiler. --- packages/ecmascript/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index 4c27300bbe..b4b84a7c89 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.7.2', + version: '0.7.3', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); From 7a9dd2b7a457cf54c5e11d1aed1102182c0688fe Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 18:11:06 -0400 Subject: [PATCH 012/125] Use tokens from Google Sign-In instead of calling getTokens. (#8604) * Use tokens from Google Sign-In instead of calling getTokens. Follow-up to https://github.com/meteor/meteor/pull/8588. * Bump google-oauth package version to 1.2.3. --- packages/google-oauth/google_server.js | 40 +++++++++++++++++--------- packages/google-oauth/package.js | 2 +- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/packages/google-oauth/google_server.js b/packages/google-oauth/google_server.js index c430bd5637..871c9c2ee8 100644 --- a/packages/google-oauth/google_server.js +++ b/packages/google-oauth/google_server.js @@ -6,21 +6,22 @@ var hasOwn = Object.prototype.hasOwnProperty; Google.whitelistedFields = ['id', 'email', 'verified_email', 'name', 'given_name', 'family_name', 'picture', 'locale', 'timezone', 'gender']; -function getServiceData(query) { - var response = getTokens(query); - var expiresAt = (+new Date) + (1000 * parseInt(response.expiresIn, 10)); - var accessToken = response.accessToken; - var idToken = response.idToken; +function getServiceDataFromTokens(tokens) { + var accessToken = tokens.accessToken; + var idToken = tokens.idToken; var scopes = getScopes(accessToken); var identity = getIdentity(accessToken); - var serviceData = { accessToken: accessToken, idToken: idToken, - expiresAt: expiresAt, scope: scopes }; + if (hasOwn.call(tokens, "expiresAt")) { + serviceData.expiresAt = + Date.now() + 1000 * parseInt(tokens.expiresIn, 10); + } + var fields = Object.create(null); Google.whitelistedFields.forEach(function (name) { if (hasOwn.call(identity, name)) { @@ -33,12 +34,17 @@ function getServiceData(query) { // only set the token in serviceData if it's there. this ensures // that we don't lose old ones (since we only get this on the first // log in attempt) - if (response.refreshToken) - serviceData.refreshToken = response.refreshToken; + if (tokens.refreshToken) { + serviceData.refreshToken = tokens.refreshToken; + } return { serviceData: serviceData, - options: {profile: {name: identity.name}} + options: { + profile: { + name: identity.name + } + } }; } @@ -47,18 +53,26 @@ Accounts.registerLoginHandler(function (request) { return; } + const { serviceData } = getServiceDataFromTokens({ + accessToken: request.accessToken, + refreshToken: request.refreshToken, + idToken: request.idToken, + }); + return Accounts.updateOrCreateUserFromExternalService("google", { id: request.userId, idToken: request.idToken, accessToken: request.accessToken, email: request.email, picture: request.imageUrl, - ...getServiceData({ - code: request.serverAuthCode - }).serviceData, + ...serviceData, }); }); +function getServiceData(query) { + return getServiceDataFromTokens(getTokens(query)); +} + OAuth.registerService('google', 2, null, getServiceData); // returns an object containing: diff --git a/packages/google-oauth/package.js b/packages/google-oauth/package.js index ea533526fa..62436fca76 100644 --- a/packages/google-oauth/package.js +++ b/packages/google-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Google OAuth flow", - version: "1.2.2" + version: "1.2.3" }); var cordovaPluginGooglePlusURL = From 6d4562656641b3c1f6c4a79e6a3c60c61b0136d5 Mon Sep 17 00:00:00 2001 From: Erik Demaine Date: Mon, 17 Apr 2017 15:41:44 -0400 Subject: [PATCH 013/125] Switch to modern nodemailer 4, Node 4 version. Fix #8591 (#8605) * Switch to modern nodemailer 4, Node 4 version. Fix #8591 * Most critically, use a pool instead of direct SMTP connection, to handle dropped connections and increase throughput, like mail module 1.1. (#8591) * New nodemailer's sendMail wants an options object, not a MailComposer object. Luckily, a MailComposer object has a "mail" field that remembers the original options, so we can keep original behavior. * However, we no longer support the mailComposer option set to a compiled MailComposer object (functionality that was briefly added in 1.2.0). * nodemailer does SMTP URL parsing now automatically for us, simplifying code. * Tests' outputs now end with additional "\r\n" * Drop underscore package dependency (no longer needed) * General formatting/style cleanup for `packages/email`. * snake_cased => camelCased for some local variables. * Added curly-brackets to `if`s. * Removed trailing spaces. * Removed commented-out code. * Removed older doc text and changed some links. * Get rid of back-and-forth assigning of `mailUrlString`. --- .../email/.npm/package/npm-shrinkwrap.json | 73 +--------- packages/email/email.js | 137 +++++++----------- packages/email/email_tests.js | 60 ++++---- packages/email/package.js | 11 +- 4 files changed, 82 insertions(+), 199 deletions(-) diff --git a/packages/email/.npm/package/npm-shrinkwrap.json b/packages/email/.npm/package/npm-shrinkwrap.json index 4028b03706..aebb613b70 100644 --- a/packages/email/.npm/package/npm-shrinkwrap.json +++ b/packages/email/.npm/package/npm-shrinkwrap.json @@ -1,79 +1,14 @@ { "dependencies": { - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "from": "addressparser@1.0.1" - }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "from": "buildmail@4.0.1" - }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "from": "httpntlm@1.6.1" - }, - "httpreq": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.23.tgz", - "from": "httpreq@>=0.4.22" - }, - "iconv-lite": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "from": "iconv-lite@0.4.15" - }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "from": "libbase64@0.1.0" - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "from": "libmime@3.0.0" - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "from": "libqp@1.1.0" - }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "from": "mailcomposer@4.0.1" - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "from": "nodemailer-fetch@1.6.0" - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "from": "nodemailer-shared@1.1.0" - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "from": "punycode@1.4.1" - }, - "smtp-connection": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.2.tgz", - "from": "smtp-connection@2.12.2" + "node4mailer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/node4mailer/-/node4mailer-4.0.2.tgz", + "from": "node4mailer@4.0.2" }, "stream-buffers": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-0.2.5.tgz", "from": "stream-buffers@0.2.5" - }, - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "from": "underscore@>=1.7.0 <1.8.0" } } } diff --git a/packages/email/email.js b/packages/email/email.js index ae8e652eba..af3c633d69 100644 --- a/packages/email/email.js +++ b/packages/email/email.js @@ -1,6 +1,6 @@ var Future = Npm.require('fibers/future'); var urlModule = Npm.require('url'); -var SMTPConnection = Npm.require('smtp-connection'); +var nodemailer = Npm.require('node4mailer'); Email = {}; EmailTest = {}; @@ -8,61 +8,60 @@ EmailTest = {}; EmailInternals = { NpmModules: { mailcomposer: { - version: Npm.require('mailcomposer/package.json').version, - module: Npm.require('mailcomposer') + version: Npm.require('node4mailer/package.json').version, + module: Npm.require('node4mailer/lib/mail-composer') + }, + nodemailer: { + version: Npm.require('node4mailer/package.json').version, + module: Npm.require('node4mailer') } } }; -var mailcomposer = EmailInternals.NpmModules.mailcomposer.module; +var MailComposer = EmailInternals.NpmModules.mailcomposer.module; -var makePool = function (mailUrlString) { - var mailUrl = urlModule.parse(mailUrlString); - if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:') +var makeTransport = function (mailUrlString) { + var mailUrl = urlModule.parse(mailUrlString, true); + + if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:') { throw new Error("Email protocol in $MAIL_URL (" + mailUrlString + ") must be 'smtp' or 'smtps'"); - - var port = +(mailUrl.port); - var auth = false; - if (mailUrl.auth) { - var parts = mailUrl.auth.split(':', 2); - auth = {user: parts[0], - pass: parts[1]}; } - var pool = new SMTPConnection({ - port: port, // Defaults to 25 - host: mailUrl.hostname, // Defaults to "localhost" - secure: (port === 465) || (mailUrl.protocol === 'smtps:') - }); - Meteor.wrapAsync(pool.connect, pool)(); - if (auth) { - //_.bind(Future.wrap(pool.login), pool)(auth).wait(); - Meteor.wrapAsync(pool.login, pool)(auth); + // Allow overriding pool setting, but default to true. + if (!mailUrl.query) { + mailUrl.query = {}; } - pool._syncSend = Meteor.wrapAsync(pool.send, pool); - return pool; + if (!mailUrl.query.pool) { + mailUrl.query.pool = 'true'; + } + + var transport = nodemailer.createTransport( + urlModule.format(mailUrl)); + + transport._syncSendMail = Meteor.wrapAsync(transport.sendMail, transport); + return transport; }; -var getPool = function() { +var getTransport = function() { // We delay this check until the first call to Email.send, in case someone // set process.env.MAIL_URL in startup code. Then we store in a cache until // process.env.MAIL_URL changes. var url = process.env.MAIL_URL; if (this.cacheKey === undefined || this.cacheKey !== url) { this.cacheKey = url; - this.cache = url ? makePool(url) : null; + this.cache = url ? makeTransport(url) : null; } return this.cache; } -var next_devmode_mail_id = 0; +var nextDevModeMailId = 0; var output_stream = process.stdout; // Testing hooks EmailTest.overrideOutputStream = function (stream) { - next_devmode_mail_id = 0; + nextDevModeMailId = 0; output_stream = stream; }; @@ -70,27 +69,27 @@ EmailTest.restoreOutputStream = function () { output_stream = process.stdout; }; -var devModeSend = function (mc) { - var devmode_mail_id = next_devmode_mail_id++; +var devModeSend = function (mail) { + var devModeMailId = nextDevModeMailId++; var stream = output_stream; // This approach does not prevent other writers to stdout from interleaving. - stream.write("====== BEGIN MAIL #" + devmode_mail_id + " ======\n"); + stream.write("====== BEGIN MAIL #" + devModeMailId + " ======\n"); stream.write("(Mail not sent; to enable sending, set the MAIL_URL " + "environment variable.)\n"); - var readStream = mc.createReadStream(); + var readStream = new MailComposer(mail).compile().createReadStream(); readStream.pipe(stream, {end: false}); var future = new Future; readStream.on('end', function () { - stream.write("====== END MAIL #" + devmode_mail_id + " ======\n"); + stream.write("====== END MAIL #" + devModeMailId + " ======\n"); future.return(); }); future.wait(); }; -var smtpSend = function (pool, mc) { - pool._syncSend(mc.getEnvelope(), mc.createReadStream()); +var smtpSend = function (transport, mail) { + transport._syncSendMail(mail); }; /** @@ -105,28 +104,6 @@ EmailTest.hookSend = function (f) { sendHooks.push(f); }; -// Old comment below -/** - * Send an email. - * - * Connects to the mail server configured via the MAIL_URL environment - * variable. If unset, prints formatted message to stdout. The "from" option - * is required, and at least one of "to", "cc", and "bcc" must be provided; - * all other options are optional. - * - * @param options - * @param options.from {String} RFC5322 "From:" address - * @param options.to {String|String[]} RFC5322 "To:" address[es] - * @param options.cc {String|String[]} RFC5322 "Cc:" address[es] - * @param options.bcc {String|String[]} RFC5322 "Bcc:" address[es] - * @param options.replyTo {String|String[]} RFC5322 "Reply-To:" address[es] - * @param options.subject {String} RFC5322 "Subject:" line - * @param options.text {String} RFC5322 mail body (plain text) - * @param options.html {String} RFC5322 mail body (HTML) - * @param options.headers {Object} custom RFC5322 headers (dictionary) - */ - -// New API doc comment below /** * @summary Send an email. Throws an `Error` on failure to contact mail server * or if mail server returns an error. All fields should match @@ -135,10 +112,9 @@ EmailTest.hookSend = function (f) { * If the `MAIL_URL` environment variable is set, actually sends the email. * Otherwise, prints the contents of the email to standard out. * - * Note that this package is based on mailcomposer version `4.0.1`, so make - * sure to refer to the documentation for that version if using the - * `attachments` or `mailComposer` options. - * [Click here to read the mailcomposer 4.0.1 docs](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md). + * Note that this package is based on **mailcomposer 4**, so make sure to refer to + * [the documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md) + * for that version when using the `attachments` or `mailComposer` options. * * @locus Server * @param {Object} options @@ -150,44 +126,29 @@ EmailTest.hookSend = function (f) { * @param {String} [options.messageId] Message-ID for this message; otherwise, will be set to a random value * @param {String} [options.subject] "Subject:" line * @param {String} [options.text|html] Mail body (in plain text and/or HTML) - * @param {String} [options.watchHtml] Mail body in HTML specific for Apple Watch - * @param {String} [options.icalEvent] iCalendar event attachment + * @param {String} [options.watchHtml] Mail body in HTML specific for Apple Watch + * @param {String} [options.icalEvent] iCalendar event attachment * @param {Object} [options.headers] Dictionary of custom headers * @param {Object[]} [options.attachments] Array of attachment objects, as * described in the [mailcomposer documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md#attachments). - * @param {MailComposer} [options.mailComposer] A [MailComposer](https://github.com/andris9/mailcomposer) - * object (or its `compile()` output) representing the message to be sent. - * Overrides all other options. You can access the `mailcomposer` npm module at - * `EmailInternals.NpmModules.mailcomposer.module`. This module is a function - * which assembles a MailComposer object and immediately `compile()`s it. - * Alternatively, you can create and pass a MailComposer object via - * `new EmailInternals.NpmModules.mailcomposer.module.MailComposer`. + * @param {MailComposer} [options.mailComposer] A [MailComposer](https://nodemailer.com/extras/mailcomposer/#e-mail-message-fields) + * object representing the message to be sent. Overrides all other options. + * You can create a `MailComposer` object via + * `new EmailInternals.NpmModules.mailcomposer.module`. */ Email.send = function (options) { for (var i = 0; i < sendHooks.length; i++) if (! sendHooks[i](options)) return; - var mc; if (options.mailComposer) { - mc = options.mailComposer; - if (mc.compile) { - mc = mc.compile(); - } - } else { - // mailcomposer now automatically adds date if omitted - //if (!options.hasOwnProperty('date') && - // (!options.headers || !options.headers.hasOwnProperty('Date'))) { - // options['date'] = new Date().toUTCString().replace(/GMT/, '+0000'); - //} - - mc = mailcomposer(options); + options = options.mailComposer.mail; } - var pool = getPool(); - if (pool) { - smtpSend(pool, mc); + var transport = getTransport(); + if (transport) { + smtpSend(transport, options); } else { - devModeSend(mc); + devModeSend(options); } }; diff --git a/packages/email/email_tests.js b/packages/email/email_tests.js index 6fe9a30954..97c0977660 100644 --- a/packages/email/email_tests.js +++ b/packages/email/email_tests.js @@ -22,7 +22,7 @@ function canonicalize(string) { // Remove generated content for test.equal to succeed. return string.replace(/Message-ID: <[^<>]*>\r\n/, "Message-ID: <...>\r\n") .replace(/Date: (?!dummy).*\r\n/, "Date: ...\r\n") - .replace(/----[^\s"]+/g, "----..."); + .replace(/(boundary="|^--)--[^\s"]+?(-Part|")/mg, "$1--...$2"); } Tinytest.add("email - fully customizable", function (test) { @@ -55,7 +55,7 @@ Tinytest.add("email - fully customizable", function (test) { "\r\n" + "This is the body\n" + "of the message\n" + - "From us." + + "From us.\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -108,33 +108,23 @@ Tinytest.add("email - multiple e-mails same stream", function (test) { Tinytest.add("email - using mail composer", function (test) { smokeEmailTest(function (stream) { // Test direct MailComposer usage. - var mcs = [ - // Test with MailComposer object (without compiling). - new EmailInternals.NpmModules.mailcomposer.module.MailComposer({ - from: "a@b.com", - text: "body" - }), - // Test calling module as a function, which compiles MailComposer object. - EmailInternals.NpmModules.mailcomposer.module({ - from: "a@b.com", - text: "body" - }) - ]; - for (var i = 0; i < mcs.length; i++) { - Email.send({mailComposer: mcs[i]}); - test.equal(canonicalize(stream.getContentsAsString("utf8")), - "====== BEGIN MAIL #"+i+" ======\n" + - devWarningBanner + - "Content-Type: text/plain\r\n" + - "From: a@b.com\r\n" + - "Message-ID: <...>\r\n" + - "Content-Transfer-Encoding: 7bit\r\n" + - "Date: ...\r\n" + - "MIME-Version: 1.0\r\n" + - "\r\n" + - "body" + - "====== END MAIL #"+i+" ======\n"); - } + var mc = new EmailInternals.NpmModules.mailcomposer.module({ + from: "a@b.com", + text: "body" + }); + Email.send({mailComposer: mc}); + test.equal(canonicalize(stream.getContentsAsString("utf8")), + "====== BEGIN MAIL #0 ======\n" + + devWarningBanner + + "Content-Type: text/plain\r\n" + + "From: a@b.com\r\n" + + "Message-ID: <...>\r\n" + + "Content-Transfer-Encoding: 7bit\r\n" + + "Date: ...\r\n" + + "MIME-Version: 1.0\r\n" + + "\r\n" + + "body\r\n" + + "====== END MAIL #0 ======\n"); }); }); @@ -181,7 +171,7 @@ Tinytest.add("email - long lines", function (test) { "MIME-Version: 1.0\r\n" + "\r\n" + "This is a very very very very very very very very very very " + - "very very long =\r\ntext" + + "very very long =\r\ntext\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -208,7 +198,7 @@ Tinytest.add("email - unicode", function (test) { "Date: ...\r\n" + "MIME-Version: 1.0\r\n" + "\r\n" + - "I =E2=99=A5 Meteor" + + "I =E2=99=A5 Meteor\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -227,24 +217,24 @@ Tinytest.add("email - text and html", function (test) { "====== BEGIN MAIL #0 ======\n" + devWarningBanner + "Content-Type: multipart/alternative;\r\n" + - ' boundary="----..."\r\n' + + ' boundary="--...-Part_1"\r\n' + "From: foo@example.com\r\n" + "To: bar@example.com\r\n" + "Message-ID: <...>\r\n" + "Date: ...\r\n" + "MIME-Version: 1.0\r\n" + "\r\n" + - "----...\r\n" + + "----...-Part_1\r\n" + "Content-Type: text/plain\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "*Cool*, man\r\n" + - "----...\r\n" + + "----...-Part_1\r\n" + "Content-Type: text/html\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "Cool, man\r\n" + - "----...\r\n" + + "----...-Part_1--\r\n" + "====== END MAIL #0 ======\n"); }); }); diff --git a/packages/email/package.js b/packages/email/package.js index 36f09e1601..7e5167f350 100644 --- a/packages/email/package.js +++ b/packages/email/package.js @@ -1,17 +1,14 @@ Package.describe({ summary: "Send email messages", - version: "1.2.0" + version: "1.2.1" }); Npm.depends({ - mailcomposer: "4.0.1", - // Using smtp-connection@2 (instead of latest) because it shares - // nodemailer-shared with mailcomposer@4: - "smtp-connection": "2.12.2", - "stream-buffers": "0.2.5"}); + node4mailer: "4.0.2", + "stream-buffers": "0.2.5" +}); Package.onUse(function (api) { - api.use('underscore', 'server'); api.export(['Email', 'EmailInternals'], 'server'); api.export('EmailTest', 'server', {testOnly: true}); api.addFiles('email.js', 'server'); From 57b050a78a2e0a0ad33767de7ae38f01e7d2c731 Mon Sep 17 00:00:00 2001 From: Erik Demaine Date: Mon, 17 Apr 2017 15:41:44 -0400 Subject: [PATCH 014/125] Switch to modern nodemailer 4, Node 4 version. Fix #8591 (#8605) * Switch to modern nodemailer 4, Node 4 version. Fix #8591 * Most critically, use a pool instead of direct SMTP connection, to handle dropped connections and increase throughput, like mail module 1.1. (#8591) * New nodemailer's sendMail wants an options object, not a MailComposer object. Luckily, a MailComposer object has a "mail" field that remembers the original options, so we can keep original behavior. * However, we no longer support the mailComposer option set to a compiled MailComposer object (functionality that was briefly added in 1.2.0). * nodemailer does SMTP URL parsing now automatically for us, simplifying code. * Tests' outputs now end with additional "\r\n" * Drop underscore package dependency (no longer needed) * General formatting/style cleanup for `packages/email`. * snake_cased => camelCased for some local variables. * Added curly-brackets to `if`s. * Removed trailing spaces. * Removed commented-out code. * Removed older doc text and changed some links. * Get rid of back-and-forth assigning of `mailUrlString`. --- .../email/.npm/package/npm-shrinkwrap.json | 73 +--------- packages/email/email.js | 137 +++++++----------- packages/email/email_tests.js | 60 ++++---- packages/email/package.js | 11 +- 4 files changed, 82 insertions(+), 199 deletions(-) diff --git a/packages/email/.npm/package/npm-shrinkwrap.json b/packages/email/.npm/package/npm-shrinkwrap.json index 4028b03706..aebb613b70 100644 --- a/packages/email/.npm/package/npm-shrinkwrap.json +++ b/packages/email/.npm/package/npm-shrinkwrap.json @@ -1,79 +1,14 @@ { "dependencies": { - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "from": "addressparser@1.0.1" - }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "from": "buildmail@4.0.1" - }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "from": "httpntlm@1.6.1" - }, - "httpreq": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.23.tgz", - "from": "httpreq@>=0.4.22" - }, - "iconv-lite": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "from": "iconv-lite@0.4.15" - }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "from": "libbase64@0.1.0" - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "from": "libmime@3.0.0" - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "from": "libqp@1.1.0" - }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "from": "mailcomposer@4.0.1" - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "from": "nodemailer-fetch@1.6.0" - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "from": "nodemailer-shared@1.1.0" - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "from": "punycode@1.4.1" - }, - "smtp-connection": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.2.tgz", - "from": "smtp-connection@2.12.2" + "node4mailer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/node4mailer/-/node4mailer-4.0.2.tgz", + "from": "node4mailer@4.0.2" }, "stream-buffers": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-0.2.5.tgz", "from": "stream-buffers@0.2.5" - }, - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "from": "underscore@>=1.7.0 <1.8.0" } } } diff --git a/packages/email/email.js b/packages/email/email.js index ae8e652eba..af3c633d69 100644 --- a/packages/email/email.js +++ b/packages/email/email.js @@ -1,6 +1,6 @@ var Future = Npm.require('fibers/future'); var urlModule = Npm.require('url'); -var SMTPConnection = Npm.require('smtp-connection'); +var nodemailer = Npm.require('node4mailer'); Email = {}; EmailTest = {}; @@ -8,61 +8,60 @@ EmailTest = {}; EmailInternals = { NpmModules: { mailcomposer: { - version: Npm.require('mailcomposer/package.json').version, - module: Npm.require('mailcomposer') + version: Npm.require('node4mailer/package.json').version, + module: Npm.require('node4mailer/lib/mail-composer') + }, + nodemailer: { + version: Npm.require('node4mailer/package.json').version, + module: Npm.require('node4mailer') } } }; -var mailcomposer = EmailInternals.NpmModules.mailcomposer.module; +var MailComposer = EmailInternals.NpmModules.mailcomposer.module; -var makePool = function (mailUrlString) { - var mailUrl = urlModule.parse(mailUrlString); - if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:') +var makeTransport = function (mailUrlString) { + var mailUrl = urlModule.parse(mailUrlString, true); + + if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:') { throw new Error("Email protocol in $MAIL_URL (" + mailUrlString + ") must be 'smtp' or 'smtps'"); - - var port = +(mailUrl.port); - var auth = false; - if (mailUrl.auth) { - var parts = mailUrl.auth.split(':', 2); - auth = {user: parts[0], - pass: parts[1]}; } - var pool = new SMTPConnection({ - port: port, // Defaults to 25 - host: mailUrl.hostname, // Defaults to "localhost" - secure: (port === 465) || (mailUrl.protocol === 'smtps:') - }); - Meteor.wrapAsync(pool.connect, pool)(); - if (auth) { - //_.bind(Future.wrap(pool.login), pool)(auth).wait(); - Meteor.wrapAsync(pool.login, pool)(auth); + // Allow overriding pool setting, but default to true. + if (!mailUrl.query) { + mailUrl.query = {}; } - pool._syncSend = Meteor.wrapAsync(pool.send, pool); - return pool; + if (!mailUrl.query.pool) { + mailUrl.query.pool = 'true'; + } + + var transport = nodemailer.createTransport( + urlModule.format(mailUrl)); + + transport._syncSendMail = Meteor.wrapAsync(transport.sendMail, transport); + return transport; }; -var getPool = function() { +var getTransport = function() { // We delay this check until the first call to Email.send, in case someone // set process.env.MAIL_URL in startup code. Then we store in a cache until // process.env.MAIL_URL changes. var url = process.env.MAIL_URL; if (this.cacheKey === undefined || this.cacheKey !== url) { this.cacheKey = url; - this.cache = url ? makePool(url) : null; + this.cache = url ? makeTransport(url) : null; } return this.cache; } -var next_devmode_mail_id = 0; +var nextDevModeMailId = 0; var output_stream = process.stdout; // Testing hooks EmailTest.overrideOutputStream = function (stream) { - next_devmode_mail_id = 0; + nextDevModeMailId = 0; output_stream = stream; }; @@ -70,27 +69,27 @@ EmailTest.restoreOutputStream = function () { output_stream = process.stdout; }; -var devModeSend = function (mc) { - var devmode_mail_id = next_devmode_mail_id++; +var devModeSend = function (mail) { + var devModeMailId = nextDevModeMailId++; var stream = output_stream; // This approach does not prevent other writers to stdout from interleaving. - stream.write("====== BEGIN MAIL #" + devmode_mail_id + " ======\n"); + stream.write("====== BEGIN MAIL #" + devModeMailId + " ======\n"); stream.write("(Mail not sent; to enable sending, set the MAIL_URL " + "environment variable.)\n"); - var readStream = mc.createReadStream(); + var readStream = new MailComposer(mail).compile().createReadStream(); readStream.pipe(stream, {end: false}); var future = new Future; readStream.on('end', function () { - stream.write("====== END MAIL #" + devmode_mail_id + " ======\n"); + stream.write("====== END MAIL #" + devModeMailId + " ======\n"); future.return(); }); future.wait(); }; -var smtpSend = function (pool, mc) { - pool._syncSend(mc.getEnvelope(), mc.createReadStream()); +var smtpSend = function (transport, mail) { + transport._syncSendMail(mail); }; /** @@ -105,28 +104,6 @@ EmailTest.hookSend = function (f) { sendHooks.push(f); }; -// Old comment below -/** - * Send an email. - * - * Connects to the mail server configured via the MAIL_URL environment - * variable. If unset, prints formatted message to stdout. The "from" option - * is required, and at least one of "to", "cc", and "bcc" must be provided; - * all other options are optional. - * - * @param options - * @param options.from {String} RFC5322 "From:" address - * @param options.to {String|String[]} RFC5322 "To:" address[es] - * @param options.cc {String|String[]} RFC5322 "Cc:" address[es] - * @param options.bcc {String|String[]} RFC5322 "Bcc:" address[es] - * @param options.replyTo {String|String[]} RFC5322 "Reply-To:" address[es] - * @param options.subject {String} RFC5322 "Subject:" line - * @param options.text {String} RFC5322 mail body (plain text) - * @param options.html {String} RFC5322 mail body (HTML) - * @param options.headers {Object} custom RFC5322 headers (dictionary) - */ - -// New API doc comment below /** * @summary Send an email. Throws an `Error` on failure to contact mail server * or if mail server returns an error. All fields should match @@ -135,10 +112,9 @@ EmailTest.hookSend = function (f) { * If the `MAIL_URL` environment variable is set, actually sends the email. * Otherwise, prints the contents of the email to standard out. * - * Note that this package is based on mailcomposer version `4.0.1`, so make - * sure to refer to the documentation for that version if using the - * `attachments` or `mailComposer` options. - * [Click here to read the mailcomposer 4.0.1 docs](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md). + * Note that this package is based on **mailcomposer 4**, so make sure to refer to + * [the documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md) + * for that version when using the `attachments` or `mailComposer` options. * * @locus Server * @param {Object} options @@ -150,44 +126,29 @@ EmailTest.hookSend = function (f) { * @param {String} [options.messageId] Message-ID for this message; otherwise, will be set to a random value * @param {String} [options.subject] "Subject:" line * @param {String} [options.text|html] Mail body (in plain text and/or HTML) - * @param {String} [options.watchHtml] Mail body in HTML specific for Apple Watch - * @param {String} [options.icalEvent] iCalendar event attachment + * @param {String} [options.watchHtml] Mail body in HTML specific for Apple Watch + * @param {String} [options.icalEvent] iCalendar event attachment * @param {Object} [options.headers] Dictionary of custom headers * @param {Object[]} [options.attachments] Array of attachment objects, as * described in the [mailcomposer documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md#attachments). - * @param {MailComposer} [options.mailComposer] A [MailComposer](https://github.com/andris9/mailcomposer) - * object (or its `compile()` output) representing the message to be sent. - * Overrides all other options. You can access the `mailcomposer` npm module at - * `EmailInternals.NpmModules.mailcomposer.module`. This module is a function - * which assembles a MailComposer object and immediately `compile()`s it. - * Alternatively, you can create and pass a MailComposer object via - * `new EmailInternals.NpmModules.mailcomposer.module.MailComposer`. + * @param {MailComposer} [options.mailComposer] A [MailComposer](https://nodemailer.com/extras/mailcomposer/#e-mail-message-fields) + * object representing the message to be sent. Overrides all other options. + * You can create a `MailComposer` object via + * `new EmailInternals.NpmModules.mailcomposer.module`. */ Email.send = function (options) { for (var i = 0; i < sendHooks.length; i++) if (! sendHooks[i](options)) return; - var mc; if (options.mailComposer) { - mc = options.mailComposer; - if (mc.compile) { - mc = mc.compile(); - } - } else { - // mailcomposer now automatically adds date if omitted - //if (!options.hasOwnProperty('date') && - // (!options.headers || !options.headers.hasOwnProperty('Date'))) { - // options['date'] = new Date().toUTCString().replace(/GMT/, '+0000'); - //} - - mc = mailcomposer(options); + options = options.mailComposer.mail; } - var pool = getPool(); - if (pool) { - smtpSend(pool, mc); + var transport = getTransport(); + if (transport) { + smtpSend(transport, options); } else { - devModeSend(mc); + devModeSend(options); } }; diff --git a/packages/email/email_tests.js b/packages/email/email_tests.js index 6fe9a30954..97c0977660 100644 --- a/packages/email/email_tests.js +++ b/packages/email/email_tests.js @@ -22,7 +22,7 @@ function canonicalize(string) { // Remove generated content for test.equal to succeed. return string.replace(/Message-ID: <[^<>]*>\r\n/, "Message-ID: <...>\r\n") .replace(/Date: (?!dummy).*\r\n/, "Date: ...\r\n") - .replace(/----[^\s"]+/g, "----..."); + .replace(/(boundary="|^--)--[^\s"]+?(-Part|")/mg, "$1--...$2"); } Tinytest.add("email - fully customizable", function (test) { @@ -55,7 +55,7 @@ Tinytest.add("email - fully customizable", function (test) { "\r\n" + "This is the body\n" + "of the message\n" + - "From us." + + "From us.\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -108,33 +108,23 @@ Tinytest.add("email - multiple e-mails same stream", function (test) { Tinytest.add("email - using mail composer", function (test) { smokeEmailTest(function (stream) { // Test direct MailComposer usage. - var mcs = [ - // Test with MailComposer object (without compiling). - new EmailInternals.NpmModules.mailcomposer.module.MailComposer({ - from: "a@b.com", - text: "body" - }), - // Test calling module as a function, which compiles MailComposer object. - EmailInternals.NpmModules.mailcomposer.module({ - from: "a@b.com", - text: "body" - }) - ]; - for (var i = 0; i < mcs.length; i++) { - Email.send({mailComposer: mcs[i]}); - test.equal(canonicalize(stream.getContentsAsString("utf8")), - "====== BEGIN MAIL #"+i+" ======\n" + - devWarningBanner + - "Content-Type: text/plain\r\n" + - "From: a@b.com\r\n" + - "Message-ID: <...>\r\n" + - "Content-Transfer-Encoding: 7bit\r\n" + - "Date: ...\r\n" + - "MIME-Version: 1.0\r\n" + - "\r\n" + - "body" + - "====== END MAIL #"+i+" ======\n"); - } + var mc = new EmailInternals.NpmModules.mailcomposer.module({ + from: "a@b.com", + text: "body" + }); + Email.send({mailComposer: mc}); + test.equal(canonicalize(stream.getContentsAsString("utf8")), + "====== BEGIN MAIL #0 ======\n" + + devWarningBanner + + "Content-Type: text/plain\r\n" + + "From: a@b.com\r\n" + + "Message-ID: <...>\r\n" + + "Content-Transfer-Encoding: 7bit\r\n" + + "Date: ...\r\n" + + "MIME-Version: 1.0\r\n" + + "\r\n" + + "body\r\n" + + "====== END MAIL #0 ======\n"); }); }); @@ -181,7 +171,7 @@ Tinytest.add("email - long lines", function (test) { "MIME-Version: 1.0\r\n" + "\r\n" + "This is a very very very very very very very very very very " + - "very very long =\r\ntext" + + "very very long =\r\ntext\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -208,7 +198,7 @@ Tinytest.add("email - unicode", function (test) { "Date: ...\r\n" + "MIME-Version: 1.0\r\n" + "\r\n" + - "I =E2=99=A5 Meteor" + + "I =E2=99=A5 Meteor\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -227,24 +217,24 @@ Tinytest.add("email - text and html", function (test) { "====== BEGIN MAIL #0 ======\n" + devWarningBanner + "Content-Type: multipart/alternative;\r\n" + - ' boundary="----..."\r\n' + + ' boundary="--...-Part_1"\r\n' + "From: foo@example.com\r\n" + "To: bar@example.com\r\n" + "Message-ID: <...>\r\n" + "Date: ...\r\n" + "MIME-Version: 1.0\r\n" + "\r\n" + - "----...\r\n" + + "----...-Part_1\r\n" + "Content-Type: text/plain\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "*Cool*, man\r\n" + - "----...\r\n" + + "----...-Part_1\r\n" + "Content-Type: text/html\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "Cool, man\r\n" + - "----...\r\n" + + "----...-Part_1--\r\n" + "====== END MAIL #0 ======\n"); }); }); diff --git a/packages/email/package.js b/packages/email/package.js index 36f09e1601..7e5167f350 100644 --- a/packages/email/package.js +++ b/packages/email/package.js @@ -1,17 +1,14 @@ Package.describe({ summary: "Send email messages", - version: "1.2.0" + version: "1.2.1" }); Npm.depends({ - mailcomposer: "4.0.1", - // Using smtp-connection@2 (instead of latest) because it shares - // nodemailer-shared with mailcomposer@4: - "smtp-connection": "2.12.2", - "stream-buffers": "0.2.5"}); + node4mailer: "4.0.2", + "stream-buffers": "0.2.5" +}); Package.onUse(function (api) { - api.use('underscore', 'server'); api.export(['Email', 'EmailInternals'], 'server'); api.export('EmailTest', 'server', {testOnly: true}); api.addFiles('email.js', 'server'); From 1c9eacaeb882f9f7b70a4a1e8b7e8d4cf7bd9161 Mon Sep 17 00:00:00 2001 From: Wexpo Lyu Date: Wed, 19 Apr 2017 23:17:53 +0800 Subject: [PATCH 015/125] Accounts login functions (#2375) (#8452) Provide AccountsClient#{call,apply}LoginFunction methods. --- packages/accounts-base/accounts_client.js | 46 +++++++++++++++++++ packages/accounts-base/package.js | 2 +- packages/accounts-facebook/facebook.js | 6 ++- packages/accounts-facebook/package.js | 2 +- packages/accounts-github/github.js | 6 ++- packages/accounts-github/package.js | 2 +- packages/accounts-google/google.js | 6 ++- packages/accounts-google/package.js | 2 +- packages/accounts-meetup/meetup.js | 6 ++- packages/accounts-meetup/package.js | 2 +- .../meteor-developer.js | 6 ++- packages/accounts-meteor-developer/package.js | 2 +- packages/accounts-twitter/package.js | 2 +- packages/accounts-twitter/twitter.js | 6 ++- packages/accounts-weibo/package.js | 2 +- packages/accounts-weibo/weibo.js | 6 ++- 16 files changed, 89 insertions(+), 15 deletions(-) diff --git a/packages/accounts-base/accounts_client.js b/packages/accounts-base/accounts_client.js index 9ff6e6f8f8..99bcdcdd81 100644 --- a/packages/accounts-base/accounts_client.js +++ b/packages/accounts-base/accounts_client.js @@ -28,6 +28,9 @@ export class AccountsClient extends AccountsCommon { // Defined in localstorage_token.js. this._initLocalStorage(); + + // This is for .registerClientLoginFunction & .callLoginFunction. + this._loginFuncs = {}; } /// @@ -62,6 +65,49 @@ export class AccountsClient extends AccountsCommon { return this._loggingOut.get(); } + /** + * @summary Register a new login function on the client. Intended for OAuth package authors. You can call the login function by using + `Accounts.callLoginFunction` or `Accounts.callLoginFunction`. + * @locus Client + * @param {String} funcName The name of your login function. Used by `Accounts.callLoginFunction` and `Accounts.applyLoginFunction`. + Should be the OAuth provider name accordingly. + * @param {Function} func The actual function you want to call. Just write it in the manner of `loginWithFoo`. + */ + registerClientLoginFunction(funcName, func) { + if (this._loginFuncs[funcName]) { + throw new Error(`${funcName} has been defined already`); + } + this._loginFuncs[funcName] = func; + } + + /** + * @summary Call a login function defined using `Accounts.registerClientLoginFunction`. Excluding the first argument, all remaining + arguments are passed to the login function accordingly. Use `applyLoginFunction` if you want to pass in an arguments array that contains + all arguments for the login function. + * @locus Client + * @param {String} funcName The name of the login function you wanted to call. + */ + callLoginFunction(funcName, ...funcArgs) { + if (!this._loginFuncs[funcName]) { + throw new Error(`${funcName} was not defined`); + } + return this._loginFuncs[funcName].apply(this, funcArgs); + } + + /** + * @summary Same as ``callLoginFunction` but accept an `arguments` which contains all arguments for the login + function. + * @locus Client + * @param {String} funcName The name of the login function you wanted to call. + * @param {Array} funcArgs The `arguments` for the login function. + */ + applyLoginFunction(funcName, funcArgs) { + if (!this._loginFuncs[funcName]) { + throw new Error(`${funcName} was not defined`); + } + return this._loginFuncs[funcName].apply(this, funcArgs); + } + /** * @summary Log the user out. * @locus Client diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index 568d29e33a..80ac334d76 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A user account system", - version: "1.2.16" + version: "1.3.0" }); Package.onUse(function (api) { diff --git a/packages/accounts-facebook/facebook.js b/packages/accounts-facebook/facebook.js index 4517bf1d5a..4179610e4b 100644 --- a/packages/accounts-facebook/facebook.js +++ b/packages/accounts-facebook/facebook.js @@ -1,7 +1,7 @@ Accounts.oauth.registerService('facebook'); if (Meteor.isClient) { - Meteor.loginWithFacebook = function(options, callback) { + const loginWithFacebook = function(options, callback) { // support a callback without options if (! callback && typeof options === "function") { callback = options; @@ -11,6 +11,10 @@ if (Meteor.isClient) { var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback); Facebook.requestCredential(options, credentialRequestCompleteCallback); }; + Accounts.registerClientLoginFunction('facebook', loginWithFacebook); + Meteor.loginWithFacebook = function () { + return Accounts.applyLoginFunction('facebook', arguments); + }; } else { Accounts.addAutopublishFields({ // publish all fields including access token, which can legitimately diff --git a/packages/accounts-facebook/package.js b/packages/accounts-facebook/package.js index 1a272a6dc7..060f01f006 100644 --- a/packages/accounts-facebook/package.js +++ b/packages/accounts-facebook/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Login service for Facebook accounts", - version: "1.1.1" + version: "1.2.0" }); Package.onUse(function(api) { diff --git a/packages/accounts-github/github.js b/packages/accounts-github/github.js index bf71477695..b2478518e5 100644 --- a/packages/accounts-github/github.js +++ b/packages/accounts-github/github.js @@ -1,7 +1,7 @@ Accounts.oauth.registerService('github'); if (Meteor.isClient) { - Meteor.loginWithGithub = function(options, callback) { + const loginWithGithub = function(options, callback) { // support a callback without options if (! callback && typeof options === "function") { callback = options; @@ -11,6 +11,10 @@ if (Meteor.isClient) { var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback); Github.requestCredential(options, credentialRequestCompleteCallback); }; + Accounts.registerClientLoginFunction('github', loginWithGithub); + Meteor.loginWithGithub = function () { + return Accounts.applyLoginFunction('github', arguments); + }; } else { Accounts.addAutopublishFields({ // not sure whether the github api can be used from the browser, diff --git a/packages/accounts-github/package.js b/packages/accounts-github/package.js index a612794ade..9e9a7abeb2 100644 --- a/packages/accounts-github/package.js +++ b/packages/accounts-github/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: 'Login service for Github accounts', - version: '1.2.1' + version: '1.3.0' }); Package.onUse(function (api) { diff --git a/packages/accounts-google/google.js b/packages/accounts-google/google.js index ab5c4c97ea..306ef7882c 100644 --- a/packages/accounts-google/google.js +++ b/packages/accounts-google/google.js @@ -1,7 +1,7 @@ Accounts.oauth.registerService('google'); if (Meteor.isClient) { - Meteor.loginWithGoogle = function(options, callback) { + const loginWithGoogle = function(options, callback) { // support a callback without options if (! callback && typeof options === "function") { callback = options; @@ -30,6 +30,10 @@ if (Meteor.isClient) { var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback); Google.requestCredential(options, credentialRequestCompleteCallback); }; + Accounts.registerClientLoginFunction('google', loginWithGoogle); + Meteor.loginWithGoogle = function () { + return Accounts.applyLoginFunction('google', arguments); + }; } else { Accounts.addAutopublishFields({ forLoggedInUser: _.map( diff --git a/packages/accounts-google/package.js b/packages/accounts-google/package.js index 6c624c9e08..0300c8159d 100644 --- a/packages/accounts-google/package.js +++ b/packages/accounts-google/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Login service for Google accounts", - version: "1.1.2" + version: "1.2.0" }); Package.onUse(function(api) { diff --git a/packages/accounts-meetup/meetup.js b/packages/accounts-meetup/meetup.js index 08e8ec0938..5a25dde195 100644 --- a/packages/accounts-meetup/meetup.js +++ b/packages/accounts-meetup/meetup.js @@ -1,7 +1,7 @@ Accounts.oauth.registerService('meetup'); if (Meteor.isClient) { - Meteor.loginWithMeetup = function(options, callback) { + const loginWithMeetup = function(options, callback) { // support a callback without options if (! callback && typeof options === "function") { callback = options; @@ -11,6 +11,10 @@ if (Meteor.isClient) { var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback); Meetup.requestCredential(options, credentialRequestCompleteCallback); }; + Accounts.registerClientLoginFunction('meetup', loginWithMeetup); + Meteor.loginWithMeetup = function () { + return Accounts.applyLoginFunction('meetup', arguments); + }; } else { Accounts.addAutopublishFields({ // publish all fields including access token, which can legitimately diff --git a/packages/accounts-meetup/package.js b/packages/accounts-meetup/package.js index ee19a9a8b9..325b535eda 100644 --- a/packages/accounts-meetup/package.js +++ b/packages/accounts-meetup/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: 'Login service for Meetup accounts', - version: '1.2.1' + version: '1.3.0' }); Package.onUse(function (api) { diff --git a/packages/accounts-meteor-developer/meteor-developer.js b/packages/accounts-meteor-developer/meteor-developer.js index 79ac4e4c2c..fed49ba759 100644 --- a/packages/accounts-meteor-developer/meteor-developer.js +++ b/packages/accounts-meteor-developer/meteor-developer.js @@ -1,7 +1,7 @@ Accounts.oauth.registerService("meteor-developer"); if (Meteor.isClient) { - Meteor.loginWithMeteorDeveloperAccount = function (options, callback) { + const loginWithMeteorDeveloperAccount = function (options, callback) { // support a callback without options if (! callback && typeof options === "function") { callback = options; @@ -12,6 +12,10 @@ if (Meteor.isClient) { Accounts.oauth.credentialRequestCompleteHandler(callback); MeteorDeveloperAccounts.requestCredential(options, credentialRequestCompleteCallback); }; + Accounts.registerClientLoginFunction('meteor-developer', loginWithMeteorDeveloperAccount); + Meteor.loginWithMeteorDeveloperAccount = function () { + return Accounts.applyLoginFunction('meteor-developer', arguments); + }; } else { Accounts.addAutopublishFields({ // publish all fields including access token, which can legitimately be used diff --git a/packages/accounts-meteor-developer/package.js b/packages/accounts-meteor-developer/package.js index a051ef61af..e788bad6b8 100644 --- a/packages/accounts-meteor-developer/package.js +++ b/packages/accounts-meteor-developer/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: 'Login service for Meteor developer accounts', - version: '1.2.1' + version: '1.3.0' }); Package.onUse(function (api) { diff --git a/packages/accounts-twitter/package.js b/packages/accounts-twitter/package.js index e07a79061d..df68761a26 100644 --- a/packages/accounts-twitter/package.js +++ b/packages/accounts-twitter/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Login service for Twitter accounts", - version: "1.2.1" + version: "1.3.0" }); Package.onUse(function(api) { diff --git a/packages/accounts-twitter/twitter.js b/packages/accounts-twitter/twitter.js index 176d82a655..1d44f474f2 100644 --- a/packages/accounts-twitter/twitter.js +++ b/packages/accounts-twitter/twitter.js @@ -1,7 +1,7 @@ Accounts.oauth.registerService('twitter'); if (Meteor.isClient) { - Meteor.loginWithTwitter = function(options, callback) { + const loginWithTwitter = function(options, callback) { // support a callback without options if (! callback && typeof options === "function") { callback = options; @@ -11,6 +11,10 @@ if (Meteor.isClient) { var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback); Twitter.requestCredential(options, credentialRequestCompleteCallback); }; + Accounts.registerClientLoginFunction('twitter', loginWithTwitter); + Meteor.loginWithTwitter = function () { + return Accounts.applyLoginFunction('twitter', arguments); + }; } else { var autopublishedFields = _.map( // don't send access token. https://dev.twitter.com/discussions/5025 diff --git a/packages/accounts-weibo/package.js b/packages/accounts-weibo/package.js index 6129b8a90a..b266fd83e9 100644 --- a/packages/accounts-weibo/package.js +++ b/packages/accounts-weibo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Login service for Sina Weibo accounts", - version: "1.1.1" + version: "1.2.0" }); Package.onUse(function(api) { diff --git a/packages/accounts-weibo/weibo.js b/packages/accounts-weibo/weibo.js index f55ec19bc7..b3fc92df0f 100644 --- a/packages/accounts-weibo/weibo.js +++ b/packages/accounts-weibo/weibo.js @@ -1,7 +1,7 @@ Accounts.oauth.registerService('weibo'); if (Meteor.isClient) { - Meteor.loginWithWeibo = function(options, callback) { + const loginWithWeibo = function(options, callback) { // support a callback without options if (! callback && typeof options === "function") { callback = options; @@ -11,6 +11,10 @@ if (Meteor.isClient) { var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback); Weibo.requestCredential(options, credentialRequestCompleteCallback); }; + Accounts.registerClientLoginFunction('weibo', loginWithWeibo); + Meteor.loginWithWeibo = function () { + return Accounts.applyLoginFunction('weibo', arguments); + }; } else { Accounts.addAutopublishFields({ // publish all fields including access token, which can legitimately From b491985b4a59f368633a225905f582933fa47f0e Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 17 Apr 2017 13:24:37 -0400 Subject: [PATCH 016/125] Make babel-runtime use ecmascript-runtime on server only. --- packages/babel-compiler/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index b229f435b1..456fd45fe6 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -14,7 +14,7 @@ Npm.depends({ }); Package.onUse(function (api) { - api.use('ecmascript-runtime'); + api.use('ecmascript-runtime', 'server'); api.addFiles([ 'babel.js', From 0042ae55f125679d4aef3bd30c5cd9bca9c891bc Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 19 Apr 2017 13:43:21 -0400 Subject: [PATCH 017/125] Split ecmascript-runtime into client and server packages. This split gives us the ability to use different sets of polyfills for server and client, which allows us to take better advantage of native support in Node 4+. We now rely on core-js as a peer dependency on the client (which is a win because core-js is always installed along with babel-runtime), and as an Npm.depends-style dependency on the server (which is necessary because there's not always an an application to provide peer node_modules on the server, e.g. in isopackets and compiler plugins). Since we're using different sets of polyfills on the client and the server, it didn't seem to make sense to rely on a single npm package, so meteor-ecmascript-runtime has been removed. --- packages/ecmascript-runtime-client/README.md | 6 + packages/ecmascript-runtime-client/package.js | 20 +++ packages/ecmascript-runtime-client/runtime.js | 127 ++++++++++++++++++ .../.npm/package/.gitignore | 0 .../.npm/package/README | 0 .../.npm/package/npm-shrinkwrap.json | 9 ++ packages/ecmascript-runtime-server/README.md | 6 + packages/ecmascript-runtime-server/package.js | 23 ++++ packages/ecmascript-runtime-server/runtime.js | 71 ++++++++++ .../.npm/package/npm-shrinkwrap.json | 14 -- packages/ecmascript-runtime/package.js | 21 +-- 11 files changed, 265 insertions(+), 32 deletions(-) create mode 100644 packages/ecmascript-runtime-client/README.md create mode 100644 packages/ecmascript-runtime-client/package.js create mode 100644 packages/ecmascript-runtime-client/runtime.js rename packages/{ecmascript-runtime => ecmascript-runtime-server}/.npm/package/.gitignore (100%) rename packages/{ecmascript-runtime => ecmascript-runtime-server}/.npm/package/README (100%) create mode 100644 packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json create mode 100644 packages/ecmascript-runtime-server/README.md create mode 100644 packages/ecmascript-runtime-server/package.js create mode 100644 packages/ecmascript-runtime-server/runtime.js delete mode 100644 packages/ecmascript-runtime/.npm/package/npm-shrinkwrap.json diff --git a/packages/ecmascript-runtime-client/README.md b/packages/ecmascript-runtime-client/README.md new file mode 100644 index 0000000000..1b24dc649f --- /dev/null +++ b/packages/ecmascript-runtime-client/README.md @@ -0,0 +1,6 @@ +# ecmascript-runtime-client +[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/ecmascript-runtime-client) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-client) +*** + +[![Build Status](https://travis-ci.org/meteor/ecmascript-runtime.svg?branch=master)](https://travis-ci.org/meteor/ecmascript-runtime) +Polyfills for new ECMAScript 2015 APIs like Map and Set diff --git a/packages/ecmascript-runtime-client/package.js b/packages/ecmascript-runtime-client/package.js new file mode 100644 index 0000000000..1bd6b8466a --- /dev/null +++ b/packages/ecmascript-runtime-client/package.js @@ -0,0 +1,20 @@ +Package.describe({ + name: "ecmascript-runtime-client", + version: "0.4.0", + summary: "Polyfills for new ECMAScript 2015 APIs like Map and Set", + git: "https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-client", + documentation: "README.md" +}); + +Package.onUse(function(api) { + // If the es5-shim package is installed, make sure it loads before + // ecmascript-runtime-server, since the runtime uses some ES5 APIs like + // Object.defineProperties that are buggy in older browsers. + api.use("es5-shim", { weak: true }); + api.use("modules", "client"); + api.use("promise", "client"); + api.mainModule("runtime.js", "client"); + api.export("Symbol", "client"); + api.export("Map", "client"); + api.export("Set", "client"); +}); diff --git a/packages/ecmascript-runtime-client/runtime.js b/packages/ecmascript-runtime-client/runtime.js new file mode 100644 index 0000000000..58e3dbe682 --- /dev/null +++ b/packages/ecmascript-runtime-client/runtime.js @@ -0,0 +1,127 @@ +try { + require("core-js/modules/es6.symbol"); + require("core-js/modules/es6.map"); + require("core-js/modules/es6.set"); +} catch (e) { + throw new Error([ + "The core-js npm package could not be found in your node_modules ", + "directory. Please run the following command to install it:", + "", + " meteor npm install --save core-js", + "" + ].join("\n")); +} + +var core = require("core-js/modules/_core"); +Symbol = exports.Symbol = core.Symbol; +Map = exports.Map = core.Map; +Set = exports.Set = core.Set; + +// List of polyfills generated by babel-preset-env with the following +// .babelrc configuration: +// +// { +// "presets": [ +// ["env", { +// "targets": { +// "browsers": [ +// "last 3 versions" +// ] +// }, +// "polyfill": true, +// "useBuiltIns": true +// }] +// ] +// } +// +// Supported browsers: http://browserl.ist/?q=last+3+versions +// +// Note that the es6.reflect.* modules have been commented out for bundle +// size reasons, and the es6.promise modules are not used because Meteor +// provides its own Promise polyfill. + +require("core-js/modules/es6.typed.array-buffer"); +require("core-js/modules/es6.typed.data-view"); +require("core-js/modules/es6.typed.int8-array"); +require("core-js/modules/es6.typed.uint8-array"); +require("core-js/modules/es6.typed.uint8-clamped-array"); +require("core-js/modules/es6.typed.int16-array"); +require("core-js/modules/es6.typed.uint16-array"); +require("core-js/modules/es6.typed.int32-array"); +require("core-js/modules/es6.typed.uint32-array"); +require("core-js/modules/es6.typed.float32-array"); +require("core-js/modules/es6.typed.float64-array"); +require("core-js/modules/es6.weak-map"); +require("core-js/modules/es6.weak-set"); +// require("core-js/modules/es6.reflect.apply"); +// require("core-js/modules/es6.reflect.construct"); +// require("core-js/modules/es6.reflect.define-property"); +// require("core-js/modules/es6.reflect.delete-property"); +// require("core-js/modules/es6.reflect.get"); +// require("core-js/modules/es6.reflect.get-own-property-descriptor"); +// require("core-js/modules/es6.reflect.get-prototype-of"); +// require("core-js/modules/es6.reflect.has"); +// require("core-js/modules/es6.reflect.is-extensible"); +// require("core-js/modules/es6.reflect.own-keys"); +// require("core-js/modules/es6.reflect.prevent-extensions"); +// require("core-js/modules/es6.reflect.set"); +// require("core-js/modules/es6.reflect.set-prototype-of"); +require("core-js/modules/es6.object.assign"); +require("core-js/modules/es6.object.is"); +require("core-js/modules/es6.object.set-prototype-of"); +// require("core-js/modules/es6.promise"); +require("core-js/modules/es6.function.bind"); +require("core-js/modules/es6.function.name"); +require("core-js/modules/es6.function.has-instance"); +require("core-js/modules/es6.string.raw"); +require("core-js/modules/es6.string.from-code-point"); +require("core-js/modules/es6.string.code-point-at"); +require("core-js/modules/es6.string.repeat"); +require("core-js/modules/es6.string.starts-with"); +require("core-js/modules/es6.string.ends-with"); +require("core-js/modules/es6.string.includes"); +require("core-js/modules/es6.regexp.flags"); +require("core-js/modules/es6.regexp.match"); +require("core-js/modules/es6.regexp.replace"); +require("core-js/modules/es6.regexp.split"); +require("core-js/modules/es6.regexp.search"); +require("core-js/modules/es6.array.from"); +require("core-js/modules/es6.array.of"); +require("core-js/modules/es6.array.copy-within"); +require("core-js/modules/es6.array.find"); +require("core-js/modules/es6.array.find-index"); +require("core-js/modules/es6.array.fill"); +require("core-js/modules/es6.array.iterator"); +require("core-js/modules/es6.number.is-finite"); +require("core-js/modules/es6.number.is-integer"); +require("core-js/modules/es6.number.is-safe-integer"); +require("core-js/modules/es6.number.is-nan"); +require("core-js/modules/es6.number.epsilon"); +require("core-js/modules/es6.number.min-safe-integer"); +require("core-js/modules/es6.number.max-safe-integer"); +require("core-js/modules/es6.math.acosh"); +require("core-js/modules/es6.math.asinh"); +require("core-js/modules/es6.math.atanh"); +require("core-js/modules/es6.math.cbrt"); +require("core-js/modules/es6.math.clz32"); +require("core-js/modules/es6.math.cosh"); +require("core-js/modules/es6.math.expm1"); +require("core-js/modules/es6.math.fround"); +require("core-js/modules/es6.math.hypot"); +require("core-js/modules/es6.math.imul"); +require("core-js/modules/es6.math.log1p"); +require("core-js/modules/es6.math.log10"); +require("core-js/modules/es6.math.log2"); +require("core-js/modules/es6.math.sign"); +require("core-js/modules/es6.math.sinh"); +require("core-js/modules/es6.math.tanh"); +require("core-js/modules/es6.math.trunc"); +require("core-js/modules/es7.array.includes"); +require("core-js/modules/es7.object.values"); +require("core-js/modules/es7.object.entries"); +require("core-js/modules/es7.object.get-own-property-descriptors"); +require("core-js/modules/es7.string.pad-start"); +require("core-js/modules/es7.string.pad-end"); +require("core-js/modules/web.timers"); +require("core-js/modules/web.immediate"); +require("core-js/modules/web.dom.iterable"); diff --git a/packages/ecmascript-runtime/.npm/package/.gitignore b/packages/ecmascript-runtime-server/.npm/package/.gitignore similarity index 100% rename from packages/ecmascript-runtime/.npm/package/.gitignore rename to packages/ecmascript-runtime-server/.npm/package/.gitignore diff --git a/packages/ecmascript-runtime/.npm/package/README b/packages/ecmascript-runtime-server/.npm/package/README similarity index 100% rename from packages/ecmascript-runtime/.npm/package/README rename to packages/ecmascript-runtime-server/.npm/package/README diff --git a/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json b/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json new file mode 100644 index 0000000000..e54b59acd6 --- /dev/null +++ b/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "core-js": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "from": "core-js@2.4.1" + } + } +} diff --git a/packages/ecmascript-runtime-server/README.md b/packages/ecmascript-runtime-server/README.md new file mode 100644 index 0000000000..d92f6a94ee --- /dev/null +++ b/packages/ecmascript-runtime-server/README.md @@ -0,0 +1,6 @@ +# ecmascript-runtime-server +[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/ecmascript-runtime-server) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-server) +*** + +[![Build Status](https://travis-ci.org/meteor/ecmascript-runtime.svg?branch=master)](https://travis-ci.org/meteor/ecmascript-runtime) +Polyfills for new ECMAScript 2015 APIs like Map and Set diff --git a/packages/ecmascript-runtime-server/package.js b/packages/ecmascript-runtime-server/package.js new file mode 100644 index 0000000000..38b80d3836 --- /dev/null +++ b/packages/ecmascript-runtime-server/package.js @@ -0,0 +1,23 @@ +Package.describe({ + name: "ecmascript-runtime-server", + version: "0.4.0", + summary: "Polyfills for new ECMAScript 2015 APIs like Map and Set", + git: "https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-client", + documentation: "README.md" +}); + +Npm.depends({ + "core-js": "2.4.1" +}); + +Package.onUse(function(api) { + // If the es5-shim package is installed, make sure it loads before + // ecmascript-runtime-server, since the runtime uses some ES5 APIs like + // Object.defineProperties that are buggy in older browsers. + api.use("es5-shim", { weak: true }); + api.use(["modules", "promise"], "server"); + api.mainModule("runtime.js", "server"); + api.export("Symbol", "server"); + api.export("Map", "server"); + api.export("Set", "server"); +}); diff --git a/packages/ecmascript-runtime-server/runtime.js b/packages/ecmascript-runtime-server/runtime.js new file mode 100644 index 0000000000..1e41296fb4 --- /dev/null +++ b/packages/ecmascript-runtime-server/runtime.js @@ -0,0 +1,71 @@ +// The ecmascript-runtime-server package depends on its own copy of +// core-js using Npm.depends, so we don't have to check that core-js is +// available (as we do in ecmascript-runtime-client/runtime.js). + +require("core-js/modules/es6.symbol"); +require("core-js/modules/es6.map"); +require("core-js/modules/es6.set"); + +var core = require("core-js/modules/_core"); +Symbol = exports.Symbol = core.Symbol; +Map = exports.Map = core.Map; +Set = exports.Set = core.Set; + +// List of polyfills generated by babel-preset-env with the following +// .babelrc configuration: +// +// { +// "presets": [ +// ["env", { +// "targets": { +// "node": 4 +// }, +// "polyfill": true, +// "useBuiltIns": true +// }] +// ] +// } +// +// Note that the es6.reflect.* modules have been commented out for bundle +// size reasons. + +require("core-js/modules/es6.typed.array-buffer"); +require("core-js/modules/es6.typed.int8-array"); +require("core-js/modules/es6.typed.uint8-array"); +require("core-js/modules/es6.typed.uint8-clamped-array"); +require("core-js/modules/es6.typed.int16-array"); +require("core-js/modules/es6.typed.uint16-array"); +require("core-js/modules/es6.typed.int32-array"); +require("core-js/modules/es6.typed.uint32-array"); +require("core-js/modules/es6.typed.float32-array"); +require("core-js/modules/es6.typed.float64-array"); +require("core-js/modules/es6.weak-map"); +require("core-js/modules/es6.weak-set"); +// require("core-js/modules/es6.reflect.apply"); +// require("core-js/modules/es6.reflect.construct"); +// require("core-js/modules/es6.reflect.define-property"); +// require("core-js/modules/es6.reflect.delete-property"); +// require("core-js/modules/es6.reflect.get"); +// require("core-js/modules/es6.reflect.get-own-property-descriptor"); +// require("core-js/modules/es6.reflect.get-prototype-of"); +// require("core-js/modules/es6.reflect.has"); +// require("core-js/modules/es6.reflect.is-extensible"); +// require("core-js/modules/es6.reflect.own-keys"); +// require("core-js/modules/es6.reflect.prevent-extensions"); +// require("core-js/modules/es6.reflect.set"); +// require("core-js/modules/es6.reflect.set-prototype-of"); +require("core-js/modules/es6.function.bind"); +require("core-js/modules/es6.function.name"); +require("core-js/modules/es6.function.has-instance"); +require("core-js/modules/es6.regexp.flags"); +require("core-js/modules/es6.regexp.match"); +require("core-js/modules/es6.regexp.replace"); +require("core-js/modules/es6.regexp.split"); +require("core-js/modules/es6.regexp.search"); +require("core-js/modules/es6.array.from"); +require("core-js/modules/es7.array.includes"); +require("core-js/modules/es7.object.values"); +require("core-js/modules/es7.object.entries"); +require("core-js/modules/es7.object.get-own-property-descriptors"); +require("core-js/modules/es7.string.pad-start"); +require("core-js/modules/es7.string.pad-end"); diff --git a/packages/ecmascript-runtime/.npm/package/npm-shrinkwrap.json b/packages/ecmascript-runtime/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 2d4e33d663..0000000000 --- a/packages/ecmascript-runtime/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "dependencies": { - "core-js": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", - "from": "core-js@2.4.1" - }, - "meteor-ecmascript-runtime": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/meteor-ecmascript-runtime/-/meteor-ecmascript-runtime-0.2.9.tgz", - "from": "meteor-ecmascript-runtime@0.2.9" - } - } -} diff --git a/packages/ecmascript-runtime/package.js b/packages/ecmascript-runtime/package.js index 78b193e14e..1f7b66f00a 100644 --- a/packages/ecmascript-runtime/package.js +++ b/packages/ecmascript-runtime/package.js @@ -1,29 +1,14 @@ Package.describe({ name: "ecmascript-runtime", - version: "0.3.15", + version: "0.4.0", summary: "Polyfills for new ECMAScript 2015 APIs like Map and Set", git: "https://github.com/meteor/ecmascript-runtime", documentation: "README.md" }); -Npm.depends({ - "meteor-ecmascript-runtime": "0.2.9", -}); - Package.onUse(function(api) { - // If the es5-shim package is installed, make sure it loads before - // ecmascript-runtime, since ecmascript-runtime uses some ES5 APIs like - // Object.defineProperties that are buggy in older browsers. - api.use("es5-shim@4.6.13", { weak: true }); - - api.use("modules@0.7.5"); - api.use("promise@0.8.3"); - - api.mainModule("runtime.js"); - - api.export("Symbol"); - api.export("Map"); - api.export("Set"); + api.imply("ecmascript-runtime-client", "client"); + api.imply("ecmascript-runtime-server", "server"); }); Package.onTest(function(api) { From 6f75eae1353b187e358ced331e5f8e3b91cda08d Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 17 Apr 2017 13:24:13 -0400 Subject: [PATCH 018/125] Remove automatic Buffer polyfill. This polyfill is unnecessary in Node, and added a whopping 22KB to the minified client bundle. If you really need the Buffer API on the client, you can get it from require("buffer").Buffer. --- packages/modules/buffer.js | 3 --- packages/modules/client.js | 1 - packages/modules/package.js | 1 - packages/modules/server.js | 1 - tools/tests/apps/modules/tests.js | 8 ++++++++ 5 files changed, 8 insertions(+), 6 deletions(-) delete mode 100644 packages/modules/buffer.js diff --git a/packages/modules/buffer.js b/packages/modules/buffer.js deleted file mode 100644 index a894cdea97..0000000000 --- a/packages/modules/buffer.js +++ /dev/null @@ -1,3 +0,0 @@ -try { - Buffer = global.Buffer || require("buffer").Buffer; -} catch (noBuffer) {} diff --git a/packages/modules/client.js b/packages/modules/client.js index b69fd2b188..8b2ff2c406 100644 --- a/packages/modules/client.js +++ b/packages/modules/client.js @@ -1,6 +1,5 @@ require("./install-packages.js"); require("./stubs.js"); -require("./buffer.js"); require("./process.js"); require("./reify.js"); diff --git a/packages/modules/package.js b/packages/modules/package.js index e986ca01fa..ef715fcf7a 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -15,6 +15,5 @@ Package.onUse(function(api) { api.mainModule("client.js", "client"); api.mainModule("server.js", "server"); api.export("meteorInstall"); - api.export("Buffer"); api.export("process"); }); diff --git a/packages/modules/server.js b/packages/modules/server.js index aa8bc7c394..0f127659b1 100644 --- a/packages/modules/server.js +++ b/packages/modules/server.js @@ -1,4 +1,3 @@ require("./install-packages.js"); -require("./buffer.js"); require("./process.js"); require("./reify.js"); diff --git a/tools/tests/apps/modules/tests.js b/tools/tests/apps/modules/tests.js index 6529402431..9bc5fcebad 100644 --- a/tools/tests/apps/modules/tests.js +++ b/tools/tests/apps/modules/tests.js @@ -213,12 +213,20 @@ describe("native node_modules", () => { }); it("can be implemented by wrapper npm packages", () => { + if (! global.Buffer) { + global.Buffer = require("buffer").Buffer; + } + const Stream = require("stream"); assert.strictEqual(typeof Stream, "function"); assert.strictEqual(typeof Stream.Readable, "function"); }); it("can all be imported", () => { + if (! global.Buffer) { + global.Buffer = require("buffer").Buffer; + } + require("_stream_duplex"); require("_stream_passthrough"); require("_stream_readable"); From 936df52b92fc0e512d5b3ea444ad4b733767a87d Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 20 Apr 2017 05:29:40 -0700 Subject: [PATCH 019/125] Exchange `serverAuthCode` for an `accessToken` in `packages/google-oauth`. The `accessToken` isn't always immediately provided (for example on Android devices) but instead needs to be retrieved by exchanging the `serverAuthCode`. Fixes https://github.com/meteor/meteor/issues/8613. --- packages/google-oauth/google_server.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/google-oauth/google_server.js b/packages/google-oauth/google_server.js index 871c9c2ee8..f553f33825 100644 --- a/packages/google-oauth/google_server.js +++ b/packages/google-oauth/google_server.js @@ -53,11 +53,19 @@ Accounts.registerLoginHandler(function (request) { return; } - const { serviceData } = getServiceDataFromTokens({ + const tokens = { accessToken: request.accessToken, refreshToken: request.refreshToken, idToken: request.idToken, - }); + }; + + if (request.serverAuthCode) { + Object.assign(tokens, getTokens({ + code: request.serverAuthCode + })); + } + + const result = getServiceDataFromTokens(tokens); return Accounts.updateOrCreateUserFromExternalService("google", { id: request.userId, @@ -65,8 +73,8 @@ Accounts.registerLoginHandler(function (request) { accessToken: request.accessToken, email: request.email, picture: request.imageUrl, - ...serviceData, - }); + ...result.serviceData, + }, result.options); }); function getServiceData(query) { From ce54e022694c9771c49060545fcd6f53412c94fa Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 20 Apr 2017 05:44:28 -0700 Subject: [PATCH 020/125] Bump `google-oauth` package version in preparation for publishing. --- packages/google-oauth/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-oauth/package.js b/packages/google-oauth/package.js index 62436fca76..09ee7166c5 100644 --- a/packages/google-oauth/package.js +++ b/packages/google-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Google OAuth flow", - version: "1.2.3" + version: "1.2.4" }); var cordovaPluginGooglePlusURL = From 1c041237d9c425d48edb37d75faf5378962bc072 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 20 Apr 2017 16:09:51 -0400 Subject: [PATCH 021/125] Fix faulty content-length comparison in utils/http-helpers.js. Since body is a string, body.length is not necessarily the number of bytes in the response body. --- tools/utils/http-helpers.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/utils/http-helpers.js b/tools/utils/http-helpers.js index 2dda4548e6..ac40002bd7 100644 --- a/tools/utils/http-helpers.js +++ b/tools/utils/http-helpers.js @@ -310,12 +310,16 @@ _.extend(exports, { var req = request(options, function (error, response, body) { if (! error && response && body) { const contentLength = Number(response.headers["content-length"]); - if (contentLength > 0 && body.length < contentLength) { + const actualLength = Buffer.byteLength(body); + + if (contentLength > 0 && + actualLength < contentLength) { error = new Error( "Expected " + contentLength + " bytes in request body " + - "but received only " + body.length); + "but received only " + actualLength); } } + return callback.call(this, error, response, body); }); From 4122e6e7f2aabf8d22c3e23943a6b247f637ffe9 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 20 Apr 2017 16:11:35 -0400 Subject: [PATCH 022/125] Minor cleanup to make import chain test more robust. --- tools/tests/modules.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tools/tests/modules.js b/tools/tests/modules.js index c89230a75f..5fa92593d2 100644 --- a/tools/tests/modules.js +++ b/tools/tests/modules.js @@ -51,18 +51,28 @@ selftest.define("modules - import chain for packages", () => { s.createApp("myapp", "package-tests"); s.cd("myapp"); - s.write(".meteor/packages", - "meteor-base \n modules \n with-add-files \n with-main-module"); - s.write("main.js", ` - var packageNameA = require('meteor/with-add-files').name; - var packageNameB = require('meteor/with-main-module').name; - console.log('with-add-files: ' + packageNameA); - console.log('with-main-module: ' + packageNameB); - `); + s.write(".meteor/packages", [ + "meteor-base", + "modules", + "with-add-files", + "with-main-module", + "" + ].join("\n")); + + s.write("main.js", [ + "var packageNameA = require('meteor/with-add-files').name;", + "var packageNameB = require('meteor/with-main-module').name;", + "", + "console.log('with-add-files: ' + packageNameA);", + "console.log('with-main-module: ' + packageNameB);", + "" + ].join("\n")); const run = startRun(s); + run.waitSecs(30); + // On the server, we just check that importing *works*, not *how* it works run.match("with-add-files: with-add-files"); run.match("with-main-module: with-main-module"); From 29a3f310ca31d7b4dd2b17ba5ff1b3732032193b Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 20 Apr 2017 16:48:20 -0400 Subject: [PATCH 023/125] Bump package versions for 1.5-beta.16 release. --- packages/babel-compiler/package.js | 2 +- packages/dynamic-import/package.js | 2 +- packages/ecmascript/package.js | 2 +- packages/localstorage/package.js | 2 +- packages/meteor-tool/package.js | 2 +- packages/modules-runtime/package.js | 2 +- packages/modules/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index c2f0aa5f45..f70575b227 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,7 +6,7 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.19.0-beta.14' + version: '6.19.0-beta.16' }); Npm.depends({ diff --git a/packages/dynamic-import/package.js b/packages/dynamic-import/package.js index 6b59645bbd..f03e833159 100644 --- a/packages/dynamic-import/package.js +++ b/packages/dynamic-import/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "dynamic-import", - version: "0.1.0-beta.14", + version: "0.1.0-beta.16", summary: "Support for module.dynamicImport(id).then(namespace => ...)", documentation: "README.md" }); diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index b40144c74e..e79c4254e3 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.8.0-beta.14', + version: '0.8.0-beta.16', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); diff --git a/packages/localstorage/package.js b/packages/localstorage/package.js index e7e1684173..fa43225a56 100644 --- a/packages/localstorage/package.js +++ b/packages/localstorage/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Simulates local storage on IE 6,7 using userData", - version: "1.1.0-beta.14" + version: "1.1.0-beta.16" }); Package.onUse(function (api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 00f3cde759..f65ee9a7c6 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.5.0-beta.14' + version: '1.5.0-beta.16' }); Package.includeTool(); diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index e4ba74d9b2..cb3e51fd28 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules-runtime", - version: "0.8.0-beta.14", + version: "0.8.0-beta.16", summary: "CommonJS module system", git: "https://github.com/benjamn/install", documentation: "README.md" diff --git a/packages/modules/package.js b/packages/modules/package.js index 9266420984..ae781cf6cc 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules", - version: "0.9.0-beta.14", + version: "0.9.0-beta.16", summary: "CommonJS module system", documentation: "README.md" }); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 627106268d..db2b049863 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5-beta.14", + "version": "1.5-beta.16", "recommended": false, "official": false, "description": "Meteor" From de6deb59542befaa0eab1992cdc77835ab2acb7d Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 21 Apr 2017 16:10:13 -0400 Subject: [PATCH 024/125] Use module.importSync instead of module.import in getNamespace. --- packages/dynamic-import/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index cf04e8a304..b074b5ab31 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -172,7 +172,7 @@ function addToTree(tree, id, value) { function getNamespace(module, id) { var namespace = Object.create(null); - module.import(id, { + module.importSync(id, { "*": function (value, name) { namespace[name] = value; } From f4fc2a904d1769a6f628c6dbbc774909d3125c84 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 21 Apr 2017 15:18:45 -0400 Subject: [PATCH 025/125] Use final hashes of dynamic modules for browser caching. Previously, the linker included a "version" hash in each stub entry corresponding to a dynamic module in the meteorInstall bundle. These stub entries also contain information about any module identifiers ("deps") imported by the module, and various other metadata. This hash was derived from the source code of the dynamic module, instead of its fully-processed generated code, which created a small risk that the source hash would remain the same when anything changed in the post-linker processing logic. This new implementation uses the same hashes found in program.json manifest files, which more reliably reflect changes in the actual final contents of the modules. Because these hashes are not known at link time, they are now injected as one blob into the meteor/dynamic-import/dynamic-versions.js module, rather than appearing in the meteorInstall bundles for their containing packages. --- packages/dynamic-import/cache.js | 21 ++++++++------ packages/dynamic-import/client.js | 26 +++++++++++++---- packages/dynamic-import/dynamic-versions.js | 4 +++ tools/isobuild/bundler.js | 23 +++++++++++++++ tools/isobuild/linker.js | 31 +++++++++++---------- 5 files changed, 75 insertions(+), 30 deletions(-) create mode 100644 packages/dynamic-import/dynamic-versions.js diff --git a/packages/dynamic-import/cache.js b/packages/dynamic-import/cache.js index 49f883ea67..e78b9b90de 100644 --- a/packages/dynamic-import/cache.js +++ b/packages/dynamic-import/cache.js @@ -98,15 +98,18 @@ exports.checkMany = function (versions) { return Promise.all(ids.map(function (id) { return new Promise(function (resolve, reject) { - var sourceRequest = sourcesByVersion.get(versions[id]); - sourceRequest.onerror = makeOnError(reject, "sourcesByVersion.get"); - sourceRequest.onsuccess = function (event) { - var result = event.target.result; - if (result) { - sourcesById[id] = result.source; - } - resolve(); - }; + var version = versions[id]; + if (version) { + var sourceRequest = sourcesByVersion.get(versions[id]); + sourceRequest.onerror = makeOnError(reject, "sourcesByVersion.get"); + sourceRequest.onsuccess = function (event) { + var result = event.target.result; + if (result) { + sourcesById[id] = result.source; + } + resolve(); + }; + } else resolve(); }); })).then(finish, finish); }); diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index b074b5ab31..9668f32bdb 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -21,11 +21,13 @@ Module.prototype.dynamicImport = function (id) { // Require the parent module from the complete meta graph. var meta = requireMeta(module.id); var versions = Object.create(null); + var dynamicVersions = require("./dynamic-versions.js"); function walk(meta) { if (meta.dynamic && ! meta.pending) { meta.pending = true; - versions[meta.module.id] = meta.version; + var id = meta.module.id; + versions[id] = getFromTree(dynamicVersions, id); meta.eachChild(walkChild); } } @@ -100,6 +102,7 @@ function installResults(resultsTree, doNotCache) { function walk(tree) { if (typeof tree === "string") { var meta = requireMeta(parts.join("/")); + var id = meta.module.id; var optionsIndex = options.indexOf(meta.options); if (optionsIndex < 0) { options[optionsIndex = options.length] = meta.options; @@ -112,7 +115,7 @@ function installResults(resultsTree, doNotCache) { // are shared by entire bundles. addToTree( trees[optionsIndex], - meta.module.id, + id, // By calling (meta.options.eval || eval) in a wrapper function, // we delay the cost of parsing and evaluating the module code // until the module is first imported. @@ -132,10 +135,13 @@ function installResults(resultsTree, doNotCache) { // Intentionally do not delay resolution waiting for the cache. if (! doNotCache) { - versionsAndSourcesById[meta.module.id] = { - version: meta.version, - source: tree - }; + var version = getFromTree(require("./dynamic-versions.js"), id); + if (version) { + versionsAndSourcesById[id] = { + version: version, + source: tree + }; + } } } else { @@ -158,6 +164,14 @@ function installResults(resultsTree, doNotCache) { } } +function getFromTree(tree, id) { + id.split("/").every(function (part) { + return ! part || (tree = tree[part]); + }); + + return tree; +} + function addToTree(tree, id, value) { var parts = id.split("/"); var lastIndex = parts.length - 1; diff --git a/packages/dynamic-import/dynamic-versions.js b/packages/dynamic-import/dynamic-versions.js new file mode 100644 index 0000000000..7599278028 --- /dev/null +++ b/packages/dynamic-import/dynamic-versions.js @@ -0,0 +1,4 @@ +// This magic double-underscored identifier gets replaced in +// tools/isobuild/bundler.js with a tree of hashes of all dynamic +// modules, for use in client.js and cache.js. +module.exports = __DYNAMIC_VERSIONS__; diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index 2c0141228b..47a10a05e5 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -159,6 +159,7 @@ import Builder from './builder.js'; var compilerPluginModule = require('./compiler-plugin.js'); import { JsFile, CssFile } from './minifier-plugin.js'; var meteorNpm = require('./meteor-npm.js'); +import { addToTree } from "./linker.js"; var files = require('../fs/files.js'); var archinfo = require('../utils/archinfo.js'); @@ -1056,6 +1057,9 @@ class Target { const jsOutputFilesMap = compilerPluginModule.PackageSourceBatch .computeJsOutputFilesMap(sourceBatches); + const versions = {}; + const dynamicImportFiles = new Set; + // Copy their resources into the bundle in order sourceBatches.forEach((sourceBatch) => { const unibuild = sourceBatch.unibuild; @@ -1177,6 +1181,16 @@ class Target { throw new Error('Unknown type ' + resource.type); }); + this.js.forEach(file => { + if (file.targetPath === "packages/dynamic-import.js") { + dynamicImportFiles.add(file); + } + + if (file.targetPath.startsWith("dynamic/")) { + addToTree(file.hash(), file.targetPath, versions); + } + }); + // Depend on the source files that produced these resources. this.watchSet.merge(unibuild.watchSet); @@ -1185,6 +1199,15 @@ class Target { // XXX assumes that this merges cleanly this.watchSet.merge(unibuild.pkg.pluginWatchSet); }); + + dynamicImportFiles.forEach(file => { + file.setContents( + new Buffer(file.contents("utf8").replace( + "__DYNAMIC_VERSIONS__", + () => JSON.stringify(versions.dynamic || {}) + ), "utf8") + ); + }); } // Minify the JS in this target diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index c00c1eaa66..3b32b8620f 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -262,9 +262,7 @@ _.extend(Module.prototype, { dynamic: true, }); - const entry = { - version: file.sourceHash, - }; + const entry = {}; if (! _.isEmpty(file.deps)) { entry.deps = file.deps; @@ -283,28 +281,18 @@ _.extend(Module.prototype, { } } - this._addToTree([entry], file.installPath, tree); + addToTree([entry], file.installPath, tree); } else { // If the file is not dynamic, then it should be included in the // initial bundle, so we add it to the static tree. - this._addToTree(file, file.installPath, tree); + addToTree(file, file.installPath, tree); } }); return tree; }, - _addToTree(obj, path, tree) { - const parts = path.split("/"); - const lastIndex = parts.length - 1; - parts.forEach((part, i) => { - tree = _.has(tree, part) - ? tree[part] - : tree[part] = i < lastIndex ? {} : obj; - }); - }, - // Take the tree generated in getPrelinkedFiles and populate the chunks // array with strings and SourceNode objects that can be combined into a // single SourceNode object. Return the count of modules in the tree. @@ -434,6 +422,19 @@ _.extend(Module.prototype, { } }); +// Insert the given value into the tree by splitting the path and +// creating/following nested objects properties named by each component of +// the split path. +export function addToTree(value, path, tree) { + const parts = path.split("/"); + const lastIndex = parts.length - 1; + parts.forEach((part, i) => { + tree = _.has(tree, part) + ? tree[part] + : tree[part] = i < lastIndex ? {} : value; + }); +} + // Given 'symbolMap' like {Foo: 's1', 'Bar.Baz': 's2', 'Bar.Quux.A': 's3', 'Bar.Quux.B': 's4'} // return something like // {Foo: 's1', Bar: {Baz: 's2', Quux: {A: 's3', B: 's4'}}} From 5477aeac3fc1b2fd67226dc271c006895d4eedfe Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 24 Apr 2017 15:49:47 -0400 Subject: [PATCH 026/125] Support module.prefetch(id) to fetch but not evaluate dynamic modules. Generally, module.prefetch(id) will not throw even if the fetched module is missing. If you need to know whether module.prefetch(id) succeeded, simply await the result of the promise, which will be null on success, or an Error object if the module could not be imported. --- packages/dynamic-import/client.js | 93 ++++++++++++------- packages/modules-runtime/meteor-install.js | 12 ++- .../dynamic-import/imports/prefetch-child.js | 1 + .../apps/dynamic-import/imports/prefetch.js | 3 + tools/tests/apps/dynamic-import/tests.js | 22 +++++ 5 files changed, 94 insertions(+), 37 deletions(-) create mode 100644 tools/tests/apps/dynamic-import/imports/prefetch-child.js create mode 100644 tools/tests/apps/dynamic-import/imports/prefetch.js diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index 9668f32bdb..b6d444f31b 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -2,8 +2,13 @@ var Module = module.constructor; var delayPromise = Promise.resolve(); var requireMeta = meteorInstall._requireMeta; var cache = require("./cache.js"); +var Mp = Module.prototype; -Module.prototype.dynamicImport = function (id) { +// Call module.dynamicImport(id) to fetch a module and any/all of its +// dependencies that have not already been fetched, and evaluate them as +// soon as they arrive. This runtime API makes it very easy to implement +// ECMAScript dynamic import(...) syntax. +Mp.dynamicImport = function (id) { // The real (not meta) parent module. var module = this; @@ -18,45 +23,59 @@ Module.prototype.dynamicImport = function (id) { throw error; } - // Require the parent module from the complete meta graph. - var meta = requireMeta(module.id); - var versions = Object.create(null); - var dynamicVersions = require("./dynamic-versions.js"); + return module.prefetch(id).then(get); + }); +}; - function walk(meta) { - if (meta.dynamic && ! meta.pending) { - meta.pending = true; - var id = meta.module.id; - versions[id] = getFromTree(dynamicVersions, id); - meta.eachChild(walkChild); +// Call module.prefetch(id) to fetch modules without evaluating them. +// Returns a Promise that resolves to an Error object if importing the +// given id failed, and null otherwise. +Mp.prefetch = function (id) { + // Require the parent module from the complete meta graph. + var meta = requireMeta(this.id); + var versions = Object.create(null); + var dynamicVersions = require("./dynamic-versions.js"); + + function walk(meta) { + if (meta.dynamic && ! meta.pending) { + meta.pending = true; + var id = meta.module.id; + versions[id] = getFromTree(dynamicVersions, id); + meta.eachChild(walkChild); + } + } + + function walkChild(childModule) { + return walk(childModule.exports); + } + + meta.eachChild(walkChild, [id]); + + var error = meta.errors && meta.errors[id]; + if (error) { + // If there was an error resolving the top-level id, let that error be + // the final result of the module.prefetch(id) promise. + return Promise.resolve(error); + } + + return cache.checkMany(versions).then(function (sources) { + var localTree = null; + var missingTree = null; + + Object.keys(sources).forEach(function (id) { + var source = sources[id]; + if (source) { + addToTree(localTree = localTree || Object.create(null), id, source); + } else { + addToTree(missingTree = missingTree || Object.create(null), id, 1); } + }); + + if (localTree) { + installResults(localTree, true); } - function walkChild(childModule) { - return walk(childModule.exports); - } - - meta.eachChild(walkChild, [id]); - - var localTree; - var missingTree; - - return cache.checkMany(versions).then(function (sources) { - Object.keys(sources).forEach(function (id) { - var source = sources[id]; - if (source) { - addToTree(localTree = localTree || Object.create(null), id, source); - } else { - addToTree(missingTree = missingTree || Object.create(null), id, 1); - } - }); - - if (localTree) { - installResults(localTree, true); - } - - return missingTree && fetchMissing(missingTree); - }).then(get); + return missingTree && fetchMissing(missingTree); }); }; @@ -162,6 +181,8 @@ function installResults(resultsTree, doNotCache) { if (! doNotCache) { cache.setMany(versionsAndSourcesById); } + + return null; } function getFromTree(tree, id) { diff --git a/packages/modules-runtime/meteor-install.js b/packages/modules-runtime/meteor-install.js index ae9f6ca33c..57c40ec4d1 100644 --- a/packages/modules-runtime/meteor-install.js +++ b/packages/modules-runtime/meteor-install.js @@ -124,6 +124,16 @@ function makeMetaFunc(value, dynamic, options) { exports.dynamic = !! dynamic; exports.options = options; + function quietRequire(id) { + try { + return require(id); + } catch (error) { + (exports.errors = + exports.errors || Object.create(null) + )[id] = error; + } + } + // One of the purposes of the meta graph is to support traversing // module dependencies without evaluating any actual module code. // The eachChild function is essential to that traversal. @@ -134,7 +144,7 @@ function makeMetaFunc(value, dynamic, options) { idsToRequire = idsToRequire || (value && value.deps); if (Array.isArray(idsToRequire)) { - idsToRequire.forEach(require); + idsToRequire.forEach(quietRequire); } // After requiring any/all dependencies of this module, iterate over diff --git a/tools/tests/apps/dynamic-import/imports/prefetch-child.js b/tools/tests/apps/dynamic-import/imports/prefetch-child.js new file mode 100644 index 0000000000..dba4092260 --- /dev/null +++ b/tools/tests/apps/dynamic-import/imports/prefetch-child.js @@ -0,0 +1 @@ +export const shared = Object.create(null); diff --git a/tools/tests/apps/dynamic-import/imports/prefetch.js b/tools/tests/apps/dynamic-import/imports/prefetch.js new file mode 100644 index 0000000000..25dcdc0e57 --- /dev/null +++ b/tools/tests/apps/dynamic-import/imports/prefetch.js @@ -0,0 +1,3 @@ +import { shared } from "./prefetch-child.js"; +export const name = module.id; +shared[name] = true; diff --git a/tools/tests/apps/dynamic-import/tests.js b/tools/tests/apps/dynamic-import/tests.js index fd38dab720..9109d5ebec 100644 --- a/tools/tests/apps/dynamic-import/tests.js +++ b/tools/tests/apps/dynamic-import/tests.js @@ -148,6 +148,28 @@ describe("dynamic import(...)", function () { global.Helper ); }); + + it("works with module.prefetch(id)", async function () { + import { shared } from "./imports/prefetch-child"; + assert.deepEqual(shared, {}); + + const error = await module.prefetch("./imports/nonexistent.js"); + assert.ok(error instanceof Error); + assert.ok(error.message.startsWith("Cannot find module")); + + assert.strictEqual( + await module.prefetch("./tests"), + null // Indicates no error. + ); + + return module.prefetch("./imports/prefetch").then(() => { + assert.deepEqual(shared, {}); + }).then(() => { + import { name } from "./imports/prefetch.js"; + assert.strictEqual(name, "/imports/prefetch.js"); + assert.deepEqual(shared, { [name]: true }); + }); + }); }); function maybeClearDynamicImportCache() { From d9264e3b4b60cd31e9012c588f61360941e0990e Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 25 Apr 2017 10:24:36 -0400 Subject: [PATCH 027/125] Better API for module.prefetch(id). --- packages/dynamic-import/client.js | 19 +++++++++++++++---- tools/tests/apps/dynamic-import/tests.js | 15 +++++++++++---- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index b6d444f31b..4a818aa57a 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -31,8 +31,10 @@ Mp.dynamicImport = function (id) { // Returns a Promise that resolves to an Error object if importing the // given id failed, and null otherwise. Mp.prefetch = function (id) { + var module = this; + // Require the parent module from the complete meta graph. - var meta = requireMeta(this.id); + var meta = requireMeta(module.id); var versions = Object.create(null); var dynamicVersions = require("./dynamic-versions.js"); @@ -53,9 +55,12 @@ Mp.prefetch = function (id) { var error = meta.errors && meta.errors[id]; if (error) { - // If there was an error resolving the top-level id, let that error be - // the final result of the module.prefetch(id) promise. - return Promise.resolve(error); + // If module.prefetch(id) fails, the failure will probably be reported + // as an uncaught promise rejection, unless the calling code + // deliberately handles the rejection. This seems appropriate because + // failed prefetches should not be fatal to the application, yet they + // should be noticeable, so that they can be cleaned up at some point. + return Promise.reject(error); } return cache.checkMany(versions).then(function (sources) { @@ -76,6 +81,12 @@ Mp.prefetch = function (id) { } return missingTree && fetchMissing(missingTree); + + }).then(function () { + // If everything was successful, the final result of the + // module.prefetch(id) promise will be the fully-resolved absolute + // form of the given identifier. + return module.resolve(id); }); }; diff --git a/tools/tests/apps/dynamic-import/tests.js b/tools/tests/apps/dynamic-import/tests.js index 9109d5ebec..41473f8883 100644 --- a/tools/tests/apps/dynamic-import/tests.js +++ b/tools/tests/apps/dynamic-import/tests.js @@ -153,13 +153,20 @@ describe("dynamic import(...)", function () { import { shared } from "./imports/prefetch-child"; assert.deepEqual(shared, {}); - const error = await module.prefetch("./imports/nonexistent.js"); - assert.ok(error instanceof Error); - assert.ok(error.message.startsWith("Cannot find module")); + const rejection = module.prefetch("./imports/nonexistent.js"); + let threw = false; + try { + await rejection; + } catch (e) { + assert.ok(e instanceof Error); + assert.ok(e.message.startsWith("Cannot find module")); + threw = true; + } + assert.strictEqual(threw, true); assert.strictEqual( await module.prefetch("./tests"), - null // Indicates no error. + "/tests.js" ); return module.prefetch("./imports/prefetch").then(() => { From 30c042c8f12afcb93d198601fec5054b9e339a8c Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Tue, 25 Apr 2017 11:41:45 -0400 Subject: [PATCH 028/125] Upgraded to Node 4.8.2 and bumped the dev bundle version. --- meteor | 2 +- scripts/build-dev-bundle-common.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/meteor b/meteor index cc0116c16a..4068a935a6 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.7.25 +BUNDLE_VERSION=4.7.26 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index d0c9b1fdd5..32cfe290ff 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -6,7 +6,7 @@ set -u UNAME=$(uname) ARCH=$(uname -m) MONGO_VERSION=3.2.12 -NODE_VERSION=4.8.1 +NODE_VERSION=4.8.2 NPM_VERSION=4.4.4 if [ "$UNAME" == "Linux" ] ; then From b6d815e9bbafcfc0545b7952bd6c4b157cf05311 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 11:33:04 -0700 Subject: [PATCH 029/125] Update `npm` package to v4.5.0. Notable changes: https://github.com/npm/npm/releases/tag/v4.5.0 --- scripts/build-dev-bundle-common.sh | 2 +- scripts/dev-bundle-tool-package.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 32cfe290ff..5e5b8062f7 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -7,7 +7,7 @@ UNAME=$(uname) ARCH=$(uname -m) MONGO_VERSION=3.2.12 NODE_VERSION=4.8.2 -NPM_VERSION=4.4.4 +NPM_VERSION=4.5.0 if [ "$UNAME" == "Linux" ] ; then if [ "$ARCH" != "i686" -a "$ARCH" != "x86_64" ] ; then diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 9d8d0ec578..e96526a883 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -11,7 +11,7 @@ var packageJson = { dependencies: { // Explicit dependency because we are replacing it with a bundled version // and we want to make sure there are no dependencies on a higher version - npm: "4.4.4", + npm: "4.5.0", "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", "meteor-babel": "0.20.1", From 45a44f35e0b70d92b40634cee018d811d1b7bcf9 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 12:01:03 -0700 Subject: [PATCH 030/125] Add `History.md` for Node.js and `npm` package updates. --- History.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/History.md b/History.md index 210c44c613..64801a8835 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,13 @@ the `reify` npm package has been upgraded to version 0.7.4, fixing [issue #8595](https://github.com/meteor/meteor/issues/8595). +* Node has been upgraded to version 4.8.2. + +* The `npm` npm package has been upgraded to version 4.5.0. + Note that when using npm `scripts` there has been a change regarding + what happens when `SIGINT` (Ctrl-C) is received. Read more + [here](https://github.com/npm/npm/releases/tag/v4.5.0). + ## v1.4.4.1, 2017-04-07 * A change in Meteor 1.4.4 to remove "garbage" directories asynchronously From e82ad976d332013dec400179372967361ec4c194 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 12:18:37 -0700 Subject: [PATCH 031/125] Update versions of `node-inspector` and `v8-profiler` packages. Notable changes in `node-inspector`: https://github.com/node-inspector/node-inspector/blob/master/ChangeLog.md#2017-04-24-version-111 Fixes meteor/meteor#8469. --- scripts/dev-bundle-tool-package.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index e96526a883..c6f89062c0 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -33,8 +33,8 @@ var packageJson = { tar: "2.2.1", kexec: "2.0.2", "source-map": "0.5.3", - "node-inspector": "0.12.8", - "v8-profiler": "5.6.5", + "node-inspector": "1.1.1", + "v8-profiler": "5.7.0", chalk: "0.5.1", sqlite3: "3.1.3", netroute: "1.0.2", From 1886bdb9d6d03cb107c744475b15020e6c049e6a Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Tue, 25 Apr 2017 11:41:45 -0400 Subject: [PATCH 032/125] Upgraded to Node 4.8.2 and bumped the dev bundle version. --- meteor | 2 +- scripts/build-dev-bundle-common.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/meteor b/meteor index 886256dfb7..4068a935a6 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.7.23 +BUNDLE_VERSION=4.7.26 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index d0c9b1fdd5..32cfe290ff 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -6,7 +6,7 @@ set -u UNAME=$(uname) ARCH=$(uname -m) MONGO_VERSION=3.2.12 -NODE_VERSION=4.8.1 +NODE_VERSION=4.8.2 NPM_VERSION=4.4.4 if [ "$UNAME" == "Linux" ] ; then From 66f353ffb063b598d47ca65ee3b73c5a5a515855 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 11:33:04 -0700 Subject: [PATCH 033/125] Update `npm` package to v4.5.0. Notable changes: https://github.com/npm/npm/releases/tag/v4.5.0 --- scripts/build-dev-bundle-common.sh | 2 +- scripts/dev-bundle-tool-package.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 32cfe290ff..5e5b8062f7 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -7,7 +7,7 @@ UNAME=$(uname) ARCH=$(uname -m) MONGO_VERSION=3.2.12 NODE_VERSION=4.8.2 -NPM_VERSION=4.4.4 +NPM_VERSION=4.5.0 if [ "$UNAME" == "Linux" ] ; then if [ "$ARCH" != "i686" -a "$ARCH" != "x86_64" ] ; then diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index f7d2ed362e..378e6e94a2 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -11,7 +11,7 @@ var packageJson = { dependencies: { // Explicit dependency because we are replacing it with a bundled version // and we want to make sure there are no dependencies on a higher version - npm: "4.4.4", + npm: "4.5.0", "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", "meteor-babel": "0.19.1", From d9f559ccc575abb33ce45d68b2a04ca3162694c6 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 12:01:03 -0700 Subject: [PATCH 034/125] Add `History.md` for Node.js and `npm` package updates. --- History.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2fa43c551b..8c2fd5dda8 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,20 @@ ## v.NEXT -## v1.4.4.1, TBD +## v1.4.4.2, TBD + +* Node has been upgraded to version 4.8.2. + +* The `npm` npm package has been upgraded to version 4.5.0. + Note that when using npm `scripts` there has been a change regarding + what happens when `SIGINT` (Ctrl-C) is received. Read more + [here](https://github.com/npm/npm/releases/tag/v4.5.0). + +* The `meteor-babel` npm package has been upgraded to version 0.20.1, and + the `reify` npm package has been upgraded to version 0.7.4, fixing + [issue #8595](https://github.com/meteor/meteor/issues/8595). + + +## v1.4.4.1, 2017-04-07 * A change in Meteor 1.4.4 to remove "garbage" directories asynchronously in `files.renameDirAlmostAtomically` had unintended consequences for From 411dd81a45b4c7bb708c9ccbf5ad5503c9f00995 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 12:18:37 -0700 Subject: [PATCH 035/125] Update versions of `node-inspector` and `v8-profiler` packages. Notable changes in `node-inspector`: https://github.com/node-inspector/node-inspector/blob/master/ChangeLog.md#2017-04-24-version-111 Fixes meteor/meteor#8469. --- scripts/dev-bundle-tool-package.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 378e6e94a2..a452bfb332 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -33,8 +33,8 @@ var packageJson = { tar: "2.2.1", kexec: "2.0.2", "source-map": "0.5.3", - "node-inspector": "0.12.8", - "v8-profiler": "5.6.5", + "node-inspector": "1.1.1", + "v8-profiler": "5.7.0", chalk: "0.5.1", sqlite3: "3.1.3", netroute: "1.0.2", From 94f8c9d7cebf980169f597a01a436c5aeee859ad Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Wed, 12 Apr 2017 09:58:16 -0700 Subject: [PATCH 036/125] Remove experimental trailing comma to avoid problems with `jsdoc`. The comma in question: a trailing comma a rest-parameter, within a function argument's parameter de-structuring: function a({ a = false, ...b, }) { // ... } Espree, the parser used by `jsdoc` (used in Meteor docs) previously allowed this with `experimentalObjectRestSpread` enabled but now throws an error with the addition of https://github.com/eslint/espree/commit/652990a7bfeb9eca2041e8cbb696de671522d420. It might have been argued at one point that the trailing-comma could allow for the easy, future addition of another parameter, ala: function a({ a = false, ...b, c = true, }) { // ... } Having the rest-parameter in the last position is certainly more clear (it is the "rest", after-all, and there can be only one) but I'm not going to have that discussion at the cost of docs not deploying! --- tools/isobuild/bundler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index 526b5e1eed..3bbc8cacb4 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -353,7 +353,7 @@ export class NodeModulesDirectory { // Options consumed by readDirsFromJSON are listed above. Any other // options will be passed on to NodeModulesDirectory constructor via // this callerInfo object: - ...callerInfo, + ...callerInfo }) { assert.strictEqual(typeof callerInfo.sourceRoot, "string"); From da9e3971f8ed734dac90ef1aeaee87e7501aeb5f Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 02:35:01 -0400 Subject: [PATCH 037/125] Upgrade meteor-babel and reify to fix #8595. (#8599) * Upgrade meteor-babel to version 0.20.1 and reify to 0.7.4. * Bump $BUNDLE_VERSION to 4.7.25 before rebuilding dev bundle. --- History.md | 1 - .../.npm/package/npm-shrinkwrap.json | 202 +++++++++--------- packages/babel-compiler/package.js | 4 +- .../modules/.npm/package/npm-shrinkwrap.json | 22 +- packages/modules/package.js | 4 +- scripts/dev-bundle-tool-package.js | 2 +- 6 files changed, 107 insertions(+), 128 deletions(-) diff --git a/History.md b/History.md index 8c2fd5dda8..c008693784 100644 --- a/History.md +++ b/History.md @@ -13,7 +13,6 @@ the `reify` npm package has been upgraded to version 0.7.4, fixing [issue #8595](https://github.com/meteor/meteor/issues/8595). - ## v1.4.4.1, 2017-04-07 * A change in Meteor 1.4.4 to remove "garbage" directories asynchronously diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index 214f819c77..7bd00f4cd2 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "acorn": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz", - "from": "acorn@>=4.0.5 <4.1.0" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "from": "acorn@>=5.0.0 <5.1.0" }, "ansi-regex": { "version": "2.1.1", @@ -21,29 +21,29 @@ "from": "babel-code-frame@>=6.22.0 <7.0.0" }, "babel-core": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.1.tgz", "from": "babel-core@>=6.22.1 <7.0.0" }, "babel-generator": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.0.tgz", - "from": "babel-generator@>=6.24.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.1.tgz", + "from": "babel-generator@>=6.24.1 <7.0.0" }, "babel-helper-builder-react-jsx": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.23.0.tgz", - "from": "babel-helper-builder-react-jsx@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz", + "from": "babel-helper-builder-react-jsx@>=6.24.1 <7.0.0" }, "babel-helper-call-delegate": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz", - "from": "babel-helper-call-delegate@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "from": "babel-helper-call-delegate@>=6.24.1 <7.0.0" }, "babel-helper-define-map": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.23.0.tgz", - "from": "babel-helper-define-map@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz", + "from": "babel-helper-define-map@>=6.24.1 <7.0.0" }, "babel-helper-evaluate-path": { "version": "0.0.3", @@ -56,19 +56,19 @@ "from": "babel-helper-flip-expressions@>=0.0.2 <0.0.3" }, "babel-helper-function-name": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz", - "from": "babel-helper-function-name@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "from": "babel-helper-function-name@>=6.24.1 <7.0.0" }, "babel-helper-get-function-arity": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz", - "from": "babel-helper-get-function-arity@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "from": "babel-helper-get-function-arity@>=6.24.1 <7.0.0" }, "babel-helper-hoist-variables": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.22.0.tgz", - "from": "babel-helper-hoist-variables@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "from": "babel-helper-hoist-variables@>=6.24.1 <7.0.0" }, "babel-helper-is-nodes-equiv": { "version": "0.0.1", @@ -86,14 +86,14 @@ "from": "babel-helper-mark-eval-scopes@>=0.0.3 <0.0.4" }, "babel-helper-optimise-call-expression": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.23.0.tgz", - "from": "babel-helper-optimise-call-expression@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "from": "babel-helper-optimise-call-expression@>=6.24.1 <7.0.0" }, "babel-helper-regex": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.22.0.tgz", - "from": "babel-helper-regex@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz", + "from": "babel-helper-regex@>=6.24.1 <7.0.0" }, "babel-helper-remove-or-void": { "version": "0.0.1", @@ -101,9 +101,9 @@ "from": "babel-helper-remove-or-void@>=0.0.1 <0.0.2" }, "babel-helper-replace-supers": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.23.0.tgz", - "from": "babel-helper-replace-supers@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "from": "babel-helper-replace-supers@>=6.24.1 <7.0.0" }, "babel-helper-to-multiple-sequence-expressions": { "version": "0.0.3", @@ -111,9 +111,9 @@ "from": "babel-helper-to-multiple-sequence-expressions@>=0.0.3 <0.0.4" }, "babel-helpers": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.23.0.tgz", - "from": "babel-helpers@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "from": "babel-helpers@>=6.24.1 <7.0.0" }, "babel-messages": { "version": "6.23.0", @@ -131,8 +131,8 @@ "from": "babel-plugin-minify-constant-folding@>=0.0.4 <0.0.5", "dependencies": { "jsesc": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.4.0.tgz", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.0.tgz", "from": "jsesc@>=2.4.0 <3.0.0" } } @@ -235,18 +235,18 @@ "from": "babel-plugin-transform-es2015-block-scoped-functions@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-block-scoping": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz", "from": "babel-plugin-transform-es2015-block-scoping@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-classes": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "from": "babel-plugin-transform-es2015-classes@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-computed-properties": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "from": "babel-plugin-transform-es2015-computed-properties@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-destructuring": { @@ -265,28 +265,28 @@ "from": "babel-plugin-transform-es2015-literals@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz", "from": "babel-plugin-transform-es2015-modules-commonjs@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-modules-reify": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.6.2.tgz", - "from": "babel-plugin-transform-es2015-modules-reify@>=0.6.0 <0.7.0" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.7.0.tgz", + "from": "babel-plugin-transform-es2015-modules-reify@>=0.7.0 <0.8.0" }, "babel-plugin-transform-es2015-object-super": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "from": "babel-plugin-transform-es2015-object-super@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-parameters": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "from": "babel-plugin-transform-es2015-parameters@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "from": "babel-plugin-transform-es2015-shorthand-properties@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-spread": { @@ -295,8 +295,8 @@ "from": "babel-plugin-transform-es2015-spread@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "from": "babel-plugin-transform-es2015-sticky-regex@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-template-literals": { @@ -310,8 +310,8 @@ "from": "babel-plugin-transform-es2015-typeof-symbol@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "from": "babel-plugin-transform-es2015-unicode-regex@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es3-property-literals": { @@ -360,9 +360,9 @@ "from": "babel-plugin-transform-react-display-name@>=6.23.0 <7.0.0" }, "babel-plugin-transform-react-jsx": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.23.0.tgz", - "from": "babel-plugin-transform-react-jsx@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "from": "babel-plugin-transform-react-jsx@>=6.24.1 <7.0.0" }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", @@ -375,8 +375,8 @@ "from": "babel-plugin-transform-react-jsx-source@>=6.22.0 <7.0.0" }, "babel-plugin-transform-regenerator": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz", "from": "babel-plugin-transform-regenerator@>=6.22.0 <7.0.0" }, "babel-plugin-transform-regexp-constructors": { @@ -410,9 +410,9 @@ "from": "babel-plugin-transform-simplify-comparison-operators@>=6.8.1 <7.0.0" }, "babel-plugin-transform-strict-mode": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.22.0.tgz", - "from": "babel-plugin-transform-strict-mode@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "from": "babel-plugin-transform-strict-mode@>=6.24.1 <7.0.0" }, "babel-plugin-transform-undefined-to-void": { "version": "6.8.0", @@ -430,19 +430,19 @@ "from": "babel-preset-flow@>=6.23.0 <7.0.0" }, "babel-preset-meteor": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-6.25.0.tgz", - "from": "babel-preset-meteor@6.25.0" + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-6.26.0.tgz", + "from": "babel-preset-meteor@6.26.0" }, "babel-preset-react": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "from": "babel-preset-react@>=6.22.0 <7.0.0" }, "babel-register": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.0.tgz", - "from": "babel-register@>=6.24.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", + "from": "babel-register@>=6.24.1 <7.0.0" }, "babel-runtime": { "version": "6.23.0", @@ -450,18 +450,18 @@ "from": "babel-runtime@>=6.22.0 <7.0.0" }, "babel-template": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", "from": "babel-template@>=6.22.0 <7.0.0" }, "babel-traverse": { - "version": "6.23.1", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.23.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", "from": "babel-traverse@>=6.22.1 <7.0.0" }, "babel-types": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", "from": "babel-types@>=6.22.0 <7.0.0" }, "babylon": { @@ -475,8 +475,8 @@ "from": "balanced-match@>=0.4.1 <0.5.0" }, "brace-expansion": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", "from": "brace-expansion@>=1.0.0 <2.0.0" }, "chalk": { @@ -490,8 +490,8 @@ "from": "concat-map@0.0.1" }, "convert-source-map": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.4.0.tgz", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", "from": "convert-source-map@>=1.3.0 <2.0.0" }, "core-js": { @@ -579,15 +579,10 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", "from": "loose-envify@>=1.0.0 <2.0.0" }, - "magic-string": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.19.0.tgz", - "from": "magic-string@>=0.19.0 <0.20.0" - }, "meteor-babel": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.19.1.tgz", - "from": "meteor-babel@0.19.1" + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.0.tgz", + "from": "meteor-babel@0.20.0" }, "meteor-babel-helpers": { "version": "0.0.3", @@ -650,9 +645,9 @@ "from": "regenerator-runtime@>=0.10.0 <0.11.0" }, "regenerator-transform": { - "version": "0.9.8", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.8.tgz", - "from": "regenerator-transform@0.9.8" + "version": "0.9.11", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.11.tgz", + "from": "regenerator-transform@0.9.11" }, "regexpu-core": { "version": "2.0.0", @@ -677,9 +672,9 @@ } }, "reify": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.6.6.tgz", - "from": "reify@>=0.6.2 <0.7.0" + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz", + "from": "reify@>=0.7.2 <0.8.0" }, "repeating": { "version": "2.0.1", @@ -720,11 +715,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "from": "trim-right@>=1.0.1 <2.0.0" - }, - "vlq": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.1.tgz", - "from": "vlq@>=0.2.1 <0.3.0" } } } diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index 44bc595b9c..dbd098e545 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,11 +6,11 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.18.1' + version: '6.18.2' }); Npm.depends({ - 'meteor-babel': '0.19.1' + 'meteor-babel': '0.20.1' }); Package.onUse(function (api) { diff --git a/packages/modules/.npm/package/npm-shrinkwrap.json b/packages/modules/.npm/package/npm-shrinkwrap.json index 0ec396bdbd..20c76d7a1d 100644 --- a/packages/modules/.npm/package/npm-shrinkwrap.json +++ b/packages/modules/.npm/package/npm-shrinkwrap.json @@ -1,24 +1,14 @@ { "dependencies": { "acorn": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz", - "from": "acorn@>=4.0.5 <4.1.0" - }, - "magic-string": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.19.0.tgz", - "from": "magic-string@>=0.19.0 <0.20.0" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "from": "acorn@>=5.0.0 <5.1.0" }, "reify": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.6.6.tgz", - "from": "reify@0.6.6" - }, - "vlq": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.1.tgz", - "from": "vlq@>=0.2.1 <0.3.0" + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz", + "from": "reify@0.7.4" } } } diff --git a/packages/modules/package.js b/packages/modules/package.js index 1153f2f9cb..49e7a97eae 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,12 +1,12 @@ Package.describe({ name: "modules", - version: "0.8.1", + version: "0.8.2", summary: "CommonJS module system", documentation: "README.md" }); Npm.depends({ - reify: "0.6.6" + reify: "0.7.4" }); Package.onUse(function(api) { diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index a452bfb332..c6f89062c0 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -14,7 +14,7 @@ var packageJson = { npm: "4.5.0", "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", - "meteor-babel": "0.19.1", + "meteor-babel": "0.20.1", "meteor-promise": "0.8.0", fibers: "1.0.15", promise: "7.1.1", From a00bcd026ea310831380122b6ee941647853695b Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 02:36:37 -0400 Subject: [PATCH 038/125] Update npm-shrinkwrap.json for babel-compiler package. --- packages/babel-compiler/.npm/package/npm-shrinkwrap.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index 7bd00f4cd2..f297b0adf2 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -580,9 +580,9 @@ "from": "loose-envify@>=1.0.0 <2.0.0" }, "meteor-babel": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.0.tgz", - "from": "meteor-babel@0.20.0" + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.1.tgz", + "from": "meteor-babel@0.20.1" }, "meteor-babel-helpers": { "version": "0.0.3", From 150ef7100eab854a06d583a55a9dbd0a1813abe4 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 02:38:20 -0400 Subject: [PATCH 039/125] Bump ecmascript package version to 0.7.3. Bumping this version is necessary after upgrading babel-compiler since ecmascript registers a compiler plugin that uses babel-compiler. --- packages/ecmascript/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index 4c27300bbe..b4b84a7c89 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.7.2', + version: '0.7.3', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); From 78c6ac915c5262303dedf1402f0a1e8c94dafc65 Mon Sep 17 00:00:00 2001 From: Erik Demaine Date: Mon, 17 Apr 2017 15:41:44 -0400 Subject: [PATCH 040/125] Switch to modern nodemailer 4, Node 4 version. Fix #8591 (#8605) * Switch to modern nodemailer 4, Node 4 version. Fix #8591 * Most critically, use a pool instead of direct SMTP connection, to handle dropped connections and increase throughput, like mail module 1.1. (#8591) * New nodemailer's sendMail wants an options object, not a MailComposer object. Luckily, a MailComposer object has a "mail" field that remembers the original options, so we can keep original behavior. * However, we no longer support the mailComposer option set to a compiled MailComposer object (functionality that was briefly added in 1.2.0). * nodemailer does SMTP URL parsing now automatically for us, simplifying code. * Tests' outputs now end with additional "\r\n" * Drop underscore package dependency (no longer needed) * General formatting/style cleanup for `packages/email`. * snake_cased => camelCased for some local variables. * Added curly-brackets to `if`s. * Removed trailing spaces. * Removed commented-out code. * Removed older doc text and changed some links. * Get rid of back-and-forth assigning of `mailUrlString`. --- .../email/.npm/package/npm-shrinkwrap.json | 73 +--------- packages/email/email.js | 137 +++++++----------- packages/email/email_tests.js | 60 ++++---- packages/email/package.js | 11 +- 4 files changed, 82 insertions(+), 199 deletions(-) diff --git a/packages/email/.npm/package/npm-shrinkwrap.json b/packages/email/.npm/package/npm-shrinkwrap.json index 4028b03706..aebb613b70 100644 --- a/packages/email/.npm/package/npm-shrinkwrap.json +++ b/packages/email/.npm/package/npm-shrinkwrap.json @@ -1,79 +1,14 @@ { "dependencies": { - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "from": "addressparser@1.0.1" - }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "from": "buildmail@4.0.1" - }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "from": "httpntlm@1.6.1" - }, - "httpreq": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.23.tgz", - "from": "httpreq@>=0.4.22" - }, - "iconv-lite": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "from": "iconv-lite@0.4.15" - }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "from": "libbase64@0.1.0" - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "from": "libmime@3.0.0" - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "from": "libqp@1.1.0" - }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "from": "mailcomposer@4.0.1" - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "from": "nodemailer-fetch@1.6.0" - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "from": "nodemailer-shared@1.1.0" - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "from": "punycode@1.4.1" - }, - "smtp-connection": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.2.tgz", - "from": "smtp-connection@2.12.2" + "node4mailer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/node4mailer/-/node4mailer-4.0.2.tgz", + "from": "node4mailer@4.0.2" }, "stream-buffers": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-0.2.5.tgz", "from": "stream-buffers@0.2.5" - }, - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "from": "underscore@>=1.7.0 <1.8.0" } } } diff --git a/packages/email/email.js b/packages/email/email.js index ae8e652eba..af3c633d69 100644 --- a/packages/email/email.js +++ b/packages/email/email.js @@ -1,6 +1,6 @@ var Future = Npm.require('fibers/future'); var urlModule = Npm.require('url'); -var SMTPConnection = Npm.require('smtp-connection'); +var nodemailer = Npm.require('node4mailer'); Email = {}; EmailTest = {}; @@ -8,61 +8,60 @@ EmailTest = {}; EmailInternals = { NpmModules: { mailcomposer: { - version: Npm.require('mailcomposer/package.json').version, - module: Npm.require('mailcomposer') + version: Npm.require('node4mailer/package.json').version, + module: Npm.require('node4mailer/lib/mail-composer') + }, + nodemailer: { + version: Npm.require('node4mailer/package.json').version, + module: Npm.require('node4mailer') } } }; -var mailcomposer = EmailInternals.NpmModules.mailcomposer.module; +var MailComposer = EmailInternals.NpmModules.mailcomposer.module; -var makePool = function (mailUrlString) { - var mailUrl = urlModule.parse(mailUrlString); - if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:') +var makeTransport = function (mailUrlString) { + var mailUrl = urlModule.parse(mailUrlString, true); + + if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:') { throw new Error("Email protocol in $MAIL_URL (" + mailUrlString + ") must be 'smtp' or 'smtps'"); - - var port = +(mailUrl.port); - var auth = false; - if (mailUrl.auth) { - var parts = mailUrl.auth.split(':', 2); - auth = {user: parts[0], - pass: parts[1]}; } - var pool = new SMTPConnection({ - port: port, // Defaults to 25 - host: mailUrl.hostname, // Defaults to "localhost" - secure: (port === 465) || (mailUrl.protocol === 'smtps:') - }); - Meteor.wrapAsync(pool.connect, pool)(); - if (auth) { - //_.bind(Future.wrap(pool.login), pool)(auth).wait(); - Meteor.wrapAsync(pool.login, pool)(auth); + // Allow overriding pool setting, but default to true. + if (!mailUrl.query) { + mailUrl.query = {}; } - pool._syncSend = Meteor.wrapAsync(pool.send, pool); - return pool; + if (!mailUrl.query.pool) { + mailUrl.query.pool = 'true'; + } + + var transport = nodemailer.createTransport( + urlModule.format(mailUrl)); + + transport._syncSendMail = Meteor.wrapAsync(transport.sendMail, transport); + return transport; }; -var getPool = function() { +var getTransport = function() { // We delay this check until the first call to Email.send, in case someone // set process.env.MAIL_URL in startup code. Then we store in a cache until // process.env.MAIL_URL changes. var url = process.env.MAIL_URL; if (this.cacheKey === undefined || this.cacheKey !== url) { this.cacheKey = url; - this.cache = url ? makePool(url) : null; + this.cache = url ? makeTransport(url) : null; } return this.cache; } -var next_devmode_mail_id = 0; +var nextDevModeMailId = 0; var output_stream = process.stdout; // Testing hooks EmailTest.overrideOutputStream = function (stream) { - next_devmode_mail_id = 0; + nextDevModeMailId = 0; output_stream = stream; }; @@ -70,27 +69,27 @@ EmailTest.restoreOutputStream = function () { output_stream = process.stdout; }; -var devModeSend = function (mc) { - var devmode_mail_id = next_devmode_mail_id++; +var devModeSend = function (mail) { + var devModeMailId = nextDevModeMailId++; var stream = output_stream; // This approach does not prevent other writers to stdout from interleaving. - stream.write("====== BEGIN MAIL #" + devmode_mail_id + " ======\n"); + stream.write("====== BEGIN MAIL #" + devModeMailId + " ======\n"); stream.write("(Mail not sent; to enable sending, set the MAIL_URL " + "environment variable.)\n"); - var readStream = mc.createReadStream(); + var readStream = new MailComposer(mail).compile().createReadStream(); readStream.pipe(stream, {end: false}); var future = new Future; readStream.on('end', function () { - stream.write("====== END MAIL #" + devmode_mail_id + " ======\n"); + stream.write("====== END MAIL #" + devModeMailId + " ======\n"); future.return(); }); future.wait(); }; -var smtpSend = function (pool, mc) { - pool._syncSend(mc.getEnvelope(), mc.createReadStream()); +var smtpSend = function (transport, mail) { + transport._syncSendMail(mail); }; /** @@ -105,28 +104,6 @@ EmailTest.hookSend = function (f) { sendHooks.push(f); }; -// Old comment below -/** - * Send an email. - * - * Connects to the mail server configured via the MAIL_URL environment - * variable. If unset, prints formatted message to stdout. The "from" option - * is required, and at least one of "to", "cc", and "bcc" must be provided; - * all other options are optional. - * - * @param options - * @param options.from {String} RFC5322 "From:" address - * @param options.to {String|String[]} RFC5322 "To:" address[es] - * @param options.cc {String|String[]} RFC5322 "Cc:" address[es] - * @param options.bcc {String|String[]} RFC5322 "Bcc:" address[es] - * @param options.replyTo {String|String[]} RFC5322 "Reply-To:" address[es] - * @param options.subject {String} RFC5322 "Subject:" line - * @param options.text {String} RFC5322 mail body (plain text) - * @param options.html {String} RFC5322 mail body (HTML) - * @param options.headers {Object} custom RFC5322 headers (dictionary) - */ - -// New API doc comment below /** * @summary Send an email. Throws an `Error` on failure to contact mail server * or if mail server returns an error. All fields should match @@ -135,10 +112,9 @@ EmailTest.hookSend = function (f) { * If the `MAIL_URL` environment variable is set, actually sends the email. * Otherwise, prints the contents of the email to standard out. * - * Note that this package is based on mailcomposer version `4.0.1`, so make - * sure to refer to the documentation for that version if using the - * `attachments` or `mailComposer` options. - * [Click here to read the mailcomposer 4.0.1 docs](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md). + * Note that this package is based on **mailcomposer 4**, so make sure to refer to + * [the documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md) + * for that version when using the `attachments` or `mailComposer` options. * * @locus Server * @param {Object} options @@ -150,44 +126,29 @@ EmailTest.hookSend = function (f) { * @param {String} [options.messageId] Message-ID for this message; otherwise, will be set to a random value * @param {String} [options.subject] "Subject:" line * @param {String} [options.text|html] Mail body (in plain text and/or HTML) - * @param {String} [options.watchHtml] Mail body in HTML specific for Apple Watch - * @param {String} [options.icalEvent] iCalendar event attachment + * @param {String} [options.watchHtml] Mail body in HTML specific for Apple Watch + * @param {String} [options.icalEvent] iCalendar event attachment * @param {Object} [options.headers] Dictionary of custom headers * @param {Object[]} [options.attachments] Array of attachment objects, as * described in the [mailcomposer documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md#attachments). - * @param {MailComposer} [options.mailComposer] A [MailComposer](https://github.com/andris9/mailcomposer) - * object (or its `compile()` output) representing the message to be sent. - * Overrides all other options. You can access the `mailcomposer` npm module at - * `EmailInternals.NpmModules.mailcomposer.module`. This module is a function - * which assembles a MailComposer object and immediately `compile()`s it. - * Alternatively, you can create and pass a MailComposer object via - * `new EmailInternals.NpmModules.mailcomposer.module.MailComposer`. + * @param {MailComposer} [options.mailComposer] A [MailComposer](https://nodemailer.com/extras/mailcomposer/#e-mail-message-fields) + * object representing the message to be sent. Overrides all other options. + * You can create a `MailComposer` object via + * `new EmailInternals.NpmModules.mailcomposer.module`. */ Email.send = function (options) { for (var i = 0; i < sendHooks.length; i++) if (! sendHooks[i](options)) return; - var mc; if (options.mailComposer) { - mc = options.mailComposer; - if (mc.compile) { - mc = mc.compile(); - } - } else { - // mailcomposer now automatically adds date if omitted - //if (!options.hasOwnProperty('date') && - // (!options.headers || !options.headers.hasOwnProperty('Date'))) { - // options['date'] = new Date().toUTCString().replace(/GMT/, '+0000'); - //} - - mc = mailcomposer(options); + options = options.mailComposer.mail; } - var pool = getPool(); - if (pool) { - smtpSend(pool, mc); + var transport = getTransport(); + if (transport) { + smtpSend(transport, options); } else { - devModeSend(mc); + devModeSend(options); } }; diff --git a/packages/email/email_tests.js b/packages/email/email_tests.js index 6fe9a30954..97c0977660 100644 --- a/packages/email/email_tests.js +++ b/packages/email/email_tests.js @@ -22,7 +22,7 @@ function canonicalize(string) { // Remove generated content for test.equal to succeed. return string.replace(/Message-ID: <[^<>]*>\r\n/, "Message-ID: <...>\r\n") .replace(/Date: (?!dummy).*\r\n/, "Date: ...\r\n") - .replace(/----[^\s"]+/g, "----..."); + .replace(/(boundary="|^--)--[^\s"]+?(-Part|")/mg, "$1--...$2"); } Tinytest.add("email - fully customizable", function (test) { @@ -55,7 +55,7 @@ Tinytest.add("email - fully customizable", function (test) { "\r\n" + "This is the body\n" + "of the message\n" + - "From us." + + "From us.\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -108,33 +108,23 @@ Tinytest.add("email - multiple e-mails same stream", function (test) { Tinytest.add("email - using mail composer", function (test) { smokeEmailTest(function (stream) { // Test direct MailComposer usage. - var mcs = [ - // Test with MailComposer object (without compiling). - new EmailInternals.NpmModules.mailcomposer.module.MailComposer({ - from: "a@b.com", - text: "body" - }), - // Test calling module as a function, which compiles MailComposer object. - EmailInternals.NpmModules.mailcomposer.module({ - from: "a@b.com", - text: "body" - }) - ]; - for (var i = 0; i < mcs.length; i++) { - Email.send({mailComposer: mcs[i]}); - test.equal(canonicalize(stream.getContentsAsString("utf8")), - "====== BEGIN MAIL #"+i+" ======\n" + - devWarningBanner + - "Content-Type: text/plain\r\n" + - "From: a@b.com\r\n" + - "Message-ID: <...>\r\n" + - "Content-Transfer-Encoding: 7bit\r\n" + - "Date: ...\r\n" + - "MIME-Version: 1.0\r\n" + - "\r\n" + - "body" + - "====== END MAIL #"+i+" ======\n"); - } + var mc = new EmailInternals.NpmModules.mailcomposer.module({ + from: "a@b.com", + text: "body" + }); + Email.send({mailComposer: mc}); + test.equal(canonicalize(stream.getContentsAsString("utf8")), + "====== BEGIN MAIL #0 ======\n" + + devWarningBanner + + "Content-Type: text/plain\r\n" + + "From: a@b.com\r\n" + + "Message-ID: <...>\r\n" + + "Content-Transfer-Encoding: 7bit\r\n" + + "Date: ...\r\n" + + "MIME-Version: 1.0\r\n" + + "\r\n" + + "body\r\n" + + "====== END MAIL #0 ======\n"); }); }); @@ -181,7 +171,7 @@ Tinytest.add("email - long lines", function (test) { "MIME-Version: 1.0\r\n" + "\r\n" + "This is a very very very very very very very very very very " + - "very very long =\r\ntext" + + "very very long =\r\ntext\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -208,7 +198,7 @@ Tinytest.add("email - unicode", function (test) { "Date: ...\r\n" + "MIME-Version: 1.0\r\n" + "\r\n" + - "I =E2=99=A5 Meteor" + + "I =E2=99=A5 Meteor\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -227,24 +217,24 @@ Tinytest.add("email - text and html", function (test) { "====== BEGIN MAIL #0 ======\n" + devWarningBanner + "Content-Type: multipart/alternative;\r\n" + - ' boundary="----..."\r\n' + + ' boundary="--...-Part_1"\r\n' + "From: foo@example.com\r\n" + "To: bar@example.com\r\n" + "Message-ID: <...>\r\n" + "Date: ...\r\n" + "MIME-Version: 1.0\r\n" + "\r\n" + - "----...\r\n" + + "----...-Part_1\r\n" + "Content-Type: text/plain\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "*Cool*, man\r\n" + - "----...\r\n" + + "----...-Part_1\r\n" + "Content-Type: text/html\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "Cool, man\r\n" + - "----...\r\n" + + "----...-Part_1--\r\n" + "====== END MAIL #0 ======\n"); }); }); diff --git a/packages/email/package.js b/packages/email/package.js index 36f09e1601..7e5167f350 100644 --- a/packages/email/package.js +++ b/packages/email/package.js @@ -1,17 +1,14 @@ Package.describe({ summary: "Send email messages", - version: "1.2.0" + version: "1.2.1" }); Npm.depends({ - mailcomposer: "4.0.1", - // Using smtp-connection@2 (instead of latest) because it shares - // nodemailer-shared with mailcomposer@4: - "smtp-connection": "2.12.2", - "stream-buffers": "0.2.5"}); + node4mailer: "4.0.2", + "stream-buffers": "0.2.5" +}); Package.onUse(function (api) { - api.use('underscore', 'server'); api.export(['Email', 'EmailInternals'], 'server'); api.export('EmailTest', 'server', {testOnly: true}); api.addFiles('email.js', 'server'); From 99fffd86708ce6fac7cd62861018beb1d59c7beb Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 14:30:30 -0700 Subject: [PATCH 041/125] Fix disappearance of debug banner when running `meteor debug`. This was broken due to a change in Node.js which enabled support for using `--debug` in combination with IPv6 addresses. --- tools/inspector.js | 2 +- tools/runners/run-app.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/inspector.js b/tools/inspector.js index 21cc3ebaf6..c23087a135 100644 --- a/tools/inspector.js +++ b/tools/inspector.js @@ -145,7 +145,7 @@ DEp.connectToChildProcess = function connectToChildProcess(child) { // port (not debugPort!), and create a connection to that port so that // the child process can communicate with node-inspector. child.stderr.on("data", function onData(buffer) { - var match = /debugger listening on port (\d+)/i + var match = /debugger listening on .+:(\d+)\n/i .exec(buffer.toString("utf8")); if (match) { child.stderr.removeListener("data", onData); diff --git a/tools/runners/run-app.js b/tools/runners/run-app.js index d1dbb1852f..26be252981 100644 --- a/tools/runners/run-app.js +++ b/tools/runners/run-app.js @@ -106,7 +106,7 @@ _.extend(AppProcess.prototype, { eachline(self.proc.stderr, 'utf8', async function (line) { if (self.debugPort && - line.indexOf("debugger listening on port ") >= 0) { + line.indexOf("Debugger listening on") >= 0) { Console.enableProgressDisplay(false); return; } From 450c734b8f07bdb68a0324267d07ff5840c3adcd Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 15:50:31 -0700 Subject: [PATCH 042/125] Add `History.md` entries for `node-inspector` and `meteor debug` fixes. --- History.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/History.md b/History.md index c008693784..d177f72254 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,13 @@ what happens when `SIGINT` (Ctrl-C) is received. Read more [here](https://github.com/npm/npm/releases/tag/v4.5.0). +* Fix a regression which prevented us from displaying a helpful banner when + running `meteor debug` because of a change in Node.js. + +* Update `node-inspector` npm to 1.1.1, fixing a problem encountered when trying + to press "Enter" in the inspector console. + [Issue #8469](https://github.com/meteor/meteor/issues/8469) + * The `meteor-babel` npm package has been upgraded to version 0.20.1, and the `reify` npm package has been upgraded to version 0.7.4, fixing [issue #8595](https://github.com/meteor/meteor/issues/8595). From db093ff316e6801b6a98657db054d2afa3c55b57 Mon Sep 17 00:00:00 2001 From: Tomas Brambora Date: Wed, 12 Apr 2017 21:51:35 +1000 Subject: [PATCH 043/125] Fixed Google OAuth user data fetching. --- packages/google-oauth/google_server.js | 47 +++++++++++--------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/packages/google-oauth/google_server.js b/packages/google-oauth/google_server.js index 4b647a37d5..6b9b3f00e5 100644 --- a/packages/google-oauth/google_server.js +++ b/packages/google-oauth/google_server.js @@ -5,34 +5,7 @@ var Accounts = require("meteor/accounts-base").Accounts; Google.whitelistedFields = ['id', 'email', 'verified_email', 'name', 'given_name', 'family_name', 'picture', 'locale', 'timezone', 'gender']; -Accounts.registerLoginHandler(function (request) { - if (request.googleSignIn !== true) { - return; - } - - var res = HTTP.get( - "https://www.googleapis.com/oauth2/v3/tokeninfo", - { headers: { "User-Agent": "Meteor/1.0" }, - params: { id_token: request.idToken }} - ); - - if (res.error) { - throw res.error; - } - - if (res.statusCode === 200 && - res.data.sub === request.userId) { - return Accounts.updateOrCreateUserFromExternalService("google", { - id: request.userId, - idToken: request.idToken, - accessToken: request.accessToken, - email: request.email, - picture: request.imageUrl - }); - } -}); - -OAuth.registerService('google', 2, null, function(query) { +function getServiceData(query) { var response = getTokens(query); var expiresAt = (+new Date) + (1000 * parseInt(response.expiresIn, 10)); var accessToken = response.accessToken; @@ -60,8 +33,26 @@ OAuth.registerService('google', 2, null, function(query) { serviceData: serviceData, options: {profile: {name: identity.name}} }; +} + +Accounts.registerLoginHandler(function (request) { + if (request.googleSignIn !== true) { + return; + } + + const res = getServiceData({code: request.serverAuthCode}); + + return Accounts.updateOrCreateUserFromExternalService("google", _.extend({ + id: request.userId, + idToken: request.idToken, + accessToken: request.accessToken, + email: request.email, + picture: request.imageUrl + }, res.serviceData)); }); +OAuth.registerService('google', 2, null, getServiceData); + // returns an object containing: // - accessToken // - expiresIn: lifetime of token in seconds From 6b44ded1e48323642547e5c855bfbab2fe8fa42d Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 12 Apr 2017 14:20:06 -0400 Subject: [PATCH 044/125] Remove underscore dependency from google-oauth package. --- packages/google-oauth/google_client.js | 41 ++++++++++++++++--------- packages/google-oauth/google_server.js | 40 ++++++++++++++++-------- packages/google-oauth/google_sign-in.js | 14 +++++---- packages/google-oauth/package.js | 5 ++- 4 files changed, 63 insertions(+), 37 deletions(-) diff --git a/packages/google-oauth/google_client.js b/packages/google-oauth/google_client.js index c7b54dccfb..a45c080011 100644 --- a/packages/google-oauth/google_client.js +++ b/packages/google-oauth/google_client.js @@ -1,5 +1,13 @@ var Google = require("./namespace.js"); +var ILLEGAL_PARAMETERS = { + 'response_type': 1, + 'client_id': 1, + 'scope': 1, + 'redirect_uri': 1, + 'state': 1 +}; + // Request Google credentials for the user // @param options {optional} // @param credentialRequestCompleteCallback {Function} Callback function to call on @@ -24,24 +32,26 @@ Google.requestCredential = function (options, credentialRequestCompleteCallback) var credentialToken = Random.secret(); // we need the email scope to get user id from google. - var requiredScope = ['email']; - var scope = ['profile']; - if (options.requestPermissions) - scope = options.requestPermissions; - scope = _.union(scope, requiredScope); + var requiredScopes = { 'email': 1 }; + var scopes = options.requestPermissions || ['profile']; + scopes.forEach(function (scope) { + requiredScopes[scope] = 1; + }); + scopes = Object.keys(requiredScopes); var loginUrlParameters = {}; if (config.loginUrlParameters){ - _.extend(loginUrlParameters, config.loginUrlParameters) + Object.assign(loginUrlParameters, config.loginUrlParameters); } if (options.loginUrlParameters){ - _.extend(loginUrlParameters, options.loginUrlParameters) + Object.assign(loginUrlParameters, options.loginUrlParameters); } - var ILLEGAL_PARAMETERS = ['response_type', 'client_id', 'scope', 'redirect_uri', 'state']; - // validate options keys - _.each(_.keys(loginUrlParameters), function (key) { - if (_.contains(ILLEGAL_PARAMETERS, key)) + + // validate options keys + Object.keys(loginUrlParameters).forEach(function (key) { + if (ILLEGAL_PARAMETERS.hasOwnProperty(key)) { throw new Error("Google.requestCredential: Invalid loginUrlParameter: " + key); + } }); // backwards compatible options @@ -60,16 +70,17 @@ Google.requestCredential = function (options, credentialRequestCompleteCallback) var loginStyle = OAuth._loginStyle('google', config, options); // https://developers.google.com/accounts/docs/OAuth2WebServer#formingtheurl - _.extend(loginUrlParameters, { + Object.assign(loginUrlParameters, { "response_type": "code", "client_id": config.clientId, - "scope": scope.join(' '), // space delimited + "scope": scopes.join(' '), // space delimited "redirect_uri": OAuth._redirectUri('google', config), "state": OAuth._stateParam(loginStyle, credentialToken, options.redirectUrl) }); var loginUrl = 'https://accounts.google.com/o/oauth2/auth?' + - _.map(loginUrlParameters, function(value, param){ - return encodeURIComponent(param) + '=' + encodeURIComponent(value); + Object.keys(loginUrlParameters).map(function (param) { + return encodeURIComponent(param) + '=' + + encodeURIComponent(loginUrlParameters[param]); }).join("&"); OAuth.launchLogin({ diff --git a/packages/google-oauth/google_server.js b/packages/google-oauth/google_server.js index 6b9b3f00e5..c430bd5637 100644 --- a/packages/google-oauth/google_server.js +++ b/packages/google-oauth/google_server.js @@ -1,5 +1,6 @@ var Google = require("./namespace.js"); var Accounts = require("meteor/accounts-base").Accounts; +var hasOwn = Object.prototype.hasOwnProperty; // https://developers.google.com/accounts/docs/OAuth2Login#userinfocall Google.whitelistedFields = ['id', 'email', 'verified_email', 'name', 'given_name', @@ -20,8 +21,14 @@ function getServiceData(query) { scope: scopes }; - var fields = _.pick(identity, Google.whitelistedFields); - _.extend(serviceData, fields); + var fields = Object.create(null); + Google.whitelistedFields.forEach(function (name) { + if (hasOwn.call(identity, name)) { + fields[name] = identity[name]; + } + }); + + Object.assign(serviceData, fields); // only set the token in serviceData if it's there. this ensures // that we don't lose old ones (since we only get this on the first @@ -40,15 +47,16 @@ Accounts.registerLoginHandler(function (request) { return; } - const res = getServiceData({code: request.serverAuthCode}); - - return Accounts.updateOrCreateUserFromExternalService("google", _.extend({ + return Accounts.updateOrCreateUserFromExternalService("google", { id: request.userId, idToken: request.idToken, accessToken: request.accessToken, email: request.email, - picture: request.imageUrl - }, res.serviceData)); + picture: request.imageUrl, + ...getServiceData({ + code: request.serverAuthCode + }).serviceData, + }); }); OAuth.registerService('google', 2, null, getServiceData); @@ -73,8 +81,10 @@ var getTokens = function (query) { grant_type: 'authorization_code' }}); } catch (err) { - throw _.extend(new Error("Failed to complete OAuth handshake with Google. " + err.message), - {response: err.response}); + throw Object.assign( + new Error("Failed to complete OAuth handshake with Google. " + err.message), + { response: err.response } + ); } if (response.data.error) { // if the http response was a json object with an error attribute @@ -95,8 +105,10 @@ var getIdentity = function (accessToken) { "https://www.googleapis.com/oauth2/v1/userinfo", {params: {access_token: accessToken}}).data; } catch (err) { - throw _.extend(new Error("Failed to fetch identity from Google. " + err.message), - {response: err.response}); + throw Object.assign( + new Error("Failed to fetch identity from Google. " + err.message), + { response: err.response } + ); } }; @@ -106,8 +118,10 @@ var getScopes = function (accessToken) { "https://www.googleapis.com/oauth2/v1/tokeninfo", {params: {access_token: accessToken}}).data.scope.split(' '); } catch (err) { - throw _.extend(new Error("Failed to fetch tokeninfo from Google. " + err.message), - {response: err.response}); + throw Object.assign( + new Error("Failed to fetch tokeninfo from Google. " + err.message), + { response: err.response } + ); } }; diff --git a/packages/google-oauth/google_sign-in.js b/packages/google-oauth/google_sign-in.js index 4d21403264..3ba3a54ea8 100644 --- a/packages/google-oauth/google_sign-in.js +++ b/packages/google-oauth/google_sign-in.js @@ -59,12 +59,14 @@ exports.signIn = Google.signIn = function (options, callback) { function getScopes(options) { // we need the email scope to get user id from google. - var requiredScopes = ['email']; - var scopes = ['profile']; - if (options && options.requestPermissions) { - scopes = options.requestPermissions; - } - return _.union(scopes, requiredScopes); + var requiredScopes = { 'email': 1 }; + var scopes = options.requestPermissions || ['profile']; + + scopes.forEach(function (scope) { + requiredScopes[scope] = 1; + }); + + return Object.keys(requiredScopes); } exports.signOut = Google.signOut = function () { diff --git a/packages/google-oauth/package.js b/packages/google-oauth/package.js index d977bb6d16..4432aff495 100644 --- a/packages/google-oauth/package.js +++ b/packages/google-oauth/package.js @@ -14,12 +14,11 @@ Cordova.depends({ }); Package.onUse(function(api) { - api.use("modules"); - api.use("promise"); + api.use("ecmascript"); api.use('oauth2', ['client', 'server']); api.use('oauth', ['client', 'server']); api.use('http', ['server']); - api.use(['underscore', 'service-configuration'], ['client', 'server']); + api.use('service-configuration'); api.use('random', 'client'); api.addFiles('google_server.js', 'server'); From a954efc2f296c1d9f1e852aab8e6797970b8ddeb Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 12 Apr 2017 15:20:43 -0400 Subject: [PATCH 045/125] Bump google-oauth package version to 1.2.2. --- packages/google-oauth/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-oauth/package.js b/packages/google-oauth/package.js index 4432aff495..ea533526fa 100644 --- a/packages/google-oauth/package.js +++ b/packages/google-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Google OAuth flow", - version: "1.2.1" + version: "1.2.2" }); var cordovaPluginGooglePlusURL = From 91636439062c59ca71a54652f5dd16b1b02e2357 Mon Sep 17 00:00:00 2001 From: Sudhanshu Date: Tue, 28 Mar 2017 15:35:46 +0530 Subject: [PATCH 046/125] Add the field name in the error When Minimongo throws an error, most of the times, the field names are not present, making it a bit difficult to debug. Updated the error messages to include the field name for which it threw the error. --- packages/minimongo/modify.js | 60 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/minimongo/modify.js b/packages/minimongo/modify.js index e5a81ba8f6..e595d82cab 100644 --- a/packages/minimongo/modify.js +++ b/packages/minimongo/modify.js @@ -185,20 +185,20 @@ var MODIFIERS = { $currentDate: function (target, field, arg) { if (typeof arg === "object" && arg.hasOwnProperty("$type")) { if (arg.$type !== "date") { - throw MinimongoError("Minimongo does currently only support the date type in $currentDate modifiers"); + throw MinimongoError("Minimongo does currently only support the date type in $currentDate modifiers: " + field); } } else if (arg !== true) { - throw MinimongoError("Invalid $currentDate modifier"); + throw MinimongoError("Invalid $currentDate modifier: " + field); } target[field] = new Date(); }, $min: function (target, field, arg) { if (typeof arg !== "number") { - throw MinimongoError("Modifier $min allowed for numbers only"); + throw MinimongoError("Modifier $min allowed for numbers only: " + field); } if (field in target) { if (typeof target[field] !== "number") { - throw MinimongoError("Cannot apply $min modifier to non-number"); + throw MinimongoError("Cannot apply $min modifier to non-number: " + field); } if (target[field] > arg) { target[field] = arg; @@ -209,11 +209,11 @@ var MODIFIERS = { }, $max: function (target, field, arg) { if (typeof arg !== "number") { - throw MinimongoError("Modifier $max allowed for numbers only"); + throw MinimongoError("Modifier $max allowed for numbers only: " + field); } if (field in target) { if (typeof target[field] !== "number") { - throw MinimongoError("Cannot apply $max modifier to non-number"); + throw MinimongoError("Cannot apply $max modifier to non-number: " + field); } if (target[field] < arg) { target[field] = arg; @@ -224,10 +224,10 @@ var MODIFIERS = { }, $inc: function (target, field, arg) { if (typeof arg !== "number") - throw MinimongoError("Modifier $inc allowed for numbers only"); + throw MinimongoError("Modifier $inc allowed for numbers only: " + field); if (field in target) { if (typeof target[field] !== "number") - throw MinimongoError("Cannot apply $inc modifier to non-number"); + throw MinimongoError("Cannot apply $inc modifier to non-number: " + field); target[field] += arg; } else { target[field] = arg; @@ -235,12 +235,12 @@ var MODIFIERS = { }, $set: function (target, field, arg) { if (!_.isObject(target)) { // not an array or an object - var e = MinimongoError("Cannot set property on non-object field"); + var e = MinimongoError("Cannot set property on non-object field: " + field); e.setPropertyError = true; throw e; } if (target === null) { - var e = MinimongoError("Cannot set property on null"); + var e = MinimongoError("Cannot set property on null: " + field); e.setPropertyError = true; throw e; } @@ -267,7 +267,7 @@ var MODIFIERS = { if (target[field] === undefined) target[field] = []; if (!(target[field] instanceof Array)) - throw MinimongoError("Cannot apply $push modifier to non-array"); + throw MinimongoError("Cannot apply $push modifier to non-array: " + field); if (!(arg && arg.$each)) { // Simple mode: not $each @@ -278,16 +278,16 @@ var MODIFIERS = { // Fancy mode: $each (and maybe $slice and $sort and $position) var toPush = arg.$each; if (!(toPush instanceof Array)) - throw MinimongoError("$each must be an array"); + throw MinimongoError("$each must be an array: " + field); // Parse $position var position = undefined; if ('$position' in arg) { if (typeof arg.$position !== "number") - throw MinimongoError("$position must be a numeric value"); + throw MinimongoError("$position must be a numeric value: " + field); // XXX should check to make sure integer if (arg.$position < 0) - throw MinimongoError("$position in $push must be zero or positive"); + throw MinimongoError("$position in $push must be zero or positive: " + field); position = arg.$position; } @@ -295,10 +295,10 @@ var MODIFIERS = { var slice = undefined; if ('$slice' in arg) { if (typeof arg.$slice !== "number") - throw MinimongoError("$slice must be a numeric value"); + throw MinimongoError("$slice must be a numeric value: " + field); // XXX should check to make sure integer if (arg.$slice > 0) - throw MinimongoError("$slice in $push must be zero or negative"); + throw MinimongoError("$slice in $push must be zero or negative: " + field); slice = arg.$slice; } @@ -306,7 +306,7 @@ var MODIFIERS = { var sortFunction = undefined; if (arg.$sort) { if (slice === undefined) - throw MinimongoError("$sort requires $slice to be present"); + throw MinimongoError("$sort requires $slice to be present: " + field); // XXX this allows us to use a $sort whose value is an array, but that's // actually an extension of the Node driver, so it won't work // server-side. Could be confusing! @@ -315,7 +315,7 @@ var MODIFIERS = { for (var i = 0; i < toPush.length; i++) { if (LocalCollection._f._type(toPush[i]) !== 3) { throw MinimongoError("$push like modifiers using $sort " + - "require all elements to be objects"); + "require all elements to be objects: " + field); } } } @@ -350,7 +350,7 @@ var MODIFIERS = { if (x === undefined) target[field] = arg; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pushAll modifier to non-array"); + throw MinimongoError("Cannot apply $pushAll modifier to non-array: " + field); else { for (var i = 0; i < arg.length; i++) x.push(arg[i]); @@ -371,7 +371,7 @@ var MODIFIERS = { if (x === undefined) target[field] = values; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $addToSet modifier to non-array"); + throw MinimongoError("Cannot apply $addToSet modifier to non-array: " + field); else { _.each(values, function (value) { for (var i = 0; i < x.length; i++) @@ -388,7 +388,7 @@ var MODIFIERS = { if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pop modifier to non-array"); + throw MinimongoError("Cannot apply $pop modifier to non-array: " + field); else { if (typeof arg === 'number' && arg < 0) x.splice(0, 1); @@ -403,7 +403,7 @@ var MODIFIERS = { if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array"); + throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array: " + field); else { var out = []; if (arg != null && typeof arg === "object" && !(arg instanceof Array)) { @@ -430,14 +430,14 @@ var MODIFIERS = { }, $pullAll: function (target, field, arg) { if (!(typeof arg === "object" && arg instanceof Array)) - throw MinimongoError("Modifier $pushAll/pullAll allowed for arrays only"); + throw MinimongoError("Modifier $pushAll/pullAll allowed for arrays only: " + field); if (target === undefined) return; var x = target[field]; if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array"); + throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array: " + field); else { var out = []; for (var i = 0; i < x.length; i++) { @@ -457,15 +457,15 @@ var MODIFIERS = { $rename: function (target, field, arg, keypath, doc) { if (keypath === arg) // no idea why mongo has this restriction.. - throw MinimongoError("$rename source must differ from target"); + throw MinimongoError("$rename source must differ from target: " + field); if (target === null) - throw MinimongoError("$rename source field invalid"); + throw MinimongoError("$rename source field invalid: " + field); if (typeof arg !== "string") - throw MinimongoError("$rename target must be a string"); + throw MinimongoError("$rename target must be a string: " + field); if (arg.indexOf('\0') > -1) { // Null bytes are not allowed in Mongo field names // https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names - throw MinimongoError("The 'to' field for $rename cannot contain an embedded null byte"); + throw MinimongoError("The 'to' field for $rename cannot contain an embedded null byte: " + field); } if (target === undefined) return; @@ -475,13 +475,13 @@ var MODIFIERS = { var keyparts = arg.split('.'); var target2 = findModTarget(doc, keyparts, {forbidArray: true}); if (target2 === null) - throw MinimongoError("$rename target field invalid"); + throw MinimongoError("$rename target field invalid: " + field); var field2 = keyparts.pop(); target2[field2] = v; }, $bit: function (target, field, arg) { // XXX mongo only supports $bit on integers, and we only support // native javascript numbers (doubles) so far, so we can't support $bit - throw MinimongoError("$bit is not supported"); + throw MinimongoError("$bit is not supported: " + field); } }; From eedf8bddbf4bc6e059d751674be2ca81826ea296 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Fri, 7 Apr 2017 17:06:13 +0300 Subject: [PATCH 047/125] Change `MinimongoError` to accept `field` in a new `options` parameter. This allows the field name to be dynamically introduced into the error message. Follows-up on meteor/meteor#8529. --- packages/minimongo/minimongo.js | 6 ++- packages/minimongo/minimongo_tests.js | 16 ++++++ packages/minimongo/modify.js | 78 ++++++++++++++++----------- packages/minimongo/package.js | 1 + 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js index f79f2d4bc1..312c9e4581 100644 --- a/packages/minimongo/minimongo.js +++ b/packages/minimongo/minimongo.js @@ -40,7 +40,11 @@ Minimongo = {}; // Use it to export private functions to test in Tinytest. MinimongoTest = {}; -MinimongoError = function (message) { +MinimongoError = function (message, options={}) { + if (typeof message === "string" && options.field) { + message += ` for field '${options.field}'`; + } + var e = new Error(message); e.name = "MinimongoError"; return e; diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 69e728448e..9edc47c52e 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -163,6 +163,22 @@ Tinytest.add("minimongo - basics", function (test) { }); +Tinytest.add("minimongo - error - no options", function (test) { + try { + throw MinimongoError("Not fun to have errors"); + } catch (e) { + test.equal(e.message, "Not fun to have errors"); + } +}); + +Tinytest.add("minimongo - error - with field", function (test) { + try { + throw MinimongoError("Cats are no fun", { field: "mice" }); + } catch (e) { + test.equal(e.message, "Cats are no fun for field 'mice'"); + } +}); + Tinytest.add("minimongo - cursors", function (test) { var c = new LocalCollection(); var res; diff --git a/packages/minimongo/modify.js b/packages/minimongo/modify.js index e595d82cab..7074482ee6 100644 --- a/packages/minimongo/modify.js +++ b/packages/minimongo/modify.js @@ -185,20 +185,24 @@ var MODIFIERS = { $currentDate: function (target, field, arg) { if (typeof arg === "object" && arg.hasOwnProperty("$type")) { if (arg.$type !== "date") { - throw MinimongoError("Minimongo does currently only support the date type in $currentDate modifiers: " + field); + throw MinimongoError( + "Minimongo does currently only support the date type " + + "in $currentDate modifiers", + { field }); } } else if (arg !== true) { - throw MinimongoError("Invalid $currentDate modifier: " + field); + throw MinimongoError("Invalid $currentDate modifier", { field }); } target[field] = new Date(); }, $min: function (target, field, arg) { if (typeof arg !== "number") { - throw MinimongoError("Modifier $min allowed for numbers only: " + field); + throw MinimongoError("Modifier $min allowed for numbers only", { field }); } if (field in target) { if (typeof target[field] !== "number") { - throw MinimongoError("Cannot apply $min modifier to non-number: " + field); + throw MinimongoError( + "Cannot apply $min modifier to non-number", { field }); } if (target[field] > arg) { target[field] = arg; @@ -209,11 +213,12 @@ var MODIFIERS = { }, $max: function (target, field, arg) { if (typeof arg !== "number") { - throw MinimongoError("Modifier $max allowed for numbers only: " + field); + throw MinimongoError("Modifier $max allowed for numbers only", { field }); } if (field in target) { if (typeof target[field] !== "number") { - throw MinimongoError("Cannot apply $max modifier to non-number: " + field); + throw MinimongoError( + "Cannot apply $max modifier to non-number", { field }); } if (target[field] < arg) { target[field] = arg; @@ -224,10 +229,11 @@ var MODIFIERS = { }, $inc: function (target, field, arg) { if (typeof arg !== "number") - throw MinimongoError("Modifier $inc allowed for numbers only: " + field); + throw MinimongoError("Modifier $inc allowed for numbers only", { field }); if (field in target) { if (typeof target[field] !== "number") - throw MinimongoError("Cannot apply $inc modifier to non-number: " + field); + throw MinimongoError( + "Cannot apply $inc modifier to non-number", { field }); target[field] += arg; } else { target[field] = arg; @@ -235,12 +241,13 @@ var MODIFIERS = { }, $set: function (target, field, arg) { if (!_.isObject(target)) { // not an array or an object - var e = MinimongoError("Cannot set property on non-object field: " + field); + var e = MinimongoError( + "Cannot set property on non-object field", { field }); e.setPropertyError = true; throw e; } if (target === null) { - var e = MinimongoError("Cannot set property on null: " + field); + var e = MinimongoError("Cannot set property on null", { field }); e.setPropertyError = true; throw e; } @@ -267,7 +274,8 @@ var MODIFIERS = { if (target[field] === undefined) target[field] = []; if (!(target[field] instanceof Array)) - throw MinimongoError("Cannot apply $push modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $push modifier to non-array", { field }); if (!(arg && arg.$each)) { // Simple mode: not $each @@ -278,16 +286,17 @@ var MODIFIERS = { // Fancy mode: $each (and maybe $slice and $sort and $position) var toPush = arg.$each; if (!(toPush instanceof Array)) - throw MinimongoError("$each must be an array: " + field); + throw MinimongoError("$each must be an array", { field }); // Parse $position var position = undefined; if ('$position' in arg) { if (typeof arg.$position !== "number") - throw MinimongoError("$position must be a numeric value: " + field); + throw MinimongoError("$position must be a numeric value", { field }); // XXX should check to make sure integer if (arg.$position < 0) - throw MinimongoError("$position in $push must be zero or positive: " + field); + throw MinimongoError( + "$position in $push must be zero or positive", { field }); position = arg.$position; } @@ -295,10 +304,11 @@ var MODIFIERS = { var slice = undefined; if ('$slice' in arg) { if (typeof arg.$slice !== "number") - throw MinimongoError("$slice must be a numeric value: " + field); + throw MinimongoError("$slice must be a numeric value", { field }); // XXX should check to make sure integer if (arg.$slice > 0) - throw MinimongoError("$slice in $push must be zero or negative: " + field); + throw MinimongoError( + "$slice in $push must be zero or negative", { field }); slice = arg.$slice; } @@ -306,7 +316,7 @@ var MODIFIERS = { var sortFunction = undefined; if (arg.$sort) { if (slice === undefined) - throw MinimongoError("$sort requires $slice to be present: " + field); + throw MinimongoError("$sort requires $slice to be present", { field }); // XXX this allows us to use a $sort whose value is an array, but that's // actually an extension of the Node driver, so it won't work // server-side. Could be confusing! @@ -315,7 +325,7 @@ var MODIFIERS = { for (var i = 0; i < toPush.length; i++) { if (LocalCollection._f._type(toPush[i]) !== 3) { throw MinimongoError("$push like modifiers using $sort " + - "require all elements to be objects: " + field); + "require all elements to be objects", { field }); } } } @@ -350,7 +360,8 @@ var MODIFIERS = { if (x === undefined) target[field] = arg; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pushAll modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $pushAll modifier to non-array", { field }); else { for (var i = 0; i < arg.length; i++) x.push(arg[i]); @@ -371,7 +382,8 @@ var MODIFIERS = { if (x === undefined) target[field] = values; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $addToSet modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $addToSet modifier to non-array", { field }); else { _.each(values, function (value) { for (var i = 0; i < x.length; i++) @@ -388,7 +400,8 @@ var MODIFIERS = { if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pop modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $pop modifier to non-array", { field }); else { if (typeof arg === 'number' && arg < 0) x.splice(0, 1); @@ -403,7 +416,8 @@ var MODIFIERS = { if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $pull/pullAll modifier to non-array", { field }); else { var out = []; if (arg != null && typeof arg === "object" && !(arg instanceof Array)) { @@ -430,14 +444,16 @@ var MODIFIERS = { }, $pullAll: function (target, field, arg) { if (!(typeof arg === "object" && arg instanceof Array)) - throw MinimongoError("Modifier $pushAll/pullAll allowed for arrays only: " + field); + throw MinimongoError( + "Modifier $pushAll/pullAll allowed for arrays only", { field }); if (target === undefined) return; var x = target[field]; if (x === undefined) return; else if (!(x instanceof Array)) - throw MinimongoError("Cannot apply $pull/pullAll modifier to non-array: " + field); + throw MinimongoError( + "Cannot apply $pull/pullAll modifier to non-array", { field }); else { var out = []; for (var i = 0; i < x.length; i++) { @@ -457,15 +473,17 @@ var MODIFIERS = { $rename: function (target, field, arg, keypath, doc) { if (keypath === arg) // no idea why mongo has this restriction.. - throw MinimongoError("$rename source must differ from target: " + field); + throw MinimongoError("$rename source must differ from target", { field }); if (target === null) - throw MinimongoError("$rename source field invalid: " + field); + throw MinimongoError("$rename source field invalid", { field }); if (typeof arg !== "string") - throw MinimongoError("$rename target must be a string: " + field); + throw MinimongoError("$rename target must be a string", { field }); if (arg.indexOf('\0') > -1) { // Null bytes are not allowed in Mongo field names // https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names - throw MinimongoError("The 'to' field for $rename cannot contain an embedded null byte: " + field); + throw MinimongoError( + "The 'to' field for $rename cannot contain an embedded null byte", + { field }); } if (target === undefined) return; @@ -475,13 +493,13 @@ var MODIFIERS = { var keyparts = arg.split('.'); var target2 = findModTarget(doc, keyparts, {forbidArray: true}); if (target2 === null) - throw MinimongoError("$rename target field invalid: " + field); + throw MinimongoError("$rename target field invalid", { field }); var field2 = keyparts.pop(); target2[field2] = v; }, $bit: function (target, field, arg) { // XXX mongo only supports $bit on integers, and we only support // native javascript numbers (doubles) so far, so we can't support $bit - throw MinimongoError("$bit is not supported: " + field); + throw MinimongoError("$bit is not supported", { field }); } }; diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index e4353c687a..d490228a29 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -7,6 +7,7 @@ Package.onUse(function (api) { api.export('LocalCollection'); api.export('Minimongo'); api.export('MinimongoTest', { testOnly: true }); + api.export('MinimongoError', { testOnly: true }); api.use([ 'underscore', 'ejson', From bc7cc19d41154e8fe33e1412e91a65fded24ee38 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 12 Apr 2017 15:25:12 -0400 Subject: [PATCH 048/125] Bump minimongo package version to 1.0.22. --- packages/minimongo/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index d490228a29..d89b5f03df 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.0.21' + version: '1.0.22' }); Package.onUse(function (api) { From 0d8e58b09df930d50fbb1f4647c0e0ce9cf573fa Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 02:35:01 -0400 Subject: [PATCH 049/125] Upgrade meteor-babel and reify to fix #8595. (#8599) * Upgrade meteor-babel to version 0.20.1 and reify to 0.7.4. * Bump $BUNDLE_VERSION to 4.7.25 before rebuilding dev bundle. --- History.md | 4 + meteor | 2 +- .../.npm/package/npm-shrinkwrap.json | 202 +++++++++--------- packages/babel-compiler/package.js | 4 +- .../modules/.npm/package/npm-shrinkwrap.json | 22 +- packages/modules/package.js | 4 +- scripts/dev-bundle-tool-package.js | 2 +- 7 files changed, 112 insertions(+), 128 deletions(-) diff --git a/History.md b/History.md index c422428108..210c44c613 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,9 @@ ## v.NEXT +* The `meteor-babel` npm package has been upgraded to version 0.20.1, and + the `reify` npm package has been upgraded to version 0.7.4, fixing + [issue #8595](https://github.com/meteor/meteor/issues/8595). + ## v1.4.4.1, 2017-04-07 * A change in Meteor 1.4.4 to remove "garbage" directories asynchronously diff --git a/meteor b/meteor index 886256dfb7..cc0116c16a 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.7.23 +BUNDLE_VERSION=4.7.25 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index 214f819c77..7bd00f4cd2 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "acorn": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz", - "from": "acorn@>=4.0.5 <4.1.0" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "from": "acorn@>=5.0.0 <5.1.0" }, "ansi-regex": { "version": "2.1.1", @@ -21,29 +21,29 @@ "from": "babel-code-frame@>=6.22.0 <7.0.0" }, "babel-core": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.1.tgz", "from": "babel-core@>=6.22.1 <7.0.0" }, "babel-generator": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.0.tgz", - "from": "babel-generator@>=6.24.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.1.tgz", + "from": "babel-generator@>=6.24.1 <7.0.0" }, "babel-helper-builder-react-jsx": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.23.0.tgz", - "from": "babel-helper-builder-react-jsx@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz", + "from": "babel-helper-builder-react-jsx@>=6.24.1 <7.0.0" }, "babel-helper-call-delegate": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz", - "from": "babel-helper-call-delegate@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "from": "babel-helper-call-delegate@>=6.24.1 <7.0.0" }, "babel-helper-define-map": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.23.0.tgz", - "from": "babel-helper-define-map@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz", + "from": "babel-helper-define-map@>=6.24.1 <7.0.0" }, "babel-helper-evaluate-path": { "version": "0.0.3", @@ -56,19 +56,19 @@ "from": "babel-helper-flip-expressions@>=0.0.2 <0.0.3" }, "babel-helper-function-name": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz", - "from": "babel-helper-function-name@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "from": "babel-helper-function-name@>=6.24.1 <7.0.0" }, "babel-helper-get-function-arity": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz", - "from": "babel-helper-get-function-arity@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "from": "babel-helper-get-function-arity@>=6.24.1 <7.0.0" }, "babel-helper-hoist-variables": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.22.0.tgz", - "from": "babel-helper-hoist-variables@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "from": "babel-helper-hoist-variables@>=6.24.1 <7.0.0" }, "babel-helper-is-nodes-equiv": { "version": "0.0.1", @@ -86,14 +86,14 @@ "from": "babel-helper-mark-eval-scopes@>=0.0.3 <0.0.4" }, "babel-helper-optimise-call-expression": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.23.0.tgz", - "from": "babel-helper-optimise-call-expression@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "from": "babel-helper-optimise-call-expression@>=6.24.1 <7.0.0" }, "babel-helper-regex": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.22.0.tgz", - "from": "babel-helper-regex@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz", + "from": "babel-helper-regex@>=6.24.1 <7.0.0" }, "babel-helper-remove-or-void": { "version": "0.0.1", @@ -101,9 +101,9 @@ "from": "babel-helper-remove-or-void@>=0.0.1 <0.0.2" }, "babel-helper-replace-supers": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.23.0.tgz", - "from": "babel-helper-replace-supers@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "from": "babel-helper-replace-supers@>=6.24.1 <7.0.0" }, "babel-helper-to-multiple-sequence-expressions": { "version": "0.0.3", @@ -111,9 +111,9 @@ "from": "babel-helper-to-multiple-sequence-expressions@>=0.0.3 <0.0.4" }, "babel-helpers": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.23.0.tgz", - "from": "babel-helpers@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "from": "babel-helpers@>=6.24.1 <7.0.0" }, "babel-messages": { "version": "6.23.0", @@ -131,8 +131,8 @@ "from": "babel-plugin-minify-constant-folding@>=0.0.4 <0.0.5", "dependencies": { "jsesc": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.4.0.tgz", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.0.tgz", "from": "jsesc@>=2.4.0 <3.0.0" } } @@ -235,18 +235,18 @@ "from": "babel-plugin-transform-es2015-block-scoped-functions@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-block-scoping": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz", "from": "babel-plugin-transform-es2015-block-scoping@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-classes": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "from": "babel-plugin-transform-es2015-classes@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-computed-properties": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "from": "babel-plugin-transform-es2015-computed-properties@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-destructuring": { @@ -265,28 +265,28 @@ "from": "babel-plugin-transform-es2015-literals@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz", "from": "babel-plugin-transform-es2015-modules-commonjs@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-modules-reify": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.6.2.tgz", - "from": "babel-plugin-transform-es2015-modules-reify@>=0.6.0 <0.7.0" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.7.0.tgz", + "from": "babel-plugin-transform-es2015-modules-reify@>=0.7.0 <0.8.0" }, "babel-plugin-transform-es2015-object-super": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "from": "babel-plugin-transform-es2015-object-super@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-parameters": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "from": "babel-plugin-transform-es2015-parameters@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "from": "babel-plugin-transform-es2015-shorthand-properties@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-spread": { @@ -295,8 +295,8 @@ "from": "babel-plugin-transform-es2015-spread@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "from": "babel-plugin-transform-es2015-sticky-regex@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-template-literals": { @@ -310,8 +310,8 @@ "from": "babel-plugin-transform-es2015-typeof-symbol@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "from": "babel-plugin-transform-es2015-unicode-regex@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es3-property-literals": { @@ -360,9 +360,9 @@ "from": "babel-plugin-transform-react-display-name@>=6.23.0 <7.0.0" }, "babel-plugin-transform-react-jsx": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.23.0.tgz", - "from": "babel-plugin-transform-react-jsx@>=6.23.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "from": "babel-plugin-transform-react-jsx@>=6.24.1 <7.0.0" }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", @@ -375,8 +375,8 @@ "from": "babel-plugin-transform-react-jsx-source@>=6.22.0 <7.0.0" }, "babel-plugin-transform-regenerator": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz", "from": "babel-plugin-transform-regenerator@>=6.22.0 <7.0.0" }, "babel-plugin-transform-regexp-constructors": { @@ -410,9 +410,9 @@ "from": "babel-plugin-transform-simplify-comparison-operators@>=6.8.1 <7.0.0" }, "babel-plugin-transform-strict-mode": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.22.0.tgz", - "from": "babel-plugin-transform-strict-mode@>=6.22.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "from": "babel-plugin-transform-strict-mode@>=6.24.1 <7.0.0" }, "babel-plugin-transform-undefined-to-void": { "version": "6.8.0", @@ -430,19 +430,19 @@ "from": "babel-preset-flow@>=6.23.0 <7.0.0" }, "babel-preset-meteor": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-6.25.0.tgz", - "from": "babel-preset-meteor@6.25.0" + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-6.26.0.tgz", + "from": "babel-preset-meteor@6.26.0" }, "babel-preset-react": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "from": "babel-preset-react@>=6.22.0 <7.0.0" }, "babel-register": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.0.tgz", - "from": "babel-register@>=6.24.0 <7.0.0" + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", + "from": "babel-register@>=6.24.1 <7.0.0" }, "babel-runtime": { "version": "6.23.0", @@ -450,18 +450,18 @@ "from": "babel-runtime@>=6.22.0 <7.0.0" }, "babel-template": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", "from": "babel-template@>=6.22.0 <7.0.0" }, "babel-traverse": { - "version": "6.23.1", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.23.1.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", "from": "babel-traverse@>=6.22.1 <7.0.0" }, "babel-types": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.23.0.tgz", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", "from": "babel-types@>=6.22.0 <7.0.0" }, "babylon": { @@ -475,8 +475,8 @@ "from": "balanced-match@>=0.4.1 <0.5.0" }, "brace-expansion": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", "from": "brace-expansion@>=1.0.0 <2.0.0" }, "chalk": { @@ -490,8 +490,8 @@ "from": "concat-map@0.0.1" }, "convert-source-map": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.4.0.tgz", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", "from": "convert-source-map@>=1.3.0 <2.0.0" }, "core-js": { @@ -579,15 +579,10 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", "from": "loose-envify@>=1.0.0 <2.0.0" }, - "magic-string": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.19.0.tgz", - "from": "magic-string@>=0.19.0 <0.20.0" - }, "meteor-babel": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.19.1.tgz", - "from": "meteor-babel@0.19.1" + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.0.tgz", + "from": "meteor-babel@0.20.0" }, "meteor-babel-helpers": { "version": "0.0.3", @@ -650,9 +645,9 @@ "from": "regenerator-runtime@>=0.10.0 <0.11.0" }, "regenerator-transform": { - "version": "0.9.8", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.8.tgz", - "from": "regenerator-transform@0.9.8" + "version": "0.9.11", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.11.tgz", + "from": "regenerator-transform@0.9.11" }, "regexpu-core": { "version": "2.0.0", @@ -677,9 +672,9 @@ } }, "reify": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.6.6.tgz", - "from": "reify@>=0.6.2 <0.7.0" + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz", + "from": "reify@>=0.7.2 <0.8.0" }, "repeating": { "version": "2.0.1", @@ -720,11 +715,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "from": "trim-right@>=1.0.1 <2.0.0" - }, - "vlq": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.1.tgz", - "from": "vlq@>=0.2.1 <0.3.0" } } } diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index 44bc595b9c..dbd098e545 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,11 +6,11 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.18.1' + version: '6.18.2' }); Npm.depends({ - 'meteor-babel': '0.19.1' + 'meteor-babel': '0.20.1' }); Package.onUse(function (api) { diff --git a/packages/modules/.npm/package/npm-shrinkwrap.json b/packages/modules/.npm/package/npm-shrinkwrap.json index 0ec396bdbd..20c76d7a1d 100644 --- a/packages/modules/.npm/package/npm-shrinkwrap.json +++ b/packages/modules/.npm/package/npm-shrinkwrap.json @@ -1,24 +1,14 @@ { "dependencies": { "acorn": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz", - "from": "acorn@>=4.0.5 <4.1.0" - }, - "magic-string": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.19.0.tgz", - "from": "magic-string@>=0.19.0 <0.20.0" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "from": "acorn@>=5.0.0 <5.1.0" }, "reify": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.6.6.tgz", - "from": "reify@0.6.6" - }, - "vlq": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.1.tgz", - "from": "vlq@>=0.2.1 <0.3.0" + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz", + "from": "reify@0.7.4" } } } diff --git a/packages/modules/package.js b/packages/modules/package.js index 1153f2f9cb..49e7a97eae 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,12 +1,12 @@ Package.describe({ name: "modules", - version: "0.8.1", + version: "0.8.2", summary: "CommonJS module system", documentation: "README.md" }); Npm.depends({ - reify: "0.6.6" + reify: "0.7.4" }); Package.onUse(function(api) { diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index f7d2ed362e..9d8d0ec578 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -14,7 +14,7 @@ var packageJson = { npm: "4.4.4", "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", - "meteor-babel": "0.19.1", + "meteor-babel": "0.20.1", "meteor-promise": "0.8.0", fibers: "1.0.15", promise: "7.1.1", From 708bbe4991dc53299d7e59269176cb18bd91f5e8 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 02:36:37 -0400 Subject: [PATCH 050/125] Update npm-shrinkwrap.json for babel-compiler package. --- packages/babel-compiler/.npm/package/npm-shrinkwrap.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index 7bd00f4cd2..f297b0adf2 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -580,9 +580,9 @@ "from": "loose-envify@>=1.0.0 <2.0.0" }, "meteor-babel": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.0.tgz", - "from": "meteor-babel@0.20.0" + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.1.tgz", + "from": "meteor-babel@0.20.1" }, "meteor-babel-helpers": { "version": "0.0.3", From 0d1cf9e7ed4f9b86e34c8b332ef742f970cbc13a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 02:38:20 -0400 Subject: [PATCH 051/125] Bump ecmascript package version to 0.7.3. Bumping this version is necessary after upgrading babel-compiler since ecmascript registers a compiler plugin that uses babel-compiler. --- packages/ecmascript/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index 4c27300bbe..b4b84a7c89 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.7.2', + version: '0.7.3', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); From d5ba2a1a37875fb5f415edd4a6f41031f58038d0 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 14 Apr 2017 18:11:06 -0400 Subject: [PATCH 052/125] Use tokens from Google Sign-In instead of calling getTokens. (#8604) * Use tokens from Google Sign-In instead of calling getTokens. Follow-up to https://github.com/meteor/meteor/pull/8588. * Bump google-oauth package version to 1.2.3. --- packages/google-oauth/google_server.js | 40 +++++++++++++++++--------- packages/google-oauth/package.js | 2 +- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/packages/google-oauth/google_server.js b/packages/google-oauth/google_server.js index c430bd5637..871c9c2ee8 100644 --- a/packages/google-oauth/google_server.js +++ b/packages/google-oauth/google_server.js @@ -6,21 +6,22 @@ var hasOwn = Object.prototype.hasOwnProperty; Google.whitelistedFields = ['id', 'email', 'verified_email', 'name', 'given_name', 'family_name', 'picture', 'locale', 'timezone', 'gender']; -function getServiceData(query) { - var response = getTokens(query); - var expiresAt = (+new Date) + (1000 * parseInt(response.expiresIn, 10)); - var accessToken = response.accessToken; - var idToken = response.idToken; +function getServiceDataFromTokens(tokens) { + var accessToken = tokens.accessToken; + var idToken = tokens.idToken; var scopes = getScopes(accessToken); var identity = getIdentity(accessToken); - var serviceData = { accessToken: accessToken, idToken: idToken, - expiresAt: expiresAt, scope: scopes }; + if (hasOwn.call(tokens, "expiresAt")) { + serviceData.expiresAt = + Date.now() + 1000 * parseInt(tokens.expiresIn, 10); + } + var fields = Object.create(null); Google.whitelistedFields.forEach(function (name) { if (hasOwn.call(identity, name)) { @@ -33,12 +34,17 @@ function getServiceData(query) { // only set the token in serviceData if it's there. this ensures // that we don't lose old ones (since we only get this on the first // log in attempt) - if (response.refreshToken) - serviceData.refreshToken = response.refreshToken; + if (tokens.refreshToken) { + serviceData.refreshToken = tokens.refreshToken; + } return { serviceData: serviceData, - options: {profile: {name: identity.name}} + options: { + profile: { + name: identity.name + } + } }; } @@ -47,18 +53,26 @@ Accounts.registerLoginHandler(function (request) { return; } + const { serviceData } = getServiceDataFromTokens({ + accessToken: request.accessToken, + refreshToken: request.refreshToken, + idToken: request.idToken, + }); + return Accounts.updateOrCreateUserFromExternalService("google", { id: request.userId, idToken: request.idToken, accessToken: request.accessToken, email: request.email, picture: request.imageUrl, - ...getServiceData({ - code: request.serverAuthCode - }).serviceData, + ...serviceData, }); }); +function getServiceData(query) { + return getServiceDataFromTokens(getTokens(query)); +} + OAuth.registerService('google', 2, null, getServiceData); // returns an object containing: diff --git a/packages/google-oauth/package.js b/packages/google-oauth/package.js index ea533526fa..62436fca76 100644 --- a/packages/google-oauth/package.js +++ b/packages/google-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Google OAuth flow", - version: "1.2.2" + version: "1.2.3" }); var cordovaPluginGooglePlusURL = From beb60090d7dc6e472dc2e2184172a1e5bb4989f5 Mon Sep 17 00:00:00 2001 From: Erik Demaine Date: Mon, 17 Apr 2017 15:41:44 -0400 Subject: [PATCH 053/125] Switch to modern nodemailer 4, Node 4 version. Fix #8591 (#8605) * Switch to modern nodemailer 4, Node 4 version. Fix #8591 * Most critically, use a pool instead of direct SMTP connection, to handle dropped connections and increase throughput, like mail module 1.1. (#8591) * New nodemailer's sendMail wants an options object, not a MailComposer object. Luckily, a MailComposer object has a "mail" field that remembers the original options, so we can keep original behavior. * However, we no longer support the mailComposer option set to a compiled MailComposer object (functionality that was briefly added in 1.2.0). * nodemailer does SMTP URL parsing now automatically for us, simplifying code. * Tests' outputs now end with additional "\r\n" * Drop underscore package dependency (no longer needed) * General formatting/style cleanup for `packages/email`. * snake_cased => camelCased for some local variables. * Added curly-brackets to `if`s. * Removed trailing spaces. * Removed commented-out code. * Removed older doc text and changed some links. * Get rid of back-and-forth assigning of `mailUrlString`. --- .../email/.npm/package/npm-shrinkwrap.json | 73 +--------- packages/email/email.js | 137 +++++++----------- packages/email/email_tests.js | 60 ++++---- packages/email/package.js | 11 +- 4 files changed, 82 insertions(+), 199 deletions(-) diff --git a/packages/email/.npm/package/npm-shrinkwrap.json b/packages/email/.npm/package/npm-shrinkwrap.json index 4028b03706..aebb613b70 100644 --- a/packages/email/.npm/package/npm-shrinkwrap.json +++ b/packages/email/.npm/package/npm-shrinkwrap.json @@ -1,79 +1,14 @@ { "dependencies": { - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "from": "addressparser@1.0.1" - }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "from": "buildmail@4.0.1" - }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "from": "httpntlm@1.6.1" - }, - "httpreq": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.23.tgz", - "from": "httpreq@>=0.4.22" - }, - "iconv-lite": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "from": "iconv-lite@0.4.15" - }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "from": "libbase64@0.1.0" - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "from": "libmime@3.0.0" - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "from": "libqp@1.1.0" - }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "from": "mailcomposer@4.0.1" - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "from": "nodemailer-fetch@1.6.0" - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "from": "nodemailer-shared@1.1.0" - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "from": "punycode@1.4.1" - }, - "smtp-connection": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.2.tgz", - "from": "smtp-connection@2.12.2" + "node4mailer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/node4mailer/-/node4mailer-4.0.2.tgz", + "from": "node4mailer@4.0.2" }, "stream-buffers": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-0.2.5.tgz", "from": "stream-buffers@0.2.5" - }, - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "from": "underscore@>=1.7.0 <1.8.0" } } } diff --git a/packages/email/email.js b/packages/email/email.js index ae8e652eba..af3c633d69 100644 --- a/packages/email/email.js +++ b/packages/email/email.js @@ -1,6 +1,6 @@ var Future = Npm.require('fibers/future'); var urlModule = Npm.require('url'); -var SMTPConnection = Npm.require('smtp-connection'); +var nodemailer = Npm.require('node4mailer'); Email = {}; EmailTest = {}; @@ -8,61 +8,60 @@ EmailTest = {}; EmailInternals = { NpmModules: { mailcomposer: { - version: Npm.require('mailcomposer/package.json').version, - module: Npm.require('mailcomposer') + version: Npm.require('node4mailer/package.json').version, + module: Npm.require('node4mailer/lib/mail-composer') + }, + nodemailer: { + version: Npm.require('node4mailer/package.json').version, + module: Npm.require('node4mailer') } } }; -var mailcomposer = EmailInternals.NpmModules.mailcomposer.module; +var MailComposer = EmailInternals.NpmModules.mailcomposer.module; -var makePool = function (mailUrlString) { - var mailUrl = urlModule.parse(mailUrlString); - if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:') +var makeTransport = function (mailUrlString) { + var mailUrl = urlModule.parse(mailUrlString, true); + + if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:') { throw new Error("Email protocol in $MAIL_URL (" + mailUrlString + ") must be 'smtp' or 'smtps'"); - - var port = +(mailUrl.port); - var auth = false; - if (mailUrl.auth) { - var parts = mailUrl.auth.split(':', 2); - auth = {user: parts[0], - pass: parts[1]}; } - var pool = new SMTPConnection({ - port: port, // Defaults to 25 - host: mailUrl.hostname, // Defaults to "localhost" - secure: (port === 465) || (mailUrl.protocol === 'smtps:') - }); - Meteor.wrapAsync(pool.connect, pool)(); - if (auth) { - //_.bind(Future.wrap(pool.login), pool)(auth).wait(); - Meteor.wrapAsync(pool.login, pool)(auth); + // Allow overriding pool setting, but default to true. + if (!mailUrl.query) { + mailUrl.query = {}; } - pool._syncSend = Meteor.wrapAsync(pool.send, pool); - return pool; + if (!mailUrl.query.pool) { + mailUrl.query.pool = 'true'; + } + + var transport = nodemailer.createTransport( + urlModule.format(mailUrl)); + + transport._syncSendMail = Meteor.wrapAsync(transport.sendMail, transport); + return transport; }; -var getPool = function() { +var getTransport = function() { // We delay this check until the first call to Email.send, in case someone // set process.env.MAIL_URL in startup code. Then we store in a cache until // process.env.MAIL_URL changes. var url = process.env.MAIL_URL; if (this.cacheKey === undefined || this.cacheKey !== url) { this.cacheKey = url; - this.cache = url ? makePool(url) : null; + this.cache = url ? makeTransport(url) : null; } return this.cache; } -var next_devmode_mail_id = 0; +var nextDevModeMailId = 0; var output_stream = process.stdout; // Testing hooks EmailTest.overrideOutputStream = function (stream) { - next_devmode_mail_id = 0; + nextDevModeMailId = 0; output_stream = stream; }; @@ -70,27 +69,27 @@ EmailTest.restoreOutputStream = function () { output_stream = process.stdout; }; -var devModeSend = function (mc) { - var devmode_mail_id = next_devmode_mail_id++; +var devModeSend = function (mail) { + var devModeMailId = nextDevModeMailId++; var stream = output_stream; // This approach does not prevent other writers to stdout from interleaving. - stream.write("====== BEGIN MAIL #" + devmode_mail_id + " ======\n"); + stream.write("====== BEGIN MAIL #" + devModeMailId + " ======\n"); stream.write("(Mail not sent; to enable sending, set the MAIL_URL " + "environment variable.)\n"); - var readStream = mc.createReadStream(); + var readStream = new MailComposer(mail).compile().createReadStream(); readStream.pipe(stream, {end: false}); var future = new Future; readStream.on('end', function () { - stream.write("====== END MAIL #" + devmode_mail_id + " ======\n"); + stream.write("====== END MAIL #" + devModeMailId + " ======\n"); future.return(); }); future.wait(); }; -var smtpSend = function (pool, mc) { - pool._syncSend(mc.getEnvelope(), mc.createReadStream()); +var smtpSend = function (transport, mail) { + transport._syncSendMail(mail); }; /** @@ -105,28 +104,6 @@ EmailTest.hookSend = function (f) { sendHooks.push(f); }; -// Old comment below -/** - * Send an email. - * - * Connects to the mail server configured via the MAIL_URL environment - * variable. If unset, prints formatted message to stdout. The "from" option - * is required, and at least one of "to", "cc", and "bcc" must be provided; - * all other options are optional. - * - * @param options - * @param options.from {String} RFC5322 "From:" address - * @param options.to {String|String[]} RFC5322 "To:" address[es] - * @param options.cc {String|String[]} RFC5322 "Cc:" address[es] - * @param options.bcc {String|String[]} RFC5322 "Bcc:" address[es] - * @param options.replyTo {String|String[]} RFC5322 "Reply-To:" address[es] - * @param options.subject {String} RFC5322 "Subject:" line - * @param options.text {String} RFC5322 mail body (plain text) - * @param options.html {String} RFC5322 mail body (HTML) - * @param options.headers {Object} custom RFC5322 headers (dictionary) - */ - -// New API doc comment below /** * @summary Send an email. Throws an `Error` on failure to contact mail server * or if mail server returns an error. All fields should match @@ -135,10 +112,9 @@ EmailTest.hookSend = function (f) { * If the `MAIL_URL` environment variable is set, actually sends the email. * Otherwise, prints the contents of the email to standard out. * - * Note that this package is based on mailcomposer version `4.0.1`, so make - * sure to refer to the documentation for that version if using the - * `attachments` or `mailComposer` options. - * [Click here to read the mailcomposer 4.0.1 docs](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md). + * Note that this package is based on **mailcomposer 4**, so make sure to refer to + * [the documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md) + * for that version when using the `attachments` or `mailComposer` options. * * @locus Server * @param {Object} options @@ -150,44 +126,29 @@ EmailTest.hookSend = function (f) { * @param {String} [options.messageId] Message-ID for this message; otherwise, will be set to a random value * @param {String} [options.subject] "Subject:" line * @param {String} [options.text|html] Mail body (in plain text and/or HTML) - * @param {String} [options.watchHtml] Mail body in HTML specific for Apple Watch - * @param {String} [options.icalEvent] iCalendar event attachment + * @param {String} [options.watchHtml] Mail body in HTML specific for Apple Watch + * @param {String} [options.icalEvent] iCalendar event attachment * @param {Object} [options.headers] Dictionary of custom headers * @param {Object[]} [options.attachments] Array of attachment objects, as * described in the [mailcomposer documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md#attachments). - * @param {MailComposer} [options.mailComposer] A [MailComposer](https://github.com/andris9/mailcomposer) - * object (or its `compile()` output) representing the message to be sent. - * Overrides all other options. You can access the `mailcomposer` npm module at - * `EmailInternals.NpmModules.mailcomposer.module`. This module is a function - * which assembles a MailComposer object and immediately `compile()`s it. - * Alternatively, you can create and pass a MailComposer object via - * `new EmailInternals.NpmModules.mailcomposer.module.MailComposer`. + * @param {MailComposer} [options.mailComposer] A [MailComposer](https://nodemailer.com/extras/mailcomposer/#e-mail-message-fields) + * object representing the message to be sent. Overrides all other options. + * You can create a `MailComposer` object via + * `new EmailInternals.NpmModules.mailcomposer.module`. */ Email.send = function (options) { for (var i = 0; i < sendHooks.length; i++) if (! sendHooks[i](options)) return; - var mc; if (options.mailComposer) { - mc = options.mailComposer; - if (mc.compile) { - mc = mc.compile(); - } - } else { - // mailcomposer now automatically adds date if omitted - //if (!options.hasOwnProperty('date') && - // (!options.headers || !options.headers.hasOwnProperty('Date'))) { - // options['date'] = new Date().toUTCString().replace(/GMT/, '+0000'); - //} - - mc = mailcomposer(options); + options = options.mailComposer.mail; } - var pool = getPool(); - if (pool) { - smtpSend(pool, mc); + var transport = getTransport(); + if (transport) { + smtpSend(transport, options); } else { - devModeSend(mc); + devModeSend(options); } }; diff --git a/packages/email/email_tests.js b/packages/email/email_tests.js index 6fe9a30954..97c0977660 100644 --- a/packages/email/email_tests.js +++ b/packages/email/email_tests.js @@ -22,7 +22,7 @@ function canonicalize(string) { // Remove generated content for test.equal to succeed. return string.replace(/Message-ID: <[^<>]*>\r\n/, "Message-ID: <...>\r\n") .replace(/Date: (?!dummy).*\r\n/, "Date: ...\r\n") - .replace(/----[^\s"]+/g, "----..."); + .replace(/(boundary="|^--)--[^\s"]+?(-Part|")/mg, "$1--...$2"); } Tinytest.add("email - fully customizable", function (test) { @@ -55,7 +55,7 @@ Tinytest.add("email - fully customizable", function (test) { "\r\n" + "This is the body\n" + "of the message\n" + - "From us." + + "From us.\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -108,33 +108,23 @@ Tinytest.add("email - multiple e-mails same stream", function (test) { Tinytest.add("email - using mail composer", function (test) { smokeEmailTest(function (stream) { // Test direct MailComposer usage. - var mcs = [ - // Test with MailComposer object (without compiling). - new EmailInternals.NpmModules.mailcomposer.module.MailComposer({ - from: "a@b.com", - text: "body" - }), - // Test calling module as a function, which compiles MailComposer object. - EmailInternals.NpmModules.mailcomposer.module({ - from: "a@b.com", - text: "body" - }) - ]; - for (var i = 0; i < mcs.length; i++) { - Email.send({mailComposer: mcs[i]}); - test.equal(canonicalize(stream.getContentsAsString("utf8")), - "====== BEGIN MAIL #"+i+" ======\n" + - devWarningBanner + - "Content-Type: text/plain\r\n" + - "From: a@b.com\r\n" + - "Message-ID: <...>\r\n" + - "Content-Transfer-Encoding: 7bit\r\n" + - "Date: ...\r\n" + - "MIME-Version: 1.0\r\n" + - "\r\n" + - "body" + - "====== END MAIL #"+i+" ======\n"); - } + var mc = new EmailInternals.NpmModules.mailcomposer.module({ + from: "a@b.com", + text: "body" + }); + Email.send({mailComposer: mc}); + test.equal(canonicalize(stream.getContentsAsString("utf8")), + "====== BEGIN MAIL #0 ======\n" + + devWarningBanner + + "Content-Type: text/plain\r\n" + + "From: a@b.com\r\n" + + "Message-ID: <...>\r\n" + + "Content-Transfer-Encoding: 7bit\r\n" + + "Date: ...\r\n" + + "MIME-Version: 1.0\r\n" + + "\r\n" + + "body\r\n" + + "====== END MAIL #0 ======\n"); }); }); @@ -181,7 +171,7 @@ Tinytest.add("email - long lines", function (test) { "MIME-Version: 1.0\r\n" + "\r\n" + "This is a very very very very very very very very very very " + - "very very long =\r\ntext" + + "very very long =\r\ntext\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -208,7 +198,7 @@ Tinytest.add("email - unicode", function (test) { "Date: ...\r\n" + "MIME-Version: 1.0\r\n" + "\r\n" + - "I =E2=99=A5 Meteor" + + "I =E2=99=A5 Meteor\r\n" + "====== END MAIL #0 ======\n"); }); }); @@ -227,24 +217,24 @@ Tinytest.add("email - text and html", function (test) { "====== BEGIN MAIL #0 ======\n" + devWarningBanner + "Content-Type: multipart/alternative;\r\n" + - ' boundary="----..."\r\n' + + ' boundary="--...-Part_1"\r\n' + "From: foo@example.com\r\n" + "To: bar@example.com\r\n" + "Message-ID: <...>\r\n" + "Date: ...\r\n" + "MIME-Version: 1.0\r\n" + "\r\n" + - "----...\r\n" + + "----...-Part_1\r\n" + "Content-Type: text/plain\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "*Cool*, man\r\n" + - "----...\r\n" + + "----...-Part_1\r\n" + "Content-Type: text/html\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "Cool, man\r\n" + - "----...\r\n" + + "----...-Part_1--\r\n" + "====== END MAIL #0 ======\n"); }); }); diff --git a/packages/email/package.js b/packages/email/package.js index 36f09e1601..7e5167f350 100644 --- a/packages/email/package.js +++ b/packages/email/package.js @@ -1,17 +1,14 @@ Package.describe({ summary: "Send email messages", - version: "1.2.0" + version: "1.2.1" }); Npm.depends({ - mailcomposer: "4.0.1", - // Using smtp-connection@2 (instead of latest) because it shares - // nodemailer-shared with mailcomposer@4: - "smtp-connection": "2.12.2", - "stream-buffers": "0.2.5"}); + node4mailer: "4.0.2", + "stream-buffers": "0.2.5" +}); Package.onUse(function (api) { - api.use('underscore', 'server'); api.export(['Email', 'EmailInternals'], 'server'); api.export('EmailTest', 'server', {testOnly: true}); api.addFiles('email.js', 'server'); From 11cf43f34849051c839fbe4b2152eaae01b5b7e6 Mon Sep 17 00:00:00 2001 From: Akarshit Date: Thu, 6 Apr 2017 22:43:47 +0530 Subject: [PATCH 054/125] Index creation in the file using the query --- packages/accounts-base/accounts_server.js | 2 ++ packages/accounts-password/password_server.js | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/accounts-base/accounts_server.js b/packages/accounts-base/accounts_server.js index ab62e14618..eca4c3e5a8 100644 --- a/packages/accounts-base/accounts_server.js +++ b/packages/accounts-base/accounts_server.js @@ -1502,6 +1502,8 @@ function setupUsersCollection(users) { { sparse: 1 }); // For expiring login tokens users._ensureIndex("services.resume.loginTokens.when", { sparse: 1 }); + // For expiring password tokens + users._ensureIndex('services.password.reset.when', { sparse: 1 }); } /// diff --git a/packages/accounts-password/password_server.js b/packages/accounts-password/password_server.js index 9102743fec..b088b0aafd 100644 --- a/packages/accounts-password/password_server.js +++ b/packages/accounts-password/password_server.js @@ -1126,5 +1126,3 @@ Meteor.users._ensureIndex('services.email.verificationTokens.token', {unique: 1, sparse: 1}); Meteor.users._ensureIndex('services.password.reset.token', {unique: 1, sparse: 1}); -Meteor.users._ensureIndex('services.password.reset.when', - {sparse: 1}); From c527be388b29f51ab9fd834e8cf4a45147d656f9 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 20 Apr 2017 05:29:40 -0700 Subject: [PATCH 055/125] Exchange `serverAuthCode` for an `accessToken` in `packages/google-oauth`. The `accessToken` isn't always immediately provided (for example on Android devices) but instead needs to be retrieved by exchanging the `serverAuthCode`. Fixes https://github.com/meteor/meteor/issues/8613. --- packages/google-oauth/google_server.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/google-oauth/google_server.js b/packages/google-oauth/google_server.js index 871c9c2ee8..f553f33825 100644 --- a/packages/google-oauth/google_server.js +++ b/packages/google-oauth/google_server.js @@ -53,11 +53,19 @@ Accounts.registerLoginHandler(function (request) { return; } - const { serviceData } = getServiceDataFromTokens({ + const tokens = { accessToken: request.accessToken, refreshToken: request.refreshToken, idToken: request.idToken, - }); + }; + + if (request.serverAuthCode) { + Object.assign(tokens, getTokens({ + code: request.serverAuthCode + })); + } + + const result = getServiceDataFromTokens(tokens); return Accounts.updateOrCreateUserFromExternalService("google", { id: request.userId, @@ -65,8 +73,8 @@ Accounts.registerLoginHandler(function (request) { accessToken: request.accessToken, email: request.email, picture: request.imageUrl, - ...serviceData, - }); + ...result.serviceData, + }, result.options); }); function getServiceData(query) { From 11db32b40d18b0fe209815f76ee6420e933b7fc9 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 20 Apr 2017 05:44:28 -0700 Subject: [PATCH 056/125] Bump `google-oauth` package version in preparation for publishing. --- packages/google-oauth/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-oauth/package.js b/packages/google-oauth/package.js index 62436fca76..09ee7166c5 100644 --- a/packages/google-oauth/package.js +++ b/packages/google-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Google OAuth flow", - version: "1.2.3" + version: "1.2.4" }); var cordovaPluginGooglePlusURL = From cfd804150c866243162a60cbd6d84c3d3507c70f Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Tue, 25 Apr 2017 11:41:45 -0400 Subject: [PATCH 057/125] Upgraded to Node 4.8.2 and bumped the dev bundle version. --- meteor | 2 +- scripts/build-dev-bundle-common.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/meteor b/meteor index cc0116c16a..4068a935a6 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.7.25 +BUNDLE_VERSION=4.7.26 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index d0c9b1fdd5..32cfe290ff 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -6,7 +6,7 @@ set -u UNAME=$(uname) ARCH=$(uname -m) MONGO_VERSION=3.2.12 -NODE_VERSION=4.8.1 +NODE_VERSION=4.8.2 NPM_VERSION=4.4.4 if [ "$UNAME" == "Linux" ] ; then From d3ab206a7a9f8482de4034d792b82de27dd66ce1 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 11:33:04 -0700 Subject: [PATCH 058/125] Update `npm` package to v4.5.0. Notable changes: https://github.com/npm/npm/releases/tag/v4.5.0 --- scripts/build-dev-bundle-common.sh | 2 +- scripts/dev-bundle-tool-package.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 32cfe290ff..5e5b8062f7 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -7,7 +7,7 @@ UNAME=$(uname) ARCH=$(uname -m) MONGO_VERSION=3.2.12 NODE_VERSION=4.8.2 -NPM_VERSION=4.4.4 +NPM_VERSION=4.5.0 if [ "$UNAME" == "Linux" ] ; then if [ "$ARCH" != "i686" -a "$ARCH" != "x86_64" ] ; then diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 9d8d0ec578..e96526a883 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -11,7 +11,7 @@ var packageJson = { dependencies: { // Explicit dependency because we are replacing it with a bundled version // and we want to make sure there are no dependencies on a higher version - npm: "4.4.4", + npm: "4.5.0", "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", "meteor-babel": "0.20.1", From bb859d8fda79fcb7e9b522cdc10af4de8de9e5fe Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 12:01:03 -0700 Subject: [PATCH 059/125] Add `History.md` for Node.js and `npm` package updates. --- History.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/History.md b/History.md index 210c44c613..64801a8835 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,13 @@ the `reify` npm package has been upgraded to version 0.7.4, fixing [issue #8595](https://github.com/meteor/meteor/issues/8595). +* Node has been upgraded to version 4.8.2. + +* The `npm` npm package has been upgraded to version 4.5.0. + Note that when using npm `scripts` there has been a change regarding + what happens when `SIGINT` (Ctrl-C) is received. Read more + [here](https://github.com/npm/npm/releases/tag/v4.5.0). + ## v1.4.4.1, 2017-04-07 * A change in Meteor 1.4.4 to remove "garbage" directories asynchronously From feb079b4bcd3943fe8292f5bdd35b44e7a9f7337 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 12:18:37 -0700 Subject: [PATCH 060/125] Update versions of `node-inspector` and `v8-profiler` packages. Notable changes in `node-inspector`: https://github.com/node-inspector/node-inspector/blob/master/ChangeLog.md#2017-04-24-version-111 Fixes meteor/meteor#8469. --- scripts/dev-bundle-tool-package.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index e96526a883..c6f89062c0 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -33,8 +33,8 @@ var packageJson = { tar: "2.2.1", kexec: "2.0.2", "source-map": "0.5.3", - "node-inspector": "0.12.8", - "v8-profiler": "5.6.5", + "node-inspector": "1.1.1", + "v8-profiler": "5.7.0", chalk: "0.5.1", sqlite3: "3.1.3", netroute: "1.0.2", From 1a036553c1068922f712afe598cfe81d4308ac44 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 20 Apr 2017 16:09:51 -0400 Subject: [PATCH 061/125] Fix faulty content-length comparison in utils/http-helpers.js. Since body is a string, body.length is not necessarily the number of bytes in the response body. --- tools/utils/http-helpers.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/utils/http-helpers.js b/tools/utils/http-helpers.js index 2dda4548e6..ac40002bd7 100644 --- a/tools/utils/http-helpers.js +++ b/tools/utils/http-helpers.js @@ -310,12 +310,16 @@ _.extend(exports, { var req = request(options, function (error, response, body) { if (! error && response && body) { const contentLength = Number(response.headers["content-length"]); - if (contentLength > 0 && body.length < contentLength) { + const actualLength = Buffer.byteLength(body); + + if (contentLength > 0 && + actualLength < contentLength) { error = new Error( "Expected " + contentLength + " bytes in request body " + - "but received only " + body.length); + "but received only " + actualLength); } } + return callback.call(this, error, response, body); }); From 6cf07832829b6bfbc2564b1744aa4d1dd51283d7 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 16:41:32 -0700 Subject: [PATCH 062/125] Additions to the `History.md` for 1.4.4.2. --- History.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/History.md b/History.md index f388f2abf6..9380b5bfc9 100644 --- a/History.md +++ b/History.md @@ -16,6 +16,16 @@ to press "Enter" in the inspector console. [Issue #8469](https://github.com/meteor/meteor/issues/8469) +* The `email` package has had its `mailcomposer` npm package swapped with + a Node 4 fork of `nodemailer` due to its ability to support connection pooling + in a similar fashion as the original `mailcomposer`. + [Issue #8591](https://github.com/meteor/meteor/issues/8591) + [PR #8605](https://github.com/meteor/meteor/pull/8605) + +* A new `Tracker.inFlush()` has been added to provide a global Tracker + "flushing" state. + [PR #8565](https://github.com/meteor/meteor/pull/8565). + * The `meteor-babel` npm package has been upgraded to version 0.20.1, and the `reify` npm package has been upgraded to version 0.7.4, fixing [issue #8595](https://github.com/meteor/meteor/issues/8595). From 3d04c48b25659883b1bfd296734b07056d07e133 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 25 Apr 2017 17:29:00 -0700 Subject: [PATCH 063/125] Bump package versions for 1.4.4.2-rc.0 release. --- packages/accounts-base/package.js | 2 +- packages/accounts-password/package.js | 2 +- packages/meetup-oauth/package.js | 2 +- packages/meteor-tool/package.js | 2 +- packages/minimongo/package.js | 2 +- packages/mongo/package.js | 2 +- packages/tracker/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index 568d29e33a..1b8a07992e 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A user account system", - version: "1.2.16" + version: "1.2.17-rc.0" }); Package.onUse(function (api) { diff --git a/packages/accounts-password/package.js b/packages/accounts-password/package.js index 77fb819816..a71eafd785 100644 --- a/packages/accounts-password/package.js +++ b/packages/accounts-password/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Password support for accounts", - version: "1.3.5" + version: "1.3.6-rc.0" }); Package.onUse(function(api) { diff --git a/packages/meetup-oauth/package.js b/packages/meetup-oauth/package.js index fb39d443f3..b50df01a30 100644 --- a/packages/meetup-oauth/package.js +++ b/packages/meetup-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: 'Meetup OAuth flow', - version: '1.0.0' + version: '1.0.1-rc.0' }); Package.onUse(function (api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index ef6a96411f..cf3bcd4938 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.4.4_1' + version: '1.4.4-2-rc.0' }); Package.includeTool(); diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index d89b5f03df..402e57eede 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.0.22' + version: '1.0.22-rc.0' }); Package.onUse(function (api) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index f268d568cc..13b6fd06ff 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.1.16' + version: '1.1.17-rc.0' }); Npm.depends({ diff --git a/packages/tracker/package.js b/packages/tracker/package.js index 467854148e..d29b0dfd06 100644 --- a/packages/tracker/package.js +++ b/packages/tracker/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Dependency tracker to allow reactive callbacks", - version: '1.1.2' + version: '1.1.3-rc.0' }); Package.onUse(function (api) { diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 6e271282a4..35e6359c03 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.4.4.1-rc.0", + "version": "1.4.4.2-rc.0", "recommended": false, "official": false, "description": "Meteor" From c50cf4f49b43a1f8c5cd04a8959827090a48441d Mon Sep 17 00:00:00 2001 From: mutdmour Date: Wed, 26 Apr 2017 18:33:46 +0300 Subject: [PATCH 064/125] [Fix #5165] don't allow invalid field names (#8608) --- packages/minimongo/helpers.js | 2 +- packages/minimongo/minimongo.js | 22 ++-------- packages/minimongo/minimongo_tests.js | 59 ++++++++++++++++++++++++--- packages/minimongo/modify.js | 28 ++++++------- packages/minimongo/validation.js | 24 +++++++++++ 5 files changed, 94 insertions(+), 41 deletions(-) create mode 100644 packages/minimongo/validation.js diff --git a/packages/minimongo/helpers.js b/packages/minimongo/helpers.js index 759ce0ca62..a21c1dc49c 100644 --- a/packages/minimongo/helpers.js +++ b/packages/minimongo/helpers.js @@ -42,4 +42,4 @@ isOperatorObject = function (valueSelector, inconsistentOK) { // string can be converted to integer isNumericKey = function (s) { return /^[0-9]+$/.test(s); -}; +}; \ No newline at end of file diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js index 312c9e4581..dd2017ebce 100644 --- a/packages/minimongo/minimongo.js +++ b/packages/minimongo/minimongo.js @@ -1,3 +1,5 @@ +import { assertHasValidFieldNames } from './validation.js'; + // XXX type checking on selectors (graceful error if malformed) // LocalCollection: a set of documents that supports queries and modifiers. @@ -540,31 +542,13 @@ LocalCollection.Cursor.prototype._depend = function (changers, _allow_unordered) } }; -// XXX enforce rule that field names can't start with '$' or contain '.' -// (real mongodb does in fact enforce this) // XXX possibly enforce that 'undefined' does not appear (we assume // this in our handling of null and $exists) LocalCollection.prototype.insert = function (doc, callback) { var self = this; doc = EJSON.clone(doc); - // Make sure field names do not contain Mongo restricted - // characters ('.', '$', '\0'). - // https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names - if (doc) { - const invalidCharMsg = { - '.': "contain '.'", - '$': "start with '$'", - '\0': "contain null bytes", - }; - JSON.stringify(doc, (key, value) => { - let match; - if (_.isString(key) && (match = key.match(/^\$|\.|\0/))) { - throw MinimongoError(`Key ${key} must not ${invalidCharMsg[match[0]]}`); - } - return value; - }); - } + assertHasValidFieldNames(doc); if (!_.has(doc, '_id')) { // if you really want to use ObjectIDs, set this global. diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 9edc47c52e..87b23b6821 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -2207,6 +2207,13 @@ Tinytest.add("minimongo - modify", function (test) { test.equal(actual, expected); }; + var upsertException = function (query, mod) { + var coll = new LocalCollection; + test.throws(function(){ + coll.upsert(query, mod); + }); + }; + // document replacement modify({}, {}, {}); modify({a: 12}, {}, {}); // tested against mongodb @@ -2215,6 +2222,11 @@ Tinytest.add("minimongo - modify", function (test) { exception({a: 12}, {a: 13, $set: {b: 13}}); exception({a: 12}, {$set: {b: 13}, a: 13}); + exception({a: 12}, {$a: 13}); //invalid operator + exception({a: 12}, {b:{$a: 13}}); + exception({a: 12}, {b:{'a.b': 13}}); + exception({a: 12}, {b:{'\0a': 13}}); + // keys modify({}, {$set: {'a': 12}}, {a: 12}); modify({}, {$set: {'a.b': 12}}, {a: {b: 12}}); @@ -2383,6 +2395,12 @@ Tinytest.add("minimongo - modify", function (test) { modify({}, {$set: {'x._id': 4}}, {x: {_id: 4}}); exception({}, {$set: {_id: 4}}); exception({_id: 4}, {$set: {_id: 4}}); // even not-changing _id is bad + //restricted field names + exception({a:{}}, {$set:{a:{$a:1}}}); + exception({ a: {} }, { $set: { a: { c: + [{ b: { $a: 1 } }] } } }); + exception({a:{}}, {$set:{a:{'\0a':1}}}); + exception({a:{}}, {$set:{a:{'a.b':1}}}); // $unset modify({}, {$unset: {a: 1}}, {}); @@ -2457,7 +2475,16 @@ Tinytest.add("minimongo - modify", function (test) { {$push: {a: {$each: [{x: 3}], $position: 0, $sort: {x: 1}, $slice: 0}}}, {a: []} ); - + //restricted field names + exception({}, {$push: {$a: 1}}); + exception({}, {$push: {'\0a': 1}}); + exception({}, {$push: {a: {$a:1}}}); + exception({}, {$push: {a: {$each: [{$a:1}]}}}); + exception({}, {$push: {a: {$each: [{"a.b":1}]}}}); + exception({}, {$push: {a: {$each: [{'\0a':1}]}}}); + modify({}, {$push: {a: {$each: [{'':1}]}}}, {a: [ { '': 1 } ]}); + modify({}, {$push: {a: {$each: [{' ':1}]}}}, {a: [ { ' ': 1 } ]}); + exception({}, {$push: {a: {$each: [{'.':1}]}}}); // $pushAll modify({}, {$pushAll: {a: [1]}}, {a: [1]}); @@ -2475,6 +2502,9 @@ Tinytest.add("minimongo - modify", function (test) { modify({a: []}, {$pushAll: {'a.1': []}}, {a: [null, []]}); modify({a: {}}, {$pushAll: {'a.x': [99]}}, {a: {x: [99]}}); modify({a: {}}, {$pushAll: {'a.x': []}}, {a: {x: []}}); + exception({a: [1]}, {$pushAll: {a: [{$a:1}]}}); + exception({a: [1]}, {$pushAll: {a: [{'\0a':1}]}}); + exception({a: [1]}, {$pushAll: {a: [{"a.b":1}]}}); // $addToSet modify({}, {$addToSet: {a: 1}}, {a: [1]}); @@ -2493,14 +2523,25 @@ Tinytest.add("minimongo - modify", function (test) { modify({a: [{x: 1, y: 2}]}, {$addToSet: {a: {y: 2, x: 1}}}, {a: [{x: 1, y: 2}, {y: 2, x: 1}]}); modify({a: [1, 2]}, {$addToSet: {a: {$each: [3, 1, 4]}}}, {a: [1, 2, 3, 4]}); - modify({a: [1, 2]}, {$addToSet: {a: {$each: [3, 1, 4], b: 12}}}, - {a: [1, 2, 3, 4]}); // tested - modify({a: [1, 2]}, {$addToSet: {a: {b: 12, $each: [3, 1, 4]}}}, - {a: [1, 2, {b: 12, $each: [3, 1, 4]}]}); // tested modify({}, {$addToSet: {a: {$each: []}}}, {a: []}); modify({}, {$addToSet: {a: {$each: [1]}}}, {a: [1]}); modify({a: []}, {$addToSet: {'a.1': 99}}, {a: [null, [99]]}); modify({a: {}}, {$addToSet: {'a.x': 99}}, {a: {x: [99]}}); + + // invalid field names + exception({}, {$addToSet: {a: {$b:1}}}); + exception({}, {$addToSet: {a: {"a.b":1}}}); + exception({}, {$addToSet: {a: {"a.":1}}}); + exception({}, {$addToSet: {a: {'\u0000a':1}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, {$a:1}]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, {'\0a':1}]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, [{$a:1}]]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, [{b:{c:[{a:1},{"d.s":2}]}}]]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{b: [3, 1, [{b:{c:[{a:1},{"d.s":2}]}}]]}}}); + //$each is first element and thus an operator + modify({a: [1, 2]}, {$addToSet: {a: {$each: [3, 1, 4], b: 12}}},{a: [ 1, 2, 3, 4 ]}); + // this should fail because $each is now a field name (not first in object) and thus invalid field name with $ + exception({a: [1, 2]}, {$addToSet: {a: {b: 12, $each: [3, 1, 4]}}}); // $pop modify({}, {$pop: {a: 1}}, {}); // tested @@ -2574,11 +2615,19 @@ Tinytest.add("minimongo - modify", function (test) { exception({}, {$rename: {'a': 'a'}}); exception({}, {$rename: {'a.b': 'a.b'}}); modify({a: 12, b: 13}, {$rename: {a: 'b'}}, {b: 12}); + exception({a: [12]}, {$rename: {a: '$b'}}); + exception({a: [12]}, {$rename: {a: '\0a'}}); // $setOnInsert modify({a: 0}, {$setOnInsert: {a: 12}}, {a: 0}); upsert({a: 12}, {$setOnInsert: {b: 12}}, {a: 12, b: 12}); upsert({a: 12}, {$setOnInsert: {_id: 'test'}}, {_id: 'test', a: 12}); + upsertException({a: 0}, {$setOnInsert: {$a: 12}}); + upsertException({a: 0}, {$setOnInsert: {'\0a': 12}}); + upsert({a: 0}, {$setOnInsert: {b: {a:1}}}, {a:0, b:{a:1}}); + upsertException({a: 0}, {$setOnInsert: {b: {$a:1}}}); + upsertException({a: 0}, {$setOnInsert: {b: {'a.b':1}}}); + upsertException({a: 0}, {$setOnInsert: {b: {'\0a':1}}}); exception({}, {$set: {_id: 'bad'}}); diff --git a/packages/minimongo/modify.js b/packages/minimongo/modify.js index 7074482ee6..ebc285ddab 100644 --- a/packages/minimongo/modify.js +++ b/packages/minimongo/modify.js @@ -1,3 +1,5 @@ +import { assertHasValidFieldNames, assertIsValidFieldName } from './validation.js'; + // XXX need a strategy for passing the binding of $ into this // function, from the compiled selector // @@ -27,11 +29,7 @@ LocalCollection._modify = function (doc, mod, options) { throw MinimongoError("Cannot change the _id of a document"); // replace the whole document - for (var k in mod) { - if (/\./.test(k)) - throw MinimongoError( - "When replacing document, field name may not contain '.'"); - } + assertHasValidFieldNames(mod); newDoc = mod; } else { // apply modifiers to the doc. @@ -155,8 +153,7 @@ var findModTarget = function (doc, keyparts, options) { "' of list value " + JSON.stringify(doc[keypart])); } } else { - if (keypart.length && keypart.substr(0, 1) === '$') - throw MinimongoError("can't set field named " + keypart); + assertIsValidFieldName(keypart); if (!(keypart in doc)) { if (options.noCreate) return undefined; @@ -251,11 +248,7 @@ var MODIFIERS = { e.setPropertyError = true; throw e; } - if (_.isString(field) && field.indexOf('\0') > -1) { - // Null bytes are not allowed in Mongo field names - // https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names - throw MinimongoError(`Key ${field} must not contain null bytes`); - } + assertHasValidFieldNames(arg); target[field] = arg; }, $setOnInsert: function (target, field, arg) { @@ -279,6 +272,7 @@ var MODIFIERS = { if (!(arg && arg.$each)) { // Simple mode: not $each + assertHasValidFieldNames(arg); target[field].push(arg); return; } @@ -287,6 +281,7 @@ var MODIFIERS = { var toPush = arg.$each; if (!(toPush instanceof Array)) throw MinimongoError("$each must be an array", { field }); + assertHasValidFieldNames(toPush); // Parse $position var position = undefined; @@ -356,6 +351,7 @@ var MODIFIERS = { $pushAll: function (target, field, arg) { if (!(typeof arg === "object" && arg instanceof Array)) throw MinimongoError("Modifier $pushAll/pullAll allowed for arrays only"); + assertHasValidFieldNames(arg); var x = target[field]; if (x === undefined) target[field] = arg; @@ -371,13 +367,13 @@ var MODIFIERS = { var isEach = false; if (typeof arg === "object") { //check if first key is '$each' - for (var k in arg) { - if (k === "$each") - isEach = true; - break; + const keys = Object.keys(arg); + if (keys[0] === "$each"){ + isEach = true; } } var values = isEach ? arg["$each"] : [arg]; + assertHasValidFieldNames(values); var x = target[field]; if (x === undefined) target[field] = values; diff --git a/packages/minimongo/validation.js b/packages/minimongo/validation.js new file mode 100644 index 0000000000..ef73560a72 --- /dev/null +++ b/packages/minimongo/validation.js @@ -0,0 +1,24 @@ +// Make sure field names do not contain Mongo restricted +// characters ('.', '$', '\0'). +// https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names +const invalidCharMsg = { + '.': "contain '.'", + '$': "start with '$'", + '\0': "contain null bytes", +}; +export function assertIsValidFieldName(key) { + let match; + if (_.isString(key) && (match = key.match(/^\$|\.|\0/))) { + throw MinimongoError(`Key ${key} must not ${invalidCharMsg[match[0]]}`); + } +}; + +// checks if all field names in an object are valid +export function assertHasValidFieldNames(doc){ + if (doc && typeof doc === "object") { + JSON.stringify(doc, (key, value) => { + assertIsValidFieldName(key); + return value; + }); + } +}; \ No newline at end of file From b7932ce9aaa8bddf50397882e656e4db57fed185 Mon Sep 17 00:00:00 2001 From: mutdmour Date: Wed, 26 Apr 2017 18:42:11 +0300 Subject: [PATCH 065/125] Handle legacy coordinates as GeoJSON in minimongo (#2077) (#8620) --- packages/minimongo/minimongo_tests.js | 29 +++++++++++++++++++++++++++ packages/minimongo/selector.js | 13 +++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 87b23b6821..21ae3169cc 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -3232,6 +3232,35 @@ Tinytest.add("minimongo - $near operator tests", function (test) { handle.stop(); }); +// issue #2077 +Tinytest.add("minimongo - $near and $geometry for legacy coordinates", function(test){ + var coll = new LocalCollection(); + + coll.insert({ + loc: { + x: 1, + y: 1 + } + }); + coll.insert({ + loc: [-1,-1] + }); + coll.insert({ + loc: [40,-10] + }); + coll.insert({ + loc: { + x: -10, + y: 40 + } + }); + + test.equal(coll.find({ 'loc': { $near: [0, 0], $maxDistance: 4 } }).count(), 2); + test.equal(coll.find({ 'loc': { $near: {$geometry: {type: "Point", coordinates: [0, 0]}}} }).count(), 4); + test.equal(coll.find({ 'loc': { $near: {$geometry: {type: "Point", coordinates: [0, 0]}, $maxDistance:200000}}}).count(), 2); + +}); + // Regression test for #4377. Previously, "replace" updates didn't clone the // argument. Tinytest.add("minimongo - update should clone", function (test) { diff --git a/packages/minimongo/selector.js b/packages/minimongo/selector.js index 7d2fcb6676..f3034094d1 100644 --- a/packages/minimongo/selector.js +++ b/packages/minimongo/selector.js @@ -435,9 +435,10 @@ var VALUE_OPERATORS = { throw Error("$near can't be inside another $ operator"); matcher._hasGeoQuery = true; - // There are two kinds of geodata in MongoDB: coordinate pairs and + // There are two kinds of geodata in MongoDB: legacy coordinate pairs and // GeoJSON. They use different distance metrics, too. GeoJSON queries are - // marked with a $geometry property. + // marked with a $geometry property, though legacy coordinates can be + // matched using $geometry. var maxDistance, point, distance; if (isPlainObject(operand) && _.has(operand, '$geometry')) { @@ -448,8 +449,11 @@ var VALUE_OPERATORS = { // XXX: for now, we don't calculate the actual distance between, say, // polygon and circle. If people care about this use-case it will get // a priority. - if (!value || !value.type) + if (!value) return null; + if(!value.type) + return GeoJSON.pointDistance(point, + { type: "Point", coordinates: pointToArray(value) }); if (value.type === "Point") { return GeoJSON.pointDistance(point, value); } else { @@ -481,6 +485,9 @@ var VALUE_OPERATORS = { branchedValues = expandArraysInBranches(branchedValues); var result = {result: false}; _.each(branchedValues, function (branch) { + if (!(typeof branch.value === "object")){ + return; + } var curDistance = distance(branch.value); // Skip branches that aren't real points or are too far away. if (curDistance === null || curDistance > maxDistance) From fcdf3515730302217ae770c250bdd0eca1715424 Mon Sep 17 00:00:00 2001 From: Bartosz Wojtkowiak Date: Wed, 26 Apr 2017 20:43:39 +0200 Subject: [PATCH 066/125] Implement CORDOVA_COMPATIBILITY_VERSION_IOS/ANDROID and EXCLUDE (#8581) * Implement CORDOVA_COMPATIBILITY_VERSION_EXCLUDE and CORDOVA_COMPATIBILITY_VERSION_IOS/ANDROID CORDOVA_COMPATIBILITY_VERSION_IOS or CORDOVA_COMPATIBILITY_VERSION_ANDROID allows to override compatibility version for a specified platform. CORDOVA_COMPATIBILITY_VERSION_EXCLUDE provides a way of excluding a certain plugin from compatibility version calculation. You can pass several plugin names with ';'. For example: `CORDOVA_COMPATIBILITY_VERSION_EXCLUDE='cordova-plugin-crosswalk-webview;cordova-plugin-device'` * Changes after review --- tools/isobuild/bundler.js | 17 +++++++++++--- tools/tests/cordova-hcp.js | 47 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index 3bbc8cacb4..87add438ad 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -1522,11 +1522,22 @@ class ClientTarget extends Target { if (this.arch === 'web.cordova') { const { WebAppHashing } = loadIsopacket('cordova-support')['webapp-hashing']; + const cordovaCompatibilityVersions = _.object(_.map(CORDOVA_PLATFORM_VERSIONS, (version, platform) => { - const hash = WebAppHashing.calculateCordovaCompatibilityHash( - version, - this.cordovaDependencies); + + const pluginsExcludedFromCompatibilityHash = (process.env.METEOR_CORDOVA_COMPAT_VERSION_EXCLUDE || '') + .split(','); + + const cordovaDependencies = Object.assign( + Object.create(null), + _.omit(this.cordovaDependencies, pluginsExcludedFromCompatibilityHash) + ); + + const hash = process.env[`METEOR_CORDOVA_COMPAT_VERSION_${platform.toUpperCase()}`] || + WebAppHashing.calculateCordovaCompatibilityHash( + version, + cordovaDependencies); return [platform, hash]; })); program.cordovaCompatibilityVersions = cordovaCompatibilityVersions; diff --git a/tools/tests/cordova-hcp.js b/tools/tests/cordova-hcp.js index 1a15ec88b8..efd7be0e55 100644 --- a/tools/tests/cordova-hcp.js +++ b/tools/tests/cordova-hcp.js @@ -39,3 +39,50 @@ selftest.define( run.stop(); }); + +selftest.define( + "cordova METEOR_CORDOVA_COMPAT_VERSION_* works", ["cordova", "slow"], function () { + var s = new Sandbox(); + var run; + + var androidCompatibilityVersion = '2.0'; + + // Override the compatibility version for android with METEOR_CORDOVA_COMPAT_VERSION_ANDROID. + s.env.METEOR_CORDOVA_COMPAT_VERSION_ANDROID = androidCompatibilityVersion; + + s.createApp("myapp", "standard-app"); + s.cd("myapp"); + + var platforms = s.read(".meteor/platforms"); + s.write(".meteor/platforms", platforms + "\nandroid\n"); + + run = s.run("run", "android", "--mobile-server", "example.com"); + run.waitSecs(30); + run.match("Started your app"); + + var result = JSON.parse(httpHelpers.getUrl( + "http://localhost:3000/__cordova/manifest.json")); + + // Check in the manifest if the overridden version was used. + selftest.expectEqual(result.cordovaCompatibilityVersions.android, androidCompatibilityVersion); + + run.stop(); + // Save the iOS compatibility version. + var iosCompatibilityVersion = result.cordovaCompatibilityVersions.ios; + + // Now exclude one of the plugins from compatibility version calculation. + s.env.METEOR_CORDOVA_COMPAT_VERSION_EXCLUDE = 'cordova-plugin-meteor-webapp,any-other-plugin'; + + run = s.run("run", "android", "--mobile-server", "example.com"); + run.waitSecs(30); + run.match("Started your app"); + + result = JSON.parse(httpHelpers.getUrl( + "http://localhost:3000/__cordova/manifest.json")); + + // Version should be different. There is no need to check if the particular plugin was not taken into account, + // if the version has changed it's proof enough. + selftest.expectFalse(result.cordovaCompatibilityVersions.ios === iosCompatibilityVersion); + + run.stop(); +}); \ No newline at end of file From ff86dcd5f101a3368348d0b0f1edcee475ac0a9a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 26 Apr 2017 14:34:24 -0400 Subject: [PATCH 067/125] Upgrade meteor-babel, reify, and meteor-ecmascript-runtime. --- History.md | 7 +-- .../.npm/package/npm-shrinkwrap.json | 51 ++++++++++++------- packages/babel-compiler/package.js | 2 +- .../modules/.npm/package/npm-shrinkwrap.json | 21 ++++++-- packages/modules/package.js | 2 +- scripts/dev-bundle-tool-package.js | 5 +- 6 files changed, 60 insertions(+), 28 deletions(-) diff --git a/History.md b/History.md index f4978a3b1f..f076518816 100644 --- a/History.md +++ b/History.md @@ -9,9 +9,10 @@ information about how dynamic `import(...)` works in Meteor, and how to use it in your applications. -* The `meteor-babel` npm package has been upgraded to version 0.20.1, and - the `reify` npm package has been upgraded to version 0.7.4, fixing - [issue #8595](https://github.com/meteor/meteor/issues/8595). +* The `meteor-babel` npm package has been upgraded to version 0.20.2, and + the `reify` npm package has been upgraded to version 0.8.2, fixing + [issue #8595](https://github.com/meteor/meteor/issues/8595) and + improving compilation performance. ## v1.4.4.1, 2017-04-07 diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index f297b0adf2..b0a59e4b42 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -270,9 +270,9 @@ "from": "babel-plugin-transform-es2015-modules-commonjs@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-modules-reify": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.7.0.tgz", - "from": "babel-plugin-transform-es2015-modules-reify@>=0.7.0 <0.8.0" + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.8.0.tgz", + "from": "babel-plugin-transform-es2015-modules-reify@>=0.8.0 <0.9.0" }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", @@ -465,8 +465,8 @@ "from": "babel-types@>=6.22.0 <7.0.0" }, "babylon": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.0.tgz", "from": "babylon@>=6.15.0 <7.0.0" }, "balanced-match": { @@ -500,8 +500,8 @@ "from": "core-js@>=2.4.0 <3.0.0" }, "debug": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.3.tgz", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.4.tgz", "from": "debug@>=2.1.1 <3.0.0" }, "detect-indent": { @@ -580,9 +580,9 @@ "from": "loose-envify@>=1.0.0 <2.0.0" }, "meteor-babel": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.1.tgz", - "from": "meteor-babel@0.20.1" + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.2.tgz", + "from": "meteor-babel@0.20.2" }, "meteor-babel-helpers": { "version": "0.0.3", @@ -599,15 +599,25 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "from": "minimist@0.0.8" }, + "minipass": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-1.1.9.tgz", + "from": "minipass@>=1.1.6 <2.0.0" + }, + "minizlib": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.2.tgz", + "from": "minizlib@>=1.0.2 <2.0.0" + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "from": "mkdirp@>=0.5.1 <0.6.0" }, "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "from": "ms@0.7.2" + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz", + "from": "ms@0.7.3" }, "number-is-nan": { "version": "1.0.1", @@ -640,8 +650,8 @@ "from": "regenerate@>=1.2.1 <2.0.0" }, "regenerator-runtime": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.4.tgz", "from": "regenerator-runtime@>=0.10.0 <0.11.0" }, "regenerator-transform": { @@ -672,9 +682,9 @@ } }, "reify": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz", - "from": "reify@>=0.7.2 <0.8.0" + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.8.2.tgz", + "from": "reify@>=0.8.0 <0.9.0" }, "repeating": { "version": "2.0.1", @@ -715,6 +725,11 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "from": "trim-right@>=1.0.1 <2.0.0" + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "from": "yallist@>=3.0.0 <4.0.0" } } } diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index f70575b227..9f4e01a024 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -10,7 +10,7 @@ Package.describe({ }); Npm.depends({ - 'meteor-babel': '0.20.1' + 'meteor-babel': '0.20.2' }); Package.onUse(function (api) { diff --git a/packages/modules/.npm/package/npm-shrinkwrap.json b/packages/modules/.npm/package/npm-shrinkwrap.json index 20c76d7a1d..b429851f1d 100644 --- a/packages/modules/.npm/package/npm-shrinkwrap.json +++ b/packages/modules/.npm/package/npm-shrinkwrap.json @@ -5,10 +5,25 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", "from": "acorn@>=5.0.0 <5.1.0" }, + "minipass": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-1.1.9.tgz", + "from": "minipass@>=1.1.6 <2.0.0" + }, + "minizlib": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.2.tgz", + "from": "minizlib@>=1.0.2 <2.0.0" + }, "reify": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz", - "from": "reify@0.7.4" + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.8.2.tgz", + "from": "reify@0.8.2" + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "from": "yallist@>=3.0.0 <4.0.0" } } } diff --git a/packages/modules/package.js b/packages/modules/package.js index ae781cf6cc..cea3053ba3 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -6,7 +6,7 @@ Package.describe({ }); Npm.depends({ - reify: "0.7.4" + reify: "0.8.2" }); Package.onUse(function(api) { diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 9d8d0ec578..2942cc3710 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -14,14 +14,15 @@ var packageJson = { npm: "4.4.4", "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", - "meteor-babel": "0.20.1", + "meteor-babel": "0.20.2", + reify: "0.8.2", "meteor-promise": "0.8.0", fibers: "1.0.15", promise: "7.1.1", // So that Babel 6 can emit require("babel-runtime/helpers/...") calls. "babel-runtime": "6.9.2", // For various ES2015 polyfills, such as Map and Set. - "meteor-ecmascript-runtime": "0.2.9", + "meteor-ecmascript-runtime": "0.3.0", // Not yet upgrading Underscore from 1.5.2 to 1.7.0 (which should be done // in the package too) because we should consider using lodash instead // (and there are backwards-incompatible changes either way). From 750217c386512778c9fc83815526e52f12bbec4a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 26 Apr 2017 14:36:03 -0400 Subject: [PATCH 068/125] Bump $BUNDLE_VERSION to 4.8.7 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index d9bb99c4d9..dd85865eb3 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.5 +BUNDLE_VERSION=4.8.7 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From f46b5f9e41aff7078acea5435778fc3741604c8d Mon Sep 17 00:00:00 2001 From: mutdmour Date: Wed, 26 Apr 2017 18:33:46 +0300 Subject: [PATCH 069/125] [Fix #5165] don't allow invalid field names (#8608) --- packages/minimongo/helpers.js | 2 +- packages/minimongo/minimongo.js | 22 ++-------- packages/minimongo/minimongo_tests.js | 59 ++++++++++++++++++++++++--- packages/minimongo/modify.js | 28 ++++++------- packages/minimongo/validation.js | 24 +++++++++++ 5 files changed, 94 insertions(+), 41 deletions(-) create mode 100644 packages/minimongo/validation.js diff --git a/packages/minimongo/helpers.js b/packages/minimongo/helpers.js index 759ce0ca62..a21c1dc49c 100644 --- a/packages/minimongo/helpers.js +++ b/packages/minimongo/helpers.js @@ -42,4 +42,4 @@ isOperatorObject = function (valueSelector, inconsistentOK) { // string can be converted to integer isNumericKey = function (s) { return /^[0-9]+$/.test(s); -}; +}; \ No newline at end of file diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js index 312c9e4581..dd2017ebce 100644 --- a/packages/minimongo/minimongo.js +++ b/packages/minimongo/minimongo.js @@ -1,3 +1,5 @@ +import { assertHasValidFieldNames } from './validation.js'; + // XXX type checking on selectors (graceful error if malformed) // LocalCollection: a set of documents that supports queries and modifiers. @@ -540,31 +542,13 @@ LocalCollection.Cursor.prototype._depend = function (changers, _allow_unordered) } }; -// XXX enforce rule that field names can't start with '$' or contain '.' -// (real mongodb does in fact enforce this) // XXX possibly enforce that 'undefined' does not appear (we assume // this in our handling of null and $exists) LocalCollection.prototype.insert = function (doc, callback) { var self = this; doc = EJSON.clone(doc); - // Make sure field names do not contain Mongo restricted - // characters ('.', '$', '\0'). - // https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names - if (doc) { - const invalidCharMsg = { - '.': "contain '.'", - '$': "start with '$'", - '\0': "contain null bytes", - }; - JSON.stringify(doc, (key, value) => { - let match; - if (_.isString(key) && (match = key.match(/^\$|\.|\0/))) { - throw MinimongoError(`Key ${key} must not ${invalidCharMsg[match[0]]}`); - } - return value; - }); - } + assertHasValidFieldNames(doc); if (!_.has(doc, '_id')) { // if you really want to use ObjectIDs, set this global. diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 9edc47c52e..87b23b6821 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -2207,6 +2207,13 @@ Tinytest.add("minimongo - modify", function (test) { test.equal(actual, expected); }; + var upsertException = function (query, mod) { + var coll = new LocalCollection; + test.throws(function(){ + coll.upsert(query, mod); + }); + }; + // document replacement modify({}, {}, {}); modify({a: 12}, {}, {}); // tested against mongodb @@ -2215,6 +2222,11 @@ Tinytest.add("minimongo - modify", function (test) { exception({a: 12}, {a: 13, $set: {b: 13}}); exception({a: 12}, {$set: {b: 13}, a: 13}); + exception({a: 12}, {$a: 13}); //invalid operator + exception({a: 12}, {b:{$a: 13}}); + exception({a: 12}, {b:{'a.b': 13}}); + exception({a: 12}, {b:{'\0a': 13}}); + // keys modify({}, {$set: {'a': 12}}, {a: 12}); modify({}, {$set: {'a.b': 12}}, {a: {b: 12}}); @@ -2383,6 +2395,12 @@ Tinytest.add("minimongo - modify", function (test) { modify({}, {$set: {'x._id': 4}}, {x: {_id: 4}}); exception({}, {$set: {_id: 4}}); exception({_id: 4}, {$set: {_id: 4}}); // even not-changing _id is bad + //restricted field names + exception({a:{}}, {$set:{a:{$a:1}}}); + exception({ a: {} }, { $set: { a: { c: + [{ b: { $a: 1 } }] } } }); + exception({a:{}}, {$set:{a:{'\0a':1}}}); + exception({a:{}}, {$set:{a:{'a.b':1}}}); // $unset modify({}, {$unset: {a: 1}}, {}); @@ -2457,7 +2475,16 @@ Tinytest.add("minimongo - modify", function (test) { {$push: {a: {$each: [{x: 3}], $position: 0, $sort: {x: 1}, $slice: 0}}}, {a: []} ); - + //restricted field names + exception({}, {$push: {$a: 1}}); + exception({}, {$push: {'\0a': 1}}); + exception({}, {$push: {a: {$a:1}}}); + exception({}, {$push: {a: {$each: [{$a:1}]}}}); + exception({}, {$push: {a: {$each: [{"a.b":1}]}}}); + exception({}, {$push: {a: {$each: [{'\0a':1}]}}}); + modify({}, {$push: {a: {$each: [{'':1}]}}}, {a: [ { '': 1 } ]}); + modify({}, {$push: {a: {$each: [{' ':1}]}}}, {a: [ { ' ': 1 } ]}); + exception({}, {$push: {a: {$each: [{'.':1}]}}}); // $pushAll modify({}, {$pushAll: {a: [1]}}, {a: [1]}); @@ -2475,6 +2502,9 @@ Tinytest.add("minimongo - modify", function (test) { modify({a: []}, {$pushAll: {'a.1': []}}, {a: [null, []]}); modify({a: {}}, {$pushAll: {'a.x': [99]}}, {a: {x: [99]}}); modify({a: {}}, {$pushAll: {'a.x': []}}, {a: {x: []}}); + exception({a: [1]}, {$pushAll: {a: [{$a:1}]}}); + exception({a: [1]}, {$pushAll: {a: [{'\0a':1}]}}); + exception({a: [1]}, {$pushAll: {a: [{"a.b":1}]}}); // $addToSet modify({}, {$addToSet: {a: 1}}, {a: [1]}); @@ -2493,14 +2523,25 @@ Tinytest.add("minimongo - modify", function (test) { modify({a: [{x: 1, y: 2}]}, {$addToSet: {a: {y: 2, x: 1}}}, {a: [{x: 1, y: 2}, {y: 2, x: 1}]}); modify({a: [1, 2]}, {$addToSet: {a: {$each: [3, 1, 4]}}}, {a: [1, 2, 3, 4]}); - modify({a: [1, 2]}, {$addToSet: {a: {$each: [3, 1, 4], b: 12}}}, - {a: [1, 2, 3, 4]}); // tested - modify({a: [1, 2]}, {$addToSet: {a: {b: 12, $each: [3, 1, 4]}}}, - {a: [1, 2, {b: 12, $each: [3, 1, 4]}]}); // tested modify({}, {$addToSet: {a: {$each: []}}}, {a: []}); modify({}, {$addToSet: {a: {$each: [1]}}}, {a: [1]}); modify({a: []}, {$addToSet: {'a.1': 99}}, {a: [null, [99]]}); modify({a: {}}, {$addToSet: {'a.x': 99}}, {a: {x: [99]}}); + + // invalid field names + exception({}, {$addToSet: {a: {$b:1}}}); + exception({}, {$addToSet: {a: {"a.b":1}}}); + exception({}, {$addToSet: {a: {"a.":1}}}); + exception({}, {$addToSet: {a: {'\u0000a':1}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, {$a:1}]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, {'\0a':1}]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, [{$a:1}]]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, [{b:{c:[{a:1},{"d.s":2}]}}]]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{b: [3, 1, [{b:{c:[{a:1},{"d.s":2}]}}]]}}}); + //$each is first element and thus an operator + modify({a: [1, 2]}, {$addToSet: {a: {$each: [3, 1, 4], b: 12}}},{a: [ 1, 2, 3, 4 ]}); + // this should fail because $each is now a field name (not first in object) and thus invalid field name with $ + exception({a: [1, 2]}, {$addToSet: {a: {b: 12, $each: [3, 1, 4]}}}); // $pop modify({}, {$pop: {a: 1}}, {}); // tested @@ -2574,11 +2615,19 @@ Tinytest.add("minimongo - modify", function (test) { exception({}, {$rename: {'a': 'a'}}); exception({}, {$rename: {'a.b': 'a.b'}}); modify({a: 12, b: 13}, {$rename: {a: 'b'}}, {b: 12}); + exception({a: [12]}, {$rename: {a: '$b'}}); + exception({a: [12]}, {$rename: {a: '\0a'}}); // $setOnInsert modify({a: 0}, {$setOnInsert: {a: 12}}, {a: 0}); upsert({a: 12}, {$setOnInsert: {b: 12}}, {a: 12, b: 12}); upsert({a: 12}, {$setOnInsert: {_id: 'test'}}, {_id: 'test', a: 12}); + upsertException({a: 0}, {$setOnInsert: {$a: 12}}); + upsertException({a: 0}, {$setOnInsert: {'\0a': 12}}); + upsert({a: 0}, {$setOnInsert: {b: {a:1}}}, {a:0, b:{a:1}}); + upsertException({a: 0}, {$setOnInsert: {b: {$a:1}}}); + upsertException({a: 0}, {$setOnInsert: {b: {'a.b':1}}}); + upsertException({a: 0}, {$setOnInsert: {b: {'\0a':1}}}); exception({}, {$set: {_id: 'bad'}}); diff --git a/packages/minimongo/modify.js b/packages/minimongo/modify.js index 7074482ee6..ebc285ddab 100644 --- a/packages/minimongo/modify.js +++ b/packages/minimongo/modify.js @@ -1,3 +1,5 @@ +import { assertHasValidFieldNames, assertIsValidFieldName } from './validation.js'; + // XXX need a strategy for passing the binding of $ into this // function, from the compiled selector // @@ -27,11 +29,7 @@ LocalCollection._modify = function (doc, mod, options) { throw MinimongoError("Cannot change the _id of a document"); // replace the whole document - for (var k in mod) { - if (/\./.test(k)) - throw MinimongoError( - "When replacing document, field name may not contain '.'"); - } + assertHasValidFieldNames(mod); newDoc = mod; } else { // apply modifiers to the doc. @@ -155,8 +153,7 @@ var findModTarget = function (doc, keyparts, options) { "' of list value " + JSON.stringify(doc[keypart])); } } else { - if (keypart.length && keypart.substr(0, 1) === '$') - throw MinimongoError("can't set field named " + keypart); + assertIsValidFieldName(keypart); if (!(keypart in doc)) { if (options.noCreate) return undefined; @@ -251,11 +248,7 @@ var MODIFIERS = { e.setPropertyError = true; throw e; } - if (_.isString(field) && field.indexOf('\0') > -1) { - // Null bytes are not allowed in Mongo field names - // https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names - throw MinimongoError(`Key ${field} must not contain null bytes`); - } + assertHasValidFieldNames(arg); target[field] = arg; }, $setOnInsert: function (target, field, arg) { @@ -279,6 +272,7 @@ var MODIFIERS = { if (!(arg && arg.$each)) { // Simple mode: not $each + assertHasValidFieldNames(arg); target[field].push(arg); return; } @@ -287,6 +281,7 @@ var MODIFIERS = { var toPush = arg.$each; if (!(toPush instanceof Array)) throw MinimongoError("$each must be an array", { field }); + assertHasValidFieldNames(toPush); // Parse $position var position = undefined; @@ -356,6 +351,7 @@ var MODIFIERS = { $pushAll: function (target, field, arg) { if (!(typeof arg === "object" && arg instanceof Array)) throw MinimongoError("Modifier $pushAll/pullAll allowed for arrays only"); + assertHasValidFieldNames(arg); var x = target[field]; if (x === undefined) target[field] = arg; @@ -371,13 +367,13 @@ var MODIFIERS = { var isEach = false; if (typeof arg === "object") { //check if first key is '$each' - for (var k in arg) { - if (k === "$each") - isEach = true; - break; + const keys = Object.keys(arg); + if (keys[0] === "$each"){ + isEach = true; } } var values = isEach ? arg["$each"] : [arg]; + assertHasValidFieldNames(values); var x = target[field]; if (x === undefined) target[field] = values; diff --git a/packages/minimongo/validation.js b/packages/minimongo/validation.js new file mode 100644 index 0000000000..ef73560a72 --- /dev/null +++ b/packages/minimongo/validation.js @@ -0,0 +1,24 @@ +// Make sure field names do not contain Mongo restricted +// characters ('.', '$', '\0'). +// https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names +const invalidCharMsg = { + '.': "contain '.'", + '$': "start with '$'", + '\0': "contain null bytes", +}; +export function assertIsValidFieldName(key) { + let match; + if (_.isString(key) && (match = key.match(/^\$|\.|\0/))) { + throw MinimongoError(`Key ${key} must not ${invalidCharMsg[match[0]]}`); + } +}; + +// checks if all field names in an object are valid +export function assertHasValidFieldNames(doc){ + if (doc && typeof doc === "object") { + JSON.stringify(doc, (key, value) => { + assertIsValidFieldName(key); + return value; + }); + } +}; \ No newline at end of file From 9da6767447e5c5afae86401e518d8d5b36519148 Mon Sep 17 00:00:00 2001 From: mutdmour Date: Wed, 26 Apr 2017 18:42:11 +0300 Subject: [PATCH 070/125] Handle legacy coordinates as GeoJSON in minimongo (#2077) (#8620) --- packages/minimongo/minimongo_tests.js | 29 +++++++++++++++++++++++++++ packages/minimongo/selector.js | 13 +++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 87b23b6821..21ae3169cc 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -3232,6 +3232,35 @@ Tinytest.add("minimongo - $near operator tests", function (test) { handle.stop(); }); +// issue #2077 +Tinytest.add("minimongo - $near and $geometry for legacy coordinates", function(test){ + var coll = new LocalCollection(); + + coll.insert({ + loc: { + x: 1, + y: 1 + } + }); + coll.insert({ + loc: [-1,-1] + }); + coll.insert({ + loc: [40,-10] + }); + coll.insert({ + loc: { + x: -10, + y: 40 + } + }); + + test.equal(coll.find({ 'loc': { $near: [0, 0], $maxDistance: 4 } }).count(), 2); + test.equal(coll.find({ 'loc': { $near: {$geometry: {type: "Point", coordinates: [0, 0]}}} }).count(), 4); + test.equal(coll.find({ 'loc': { $near: {$geometry: {type: "Point", coordinates: [0, 0]}, $maxDistance:200000}}}).count(), 2); + +}); + // Regression test for #4377. Previously, "replace" updates didn't clone the // argument. Tinytest.add("minimongo - update should clone", function (test) { diff --git a/packages/minimongo/selector.js b/packages/minimongo/selector.js index 7d2fcb6676..f3034094d1 100644 --- a/packages/minimongo/selector.js +++ b/packages/minimongo/selector.js @@ -435,9 +435,10 @@ var VALUE_OPERATORS = { throw Error("$near can't be inside another $ operator"); matcher._hasGeoQuery = true; - // There are two kinds of geodata in MongoDB: coordinate pairs and + // There are two kinds of geodata in MongoDB: legacy coordinate pairs and // GeoJSON. They use different distance metrics, too. GeoJSON queries are - // marked with a $geometry property. + // marked with a $geometry property, though legacy coordinates can be + // matched using $geometry. var maxDistance, point, distance; if (isPlainObject(operand) && _.has(operand, '$geometry')) { @@ -448,8 +449,11 @@ var VALUE_OPERATORS = { // XXX: for now, we don't calculate the actual distance between, say, // polygon and circle. If people care about this use-case it will get // a priority. - if (!value || !value.type) + if (!value) return null; + if(!value.type) + return GeoJSON.pointDistance(point, + { type: "Point", coordinates: pointToArray(value) }); if (value.type === "Point") { return GeoJSON.pointDistance(point, value); } else { @@ -481,6 +485,9 @@ var VALUE_OPERATORS = { branchedValues = expandArraysInBranches(branchedValues); var result = {result: false}; _.each(branchedValues, function (branch) { + if (!(typeof branch.value === "object")){ + return; + } var curDistance = distance(branch.value); // Skip branches that aren't real points or are too far away. if (curDistance === null || curDistance > maxDistance) From 5a4d5035c3deffca5384366e15c3f4d14b55a551 Mon Sep 17 00:00:00 2001 From: Bartosz Wojtkowiak Date: Wed, 26 Apr 2017 20:43:39 +0200 Subject: [PATCH 071/125] Implement CORDOVA_COMPATIBILITY_VERSION_IOS/ANDROID and EXCLUDE (#8581) * Implement CORDOVA_COMPATIBILITY_VERSION_EXCLUDE and CORDOVA_COMPATIBILITY_VERSION_IOS/ANDROID CORDOVA_COMPATIBILITY_VERSION_IOS or CORDOVA_COMPATIBILITY_VERSION_ANDROID allows to override compatibility version for a specified platform. CORDOVA_COMPATIBILITY_VERSION_EXCLUDE provides a way of excluding a certain plugin from compatibility version calculation. You can pass several plugin names with ';'. For example: `CORDOVA_COMPATIBILITY_VERSION_EXCLUDE='cordova-plugin-crosswalk-webview;cordova-plugin-device'` * Changes after review --- tools/isobuild/bundler.js | 17 +++++++++++--- tools/tests/cordova-hcp.js | 47 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index 3bbc8cacb4..87add438ad 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -1522,11 +1522,22 @@ class ClientTarget extends Target { if (this.arch === 'web.cordova') { const { WebAppHashing } = loadIsopacket('cordova-support')['webapp-hashing']; + const cordovaCompatibilityVersions = _.object(_.map(CORDOVA_PLATFORM_VERSIONS, (version, platform) => { - const hash = WebAppHashing.calculateCordovaCompatibilityHash( - version, - this.cordovaDependencies); + + const pluginsExcludedFromCompatibilityHash = (process.env.METEOR_CORDOVA_COMPAT_VERSION_EXCLUDE || '') + .split(','); + + const cordovaDependencies = Object.assign( + Object.create(null), + _.omit(this.cordovaDependencies, pluginsExcludedFromCompatibilityHash) + ); + + const hash = process.env[`METEOR_CORDOVA_COMPAT_VERSION_${platform.toUpperCase()}`] || + WebAppHashing.calculateCordovaCompatibilityHash( + version, + cordovaDependencies); return [platform, hash]; })); program.cordovaCompatibilityVersions = cordovaCompatibilityVersions; diff --git a/tools/tests/cordova-hcp.js b/tools/tests/cordova-hcp.js index 1a15ec88b8..efd7be0e55 100644 --- a/tools/tests/cordova-hcp.js +++ b/tools/tests/cordova-hcp.js @@ -39,3 +39,50 @@ selftest.define( run.stop(); }); + +selftest.define( + "cordova METEOR_CORDOVA_COMPAT_VERSION_* works", ["cordova", "slow"], function () { + var s = new Sandbox(); + var run; + + var androidCompatibilityVersion = '2.0'; + + // Override the compatibility version for android with METEOR_CORDOVA_COMPAT_VERSION_ANDROID. + s.env.METEOR_CORDOVA_COMPAT_VERSION_ANDROID = androidCompatibilityVersion; + + s.createApp("myapp", "standard-app"); + s.cd("myapp"); + + var platforms = s.read(".meteor/platforms"); + s.write(".meteor/platforms", platforms + "\nandroid\n"); + + run = s.run("run", "android", "--mobile-server", "example.com"); + run.waitSecs(30); + run.match("Started your app"); + + var result = JSON.parse(httpHelpers.getUrl( + "http://localhost:3000/__cordova/manifest.json")); + + // Check in the manifest if the overridden version was used. + selftest.expectEqual(result.cordovaCompatibilityVersions.android, androidCompatibilityVersion); + + run.stop(); + // Save the iOS compatibility version. + var iosCompatibilityVersion = result.cordovaCompatibilityVersions.ios; + + // Now exclude one of the plugins from compatibility version calculation. + s.env.METEOR_CORDOVA_COMPAT_VERSION_EXCLUDE = 'cordova-plugin-meteor-webapp,any-other-plugin'; + + run = s.run("run", "android", "--mobile-server", "example.com"); + run.waitSecs(30); + run.match("Started your app"); + + result = JSON.parse(httpHelpers.getUrl( + "http://localhost:3000/__cordova/manifest.json")); + + // Version should be different. There is no need to check if the particular plugin was not taken into account, + // if the version has changed it's proof enough. + selftest.expectFalse(result.cordovaCompatibilityVersions.ios === iosCompatibilityVersion); + + run.stop(); +}); \ No newline at end of file From 30e9e01afaa5d72453ab32467e5c5059319fd02e Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Wed, 26 Apr 2017 13:26:09 -0700 Subject: [PATCH 072/125] Bump package versions for 1.4.4.2-rc.1 release. --- packages/accounts-base/package.js | 2 +- packages/accounts-password/package.js | 2 +- packages/meetup-oauth/package.js | 2 +- packages/meteor-tool/package.js | 2 +- packages/minimongo/package.js | 2 +- packages/mongo/package.js | 2 +- packages/tracker/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index 1b8a07992e..86d2be8d2a 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A user account system", - version: "1.2.17-rc.0" + version: "1.2.17-rc.1" }); Package.onUse(function (api) { diff --git a/packages/accounts-password/package.js b/packages/accounts-password/package.js index a71eafd785..0b9f21a7e1 100644 --- a/packages/accounts-password/package.js +++ b/packages/accounts-password/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Password support for accounts", - version: "1.3.6-rc.0" + version: "1.3.6-rc.1" }); Package.onUse(function(api) { diff --git a/packages/meetup-oauth/package.js b/packages/meetup-oauth/package.js index b50df01a30..2a1a017579 100644 --- a/packages/meetup-oauth/package.js +++ b/packages/meetup-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: 'Meetup OAuth flow', - version: '1.0.1-rc.0' + version: '1.0.1-rc.1' }); Package.onUse(function (api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index cf3bcd4938..dedda8811e 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.4.4-2-rc.0' + version: '1.4.4-2-rc.1' }); Package.includeTool(); diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index 402e57eede..00e983b9e2 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.0.22-rc.0' + version: '1.0.22-rc.1' }); Package.onUse(function (api) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 13b6fd06ff..5ceeadce0e 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.1.17-rc.0' + version: '1.1.17-rc.1' }); Npm.depends({ diff --git a/packages/tracker/package.js b/packages/tracker/package.js index d29b0dfd06..de0712cc12 100644 --- a/packages/tracker/package.js +++ b/packages/tracker/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Dependency tracker to allow reactive callbacks", - version: '1.1.3-rc.0' + version: '1.1.3-rc.1' }); Package.onUse(function (api) { diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 35e6359c03..a92fd7261f 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.4.4.2-rc.0", + "version": "1.4.4.2-rc.1", "recommended": false, "official": false, "description": "Meteor" From 03e998c0daf5a1734699c5a442634df5b6d5caed Mon Sep 17 00:00:00 2001 From: mutdmour Date: Sat, 22 Apr 2017 09:15:30 +0300 Subject: [PATCH 073/125] sort overrides $near sort - minimongo (#3599) --- packages/minimongo/minimongo_tests.js | 5 +++-- packages/minimongo/sort.js | 16 +++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 21ae3169cc..c03e885995 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -3207,13 +3207,14 @@ Tinytest.add("minimongo - $near operator tests", function (test) { // 'y'. testNear([2, 2], 1000, ['x', 'y']); - // Ensure that distance is used as a tie-breaker for sort. + // issue #3599 + // Ensure that distance are not used as a tie-breaker for sort. test.equal( _.pluck(coll.find({'a.b': {$near: [1, 1]}}, {sort: {k: 1}}).fetch(), '_id'), ['x', 'y']); test.equal( _.pluck(coll.find({'a.b': {$near: [5, 5]}}, {sort: {k: 1}}).fetch(), '_id'), - ['y', 'x']); + ['x', 'y']); var operations = []; var cbs = log_callbacks(operations); diff --git a/packages/minimongo/sort.js b/packages/minimongo/sort.js index 7c90b8f650..aebbcc2d4f 100644 --- a/packages/minimongo/sort.js +++ b/packages/minimongo/sort.js @@ -81,23 +81,25 @@ _.extend(Minimongo.Sorter.prototype, { getComparator: function (options) { var self = this; - // If we have no distances, just use the comparator from the source - // specification (which defaults to "everything is equal". - if (!options || !options.distances) { + // If sort is specified or have no distances, just use the comparator from + // the source specification (which defaults to "everything is equal". + // issue #3599 + // https://docs.mongodb.com/manual/reference/operator/query/near/#sort-operation + // sort effectively overrides $near + if (self._sortSpecParts.length || !options || !options.distances) { return self._getBaseComparator(); } var distances = options.distances; - // Return a comparator which first tries the sort specification, and if that - // says "it's equal", breaks ties using $near distances. - return composeComparators([self._getBaseComparator(), function (a, b) { + // Return a comparator which compares using $near distances. + return function (a, b) { if (!distances.has(a._id)) throw Error("Missing distance for " + a._id); if (!distances.has(b._id)) throw Error("Missing distance for " + b._id); return distances.get(a._id) - distances.get(b._id); - }]); + }; }, _getPaths: function () { From 3ad95d4deff13329846c78fb01528415053293a7 Mon Sep 17 00:00:00 2001 From: mutdmour Date: Wed, 26 Apr 2017 08:35:55 +0300 Subject: [PATCH 074/125] Using $near to query with an update (#3599) --- packages/minimongo/minimongo.js | 2 +- packages/minimongo/minimongo_tests.js | 40 ++++++++++++++++++++++----- packages/minimongo/selector.js | 10 +++++-- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js index dd2017ebce..92265e6a90 100644 --- a/packages/minimongo/minimongo.js +++ b/packages/minimongo/minimongo.js @@ -699,7 +699,7 @@ LocalCollection.prototype.update = function (selector, mod, options, callback) { } if (!options) options = {}; - var matcher = new Minimongo.Matcher(selector); + var matcher = new Minimongo.Matcher(selector, true); // Save the original results of any query that we might need to // _recomputeResults on, because _modifyAndNotify will mutate the objects in diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index c03e885995..ae8c12867a 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -2301,13 +2301,7 @@ Tinytest.add("minimongo - modify", function (test) { {'a.x': 1, 'a.y': 3}, {$set: {'a.$.z': 5}}, {a: [{x: 1}, {y: 3, z: 5}]}); - // with $near, make sure it finds the closest one - modifyWithQuery({a: [{b: [1,1]}, - {b: [ [3,3], [4,4] ]}, - {b: [9,9]}]}, - {'a.b': {$near: [5, 5]}}, - {$set: {'a.$.b': 'k'}}, - {a: [{b: [1,1]}, {b: 'k'}, {b: [9,9]}]}); + // with $near, make sure it does not find the closest one (#3599) modifyWithQuery({a: [{x: 1}, {y: 1}, {x: 1, y: 1}]}, {a: {$elemMatch: {x: 1, y: 1}}}, {$set: {'a.$.x': 2}}, @@ -2316,6 +2310,38 @@ Tinytest.add("minimongo - modify", function (test) { {'a.b': {$elemMatch: {x: 1, y: 1}}}, {$set: {'a.$.b': 3}}, {a: [{b: 3}]}); + modifyWithQuery({a: []}, + {'a.b': {$near: [5, 5]}}, + {$set: {'a.$.b': 'k'}}, + {"a":[]}); + modifyWithQuery({a: [{b: [ [3,3], [4,4] ]}]}, + {'a.b': {$near: [5, 5]}}, + {$set: {'a.$.b': 'k'}}, + {"a":[{"b":"k"}]}); + modifyWithQuery({a: [{b: [1,1]}, + {b: [ [3,3], [4,4] ]}, + {b: [9,9]}]}, + {'a.b': {$near: [5, 5]}}, + {$set: {'a.$.b': 'k'}}, + {"a":[{"b":"k"},{"b":[[3,3],[4,4]]},{"b":[9,9]}]}); + modifyWithQuery({a: [{b: [1,1]}, + {b: [ [3,3], [4,4] ]}, + {b: [9,9]}]}, + {'a.b': {$near: [9, 9]}}, + {$set: {'a.$.b': 'k'}}, + {"a":[{"b":"k"},{"b":[[3,3],[4,4]]},{"b":[9,9]}]}); + modifyWithQuery({a: [{b: [9,9]}, + {b: [ [3,3], [4,4] ]}, + {b: [9,9]}]}, + {'a.b': {$near: [9, 9]}}, + {$set: {'a.$.b': 'k'}}, + {"a":[{"b":"k"},{"b":[[3,3],[4,4]]},{"b":[9,9]}]}); + modifyWithQuery({a: [{b: [9,9]}, + {b: [ [3,3], [4,4] ]}, + {b: [1,1]}]}, + {'a.b': {$near: [9, 9]}}, + {$set: {'a.$.b': 'k'}}, + {"a":[{"b":"k"},{"b":[[3,3],[4,4]]},{"b":[1,1]}]}); // $inc modify({a: 1, b: 2}, {$inc: {a: 10}}, {a: 11, b: 2}); diff --git a/packages/minimongo/selector.js b/packages/minimongo/selector.js index f3034094d1..355abbf3e8 100644 --- a/packages/minimongo/selector.js +++ b/packages/minimongo/selector.js @@ -18,7 +18,7 @@ // Main entry point. // var matcher = new Minimongo.Matcher({a: {$gt: 5}}); // if (matcher.documentMatches({a: 7})) ... -Minimongo.Matcher = function (selector) { +Minimongo.Matcher = function (selector, isUpdate = false) { var self = this; // A set (object mapping string -> *) of all of the document paths looked // at by the selector. Also includes the empty string if it may look at any @@ -41,6 +41,10 @@ Minimongo.Matcher = function (selector) { // Sorter._useWithMatcher. self._selector = null; self._docMatcher = self._compileSelector(selector); + // Set to true if selection is done for an update operation + // Default is false + // Used for $near array update (issue #3599) + self._isUpdate = isUpdate; }; _.extend(Minimongo.Matcher.prototype, { @@ -497,7 +501,9 @@ var VALUE_OPERATORS = { return; result.result = true; result.distance = curDistance; - if (!branch.arrayIndices) + if (matcher._isUpdate) + result.arrayIndices = [0,0]; + else if (!branch.arrayIndices) delete result.arrayIndices; else result.arrayIndices = branch.arrayIndices; From 9efa22fd8fc49c8c549e985203cf0f477e9f0421 Mon Sep 17 00:00:00 2001 From: mutdmour Date: Thu, 27 Apr 2017 08:49:12 +0300 Subject: [PATCH 075/125] More test cases for update with $near (#3599) --- packages/minimongo/minimongo_tests.js | 27 +++++++++++++++++++----- packages/minimongo/selector.js | 30 +++++++++++++++------------ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index ae8c12867a..2ad86ad6c4 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -2301,7 +2301,6 @@ Tinytest.add("minimongo - modify", function (test) { {'a.x': 1, 'a.y': 3}, {$set: {'a.$.z': 5}}, {a: [{x: 1}, {y: 3, z: 5}]}); - // with $near, make sure it does not find the closest one (#3599) modifyWithQuery({a: [{x: 1}, {y: 1}, {x: 1, y: 1}]}, {a: {$elemMatch: {x: 1, y: 1}}}, {$set: {'a.$.x': 2}}, @@ -2310,6 +2309,7 @@ Tinytest.add("minimongo - modify", function (test) { {'a.b': {$elemMatch: {x: 1, y: 1}}}, {$set: {'a.$.b': 3}}, {a: [{b: 3}]}); + // with $near, make sure it does not find the closest one (#3599) modifyWithQuery({a: []}, {'a.b': {$near: [5, 5]}}, {$set: {'a.$.b': 'k'}}, @@ -2323,7 +2323,13 @@ Tinytest.add("minimongo - modify", function (test) { {b: [9,9]}]}, {'a.b': {$near: [5, 5]}}, {$set: {'a.$.b': 'k'}}, - {"a":[{"b":"k"},{"b":[[3,3],[4,4]]},{"b":[9,9]}]}); + {"a":[{"b":"k"},{"b":[[3,3],[4,4]]},{"b":[9,9]}]}); + modifyWithQuery({a: [{b: [1,1]}, + {b: [ [3,3], [4,4] ]}, + {b: [9,9]}]}, + {'a.b': {$near: [9, 9], $maxDistance: 1}}, + {$set: {'a.$.b': 'k'}}, + {"a":[{"b":"k"},{"b":[[3,3],[4,4]]},{"b":[9,9]}]}); modifyWithQuery({a: [{b: [1,1]}, {b: [ [3,3], [4,4] ]}, {b: [9,9]}]}, @@ -2336,12 +2342,23 @@ Tinytest.add("minimongo - modify", function (test) { {'a.b': {$near: [9, 9]}}, {$set: {'a.$.b': 'k'}}, {"a":[{"b":"k"},{"b":[[3,3],[4,4]]},{"b":[9,9]}]}); - modifyWithQuery({a: [{b: [9,9]}, + modifyWithQuery({a: [{b:[4,3]}, + {c: [1,1]}]}, + {'a.c': {$near: [1, 1]}}, + {$set: {'a.$.c': 'k'}}, + {"a":[{"c": "k", "b":[4,3]},{"c":[1,1]}]}); + modifyWithQuery({a: [{c: [9,9]}, {b: [ [3,3], [4,4] ]}, {b: [1,1]}]}, - {'a.b': {$near: [9, 9]}}, + {'a.b': {$near: [1, 1]}}, {$set: {'a.$.b': 'k'}}, - {"a":[{"b":"k"},{"b":[[3,3],[4,4]]},{"b":[1,1]}]}); + {"a":[{"c": [9,9], "b":"k"},{"b": [ [3,3], [4,4]]},{"b":[1,1]}]}); + modifyWithQuery({a: [{c: [9,9], b:[4,3]}, + {b: [ [3,3], [4,4] ]}, + {b: [1,1]}]}, + {'a.b': {$near: [1, 1]}}, + {$set: {'a.$.b': 'k'}}, + {"a":[{"c": [9,9], "b":"k"},{"b": [ [3,3], [4,4]]},{"b":[1,1]}]}); // $inc modify({a: 1, b: 2}, {$inc: {a: 10}}, {a: 11, b: 2}); diff --git a/packages/minimongo/selector.js b/packages/minimongo/selector.js index 355abbf3e8..7088fa751a 100644 --- a/packages/minimongo/selector.js +++ b/packages/minimongo/selector.js @@ -488,25 +488,29 @@ var VALUE_OPERATORS = { // each within-$maxDistance branching point. branchedValues = expandArraysInBranches(branchedValues); var result = {result: false}; - _.each(branchedValues, function (branch) { - if (!(typeof branch.value === "object")){ - return; + _.every(branchedValues, function (branch) { + // if operation is an update, don't skip branches, just return the first one (#3599) + if (!matcher._isUpdate){ + if (!(typeof branch.value === "object")){ + return true; + } + var curDistance = distance(branch.value); + // Skip branches that aren't real points or are too far away. + if (curDistance === null || curDistance > maxDistance) + return true; + // Skip anything that's a tie. + if (result.distance !== undefined && result.distance <= curDistance) + return true; } - var curDistance = distance(branch.value); - // Skip branches that aren't real points or are too far away. - if (curDistance === null || curDistance > maxDistance) - return; - // Skip anything that's a tie. - if (result.distance !== undefined && result.distance <= curDistance) - return; result.result = true; result.distance = curDistance; - if (matcher._isUpdate) - result.arrayIndices = [0,0]; - else if (!branch.arrayIndices) + if (!branch.arrayIndices) delete result.arrayIndices; else result.arrayIndices = branch.arrayIndices; + if (matcher._isUpdate) + return false; + return true; }); return result; }; From a061567f4075d9a0620efaaf843ae888ed567a7a Mon Sep 17 00:00:00 2001 From: mutdmour Date: Thu, 27 Apr 2017 08:57:38 +0300 Subject: [PATCH 076/125] comment grammar (#3599) --- packages/minimongo/minimongo_tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 2ad86ad6c4..8ab18a39c7 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -3251,7 +3251,7 @@ Tinytest.add("minimongo - $near operator tests", function (test) { testNear([2, 2], 1000, ['x', 'y']); // issue #3599 - // Ensure that distance are not used as a tie-breaker for sort. + // Ensure that distance is not used as a tie-breaker for sort. test.equal( _.pluck(coll.find({'a.b': {$near: [1, 1]}}, {sort: {k: 1}}).fetch(), '_id'), ['x', 'y']); From dbc3f8461e31b8f9d6878e6fc6b6f8b970f78642 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 27 Apr 2017 17:18:32 -0400 Subject: [PATCH 077/125] Upgrade the `reify` npm package to version 0.8.3. --- History.md | 2 +- packages/modules/.npm/package/npm-shrinkwrap.json | 6 +++--- packages/modules/package.js | 2 +- scripts/dev-bundle-tool-package.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index 538e6512bc..0ae0a1e646 100644 --- a/History.md +++ b/History.md @@ -10,7 +10,7 @@ use it in your applications. * The `meteor-babel` npm package has been upgraded to version 0.20.2, and - the `reify` npm package has been upgraded to version 0.8.2, fixing + the `reify` npm package has been upgraded to version 0.8.3, fixing [issue #8595](https://github.com/meteor/meteor/issues/8595) and improving compilation performance. diff --git a/packages/modules/.npm/package/npm-shrinkwrap.json b/packages/modules/.npm/package/npm-shrinkwrap.json index b429851f1d..f8f8d11e48 100644 --- a/packages/modules/.npm/package/npm-shrinkwrap.json +++ b/packages/modules/.npm/package/npm-shrinkwrap.json @@ -16,9 +16,9 @@ "from": "minizlib@>=1.0.2 <2.0.0" }, "reify": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.8.2.tgz", - "from": "reify@0.8.2" + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.8.3.tgz", + "from": "reify@0.8.3" }, "yallist": { "version": "3.0.2", diff --git a/packages/modules/package.js b/packages/modules/package.js index cea3053ba3..554fa59771 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -6,7 +6,7 @@ Package.describe({ }); Npm.depends({ - reify: "0.8.2" + reify: "0.8.3" }); Package.onUse(function(api) { diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index e797a5f4e1..9d0a91c697 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -15,7 +15,7 @@ var packageJson = { "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", "meteor-babel": "0.20.2", - reify: "0.8.2", + reify: "0.8.3", "meteor-promise": "0.8.0", fibers: "1.0.15", promise: "7.1.1", From 9cc97f28a92b52fd56062366fd012ca843de98a7 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 27 Apr 2017 17:19:19 -0400 Subject: [PATCH 078/125] Bump $BUNDLE_VERSION to 4.8.8 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index dd85865eb3..638c472594 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.7 +BUNDLE_VERSION=4.8.8 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From d7cae3c939e2231ed89e694d05fe5f3698540b72 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 25 Apr 2017 20:03:05 -0400 Subject: [PATCH 079/125] Support pkg.module in client bundles, even for node_modules. As proposed here: https://github.com/rollup/rollup/wiki/pkg.module By supporting ECMAScript module entry points for npm packages in Meteor 1.5, we will be well-positioned to do more effective import/export-based tree shaking in future versions of Meteor. We can't do the same thing on the server because we can't change how native Node resolves package entry points based on the "main" field of the package.json module. On the other hand, all npm packages have to work in Node using the "main" field, and client bundles stand to benefit the most from tree shaking, so this client/server difference should not be problematic. Note that the "jsnext:main" property is also supported as a legacy synonym for "module". --- packages/dynamic-import/client.js | 4 +- .../.npm/package/npm-shrinkwrap.json | 6 +-- packages/modules-runtime/client.js | 2 + packages/modules-runtime/meteor-install.js | 21 +++++--- packages/modules-runtime/package.js | 2 +- tools/isobuild/import-scanner.js | 17 +++++- tools/isobuild/js-analyze.js | 54 ++++++++++++++++++- tools/isobuild/linker.js | 16 +++--- tools/isobuild/resolver.js | 20 ++++--- tools/tests/apps/dynamic-import/package.json | 2 +- tools/tests/apps/dynamic-import/tests.js | 10 +++- 11 files changed, 121 insertions(+), 33 deletions(-) diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index 4a818aa57a..17703c4b6e 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -41,7 +41,7 @@ Mp.prefetch = function (id) { function walk(meta) { if (meta.dynamic && ! meta.pending) { meta.pending = true; - var id = meta.module.id; + var id = meta.mod.id; versions[id] = getFromTree(dynamicVersions, id); meta.eachChild(walkChild); } @@ -132,7 +132,7 @@ function installResults(resultsTree, doNotCache) { function walk(tree) { if (typeof tree === "string") { var meta = requireMeta(parts.join("/")); - var id = meta.module.id; + var id = meta.mod.id; var optionsIndex = options.indexOf(meta.options); if (optionsIndex < 0) { options[optionsIndex = options.length] = meta.options; diff --git a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json index 5186366969..9923bcf12b 100644 --- a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json +++ b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "install": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/install/-/install-0.8.8.tgz", - "from": "install@0.8.8" + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/install/-/install-0.8.9.tgz", + "from": "install@0.8.9" } } } diff --git a/packages/modules-runtime/client.js b/packages/modules-runtime/client.js index 570609ef60..a6be2fb3d1 100644 --- a/packages/modules-runtime/client.js +++ b/packages/modules-runtime/client.js @@ -1,5 +1,7 @@ // On the client, make package resolution prefer the "browser" field of // package.json files to the "main" field. makeInstallerOptions.browser = true; +makeInstallerOptions.mainFields = + ["browser", "module", "jsnext:main", "main"]; install = makeInstaller(makeInstallerOptions); diff --git a/packages/modules-runtime/meteor-install.js b/packages/modules-runtime/meteor-install.js index 57c40ec4d1..9b9263f61b 100644 --- a/packages/modules-runtime/meteor-install.js +++ b/packages/modules-runtime/meteor-install.js @@ -3,7 +3,8 @@ // metadata about all available modules, not only those already installed // but also modules that can be fetched dynamically. var metaInstall = makeInstaller({ - browser: makeInstallerOptions.browser + browser: makeInstallerOptions.browser, + mainFields: makeInstallerOptions.mainFields }); meteorInstall = function (tree, options) { @@ -111,16 +112,24 @@ function makeMetaFunc(value, dynamic, options) { // graph to read its "main" and "browser" properties. var pkg = requireReal(module.id); - if (typeof pkg.main === "string") { - exports.main = pkg.main; + function copy(name) { + if (typeof pkg[name] === "string") { + exports[name] = pkg[name]; + } } - if (typeof pkg.browser === "string") { - exports.browser = pkg.browser; + if (Meteor.isClient) { + copy("browser"); + copy("module"); + copy("jsnext:main"); } + + copy("main"); } - exports.module = module; + // This needs to have a different name from the "module" property that + // may have been added above. + exports.mod = module; exports.dynamic = !! dynamic; exports.options = options; diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index cb3e51fd28..7bc4e61aeb 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -7,7 +7,7 @@ Package.describe({ }); Npm.depends({ - install: "0.8.8" + install: "0.8.9" }); Package.onUse(function(api) { diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index d71568de7c..6026935029 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -6,7 +6,10 @@ import { } from "underscore"; import {sha1} from "../fs/watch.js"; import {matches as archMatches} from "../utils/archinfo.js"; -import {findImportedModuleIdentifiers} from "./js-analyze.js"; +import { + findImportedModuleIdentifiers, + reifyCompileWithCache, +} from "./js-analyze.js"; import {cssToCommonJS} from "./css-modules.js"; import buildmessage from "../utils/buildmessage.js"; import LRU from "lru-cache"; @@ -740,6 +743,12 @@ export default class ImportScanner { info.hash, ); + if (this.isWeb()) { + const result = reifyCompileWithCache(info.dataString, info.hash); + info.dataString = result.code; + info.deps = result.deps; + } + if (info.dataString !== dataString) { info.data = new Buffer(info.dataString, "utf8"); } @@ -932,7 +941,11 @@ export default class ImportScanner { } const data = new Buffer(map(pkg, (value, key) => { - return `exports.${key} = ${JSON.stringify(value)};\n`; + const isIdentifier = /^[_$a-zA-Z]\w*$/.test(key); + const prop = isIdentifier + ? "." + key + : "[" + JSON.stringify(key) + "]"; + return `exports${prop} = ${JSON.stringify(value)};\n`; }).join("")); const relPkgJsonPath = pathRelative(this.sourceRoot, pkgJsonPath); diff --git a/tools/isobuild/js-analyze.js b/tools/isobuild/js-analyze.js index bc36d061a6..cb945fd663 100644 --- a/tools/isobuild/js-analyze.js +++ b/tools/isobuild/js-analyze.js @@ -1,5 +1,7 @@ -import { parse } from 'meteor-babel'; +import { parse as meteorBabelParse } from 'meteor-babel'; import { analyze as analyzeScope } from 'escope'; +import { Profile } from "../tool-env/profile.js"; +import { compile as reifyCompile } from "reify/lib/compiler.js"; import LRU from "lru-cache"; const hasOwn = Object.prototype.hasOwnProperty; @@ -20,7 +22,7 @@ function tryToParse(source, hash) { let ast; try { - ast = parse(source); + ast = meteorBabelParse(source); } catch (e) { if (typeof e.loc === 'object') { e.$ParseError = true; @@ -35,6 +37,54 @@ function tryToParse(source, hash) { return ast; } +// Map from file hash to Reify-compiled output. +const REIFY_COMPILE_CACHE = new LRU({ + max: Math.pow(2, 20), + length(result) { + return result.code.length; + } +}); + +export const reifyCompileWithCache = Profile( + "reifyCompileWithCache (js-analyze.js)", + function (source, hash) { + if (hash && REIFY_COMPILE_CACHE.has(hash)) { + return REIFY_COMPILE_CACHE.get(hash); + } + + const result = reifyCompile(source, { + // Do not modify the AST, nor bother returning result.ast. + ast: false, + // It's not our job to enforce strict mode here. + enforceStrictMode: false, + // We may be generating code for JavaScript environments that don't + // support const and let declarations (e.g. older browsers), so it + // would be dangerous at this stage to introduce such declarations. + // Fortunately, reifyCompileWithCache is only called for modules in + // node_modules, which should only be using top-level import and + // export declarations, so there should not be any difference. + generateLetDeclarations: false, + // Same concern for arrow functions as for const/let declarations. + avoidArrowFunctions: true, + parse(code) { + // Avoid double-parsing the input source, but allow Reify to parse + // other strings using the meteor-babel parser. + return code === source + ? tryToParse(code, hash) + : meteorBabelParse(code); + } + }); + + result.deps = findImportedModuleIdentifiers(source, hash); + + if (hash) { + REIFY_COMPILE_CACHE.set(hash, result); + } + + return result; + } +); + var dependencyKeywordPattern = /\b(?:require|import|importSync|dynamicImport|export)\b/g; diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index 3b32b8620f..58b8c69418 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -270,15 +270,17 @@ _.extend(Module.prototype, { if (file.installPath.endsWith("/package.json") && file.jsonData) { - const main = file.jsonData.main; - if (_.isString(main)) { - entry.main = main; + function tryMain(name) { + const value = file.jsonData[name]; + if (_.isString(value)) { + entry[name] = value; + } } - const browser = file.jsonData.browser; - if (_.isString(browser)) { - entry.browser = browser; - } + tryMain("browser"); + tryMain("module"); + tryMain("jsnext:main"); + tryMain("main"); } addToTree([entry], file.installPath, tree); diff --git a/tools/isobuild/resolver.js b/tools/isobuild/resolver.js index 499178f703..6cf8a4aa75 100644 --- a/tools/isobuild/resolver.js +++ b/tools/isobuild/resolver.js @@ -297,17 +297,23 @@ export default class Resolver { pkgSubset.version = pkg.version; } - let main = pkg.main; - if (has(pkg, "main")) { - pkgSubset.main = pkg.main; + let main; + function tryMain(name) { + const value = pkg[name]; + if (isString(value)) { + main = main || value; + pkgSubset[name] = value; + } } - if (archMatches(this.targetArch, "web") && - isString(pkg.browser)) { - main = pkg.browser; - pkgSubset.browser = pkg.browser; + if (archMatches(this.targetArch, "web")) { + tryMain("browser"); + tryMain("module"); + tryMain("jsnext:main"); } + tryMain("main"); + if (isString(main)) { // The "main" field of package.json does not have to begin with ./ // to be considered relative, so first we try simply appending it to diff --git a/tools/tests/apps/dynamic-import/package.json b/tools/tests/apps/dynamic-import/package.json index 1a6a568e7c..ac7a9c28e3 100644 --- a/tools/tests/apps/dynamic-import/package.json +++ b/tools/tests/apps/dynamic-import/package.json @@ -6,7 +6,7 @@ "test": "meteor test --full-app --driver-package dispatch:mocha-browser" }, "dependencies": { - "acorn": "^4.0.11", + "acorn": "^5.0.0", "arson": "^0.2.3", "babel-runtime": "^6.20.0", "meteor-node-stubs": "~0.2.4", diff --git a/tools/tests/apps/dynamic-import/tests.js b/tools/tests/apps/dynamic-import/tests.js index 41473f8883..2619143e0b 100644 --- a/tools/tests/apps/dynamic-import/tests.js +++ b/tools/tests/apps/dynamic-import/tests.js @@ -31,10 +31,16 @@ describe("dynamic import(...)", function () { }); it("static package.json, static package", function () { - import { name } from "acorn/package.json"; + import * as pkg from "acorn/package.json"; import acorn from "acorn"; - assert.strictEqual(name, "acorn"); + assert.strictEqual(pkg.name, "acorn"); assert.strictEqual(typeof acorn.parse, "function"); + assert.strictEqual( + require.resolve("acorn"), + Meteor.isServer + ? "/node_modules/acorn/dist/acorn.js" + : "/node_modules/acorn/dist/acorn.es.js" + ); }); it("static package.json, dynamic package", function () { From 79ad707c6a3d99cddcd3e73e43b0616018167395 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 27 Apr 2017 17:43:45 -0400 Subject: [PATCH 080/125] Bump package versions for 1.5-beta.17 release. --- packages/babel-compiler/package.js | 2 +- packages/dynamic-import/package.js | 2 +- packages/ecmascript/package.js | 2 +- packages/localstorage/package.js | 2 +- packages/meteor-tool/package.js | 2 +- packages/minimongo/package.js | 2 +- packages/modules-runtime/package.js | 2 +- packages/modules/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index 9f4e01a024..a43d1b377a 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,7 +6,7 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.19.0-beta.16' + version: '6.19.0-beta.17' }); Npm.depends({ diff --git a/packages/dynamic-import/package.js b/packages/dynamic-import/package.js index f03e833159..9d42902d92 100644 --- a/packages/dynamic-import/package.js +++ b/packages/dynamic-import/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "dynamic-import", - version: "0.1.0-beta.16", + version: "0.1.0-beta.17", summary: "Support for module.dynamicImport(id).then(namespace => ...)", documentation: "README.md" }); diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index e79c4254e3..3e39c0ccb2 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.8.0-beta.16', + version: '0.8.0-beta.17', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); diff --git a/packages/localstorage/package.js b/packages/localstorage/package.js index fa43225a56..d6f8683458 100644 --- a/packages/localstorage/package.js +++ b/packages/localstorage/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Simulates local storage on IE 6,7 using userData", - version: "1.1.0-beta.16" + version: "1.1.0-beta.17" }); Package.onUse(function (api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index f65ee9a7c6..554cfb5c1e 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.5.0-beta.16' + version: '1.5.0-beta.17' }); Package.includeTool(); diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index f941764096..5d787f897b 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.1.0' + version: '1.1.0-beta.17' }); Package.onUse(function (api) { diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index 7bc4e61aeb..5af7f2300b 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules-runtime", - version: "0.8.0-beta.16", + version: "0.8.0-beta.17", summary: "CommonJS module system", git: "https://github.com/benjamn/install", documentation: "README.md" diff --git a/packages/modules/package.js b/packages/modules/package.js index 554fa59771..c5fa8f4292 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules", - version: "0.9.0-beta.16", + version: "0.9.0-beta.17", summary: "CommonJS module system", documentation: "README.md" }); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index db2b049863..915360b00d 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5-beta.16", + "version": "1.5-beta.17", "recommended": false, "official": false, "description": "Meteor" From 9c7778da364550528de9c966b6976e952c714755 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 1 May 2017 17:04:24 -0400 Subject: [PATCH 081/125] Let the `install` npm package implement Module.prototype.prefetch. Now anyone can define meteorInstall.fetch however they see fit, and the install.js implementation will handle everything else. This separation of concerns leads to significantly less code, too. --- packages/dynamic-import/client.js | 230 ++++++------------ .../.npm/package/npm-shrinkwrap.json | 6 +- packages/modules-runtime/client.js | 2 +- packages/modules-runtime/meteor-install.js | 168 ------------- packages/modules-runtime/package.js | 3 +- packages/modules-runtime/server.js | 4 +- tools/isobuild/linker.js | 14 +- 7 files changed, 90 insertions(+), 337 deletions(-) delete mode 100644 packages/modules-runtime/meteor-install.js diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index 17703c4b6e..843a5f6ba7 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -1,199 +1,121 @@ var Module = module.constructor; -var delayPromise = Promise.resolve(); -var requireMeta = meteorInstall._requireMeta; var cache = require("./cache.js"); -var Mp = Module.prototype; // Call module.dynamicImport(id) to fetch a module and any/all of its // dependencies that have not already been fetched, and evaluate them as // soon as they arrive. This runtime API makes it very easy to implement // ECMAScript dynamic import(...) syntax. -Mp.dynamicImport = function (id) { - // The real (not meta) parent module. +Module.prototype.dynamicImport = function (id) { var module = this; - - function get() { + return module.prefetch(id).then(function () { return getNamespace(module, id); - } - - return delayPromise.then(get).catch(function (error) { - var message = error.message; - if (! (message && - message.startsWith("Cannot find module"))) { - throw error; - } - - return module.prefetch(id).then(get); }); }; -// Call module.prefetch(id) to fetch modules without evaluating them. -// Returns a Promise that resolves to an Error object if importing the -// given id failed, and null otherwise. -Mp.prefetch = function (id) { - var module = this; - - // Require the parent module from the complete meta graph. - var meta = requireMeta(module.id); +// Called by Module.prototype.fetch if there are any missing dynamic +// modules that need to be fetched. +meteorInstall.fetch = function (ids) { + var tree = Object.create(null); var versions = Object.create(null); var dynamicVersions = require("./dynamic-versions.js"); + var missing; - function walk(meta) { - if (meta.dynamic && ! meta.pending) { - meta.pending = true; - var id = meta.mod.id; - versions[id] = getFromTree(dynamicVersions, id); - meta.eachChild(walkChild); + Object.keys(ids).forEach(function (id) { + var version = getFromTree(dynamicVersions, id); + if (version) { + versions[id] = version; + } else { + addToTree(missing = missing || Object.create(null), id, 1); } - } - - function walkChild(childModule) { - return walk(childModule.exports); - } - - meta.eachChild(walkChild, [id]); - - var error = meta.errors && meta.errors[id]; - if (error) { - // If module.prefetch(id) fails, the failure will probably be reported - // as an uncaught promise rejection, unless the calling code - // deliberately handles the rejection. This seems appropriate because - // failed prefetches should not be fatal to the application, yet they - // should be noticeable, so that they can be cleaned up at some point. - return Promise.reject(error); - } + }); return cache.checkMany(versions).then(function (sources) { - var localTree = null; - var missingTree = null; - Object.keys(sources).forEach(function (id) { var source = sources[id]; if (source) { - addToTree(localTree = localTree || Object.create(null), id, source); + addToTree(tree, id, makeModuleFunction(source, ids[id])); } else { - addToTree(missingTree = missingTree || Object.create(null), id, 1); + addToTree(missing = missing || Object.create(null), id, 1); } }); - if (localTree) { - installResults(localTree, true); - } + return missing && fetchMissing(missing).then(function (results) { + var versionsAndSourcesById = Object.create(null); + var flatResults = flattenModuleTree(results); - return missingTree && fetchMissing(missingTree); + Object.keys(flatResults).forEach(function (id) { + var source = flatResults[id]; + var options = ids[id]; + + addToTree(tree, id, makeModuleFunction(source, options)); + + var version = getFromTree(dynamicVersions, id); + if (version) { + versionsAndSourcesById[id] = { + version: version, + source: source + }; + } + }); + + cache.setMany(versionsAndSourcesById); + }); }).then(function () { - // If everything was successful, the final result of the - // module.prefetch(id) promise will be the fully-resolved absolute - // form of the given identifier. - return module.resolve(id); + return tree; }); }; -// Results from fetchMissing must be delivered in the same order as calls -// to fetchMissing, because previous results may include modules needed by -// more recent calls. In practice, results are usually delivered in order, -// but might be delivered out of order because the __dynamicImport method -// calls this.unblock(). To achieve this ordering of results while still -// allowing parallel __dynamicImport method calls, we keep track of the -// most recent Promise returned by fetchMissing, and delay resolving the -// next Promise until the previous Promise has been resolved or rejected. -var lastFetchMissingPromise = delayPromise; +function flattenModuleTree(tree) { + var parts = [""]; + var result = Object.create(null); + + function walk(t) { + if (t && typeof t === "object") { + Object.keys(t).forEach(function (key) { + parts.push(key); + walk(t[key]); + parts.pop(); + }); + } else if (typeof t === "string") { + result[parts.join("/")] = t; + } + } + + walk(tree); + + return result; +} + +function makeModuleFunction(source, options) { + // By calling (options && options.eval || eval) in a wrapper function, + // we delay the cost of parsing and evaluating the module code until the + // module is first imported. + return function () { + // If an options.eval function was provided in the second argument to + // meteorInstall when this bundle was first installed, use that + // function to parse and evaluate the dynamic module code in the scope + // of the package. Otherwise fall back to indirect (global) eval. + return (options && options.eval || eval)( + // Wrap the function(require,exports,module){...} expression in + // parentheses to force it to be parsed as an expression. + "(" + source + ")" + ).apply(this, arguments); + }; +} function fetchMissing(missingTree) { - // Save the Promise that was most recent when fetchMissing was called. - var previousPromise = lastFetchMissingPromise; - // Update lastFetchMissingPromise immediately, without waiting for // the results to be delivered. - return lastFetchMissingPromise = new Promise(function (resolve, reject) { + return new Promise(function (resolve, reject) { Meteor.call( "__dynamicImport", missingTree, function (error, resultsTree) { - if (error) { - reject(error); - } else { - resolve = resolve.bind(null, resultsTree) - // Continue even if previousPromise was rejected. - previousPromise.then(resolve, resolve); - } + error ? reject(error) : resolve(resultsTree); } ); - }).then(installResults); -} - -function installResults(resultsTree, doNotCache) { - var parts = [""]; - var trees = []; - var options = []; - var versionsAndSourcesById = Object.create(null); - - function walk(tree) { - if (typeof tree === "string") { - var meta = requireMeta(parts.join("/")); - var id = meta.mod.id; - var optionsIndex = options.indexOf(meta.options); - if (optionsIndex < 0) { - options[optionsIndex = options.length] = meta.options; - trees.push(Object.create(null)); - } - - // The results tree is partitioned into separate trees according - // to the meta.options object that governs the tree. Usually the - // number of trees will be approximately one, because options - // are shared by entire bundles. - addToTree( - trees[optionsIndex], - id, - // By calling (meta.options.eval || eval) in a wrapper function, - // we delay the cost of parsing and evaluating the module code - // until the module is first imported. - function () { - // If an options.eval function was provided in the second - // argument to meteorInstall when this bundle was first - // installed, use that function to parse and evaluate the - // dynamic module code in the scope of the package. Otherwise - // fall back to indirect (global) eval. - return (meta.options.eval || eval)( - // Wrap the function(require,exports,module){...} expression - // in parentheses to force it to be parsed as an expression. - "(" + tree + ")" - ).apply(this, arguments); - } - ); - - // Intentionally do not delay resolution waiting for the cache. - if (! doNotCache) { - var version = getFromTree(require("./dynamic-versions.js"), id); - if (version) { - versionsAndSourcesById[id] = { - version: version, - source: tree - }; - } - } - - } else { - Object.keys(tree).forEach(function (name) { - parts.push(name); - walk(tree[name]); - parts.pop(name); - }); - } - } - - walk(resultsTree); - - trees.forEach(function (tree, i) { - meteorInstall(tree, options[i]); }); - - if (! doNotCache) { - cache.setMany(versionsAndSourcesById); - } - - return null; } function getFromTree(tree, id) { diff --git a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json index 9923bcf12b..ad61832e44 100644 --- a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json +++ b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "install": { - "version": "0.8.9", - "resolved": "https://registry.npmjs.org/install/-/install-0.8.9.tgz", - "from": "install@0.8.9" + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/install/-/install-0.9.5.tgz", + "from": "install@0.9.5" } } } diff --git a/packages/modules-runtime/client.js b/packages/modules-runtime/client.js index a6be2fb3d1..1fbf18f13d 100644 --- a/packages/modules-runtime/client.js +++ b/packages/modules-runtime/client.js @@ -4,4 +4,4 @@ makeInstallerOptions.browser = true; makeInstallerOptions.mainFields = ["browser", "module", "jsnext:main", "main"]; -install = makeInstaller(makeInstallerOptions); +meteorInstall = makeInstaller(makeInstallerOptions); diff --git a/packages/modules-runtime/meteor-install.js b/packages/modules-runtime/meteor-install.js deleted file mode 100644 index 9b9263f61b..0000000000 --- a/packages/modules-runtime/meteor-install.js +++ /dev/null @@ -1,168 +0,0 @@ -// The metaInstall function will be used to create a module graph that -// parallels the installed module graph. This parallel graph consists of -// metadata about all available modules, not only those already installed -// but also modules that can be fetched dynamically. -var metaInstall = makeInstaller({ - browser: makeInstallerOptions.browser, - mainFields: makeInstallerOptions.mainFields -}); - -meteorInstall = function (tree, options) { - if (isObject(tree)) { - var meta = Object.create(null); - var real = Object.create(null); - walk(options, tree, meta, real); - metaInstall(meta, options); - return install(real, options); - } - - return install(); -}; - -// Other packages (namely the dynamic-import package) call this function -// to retrieve module metadata from the metaInstall graph. -meteorInstall._requireMeta = metaInstall(); - -function isObject(value) { - return value && typeof value === "object"; -} - -function getOrSet(obj, name) { - return obj[name] = obj[name] || Object.create(null); -} - -function walk(options, input, meta, real) { - Object.keys(input).forEach(function (name) { - var value = input[name]; - - if (tryChild(value, name, meta, real, options)) { - // If the value was a leaf node that we were able to handle, then we - // don't need to (and can't) keep walking it. - return; - } - - if (isObject(value)) { - walk( - options, - value, - getOrSet(meta, name), - getOrSet(real, name) - ); - } - }); - - return this; -} - -function tryChild(value, name, meta, real, options) { - function tryFunc(value) { - if (typeof value === "function") { - meta[name] = makeMetaFunc({}, false, options); - real[name] = value; - return true; - } - } - - if (Array.isArray(value)) { - return value.some(function (value) { - // Dynamic stub modules are represented by objects wrapped in array - // brackets. When we find one of these objects, we install it in the - // meta graph, but not in the installed modules graph. Later, this - // information may be used to fetch dynamic modules from the server, - // which will then be installed into the real graph. - if (isObject(value)) { - meta[name] = makeMetaFunc(value, true, options); - return true; - } - - // Older versions of the install.js library supported wrapping a - // module function in an array that also contained the dependency - // identifier strings of that module. That style should no longer be - // used, but we might as well handle it gracefully, since it is not - // ambiguous with the [{...}] style. - return tryFunc(value); - }); - } - - // Installed (immediately importable) modules are represented by - // function expressions with the parameters (require, exports, module). - if (tryFunc(value)) { - return true; - } - - // The install.js library supports a notion of aliases, represented by - // module identifier strings. This functionality works the same way in - // both the meta graph and the real graph. - if (typeof value === "string") { - meta[name] = value; - real[name] = value; - return true; - } -} - -var requireReal = install(); - -function makeMetaFunc(value, dynamic, options) { - return function (require, exports, module) { - Object.assign(exports, value); - - if (! dynamic && - module.id.endsWith("/package.json")) { - // If the package.json file is not dynamic, require it from the real - // graph to read its "main" and "browser" properties. - var pkg = requireReal(module.id); - - function copy(name) { - if (typeof pkg[name] === "string") { - exports[name] = pkg[name]; - } - } - - if (Meteor.isClient) { - copy("browser"); - copy("module"); - copy("jsnext:main"); - } - - copy("main"); - } - - // This needs to have a different name from the "module" property that - // may have been added above. - exports.mod = module; - exports.dynamic = !! dynamic; - exports.options = options; - - function quietRequire(id) { - try { - return require(id); - } catch (error) { - (exports.errors = - exports.errors || Object.create(null) - )[id] = error; - } - } - - // One of the purposes of the meta graph is to support traversing - // module dependencies without evaluating any actual module code. - // The eachChild function is essential to that traversal. - exports.eachChild = function (callback, idsToRequire) { - // By default, this function requires all value.deps dependencies - // before iterating over the resulting children, but the caller can - // provide a custom array of modules to require instead. - idsToRequire = idsToRequire || (value && value.deps); - - if (Array.isArray(idsToRequire)) { - idsToRequire.forEach(quietRequire); - } - - // After requiring any/all dependencies of this module, iterate over - // the children according to module.childrenById. Note that this - // includes all children ever imported by this module, including - // implicit modules such as package.json files. - Object.keys(module.childrenById).forEach(function (id) { - callback(module.childrenById[id]); - }); - }; - }; -} diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index 5af7f2300b..480b57dea1 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -7,7 +7,7 @@ Package.describe({ }); Npm.depends({ - install: "0.8.9" + install: "0.9.5" }); Package.onUse(function(api) { @@ -21,7 +21,6 @@ Package.onUse(function(api) { api.addFiles("options.js"); api.addFiles("client.js", "client"); api.addFiles("server.js", "server"); - api.addFiles("meteor-install.js"); api.export("meteorInstall"); }); diff --git a/packages/modules-runtime/server.js b/packages/modules-runtime/server.js index 1ce8ffb0be..367a60c769 100644 --- a/packages/modules-runtime/server.js +++ b/packages/modules-runtime/server.js @@ -32,8 +32,8 @@ makeInstallerOptions.fallback.resolve = function (id, parentId, error) { throw error; }; -install = makeInstaller(makeInstallerOptions); -var Module = install.Module; +meteorInstall = makeInstaller(makeInstallerOptions); +var Module = meteorInstall.Module; Module.prototype.useNode = function () { if (typeof npmRequire !== "function") { diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index 58b8c69418..9858923305 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -262,18 +262,16 @@ _.extend(Module.prototype, { dynamic: true, }); - const entry = {}; - - if (! _.isEmpty(file.deps)) { - entry.deps = file.deps; - } + const stubArray = file.deps.slice(0); if (file.installPath.endsWith("/package.json") && file.jsonData) { + const stub = {}; + function tryMain(name) { const value = file.jsonData[name]; if (_.isString(value)) { - entry[name] = value; + stub[name] = value; } } @@ -281,9 +279,11 @@ _.extend(Module.prototype, { tryMain("module"); tryMain("jsnext:main"); tryMain("main"); + + stubArray.push(stub); } - addToTree([entry], file.installPath, tree); + addToTree(stubArray, file.installPath, tree); } else { // If the file is not dynamic, then it should be included in the From 0223c6a8ed723a08ed77e28f416825c6f05d7080 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 2 May 2017 10:42:42 +0300 Subject: [PATCH 082/125] Add message about `MAIL_URL` scheme in `History.md`. This should act as a reminder for those who may be using `smtp://` when they should be using `smtps://`. Previously, the scheme was implied by the port number, however this is not the ideal behavior in the same way that it is unsafe to assume that port 443 is always `https://`. --- History.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/History.md b/History.md index 9380b5bfc9..c5c11cdc24 100644 --- a/History.md +++ b/History.md @@ -22,6 +22,12 @@ [Issue #8591](https://github.com/meteor/meteor/issues/8591) [PR #8605](https://github.com/meteor/meteor/pull/8605) + > Note: The `MAIL_URL` should be configured with a scheme which matches the + > protocol desired by your e-mail vendor/mail-transport agent. For + > encrypted connections (typically listening on port 465 or 587), this means + > using `smtps://`. Unencrypted connections should continue to use + > `smtp://`. + * A new `Tracker.inFlush()` has been added to provide a global Tracker "flushing" state. [PR #8565](https://github.com/meteor/meteor/pull/8565). From 15542d7de258c107b946ef141a872291cb065928 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 2 May 2017 10:46:59 +0300 Subject: [PATCH 083/125] Add date to `History.md` for official 1.4.4.2 release. --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index c5c11cdc24..1f9753564f 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,6 @@ ## v.NEXT -## v1.4.4.2, TBD +## v1.4.4.2, 2017-05-02 * Node has been upgraded to version 4.8.2. From 1ac0d4ca2f263b1b747628267f44c648eee3e4c9 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 2 May 2017 10:56:09 +0300 Subject: [PATCH 084/125] Bump package versions for the official 1.4.4.2 release. --- packages/accounts-base/package.js | 2 +- packages/accounts-password/package.js | 2 +- packages/meetup-oauth/package.js | 2 +- packages/meteor-tool/package.js | 2 +- packages/minimongo/package.js | 2 +- packages/mongo/package.js | 2 +- packages/tracker/package.js | 2 +- scripts/admin/meteor-release-official.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index 86d2be8d2a..0b5166e0e0 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A user account system", - version: "1.2.17-rc.1" + version: "1.2.17" }); Package.onUse(function (api) { diff --git a/packages/accounts-password/package.js b/packages/accounts-password/package.js index 0b9f21a7e1..c43ea38a0b 100644 --- a/packages/accounts-password/package.js +++ b/packages/accounts-password/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Password support for accounts", - version: "1.3.6-rc.1" + version: "1.3.6" }); Package.onUse(function(api) { diff --git a/packages/meetup-oauth/package.js b/packages/meetup-oauth/package.js index 2a1a017579..ff189c5ad4 100644 --- a/packages/meetup-oauth/package.js +++ b/packages/meetup-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: 'Meetup OAuth flow', - version: '1.0.1-rc.1' + version: '1.0.1' }); Package.onUse(function (api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index dedda8811e..0e1716adba 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.4.4-2-rc.1' + version: '1.4.4_2' }); Package.includeTool(); diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index 00e983b9e2..d89b5f03df 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.0.22-rc.1' + version: '1.0.22' }); Package.onUse(function (api) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 5ceeadce0e..0c442d6e42 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.1.17-rc.1' + version: '1.1.17' }); Npm.depends({ diff --git a/packages/tracker/package.js b/packages/tracker/package.js index de0712cc12..e18baa9527 100644 --- a/packages/tracker/package.js +++ b/packages/tracker/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Dependency tracker to allow reactive callbacks", - version: '1.1.3-rc.1' + version: '1.1.3' }); Package.onUse(function (api) { diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index 748abf611f..1e5f97cce6 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.4.4.1", + "version": "1.4.4.2", "recommended": false, "official": true, "description": "The Official Meteor Distribution" From 5e617b93c87e4ab3fa623f63ebaf859d02d2a229 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 2 May 2017 12:28:24 +0300 Subject: [PATCH 085/125] Bump minimongo package version to 1.0.23 in preparation for publishing. --- packages/minimongo/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index d89b5f03df..ca24cea70e 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.0.22' + version: '1.0.23' }); Package.onUse(function (api) { From 807c4224eb6ac4111102199f42a60e0c269182b8 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 2 May 2017 11:04:52 -0400 Subject: [PATCH 086/125] Update to latest meteorInstall.fetch API. https://github.com/benjamn/install/commit/90fd573f8617586b0404547153ba552b8f0fc745 --- packages/dynamic-import/client.js | 7 ++++--- packages/modules-runtime/.npm/package/npm-shrinkwrap.json | 6 +++--- packages/modules-runtime/package.js | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index 843a5f6ba7..9d5f9593b9 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -33,7 +33,8 @@ meteorInstall.fetch = function (ids) { Object.keys(sources).forEach(function (id) { var source = sources[id]; if (source) { - addToTree(tree, id, makeModuleFunction(source, ids[id])); + var info = ids[id]; + addToTree(tree, id, makeModuleFunction(source, info.options)); } else { addToTree(missing = missing || Object.create(null), id, 1); } @@ -45,9 +46,9 @@ meteorInstall.fetch = function (ids) { Object.keys(flatResults).forEach(function (id) { var source = flatResults[id]; - var options = ids[id]; + var info = ids[id]; - addToTree(tree, id, makeModuleFunction(source, options)); + addToTree(tree, id, makeModuleFunction(source, info.options)); var version = getFromTree(dynamicVersions, id); if (version) { diff --git a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json index ad61832e44..45dca93b24 100644 --- a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json +++ b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "install": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/install/-/install-0.9.5.tgz", - "from": "install@0.9.5" + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/install/-/install-0.9.6.tgz", + "from": "install@0.9.6" } } } diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index 480b57dea1..8efbd7e6dd 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -7,7 +7,7 @@ Package.describe({ }); Npm.depends({ - install: "0.9.5" + install: "0.9.6" }); Package.onUse(function(api) { From cccf387c44184247dcbf6153c0cd9a44752f7ba5 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 2 May 2017 11:21:06 -0400 Subject: [PATCH 087/125] Bump $BUNDLE_VERSION to 4.8.9 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 638c472594..f9d170a472 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.8 +BUNDLE_VERSION=4.8.9 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 6fb8e1f0ab7837bbc09ad27dbd157c4b1b5160ee Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 2 May 2017 11:42:53 -0400 Subject: [PATCH 088/125] Bump package versions for 1.5-beta.18 release. --- packages/babel-compiler/package.js | 2 +- packages/dynamic-import/package.js | 2 +- packages/ecmascript/package.js | 2 +- packages/localstorage/package.js | 2 +- packages/meteor-tool/package.js | 2 +- packages/minimongo/package.js | 2 +- packages/modules-runtime/package.js | 2 +- packages/modules/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index a43d1b377a..dc9749cc5c 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,7 +6,7 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.19.0-beta.17' + version: '6.19.0-beta.18' }); Npm.depends({ diff --git a/packages/dynamic-import/package.js b/packages/dynamic-import/package.js index 9d42902d92..8b96290cfa 100644 --- a/packages/dynamic-import/package.js +++ b/packages/dynamic-import/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "dynamic-import", - version: "0.1.0-beta.17", + version: "0.1.0-beta.18", summary: "Support for module.dynamicImport(id).then(namespace => ...)", documentation: "README.md" }); diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index 3e39c0ccb2..ae5d723ebf 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.8.0-beta.17', + version: '0.8.0-beta.18', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); diff --git a/packages/localstorage/package.js b/packages/localstorage/package.js index d6f8683458..0f9fe32981 100644 --- a/packages/localstorage/package.js +++ b/packages/localstorage/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Simulates local storage on IE 6,7 using userData", - version: "1.1.0-beta.17" + version: "1.1.0-beta.18" }); Package.onUse(function (api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 554cfb5c1e..79f89bb918 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.5.0-beta.17' + version: '1.5.0-beta.18' }); Package.includeTool(); diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index ab9fc65043..9d75927950 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.2.0-beta.17' + version: '1.2.0-beta.18' }); Package.onUse(function (api) { diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index 8efbd7e6dd..fb953a6b5e 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules-runtime", - version: "0.8.0-beta.17", + version: "0.8.0-beta.18", summary: "CommonJS module system", git: "https://github.com/benjamn/install", documentation: "README.md" diff --git a/packages/modules/package.js b/packages/modules/package.js index c5fa8f4292..840b146401 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules", - version: "0.9.0-beta.17", + version: "0.9.0-beta.18", summary: "CommonJS module system", documentation: "README.md" }); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 915360b00d..7e4e12b7c1 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5-beta.17", + "version": "1.5-beta.18", "recommended": false, "official": false, "description": "Meteor" From 9900c226dfe9d5e6263ed77871d5b1bcfc79a005 Mon Sep 17 00:00:00 2001 From: mutdmour Date: Wed, 3 May 2017 18:09:54 +0300 Subject: [PATCH 089/125] $push $slice with positive numbers (#5167) (#8623) --- packages/minimongo/minimongo_tests.js | 13 +++++++++++-- packages/minimongo/modify.js | 7 +++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 21ae3169cc..bad54b3079 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -2434,8 +2434,6 @@ Tinytest.add("minimongo - modify", function (test) { {a: [1, 2, 3]}); modify({a: [true]}, {$push: {a: {$each: [1, 2, 3]}}}, {a: [true, 1, 2, 3]}); - // No positive numbers for $slice - exception({}, {$push: {a: {$each: [], $slice: 5}}}); modify({a: [true]}, {$push: {a: {$each: [1, 2, 3], $slice: -2}}}, {a: [2, 3]}); modify({a: [false, true]}, {$push: {a: {$each: [1], $slice: -2}}}, @@ -2486,6 +2484,17 @@ Tinytest.add("minimongo - modify", function (test) { modify({}, {$push: {a: {$each: [{' ':1}]}}}, {a: [ { ' ': 1 } ]}); exception({}, {$push: {a: {$each: [{'.':1}]}}}); + // #issue 5167 + // $push $slice with positive numbers + modify({}, {$push: {a: {$each: [], $slice: 5}}}, {a:[]}); + modify({a:[1,2,3]}, {$push: {a: {$each: [], $slice: 1}}}, {a:[1]}); + modify({a:[1,2,3]}, {$push: {a: {$each: [4,5], $slice: 1}}}, {a:[1]}); + modify({a:[1,2,3]}, {$push: {a: {$each: [4,5], $slice: 2}}}, {a:[1,2]}); + modify({a:[1,2,3]}, {$push: {a: {$each: [4,5], $slice: 4}}}, {a:[1,2,3,4]}); + modify({a:[1,2,3]}, {$push: {a: {$each: [4,5], $slice: 5}}}, {a:[1,2,3,4,5]}); + modify({a:[1,2,3]}, {$push: {a: {$each: [4,5], $slice: 10}}}, {a:[1,2,3,4,5]}); + + // $pushAll modify({}, {$pushAll: {a: [1]}}, {a: [1]}); modify({a: []}, {$pushAll: {a: [1]}}, {a: [1]}); diff --git a/packages/minimongo/modify.js b/packages/minimongo/modify.js index ebc285ddab..e0df49a274 100644 --- a/packages/minimongo/modify.js +++ b/packages/minimongo/modify.js @@ -301,9 +301,6 @@ var MODIFIERS = { if (typeof arg.$slice !== "number") throw MinimongoError("$slice must be a numeric value", { field }); // XXX should check to make sure integer - if (arg.$slice > 0) - throw MinimongoError( - "$slice in $push must be zero or negative", { field }); slice = arg.$slice; } @@ -344,8 +341,10 @@ var MODIFIERS = { if (slice !== undefined) { if (slice === 0) target[field] = []; // differs from Array.slice! - else + else if (slice < 0) target[field] = target[field].slice(slice); + else + target[field] = target[field].slice(0, slice); } }, $pushAll: function (target, field, arg) { From f0223c9151ea6c8063d0deb73368fbf534537fd0 Mon Sep 17 00:00:00 2001 From: Christian Klaussner Date: Wed, 3 May 2017 17:14:21 +0200 Subject: [PATCH 090/125] Remove leading slash from paths in Babel options (#8610) --- packages/babel-compiler/babel-compiler.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/babel-compiler/babel-compiler.js b/packages/babel-compiler/babel-compiler.js index 7a06290419..c10289c199 100644 --- a/packages/babel-compiler/babel-compiler.js +++ b/packages/babel-compiler/babel-compiler.js @@ -86,8 +86,8 @@ BCp.processOneFileForTarget = function (inputFile, source) { babelOptions.sourceMap = true; babelOptions.filename = babelOptions.sourceFileName = packageName - ? "/packages/" + packageName + "/" + inputFilePath - : "/" + inputFilePath; + ? "packages/" + packageName + "/" + inputFilePath + : inputFilePath; babelOptions.sourceMapTarget = babelOptions.filename + ".map"; From 541bfbf820233c62a33e6f3b7bfc8a37955be479 Mon Sep 17 00:00:00 2001 From: Seba Kerckhof Date: Wed, 3 May 2017 17:17:41 +0200 Subject: [PATCH 091/125] Remove nested properties from upsert selector document (#8633) * Remove nested properties from upsert selector document Fixes https://github.com/meteor/meteor/issues/8631 * Fix upserts that include _id in the selector * Incorporate PR review requests. --- packages/minimongo/minimongo.js | 18 +++++++++++++++++- packages/minimongo/minimongo_tests.js | 18 +++++++++++------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js index dd2017ebce..27e5f643ca 100644 --- a/packages/minimongo/minimongo.js +++ b/packages/minimongo/minimongo.js @@ -782,8 +782,24 @@ LocalCollection.prototype.update = function (selector, mod, options, callback) { // generate an id for it. var insertedId; if (updateCount === 0 && options.upsert) { - var newDoc = LocalCollection._removeDollarOperators(selector); + + let selectorModifier = LocalCollection._selectorIsId(selector) + ? { _id: selector } + : selector; + + selectorModifier = LocalCollection._removeDollarOperators(selectorModifier); + + const newDoc = {}; + if (selectorModifier._id) { + newDoc._id = selectorModifier._id; + delete selectorModifier._id; + } + + // This double _modify call is made to help work around an issue where collection + // upserts won't work properly, with nested properties (see issue #8631). + LocalCollection._modify(newDoc, {$set: selectorModifier}); LocalCollection._modify(newDoc, mod, {isInsert: true}); + if (! newDoc._id && options.insertedId) newDoc._id = options.insertedId; insertedId = self.insert(newDoc); diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index bad54b3079..ad38b97131 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -2396,7 +2396,7 @@ Tinytest.add("minimongo - modify", function (test) { exception({}, {$set: {_id: 4}}); exception({_id: 4}, {$set: {_id: 4}}); // even not-changing _id is bad //restricted field names - exception({a:{}}, {$set:{a:{$a:1}}}); + exception({a:{}}, {$set:{a:{$a:1}}}); exception({ a: {} }, { $set: { a: { c: [{ b: { $a: 1 } }] } } }); exception({a:{}}, {$set:{a:{'\0a':1}}}); @@ -2536,21 +2536,21 @@ Tinytest.add("minimongo - modify", function (test) { modify({}, {$addToSet: {a: {$each: [1]}}}, {a: [1]}); modify({a: []}, {$addToSet: {'a.1': 99}}, {a: [null, [99]]}); modify({a: {}}, {$addToSet: {'a.x': 99}}, {a: {x: [99]}}); - + // invalid field names exception({}, {$addToSet: {a: {$b:1}}}); exception({}, {$addToSet: {a: {"a.b":1}}}); exception({}, {$addToSet: {a: {"a.":1}}}); exception({}, {$addToSet: {a: {'\u0000a':1}}}); - exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, {$a:1}]}}}); - exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, {'\0a':1}]}}}); - exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, [{$a:1}]]}}}); - exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, [{b:{c:[{a:1},{"d.s":2}]}}]]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, {$a:1}]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, {'\0a':1}]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, [{$a:1}]]}}}); + exception({a: [1, 2]}, {$addToSet: {a:{$each: [3, 1, [{b:{c:[{a:1},{"d.s":2}]}}]]}}}); exception({a: [1, 2]}, {$addToSet: {a:{b: [3, 1, [{b:{c:[{a:1},{"d.s":2}]}}]]}}}); //$each is first element and thus an operator modify({a: [1, 2]}, {$addToSet: {a: {$each: [3, 1, 4], b: 12}}},{a: [ 1, 2, 3, 4 ]}); // this should fail because $each is now a field name (not first in object) and thus invalid field name with $ - exception({a: [1, 2]}, {$addToSet: {a: {b: 12, $each: [3, 1, 4]}}}); + exception({a: [1, 2]}, {$addToSet: {a: {b: 12, $each: [3, 1, 4]}}}); // $pop modify({}, {$pop: {a: 1}}, {}); // tested @@ -2631,6 +2631,10 @@ Tinytest.add("minimongo - modify", function (test) { modify({a: 0}, {$setOnInsert: {a: 12}}, {a: 0}); upsert({a: 12}, {$setOnInsert: {b: 12}}, {a: 12, b: 12}); upsert({a: 12}, {$setOnInsert: {_id: 'test'}}, {_id: 'test', a: 12}); + upsert({"a.b": 10}, {$setOnInsert: {a: {b: 10, c: 12}}}, {a: {b: 10, c: 12}}); + upsert({"a.b": 10}, {$setOnInsert: {c: 12}}, {a: {b: 10}, c: 12}); + upsert({"_id": 'test'}, {$setOnInsert: {c: 12}}, {_id: 'test', c: 12}); + upsert('test', {$setOnInsert: {c: 12}}, {_id: 'test', c: 12}); upsertException({a: 0}, {$setOnInsert: {$a: 12}}); upsertException({a: 0}, {$setOnInsert: {'\0a': 12}}); upsert({a: 0}, {$setOnInsert: {b: {a:1}}}, {a:0, b:{a:1}}); From 534477b9acaf9171b52c63f81fc3ec5dc3c39636 Mon Sep 17 00:00:00 2001 From: ziedmahdi Date: Wed, 3 May 2017 16:32:51 +0100 Subject: [PATCH 092/125] fix bug when initiating dict with non string values (#8643) --- packages/reactive-dict/reactive-dict-tests.js | 10 ++++++++++ packages/reactive-dict/reactive-dict.js | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/reactive-dict/reactive-dict-tests.js b/packages/reactive-dict/reactive-dict-tests.js index f67530d011..fdf5ad7d9d 100644 --- a/packages/reactive-dict/reactive-dict-tests.js +++ b/packages/reactive-dict/reactive-dict-tests.js @@ -6,6 +6,16 @@ Tinytest.add('ReactiveDict - set to undefined', function (test) { test.equal(dict.get('foo'), undefined); }); +Tinytest.add('ReactiveDict - initialize with data', function (test) { + var now = new Date(); + var dict = new ReactiveDict({ + now: now + }); + + var nowFromDict = dict.get('now'); + test.equal(nowFromDict, now); +}); + Tinytest.add('ReactiveDict - setDefault', function (test) { var dict = new ReactiveDict; dict.set('A', 'blah'); diff --git a/packages/reactive-dict/reactive-dict.js b/packages/reactive-dict/reactive-dict.js index a4d4592a54..4ff1a94634 100644 --- a/packages/reactive-dict/reactive-dict.js +++ b/packages/reactive-dict/reactive-dict.js @@ -27,7 +27,10 @@ ReactiveDict = function (dictName) { this.name = dictName; } else if (typeof dictName === 'object') { // back-compat case: dictName is actually migrationData - this.keys = dictName; + this.keys = {}; + for (let [key, value] of Object.entries(dictName)) { + this.keys[key] = stringify(value); + } } else { throw new Error("Invalid ReactiveDict argument: " + dictName); } From 4887a4863949d92d5cbf21f39fd4d7ae1a3dbde8 Mon Sep 17 00:00:00 2001 From: nick-gudumac Date: Wed, 3 May 2017 18:42:01 +0300 Subject: [PATCH 093/125] Added support for making secure graph api requests with appsecret_proof (#8657) * Added support for making graph api requests with appsecret_proof * Add missing comma --- packages/facebook-oauth/facebook_server.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/facebook-oauth/facebook_server.js b/packages/facebook-oauth/facebook_server.js index 04a5179f31..f124676deb 100644 --- a/packages/facebook-oauth/facebook_server.js +++ b/packages/facebook-oauth/facebook_server.js @@ -1,4 +1,5 @@ Facebook = {}; +var crypto = Npm.require('crypto'); Facebook.handleAuthFromAccessToken = function handleAuthFromAccessToken(accessToken, expiresAt) { // include all fields from facebook @@ -79,10 +80,20 @@ var getTokenResponse = function (query) { }; var getIdentity = function (accessToken, fields) { + var config = ServiceConfiguration.configurations.findOne({service: 'facebook'}); + if (!config) + throw new ServiceConfiguration.ConfigError(); + + // Generate app secret proof that is a sha256 hash of the app access token, with the app secret as the key + // https://developers.facebook.com/docs/graph-api/securing-requests#appsecret_proof + var hmac = crypto.createHmac('sha256', OAuth.openSecret(config.secret)); + hmac.update(accessToken); + try { return HTTP.get("https://graph.facebook.com/v2.8/me", { params: { access_token: accessToken, + appsecret_proof: hmac.digest('hex'), fields: fields.join(",") } }).data; From 0d10b33be632afbaa72bfe3a780854f850462b95 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Wed, 3 May 2017 13:30:05 -0400 Subject: [PATCH 094/125] Added a small note explaining how to get dev_bundle changes published. (#8652) * Added a small note explaining how to get dev_bundle changes published. * Fixed grammar errors with 's; Updated @meteor/platform mention. * Removed @meteor/platform suggestion since it can only be used by team members. --- Development.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Development.md b/Development.md index fc36eea113..1138c53d79 100644 --- a/Development.md +++ b/Development.md @@ -88,6 +88,12 @@ $ ./scripts/generate-dev-bundle.sh This will generate a new tarball (`dev_bundle___.tar.gz`) in the root of the checkout. Assuming you bumped the `BUNDLE_VERSION`, the new version will be extracted automatically when you run `./meteor`. If you are rebuilding the same version (or didn't bump the version number), you should delete the existing `dev_bundle` directory to ensure the new tarball is extracted when you run `./meteor`. +### Submitting "Dev Bundle" Pull Requests + +It's important to note that while `dev_bundle` pull requests are accepted/reviewed, a new `dev_bundle` can only be published to MDG's Meteor infrastructure by an MDG staff member. This means that the build tool and package tests of submitted `dev_bundle` pull requests will always initially fail (since the new `dev_bundle` hasn't yet been built/published by MDG, which means it can't be downloaded by Meteor's continuous integration environment). + +Pull requests that contain `dev_bundle` changes will be noted by repo collaborators, and a request to have a new `dev_bundle` built/published will be forwarded to MDG. + ## Additional documentation The Meteor core is best documented within the code itself, however, many components also have a `README.md` in their respective directories. From cf851b06608420c3455935f15a1ab6f118cb6c81 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 4 May 2017 17:05:53 +0300 Subject: [PATCH 095/125] Update Contributing.md. (#8664) * Update Contributing.md. Various changes and cleanups to the Contributing information but primarily, remove the team mentions part of "Need help with your pull request?" (which don't work unless you're a member of the GitHub org). In general, contributors can get ahold of the correct person(s). /cc @hwillson * Update Contributing.md --- Contributing.md | 71 +++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/Contributing.md b/Contributing.md index c4db02a8a4..1eb6c36067 100644 --- a/Contributing.md +++ b/Contributing.md @@ -2,23 +2,24 @@ We are excited to have your help building Meteor — both the platform and the community behind it. Please read the project overview and guidelines for contributing bug reports and new code, or it might be hard for the community to help you with your issue or pull request. -

Project overview

+## Project overview Before we jump into detailed guidelines for opening and triaging issues and submitting pull requests, here is some information about how our project is structured and resources you should refer to as you start contributing. ### Ways to contribute There are many ways to contribute to the Meteor Project. Here’s a list of technical contributions with increasing levels of involvement and required knowledge of Meteor’s code and operations. -- [Reporting a bug](https://github.com/meteor/meteor/blob/devel/Contributing.md#reporting-a-bug-in-meteor) -- [Triaging issues](https://github.com/meteor/meteor/blob/devel/IssueTriage.md) -- [Contributing to documentation](https://github.com/meteor/docs/blob/master/Contributing.md) -- [Submitting pull requests](https://github.com/meteor/meteor/blob/devel/Contributing.md#making-changes-to-meteor-core) (See "Finding work" below) -- [Reviewing pull requests](https://github.com/meteor/meteor/blob/devel/Contributing.md#reviewer) -- [Maintaining a community package](https://github.com/meteor/meteor/blob/devel/Contributing.md#community-package-maintainer) +- [Reporting a bug](Contributing.md#reporting-a-bug-in-meteor) +- [Triaging issues](IssueTriage.md) +- [Contributing to documentation](https://github.com/meteor/docs/blob/master/Contributing.md) +- [Finding work](Contributing.md#finding-work) +- [Submitting pull requests](Contributing.md#making-changes-to-meteor-core) +- [Reviewing pull requests](Contributing.md#reviewer) +- [Maintaining a community package](Contributing.md#community-package-maintainer) -There are also several ways to contribute to the Meteor Project outside of GitHub, like organizing or speaking at [Meetups](https://www.meetup.com/topics/meteor/) and events and helping to moderate our [forums](https://forums.meteor.com/). Stay tuned for more documentation around non-code contributions. +There are also several ways to contribute to the Meteor Project outside of GitHub, like organizing or speaking at [Meetups](https://www.meetup.com/topics/meteor/) and events and helping to moderate our [forums](https://forums.meteor.com/). -If you can think of any changes to the project, [documentation](https://github.com/meteor/docs), or [guide](https://github.com/meteor/guide) that would improve the contributor experience, let us know by opening an issue! +If you can think of any changes to the project, [documentation](https://github.com/meteor/docs), or [guide](https://github.com/meteor/guide) that would improve the contributor experience, let us know by opening an issue in the correct repository! ### Finding work @@ -26,7 +27,7 @@ We curate specific issues that would make great pull requests for community cont Issues which *also* have the [`confirmed` label](https://github.com/meteor/meteor/issues?q=is%3Aissue%20is%3Aopen%20label%3Apull-requests-encouraged%20label%3Aconfirmed) are considered to have their details clear enough to begin working on. -Any issue which does not have the `confirmed` label still requires discussion on implementation details but input and positive commentary is welcome! Any pull-request opened on an issue which is not `confirmed` is still welcome, however the pull-request is more likely to be sent back for reworking than a `confirmed` issue. If in doubt about the best way to implement something, please create additional conversation on the issue. +Any issue which does not have the `confirmed` label still requires discussion on implementation details but input and positive commentary is welcome! Any pull request opened on an issue which is not `confirmed` is still welcome, however the pull-request is more likely to be sent back for reworking than a `confirmed` issue. If in doubt about the best way to implement something, please create additional conversation on the issue. ### Project roles @@ -72,7 +73,7 @@ Current Documentation Maintainers: #### Community Package Maintainer: -Community package maintainers are community members who maintain packages outside of Meteor core. This requires code to be extracted from meteor/meteor, and entails a high level of responsibility. For this reason, community maintainers generally (and currently) must first become an advanced contributor to Meteor core and have 4-5 non-trivial pull requests merged that went through the proper contribution workflow. At that point, core contributors may make the case for breaking out a particular core package, and assist in the technical process around doing so. +Community package maintainers are community members who maintain packages outside of Meteor core. This requires code to be extracted from meteor/meteor, and entails a high level of responsibility. For this reason, community maintainers generally (and currently) must first become an advanced contributor to Meteor core and have 4-5 non-trivial pull requests merged that went through the proper contribution work-flow. At that point, core contributors may make the case for breaking out a particular core package, and assist in the technical process around doing so. Current Community Package Maintainers: - [@mitar](https://github.com/mitar) for [Blaze](https://github.com/meteor/blaze) @@ -88,11 +89,12 @@ Current Community Manager: Right now, the best place to track the work being done on Meteor is to take a look at the latest release milestone [here](https://github.com/meteor/meteor/milestones). Also, the [Meteor Roadmap](Roadmap.md) contains high-level information on the current priorities of the project. -

Reporting a bug in Meteor

+## Reporting a bug in Meteor + We welcome clear bug reports. If you've found a bug in Meteor that isn't a security risk, please file a report in -[our issue tracker](https://github.com/meteor/meteor/issues). Before you file your issue, look to see if it has already been reported. If so, comment, up-vote or +1 the existing issue to show that it's affecting multiple people. +[our issue tracker](https://github.com/meteor/meteor/issues). Before you file your issue, **search** to see if it has already been reported. If so, up-vote (using GitHub reactions) or add additional helpful details to the existing issue to show that it's affecting multiple people. > There is a separate procedure for security-related issues. If the > issue you've found contains sensitive information or raises a security @@ -135,19 +137,18 @@ A reproduction recipe works like this: If you want to submit a pull request that fixes your bug, that's even better. We love getting bugfix pull requests. Just make sure they're -written to the MDG style guide and *come with tests*. Read further down +written with the [correct style](Development.md#code-style) and *come with tests*. Read further down for more details on proposing changes to core code. -

Feature requests

+## Feature requests -As of May 2016, we use GitHub to track feature requests. Feature request issues get the `feature` label, as well as a label +We use GitHub to track feature requests. Feature request issues get the `feature` label, as well as a label corresponding to the Meteor subproject that they are a part of. -Meteor is a big project with [many subprojects](https://github.com/meteor/meteor/tree/devel/packages). -Right now, the project doesn't have as many -[core developers (we're hiring!)](https://www.meteor.com/jobs/core-developer) -as subprojects, so we're not able to work on every single subproject every -month. We use our [roadmap](Roadmap.md) to communicate the high level features we're prioritizing over the near and medium term. +Meteor is a big project with [many sub-projects](https://github.com/meteor/meteor/tree/devel/packages). +There aren't as many [core developers (we're hiring!)](https://www.meteor.io/jobs/) +as there are sub-projects, so we're not able to work on every single sub-project every +month. We use our [roadmap](Roadmap.md) to communicate the high-level features we're currently prioritizing. Every additional feature adds a maintenance cost in addition to its value. This cost starts with the work of writing the feature or reviewing a community pull @@ -160,7 +161,7 @@ For these reasons, we strongly encourage features to be implemented as [Atmosphe Feature requests should be well specified and unambiguous to have the greatest chance of being worked on by a contributor. -Finally, you can show your support for features you would like by commenting with a +1 or up-voting the issue. +Finally, you can show your support for (or against!) features by using [GitHub reactions](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) or by adding meaningful details which help the feature definition become more clear. Please do not comment with "+1" since it creates a lot of noise (e-mails, notifications, etc.). ## Triaging issues @@ -170,6 +171,10 @@ A great way to contribute to Meteor is by helping keep the issues in the reposit If you'd like to contribution to Meteor's documentation, head over to https://github.com/meteor/docs and create issues or pull requests there. +## Blaze + +Blaze lives in its [own repository](https://github.com/meteor/blaze/) with its own [issue tracker and feature prioritization](https://github.com/meteor/blaze/issues/) and is not tracked within Meteor core. + ## Making changes to Meteor core Eventually you may want to change something in a core Meteor package, or @@ -189,7 +194,7 @@ any change to a core package: 1. Nothing in Meteor should harm the experience of a new Meteor developer. That can be a difficult standard to reach, because we're - concerned here with the entire experience of developing and deploying + concerned with the entire experience of developing and deploying an application. For example, we work hard to make sure that the Meteor docs don't force new users to understand advanced concepts before they need them. And we think a great deal about making our APIs as @@ -206,8 +211,7 @@ any change to a core package: an expert then we'll probably prefer a different approach. 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. +same time is hard but incredibly rewarding. We hope you come to feel the same way. ### Understanding the core @@ -219,19 +223,18 @@ You'll have the best chance of getting a change into core if you can build conse Help drive discussion and advocate for your feature on the Github ticket (and perhaps the forums). The higher the demand for the feature and the greater the clarity of it's specification will determine the likelihood of a core contributor prioritizing your feature by flagging it with the `pull-requests-encouraged` label. -Split features up into smaller, logically separable chunks. It is unlikely that large and complicated PRs will be merged. +Split features up into smaller, logically separate chunks. It is unlikely that large and complicated PRs will be merged. Once your feature has been labelled with `pull-requests-encouraged`, leave a comment letting people know you're working on it and you can begin work on the code. ### Submitting pull requests -Once you've hammered out a good design go ahead and submit a pull request. If your PR isn't against a bug with the `confirmed` label or a feature request with the `pull-requests-encouraged` label, don't expect your PR to be merged unless it's a trivial and obvious fix (e.g documentation). When submitting a PR, please follow -these guidelines: +Once you've come up with a good design, go ahead and submit a pull request (PR). If your PR isn't against a bug with the `confirmed` label or a feature request with the `pull-requests-encouraged` label, don't expect your PR to be merged unless it's a trivial and obvious fix (e.g. documentation). When submitting a PR, please follow these guidelines: * Sign the [contributor's agreement](http://contribute.meteor.com/). * Base all your work off of the **devel** branch. The **devel** branch - is where active development happens. **We do not merge patches + is where active development happens. **We do not merge pull requests directly into master.** * Name your branch to match the feature/bug fix that you are @@ -251,12 +254,6 @@ these guidelines: ### Need help with your pull request? -Meteor now has groups defined to cover different areas of the codebase. If you need help getting acceptance on certain pull requests with an area of focus listed below, you can address the appropriate people in the pull request: +If you need help with a pull request, you should start by asking questions in the issue which it pertains to. If you feel that your pull request is almost ready or needs feedback which can only be demonstrated with code, go ahead and open a pull-request with as much progress as possible. By including a "[Work in Progress]" note in the subject, project contributors will know you need help! -* Meteor Data Team - This includes DDP, tracker, mongo, accounts, etc. You can mention @data in the PR. -* Blaze - This includes Spacebars, Blaze, etc. You can mention @view-layer in the PR. -* Build tools - This includes modules, build tool changes, etc. You can mention @platform in the PR. -* Mobile integration - This includes Cordova, React Native, etc. You can mention @mobile in the PR. -* Documentation - This includes the Guide, the Docs, and any supporting material. You can mention @guide in the PR. - -Including the people above is no guarantee that you will get a response, or ultimately that your pull request will be accepted. This section exists to give some minor guidance on internal Meteor Development Group team structures. +Submitting a pull request is no guarantee it will be accepted, but contributors will do their best to help move your pull request toward release. From 46e00ab517e80d525da6c1426ec6fcaf955e868f Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 4 May 2017 16:00:23 -0400 Subject: [PATCH 096/125] Upgrade the `reify` npm package to version 0.9.2. --- History.md | 6 +-- .../.npm/package/npm-shrinkwrap.json | 50 +++++++++---------- packages/babel-compiler/package.js | 2 +- .../.npm/package/npm-shrinkwrap.json | 6 +-- packages/modules-runtime/package.js | 2 +- .../modules/.npm/package/npm-shrinkwrap.json | 18 +++---- packages/modules/package.js | 2 +- scripts/dev-bundle-tool-package.js | 4 +- 8 files changed, 45 insertions(+), 45 deletions(-) diff --git a/History.md b/History.md index f830eec702..8bbb71b861 100644 --- a/History.md +++ b/History.md @@ -9,10 +9,10 @@ information about how dynamic `import(...)` works in Meteor, and how to use it in your applications. -* The `meteor-babel` npm package has been upgraded to version 0.20.2, and - the `reify` npm package has been upgraded to version 0.8.3, fixing +* The `meteor-babel` npm package has been upgraded to version 0.20.3, and + the `reify` npm package has been upgraded to version 0.9.2, fixing [issue #8595](https://github.com/meteor/meteor/issues/8595) and - improving compilation performance. + improving compilation and runtime performance. ## v1.4.4.2, 2017-05-02 diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index b63f3111c7..c52b3cbdc0 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -131,8 +131,8 @@ "from": "babel-plugin-minify-constant-folding@>=0.0.4 <0.0.5", "dependencies": { "jsesc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.0.tgz", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", "from": "jsesc@>=2.4.0 <3.0.0" } } @@ -270,9 +270,9 @@ "from": "babel-plugin-transform-es2015-modules-commonjs@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-modules-reify": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.8.0.tgz", - "from": "babel-plugin-transform-es2015-modules-reify@>=0.8.0 <0.9.0" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.9.0.tgz", + "from": "babel-plugin-transform-es2015-modules-reify@>=0.9.0 <0.10.0" }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", @@ -500,8 +500,8 @@ "from": "core-js@>=2.4.0 <3.0.0" }, "debug": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.5.tgz", + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.6.tgz", "from": "debug@>=2.1.1 <3.0.0" }, "detect-indent": { @@ -580,9 +580,9 @@ "from": "loose-envify@>=1.0.0 <2.0.0" }, "meteor-babel": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.2.tgz", - "from": "meteor-babel@0.20.2" + "version": "0.20.3", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.3.tgz", + "from": "meteor-babel@0.20.3" }, "meteor-babel-helpers": { "version": "0.0.3", @@ -600,14 +600,14 @@ "from": "minimist@0.0.8" }, "minipass": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-1.1.9.tgz", - "from": "minipass@>=1.1.6 <2.0.0" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.0.0.tgz", + "from": "minipass@>=2.0.0 <3.0.0" }, "minizlib": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.2.tgz", - "from": "minizlib@>=1.0.2 <2.0.0" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.3.tgz", + "from": "minizlib@>=1.0.3 <2.0.0" }, "mkdirp": { "version": "0.5.1", @@ -650,8 +650,8 @@ "from": "regenerate@>=1.2.1 <2.0.0" }, "regenerator-runtime": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.4.tgz", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", "from": "regenerator-runtime@>=0.10.0 <0.11.0" }, "regenerator-transform": { @@ -682,9 +682,9 @@ } }, "reify": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.8.3.tgz", - "from": "reify@>=0.8.0 <0.9.0" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.9.2.tgz", + "from": "reify@>=0.9.1 <0.10.0" }, "repeating": { "version": "2.0.1", @@ -702,8 +702,8 @@ "from": "source-map@>=0.5.0 <0.6.0" }, "source-map-support": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.14.tgz", + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", "from": "source-map-support@>=0.4.2 <0.5.0" }, "strip-ansi": { @@ -717,8 +717,8 @@ "from": "supports-color@>=2.0.0 <3.0.0" }, "to-fast-properties": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", "from": "to-fast-properties@>=1.0.1 <2.0.0" }, "trim-right": { diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index dc9749cc5c..fe930543df 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -10,7 +10,7 @@ Package.describe({ }); Npm.depends({ - 'meteor-babel': '0.20.2' + 'meteor-babel': '0.20.3' }); Package.onUse(function (api) { diff --git a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json index 45dca93b24..f02ecf48bf 100644 --- a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json +++ b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "install": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/install/-/install-0.9.6.tgz", - "from": "install@0.9.6" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/install/-/install-0.10.0.tgz", + "from": "install@0.10.0" } } } diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index fb953a6b5e..abedb00e02 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -7,7 +7,7 @@ Package.describe({ }); Npm.depends({ - install: "0.9.6" + install: "0.10.0" }); Package.onUse(function(api) { diff --git a/packages/modules/.npm/package/npm-shrinkwrap.json b/packages/modules/.npm/package/npm-shrinkwrap.json index f8f8d11e48..32ff3e2743 100644 --- a/packages/modules/.npm/package/npm-shrinkwrap.json +++ b/packages/modules/.npm/package/npm-shrinkwrap.json @@ -6,19 +6,19 @@ "from": "acorn@>=5.0.0 <5.1.0" }, "minipass": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-1.1.9.tgz", - "from": "minipass@>=1.1.6 <2.0.0" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.0.0.tgz", + "from": "minipass@>=2.0.0 <3.0.0" }, "minizlib": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.2.tgz", - "from": "minizlib@>=1.0.2 <2.0.0" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.3.tgz", + "from": "minizlib@>=1.0.3 <2.0.0" }, "reify": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.8.3.tgz", - "from": "reify@0.8.3" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.9.2.tgz", + "from": "reify@0.9.2" }, "yallist": { "version": "3.0.2", diff --git a/packages/modules/package.js b/packages/modules/package.js index 840b146401..819ebb55f1 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -6,7 +6,7 @@ Package.describe({ }); Npm.depends({ - reify: "0.8.3" + reify: "0.9.2" }); Package.onUse(function(api) { diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 9d0a91c697..07bd68d707 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -14,8 +14,8 @@ var packageJson = { npm: "4.5.0", "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", - "meteor-babel": "0.20.2", - reify: "0.8.3", + "meteor-babel": "0.20.3", + reify: "0.9.2", "meteor-promise": "0.8.0", fibers: "1.0.15", promise: "7.1.1", From 269e10caa6c72312e7032f4c23b4f06f974320d4 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 4 May 2017 16:07:42 -0400 Subject: [PATCH 097/125] Remove support for pkg.module in client bundles. This partially reverts commit d7cae3c939e2231ed89e694d05fe5f3698540b72. This functionality was problematic without providing any clear benefits to Meteor developers, as reported by @fermuch and @markoshust: https://github.com/meteor/meteor/pull/8327#issuecomment-298723203 --- packages/modules-runtime/client.js | 2 - tools/isobuild/import-scanner.js | 11 +--- tools/isobuild/js-analyze.js | 54 +------------------- tools/isobuild/linker.js | 2 - tools/isobuild/resolver.js | 2 - tools/tests/apps/dynamic-import/package.json | 2 +- tools/tests/apps/dynamic-import/tests.js | 10 +--- 7 files changed, 6 insertions(+), 77 deletions(-) diff --git a/packages/modules-runtime/client.js b/packages/modules-runtime/client.js index 1fbf18f13d..d902671864 100644 --- a/packages/modules-runtime/client.js +++ b/packages/modules-runtime/client.js @@ -1,7 +1,5 @@ // On the client, make package resolution prefer the "browser" field of // package.json files to the "main" field. makeInstallerOptions.browser = true; -makeInstallerOptions.mainFields = - ["browser", "module", "jsnext:main", "main"]; meteorInstall = makeInstaller(makeInstallerOptions); diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index 6026935029..dcd26d956d 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -6,10 +6,7 @@ import { } from "underscore"; import {sha1} from "../fs/watch.js"; import {matches as archMatches} from "../utils/archinfo.js"; -import { - findImportedModuleIdentifiers, - reifyCompileWithCache, -} from "./js-analyze.js"; +import {findImportedModuleIdentifiers} from "./js-analyze.js"; import {cssToCommonJS} from "./css-modules.js"; import buildmessage from "../utils/buildmessage.js"; import LRU from "lru-cache"; @@ -743,12 +740,6 @@ export default class ImportScanner { info.hash, ); - if (this.isWeb()) { - const result = reifyCompileWithCache(info.dataString, info.hash); - info.dataString = result.code; - info.deps = result.deps; - } - if (info.dataString !== dataString) { info.data = new Buffer(info.dataString, "utf8"); } diff --git a/tools/isobuild/js-analyze.js b/tools/isobuild/js-analyze.js index cb945fd663..bc36d061a6 100644 --- a/tools/isobuild/js-analyze.js +++ b/tools/isobuild/js-analyze.js @@ -1,7 +1,5 @@ -import { parse as meteorBabelParse } from 'meteor-babel'; +import { parse } from 'meteor-babel'; import { analyze as analyzeScope } from 'escope'; -import { Profile } from "../tool-env/profile.js"; -import { compile as reifyCompile } from "reify/lib/compiler.js"; import LRU from "lru-cache"; const hasOwn = Object.prototype.hasOwnProperty; @@ -22,7 +20,7 @@ function tryToParse(source, hash) { let ast; try { - ast = meteorBabelParse(source); + ast = parse(source); } catch (e) { if (typeof e.loc === 'object') { e.$ParseError = true; @@ -37,54 +35,6 @@ function tryToParse(source, hash) { return ast; } -// Map from file hash to Reify-compiled output. -const REIFY_COMPILE_CACHE = new LRU({ - max: Math.pow(2, 20), - length(result) { - return result.code.length; - } -}); - -export const reifyCompileWithCache = Profile( - "reifyCompileWithCache (js-analyze.js)", - function (source, hash) { - if (hash && REIFY_COMPILE_CACHE.has(hash)) { - return REIFY_COMPILE_CACHE.get(hash); - } - - const result = reifyCompile(source, { - // Do not modify the AST, nor bother returning result.ast. - ast: false, - // It's not our job to enforce strict mode here. - enforceStrictMode: false, - // We may be generating code for JavaScript environments that don't - // support const and let declarations (e.g. older browsers), so it - // would be dangerous at this stage to introduce such declarations. - // Fortunately, reifyCompileWithCache is only called for modules in - // node_modules, which should only be using top-level import and - // export declarations, so there should not be any difference. - generateLetDeclarations: false, - // Same concern for arrow functions as for const/let declarations. - avoidArrowFunctions: true, - parse(code) { - // Avoid double-parsing the input source, but allow Reify to parse - // other strings using the meteor-babel parser. - return code === source - ? tryToParse(code, hash) - : meteorBabelParse(code); - } - }); - - result.deps = findImportedModuleIdentifiers(source, hash); - - if (hash) { - REIFY_COMPILE_CACHE.set(hash, result); - } - - return result; - } -); - var dependencyKeywordPattern = /\b(?:require|import|importSync|dynamicImport|export)\b/g; diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index 9858923305..d117fb88f7 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -276,8 +276,6 @@ _.extend(Module.prototype, { } tryMain("browser"); - tryMain("module"); - tryMain("jsnext:main"); tryMain("main"); stubArray.push(stub); diff --git a/tools/isobuild/resolver.js b/tools/isobuild/resolver.js index 6cf8a4aa75..e2a7c50954 100644 --- a/tools/isobuild/resolver.js +++ b/tools/isobuild/resolver.js @@ -308,8 +308,6 @@ export default class Resolver { if (archMatches(this.targetArch, "web")) { tryMain("browser"); - tryMain("module"); - tryMain("jsnext:main"); } tryMain("main"); diff --git a/tools/tests/apps/dynamic-import/package.json b/tools/tests/apps/dynamic-import/package.json index ac7a9c28e3..1a6a568e7c 100644 --- a/tools/tests/apps/dynamic-import/package.json +++ b/tools/tests/apps/dynamic-import/package.json @@ -6,7 +6,7 @@ "test": "meteor test --full-app --driver-package dispatch:mocha-browser" }, "dependencies": { - "acorn": "^5.0.0", + "acorn": "^4.0.11", "arson": "^0.2.3", "babel-runtime": "^6.20.0", "meteor-node-stubs": "~0.2.4", diff --git a/tools/tests/apps/dynamic-import/tests.js b/tools/tests/apps/dynamic-import/tests.js index 2619143e0b..41473f8883 100644 --- a/tools/tests/apps/dynamic-import/tests.js +++ b/tools/tests/apps/dynamic-import/tests.js @@ -31,16 +31,10 @@ describe("dynamic import(...)", function () { }); it("static package.json, static package", function () { - import * as pkg from "acorn/package.json"; + import { name } from "acorn/package.json"; import acorn from "acorn"; - assert.strictEqual(pkg.name, "acorn"); + assert.strictEqual(name, "acorn"); assert.strictEqual(typeof acorn.parse, "function"); - assert.strictEqual( - require.resolve("acorn"), - Meteor.isServer - ? "/node_modules/acorn/dist/acorn.js" - : "/node_modules/acorn/dist/acorn.es.js" - ); }); it("static package.json, dynamic package", function () { From 509f9aee11523902f8ac506d231d878170d2f7c8 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 4 May 2017 16:23:48 -0400 Subject: [PATCH 098/125] Bump $BUNDLE_VERSION to 4.8.10 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index f9d170a472..6f753b7931 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.9 +BUNDLE_VERSION=4.8.10 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 9228345ce666bc75ee14a84b20a251d062ffb6ba Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Thu, 4 May 2017 16:42:05 -0400 Subject: [PATCH 099/125] Fixed broken upserts with undefined selectors (#8668). Fixes #8666. --- packages/mongo/collection.js | 2 +- packages/mongo/mongo_livedata_tests.js | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/mongo/collection.js b/packages/mongo/collection.js index 000e84e850..45b296d860 100644 --- a/packages/mongo/collection.js +++ b/packages/mongo/collection.js @@ -558,7 +558,7 @@ Mongo.Collection.prototype.update = function update(selector, modifier, ...optio if (!(typeof options.insertedId === 'string' || options.insertedId instanceof Mongo.ObjectID)) throw new Error("insertedId must be string or ObjectID"); insertedId = options.insertedId; - } else if (! selector._id) { + } else if (!selector || !selector._id) { insertedId = this._makeNewID(); options.insertedId = insertedId; } diff --git a/packages/mongo/mongo_livedata_tests.js b/packages/mongo/mongo_livedata_tests.js index 09759f0097..1e1ea0174e 100644 --- a/packages/mongo/mongo_livedata_tests.js +++ b/packages/mongo/mongo_livedata_tests.js @@ -1301,6 +1301,29 @@ testAsyncMulti('mongo-livedata - upsert without callback, ' + idGeneration, [ } ]); +// Regression test for https://github.com/meteor/meteor/issues/8666. +testAsyncMulti('mongo-livedata - upsert with an undefined selector, ' + idGeneration, [ + function (test, expect) { + this.collectionName = Random.id(); + if (Meteor.isClient) { + Meteor.call('createInsecureCollection', this.collectionName); + Meteor.subscribe('c-' + this.collectionName, expect()); + } + }, function (test, expect) { + var coll = new Mongo.Collection(this.collectionName, collectionOptions); + var testWidget = { + name: 'Widget name' + }; + coll.upsert(testWidget._id, testWidget, expect(function (error, insertDetails) { + test.isFalse(error); + test.equal( + coll.findOne(insertDetails.insertedId), + Object.assign({ _id: insertDetails.insertedId }, testWidget) + ); + })); + } +]); + // See https://github.com/meteor/meteor/issues/594. testAsyncMulti('mongo-livedata - document with length, ' + idGeneration, [ function (test, expect) { From a89963fdbe5a55d0741cecae6bbb2fe52ca02063 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 4 May 2017 16:23:07 -0400 Subject: [PATCH 100/125] Bump package versions for 1.5-beta.19 release. --- packages/babel-compiler/package.js | 2 +- packages/dynamic-import/package.js | 2 +- packages/ecmascript/package.js | 2 +- packages/facebook-oauth/package.js | 2 +- packages/localstorage/package.js | 2 +- packages/meteor-tool/package.js | 2 +- packages/minimongo/package.js | 2 +- packages/modules-runtime/package.js | 2 +- packages/modules/package.js | 2 +- packages/mongo/package.js | 2 +- packages/reactive-dict/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index fe930543df..4a3309cb00 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,7 +6,7 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.19.0-beta.18' + version: '6.19.1-beta.19' }); Npm.depends({ diff --git a/packages/dynamic-import/package.js b/packages/dynamic-import/package.js index 8b96290cfa..94908b7c81 100644 --- a/packages/dynamic-import/package.js +++ b/packages/dynamic-import/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "dynamic-import", - version: "0.1.0-beta.18", + version: "0.1.0-beta.19", summary: "Support for module.dynamicImport(id).then(namespace => ...)", documentation: "README.md" }); diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index ae5d723ebf..28f837d339 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.8.0-beta.18', + version: '0.8.0-beta.19', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); diff --git a/packages/facebook-oauth/package.js b/packages/facebook-oauth/package.js index e6acd883db..e79740cd61 100644 --- a/packages/facebook-oauth/package.js +++ b/packages/facebook-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Facebook OAuth flow", - version: "1.3.0" + version: "1.3.1-beta.19" }); Package.onUse(function(api) { diff --git a/packages/localstorage/package.js b/packages/localstorage/package.js index 0f9fe32981..d8ed167141 100644 --- a/packages/localstorage/package.js +++ b/packages/localstorage/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Simulates local storage on IE 6,7 using userData", - version: "1.1.0-beta.18" + version: "1.1.0-beta.19" }); Package.onUse(function (api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 79f89bb918..24df7a41f1 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.5.0-beta.18' + version: '1.5.0-beta.19' }); Package.includeTool(); diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index 9d75927950..541e9ea468 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.2.0-beta.18' + version: '1.2.0-beta.19' }); Package.onUse(function (api) { diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index abedb00e02..06917e328c 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules-runtime", - version: "0.8.0-beta.18", + version: "0.8.0-beta.19", summary: "CommonJS module system", git: "https://github.com/benjamn/install", documentation: "README.md" diff --git a/packages/modules/package.js b/packages/modules/package.js index 819ebb55f1..3da4d3e38f 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules", - version: "0.9.0-beta.18", + version: "0.9.0-beta.19", summary: "CommonJS module system", documentation: "README.md" }); diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 0c442d6e42..bfc3b3034d 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.1.17' + version: '1.1.18-beta.19' }); Npm.depends({ diff --git a/packages/reactive-dict/package.js b/packages/reactive-dict/package.js index c7d75f7fd0..215517b833 100644 --- a/packages/reactive-dict/package.js +++ b/packages/reactive-dict/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Reactive dictionary", - version: '1.1.8' + version: '1.1.9-beta.19' }); Package.onUse(function (api) { diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 7e4e12b7c1..e51412b902 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5-beta.18", + "version": "1.5-beta.19", "recommended": false, "official": false, "description": "Meteor" From 95c4bcd6f2bd73f932d951f875c2d1029f3152dd Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 5 May 2017 20:05:12 -0400 Subject: [PATCH 101/125] Make `meteor create --bare` apps use static-html. Perhaps most importantly, this means bare apps no longer depend on jquery. --- tools/static-assets/skel-bare/.meteor/packages | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/static-assets/skel-bare/.meteor/packages b/tools/static-assets/skel-bare/.meteor/packages index 199c1c1034..56a930a9ed 100644 --- a/tools/static-assets/skel-bare/.meteor/packages +++ b/tools/static-assets/skel-bare/.meteor/packages @@ -7,7 +7,7 @@ meteor-base # Packages every Meteor app needs to have mobile-experience # Packages for a great mobile UX mongo # The database Meteor supports right now -blaze-html-templates # Compile .html files into Meteor Blaze views +static-html # Define static page content in .html files reactive-var # Reactive variable for tracker tracker # Meteor's client-side reactive programming library From 084801237a8c288d99ec82b0fbc1c76bdf1aab16 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 5 May 2017 20:07:23 -0400 Subject: [PATCH 102/125] Report per-bundle stats from minifier. --- packages/babel-compiler/babel.js | 4 + packages/standard-minifier-js/package.js | 5 ++ .../standard-minifier-js/plugin/minify-js.js | 65 +++++++++------ packages/standard-minifier-js/plugin/stats.js | 83 +++++++++++++++++++ packages/standard-minifier-js/plugin/utils.js | 26 ++++++ .../standard-minifier-js/plugin/visitor.js | 57 +++++++++++++ tools/isobuild/bundler.js | 4 + tools/isobuild/minifier-plugin.js | 15 +--- 8 files changed, 224 insertions(+), 35 deletions(-) create mode 100644 packages/standard-minifier-js/plugin/stats.js create mode 100644 packages/standard-minifier-js/plugin/utils.js create mode 100644 packages/standard-minifier-js/plugin/visitor.js diff --git a/packages/babel-compiler/babel.js b/packages/babel-compiler/babel.js index ac518d1034..13306f306b 100644 --- a/packages/babel-compiler/babel.js +++ b/packages/babel-compiler/babel.js @@ -21,6 +21,10 @@ Babel = { // Deprecated, now a no-op. validateExtraFeatures: Function.prototype, + parse: function (source) { + return Npm.require('meteor-babel').parse(source); + }, + compile: function (source, options) { var meteorBabel = Npm.require('meteor-babel'); options = options || getDefaultOptions(); diff --git a/packages/standard-minifier-js/package.js b/packages/standard-minifier-js/package.js index e2bc14e36e..8b9900cc8b 100644 --- a/packages/standard-minifier-js/package.js +++ b/packages/standard-minifier-js/package.js @@ -9,9 +9,14 @@ Package.registerBuildPlugin({ name: "minifyStdJS", use: [ 'minifier-js', + 'babel-compiler', + 'ecmascript' ], sources: [ 'plugin/minify-js.js', + 'plugin/stats.js', + 'plugin/visitor.js', + 'plugin/utils.js', ], }); diff --git a/packages/standard-minifier-js/plugin/minify-js.js b/packages/standard-minifier-js/plugin/minify-js.js index 202f3b2a55..d1d67482d1 100644 --- a/packages/standard-minifier-js/plugin/minify-js.js +++ b/packages/standard-minifier-js/plugin/minify-js.js @@ -1,3 +1,5 @@ +import { extractModuleSizesTree } from "./stats.js"; + Plugin.registerMinifier({ extensions: ['js'], archMatching: 'web' @@ -108,37 +110,52 @@ MeteorBabelMinifier.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; + const toBeAdded = { + data: "", + stats: Object.create(null) + }; - try { - minified = meteorJsMinify(file.getContentsAsString()); + files.forEach(file => { + // Don't reminify *.min.js. + if (/\.min\.js$/.test(file.getPathInBundle())) { + toBeAdded.data += file.getContentsAsString(); + } else { + var minified; - if (!(minified && typeof minified.code === "string")) { - throw new Error(); - } - } catch (err) { - var filePath = file.getPathInBundle(); + try { + minified = meteorJsMinify(file.getContentsAsString()); - maybeThrowMinifyErrorBySourceFile(err, file); - - err.message += " while minifying " + filePath; - throw err; + if (!(minified && typeof minified.code === "string")) { + throw new Error(); } - allJs += minified.code; - } - allJs += '\n\n'; + } catch (err) { + var filePath = file.getPathInBundle(); - Plugin.nudge(); - }); + maybeThrowMinifyErrorBySourceFile(err, file); + + err.message += " while minifying " + filePath; + throw err; + } + + const tree = extractModuleSizesTree(minified.code); + if (tree) { + toBeAdded.stats[file.getPathInBundle()] = + [Buffer.byteLength(minified.code), tree]; + } else { + toBeAdded.stats[file.getPathInBundle()] = + Buffer.byteLength(minified.code); + } + + toBeAdded.data += minified.code; + } + + toBeAdded.data += '\n\n'; + + Plugin.nudge(); + }); if (files.length) { - files[0].addJavaScript({ data: allJs }); + files[0].addJavaScript(toBeAdded); } }; diff --git a/packages/standard-minifier-js/plugin/stats.js b/packages/standard-minifier-js/plugin/stats.js new file mode 100644 index 0000000000..b8c5d408c9 --- /dev/null +++ b/packages/standard-minifier-js/plugin/stats.js @@ -0,0 +1,83 @@ +import Visitor from "./visitor.js"; + +// This RegExp will be used to scan the source for calls to meteorInstall, +// taking into consideration that the function name may have been mangled +// to something other than "meteorInstall" by the minifier. +const meteorInstallRegExp = new RegExp([ + // If meteorInstall is called by its unminified name, then that's what + // we should be looking for in the AST. + /\b(meteorInstall)\(\{/, + // If the meteorInstall function name has been minified, we can figure + // out its mangled name by examining the import assingment. + /\b(\w+)=Package.modules.meteorInstall\b/, + /\b(\w+)=Package\["modules-runtime"\].meteorInstall\b/, +].map(exp => exp.source).join("|")); + +export function extractModuleSizesTree(source) { + const match = meteorInstallRegExp.exec(source); + if (match) { + const ast = Babel.parse(source); + const name = match[1] || match[2] || match[3]; + meteorInstallVisitor.visit(ast, name, source); + return meteorInstallVisitor.tree; + } +} + +const meteorInstallVisitor = new (class extends Visitor { + reset(root, meteorInstallName, source) { + this.name = meteorInstallName; + this.source = source; + this.tree = null; + } + + visitCallExpression(node) { + if (this.tree !== null) { + return; + } + + if (isIdWithName(node.callee, this.name)) { + const source = this.source; + + function walk(expr) { + if (expr.type !== "ObjectExpression") { + return Buffer.byteLength(source.slice(expr.start, expr.end)); + } + + const contents = Object.create(null); + + expr.properties.forEach(prop => { + const keyName = getKeyName(prop.key); + if (typeof keyName === "string") { + contents[keyName] = walk(prop.value); + } + }); + + return contents; + } + + this.tree = walk(node.arguments[0]); + + } else { + this.visitChildren(node); + } + } +}); + +function isIdWithName(node, name) { + return node && + node.type === "Identifier" && + node.name === name; +} + +function getKeyName(key) { + if (key.type === "Identifier") { + return key.name; + } + + if (key.type === "StringLiteral" || + key.type === "Literal") { + return key.value; + } + + return null; +} \ No newline at end of file diff --git a/packages/standard-minifier-js/plugin/utils.js b/packages/standard-minifier-js/plugin/utils.js new file mode 100644 index 0000000000..0ce207b24e --- /dev/null +++ b/packages/standard-minifier-js/plugin/utils.js @@ -0,0 +1,26 @@ +"use strict"; + +const codeOfA = "A".charCodeAt(0); +const codeOfZ = "Z".charCodeAt(0); + +export function isObject(value) { + return typeof value === "object" && value !== null; +} + +// Without a complete list of Node .type names, we have to settle for this +// fuzzy matching of object shapes. However, the infeasibility of +// maintaining a complete list of type names is one of the reasons we're +// using the FastPath/Visitor abstraction in the first place. +export function isNodeLike(value) { + return isObject(value) && + ! Array.isArray(value) && + isCapitalized(value.type); +} + +function isCapitalized(string) { + if (typeof string !== "string") { + return false; + } + const code = string.charCodeAt(0); + return code >= codeOfA && code <= codeOfZ; +} diff --git a/packages/standard-minifier-js/plugin/visitor.js b/packages/standard-minifier-js/plugin/visitor.js new file mode 100644 index 0000000000..495dbb7307 --- /dev/null +++ b/packages/standard-minifier-js/plugin/visitor.js @@ -0,0 +1,57 @@ +"use strict"; + +import { + isObject, + isNodeLike, +} from "./utils.js"; + +const codeOfUnderscore = "_".charCodeAt(0); + +export default class Visitor { + visit(root) { + this.reset.apply(this, arguments); + this.visitWithoutReset(root); + } + + visitWithoutReset(node) { + if (Array.isArray(node)) { + node.forEach(this.visitWithoutReset, this); + } else if (isNodeLike(node)) { + const method = this["visit" + node.type]; + if (typeof method === "function") { + // The method must call this.visitChildren(node) to continue + // traversing. + method.call(this, node); + } else { + this.visitChildren(node); + } + } + } + + visitChildren(node) { + if (! isNodeLike(node)) { + return; + } + + const keys = Object.keys(node); + const keyCount = keys.length; + + for (let i = 0; i < keyCount; ++i) { + const key = keys[i]; + + if (key === "loc" || // Ignore .loc.{start,end} objects. + // Ignore "private" properties added by Babel. + key.charCodeAt(0) === codeOfUnderscore) { + continue; + } + + const child = node[key]; + if (! isObject(child)) { + // Ignore properties whose values aren't objects. + continue; + } + + this.visitWithoutReset(child); + } + } +} diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index a90bed4907..f4a7c2111e 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -1286,6 +1286,10 @@ class Target { newFile.setUrlToHash('.js', '?meteor_js_resource=true'); } + if (! dynamic) { + console.log(file.stats); + } + return newFile; }); diff --git a/tools/isobuild/minifier-plugin.js b/tools/isobuild/minifier-plugin.js index f75c3b4b7b..7a34efbf37 100644 --- a/tools/isobuild/minifier-plugin.js +++ b/tools/isobuild/minifier-plugin.js @@ -60,13 +60,9 @@ export class JsFile extends InputFile { // - sourceMap // - path // - hash? + // - stats? addJavaScript(options) { - const self = this; - self._minifiedFiles.push({ - data: options.data, - sourceMap: options.sourceMap, - path: options.path - }); + this._minifiedFiles.push({ ...options }); } } @@ -75,12 +71,9 @@ export class CssFile extends InputFile { // - sourceMap // - path // - hash? + // - stats? addStylesheet(options) { - this._minifiedFiles.push({ - data: options.data, - sourceMap: options.sourceMap, - path: options.path - }); + this._minifiedFiles.push({ ...options }); } } From 1c8bc7353e9a8d526880634a58c506b423c4a55e Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 8 May 2017 17:34:14 -0400 Subject: [PATCH 103/125] Serve .stats.json for every .js bundle. --- tools/isobuild/bundler.js | 43 +++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index f4a7c2111e..09a8b8c3ba 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -171,6 +171,7 @@ var packageVersionParser = require('../packaging/package-version-parser.js'); var release = require('../packaging/release.js'); import { load as loadIsopacket } from '../tool-env/isopackets.js'; import { CORDOVA_PLATFORM_VERSIONS } from '../cordova'; +import { gzipSync } from "zlib"; // files to ignore when bundling. node has no globs, so use regexps exports.ignoreFiles = [ @@ -1259,7 +1260,7 @@ class Target { const js = []; function handle(source, dynamic) { - const newFiles = source._minifiedFiles.map(file => { + source._minifiedFiles.forEach(file => { // Remove the function name __minifyJs that was added above. file.data = file.data .toString("utf8") @@ -1286,14 +1287,40 @@ class Target { newFile.setUrlToHash('.js', '?meteor_js_resource=true'); } - if (! dynamic) { - console.log(file.stats); + js.push(newFile); + + if (file.stats && + ! dynamic && + minifyMode === "production") { + // If the minifier reported any statistics, serve those data as + // a .stats.json file alongside the newFile. + const contents = newFile.contents(); + const statsFile = new File({ + info: "bundle size stats JSON", + data: new Buffer(JSON.stringify({ + totalMinifiedBytes: contents.length, + totalMinifiedGzipBytes: gzipSync(contents).length, + minifiedBytesByPackage: file.stats, + }, null, 2) + "\n", "utf8") + }); + + statsFile.url = newFile.url.replace(/\.js\b/, ".stats.json"); + statsFile.targetPath = + newFile.targetPath.replace(/\.js\b/, ".stats.json"); + statsFile.cacheable = true; + statsFile.type = "json"; + + if (statsFile.url !== newFile.url && + statsFile.targetPath !== newFile.targetPath) { + // If the minifier used a file extension other than .js, the + // .replace calls above won't inject the .stats.json extension + // into the statsFile.{url,targetPath} strings, and it would + // be a mistake to serve the statsFile with the same URL as + // the real JS bundle. This should be a very uncommon case. + js.push(statsFile); + } } - - return newFile; }); - - js.push(...newFiles); } staticFiles.forEach(file => handle(file, false)); @@ -1511,7 +1538,7 @@ class ClientTarget extends Target { const eachResource = function (f) { ["js", "css", "asset"].forEach((type) => { this[type].forEach((file) => { - f(file, type); + f(file, file.type || type); }); }); }.bind(this); From b5b76a850e175afe7fc3c91b9d42cffbaf753cd1 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 11:44:37 -0400 Subject: [PATCH 104/125] Include minifier package name and version in .stats.json file. --- tools/isobuild/bundler.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index 09a8b8c3ba..d64e3c995b 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -1298,6 +1298,10 @@ class Target { const statsFile = new File({ info: "bundle size stats JSON", data: new Buffer(JSON.stringify({ + minifier: { + name: minifierDef.isopack.name, + version: minifierDef.isopack.version, + }, totalMinifiedBytes: contents.length, totalMinifiedGzipBytes: gzipSync(contents).length, minifiedBytesByPackage: file.stats, From 3bda1c3df844d7d0037d1771c82cebd8ae79bb24 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Sat, 6 May 2017 20:43:23 -0400 Subject: [PATCH 105/125] Upgrade the `meteor-babel`, `reify`, and `install` npm packages. --- History.md | 13 ++++++-- .../.npm/package/npm-shrinkwrap.json | 33 +++++++++++-------- packages/babel-compiler/package.js | 2 +- .../.npm/package/npm-shrinkwrap.json | 6 ++-- packages/modules-runtime/package.js | 2 +- .../modules/.npm/package/npm-shrinkwrap.json | 15 ++++++--- packages/modules/package.js | 2 +- packages/modules/reify.js | 2 +- scripts/dev-bundle-tool-package.js | 4 +-- 9 files changed, 49 insertions(+), 30 deletions(-) diff --git a/History.md b/History.md index 8bbb71b861..486b5ef79d 100644 --- a/History.md +++ b/History.md @@ -9,11 +9,20 @@ information about how dynamic `import(...)` works in Meteor, and how to use it in your applications. -* The `meteor-babel` npm package has been upgraded to version 0.20.3, and - the `reify` npm package has been upgraded to version 0.9.2, fixing +* The `meteor-babel` npm package has been upgraded to version 0.21.1. + +* The `reify` npm package has been upgraded to version 0.11.0, fixing [issue #8595](https://github.com/meteor/meteor/issues/8595) and improving compilation and runtime performance. +> Note: With this version of Reify, `import` declarations are compiled to + `module.watch(require(id), ...)` instead of `module.importSync(id, ...)` + or the older `module.import(id, ...)`. The behavior of the compiled code + should be the same as before, but the details seemed different enough to + warrant a note. + +* The `install` npm package has been upgraded to version 0.10.1. + ## v1.4.4.2, 2017-05-02 * Node has been upgraded to version 4.8.2. diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index c52b3cbdc0..c6866fd16c 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -270,9 +270,9 @@ "from": "babel-plugin-transform-es2015-modules-commonjs@>=6.22.0 <7.0.0" }, "babel-plugin-transform-es2015-modules-reify": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.9.0.tgz", - "from": "babel-plugin-transform-es2015-modules-reify@>=0.9.0 <0.10.0" + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.11.0.tgz", + "from": "babel-plugin-transform-es2015-modules-reify@>=0.11.0 <0.12.0" }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", @@ -477,7 +477,7 @@ "brace-expansion": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", - "from": "brace-expansion@>=1.0.0 <2.0.0" + "from": "brace-expansion@>=1.1.7 <2.0.0" }, "chalk": { "version": "1.1.3", @@ -580,9 +580,9 @@ "from": "loose-envify@>=1.0.0 <2.0.0" }, "meteor-babel": { - "version": "0.20.3", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.3.tgz", - "from": "meteor-babel@0.20.3" + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.21.1.tgz", + "from": "meteor-babel@0.21.1" }, "meteor-babel-helpers": { "version": "0.0.3", @@ -590,8 +590,8 @@ "from": "meteor-babel-helpers@0.0.3" }, "minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "from": "minimatch@>=3.0.2 <4.0.0" }, "minimist": { @@ -600,8 +600,8 @@ "from": "minimist@0.0.8" }, "minipass": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.0.0.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.0.1.tgz", "from": "minipass@>=2.0.0 <3.0.0" }, "minizlib": { @@ -682,15 +682,20 @@ } }, "reify": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.9.2.tgz", - "from": "reify@>=0.9.1 <0.10.0" + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.11.0.tgz", + "from": "reify@>=0.11.0 <0.12.0" }, "repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "from": "repeating@>=2.0.0 <3.0.0" }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "from": "semver@>=5.3.0 <6.0.0" + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index 4a3309cb00..e6d14c7981 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -10,7 +10,7 @@ Package.describe({ }); Npm.depends({ - 'meteor-babel': '0.20.3' + 'meteor-babel': '0.21.1' }); Package.onUse(function (api) { diff --git a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json index f02ecf48bf..1bbd59e1e2 100644 --- a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json +++ b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "install": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/install/-/install-0.10.0.tgz", - "from": "install@0.10.0" + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/install/-/install-0.10.1.tgz", + "from": "install@0.10.1" } } } diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index 06917e328c..7ba33bfaa8 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -7,7 +7,7 @@ Package.describe({ }); Npm.depends({ - install: "0.10.0" + install: "0.10.1" }); Package.onUse(function(api) { diff --git a/packages/modules/.npm/package/npm-shrinkwrap.json b/packages/modules/.npm/package/npm-shrinkwrap.json index 32ff3e2743..0c95dcf9fd 100644 --- a/packages/modules/.npm/package/npm-shrinkwrap.json +++ b/packages/modules/.npm/package/npm-shrinkwrap.json @@ -6,8 +6,8 @@ "from": "acorn@>=5.0.0 <5.1.0" }, "minipass": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.0.0.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.0.1.tgz", "from": "minipass@>=2.0.0 <3.0.0" }, "minizlib": { @@ -16,9 +16,14 @@ "from": "minizlib@>=1.0.3 <2.0.0" }, "reify": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.9.2.tgz", - "from": "reify@0.9.2" + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/reify/-/reify-0.11.0.tgz", + "from": "reify@0.11.0" + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "from": "semver@>=5.3.0 <6.0.0" }, "yallist": { "version": "3.0.2", diff --git a/packages/modules/package.js b/packages/modules/package.js index 3da4d3e38f..c245ebdb3c 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -6,7 +6,7 @@ Package.describe({ }); Npm.depends({ - reify: "0.9.2" + reify: "0.11.0" }); Package.onUse(function(api) { diff --git a/packages/modules/reify.js b/packages/modules/reify.js index 5b8fa26bcf..6bbb48af8a 100644 --- a/packages/modules/reify.js +++ b/packages/modules/reify.js @@ -1,5 +1,5 @@ var Module = module.constructor; -require("reify/lib/runtime").enable(Module); var Mp = Module.prototype; +require("reify/lib/runtime").enable(Mp); Mp.importSync = Mp.importSync || Mp.import; Mp.import = Mp.import || Mp.importSync; diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 07bd68d707..de3790f2c7 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -14,8 +14,8 @@ var packageJson = { npm: "4.5.0", "node-gyp": "3.6.0", "node-pre-gyp": "0.6.34", - "meteor-babel": "0.20.3", - reify: "0.9.2", + "meteor-babel": "0.21.1", + reify: "0.11.0", "meteor-promise": "0.8.0", fibers: "1.0.15", promise: "7.1.1", From ea286d0aba06c0320b85b4e828662e779f54e7ed Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 13:51:46 -0400 Subject: [PATCH 106/125] Upgrade Node to version 4.8.3. https://nodejs.org/en/blog/release/v4.8.3/ --- History.md | 2 ++ scripts/build-dev-bundle-common.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 486b5ef79d..d4800a9aaa 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,7 @@ ## v.NEXT +* Node has been upgraded to version 4.8.3. + * Running `meteor add dynamic-import` installs support for ECMAScript [dynamic `import(...)`](https://github.com/tc39/proposal-dynamic-import), a new language feature which allows for asynchronous module fetching diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 5e5b8062f7..da0f8253f9 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -6,7 +6,7 @@ set -u UNAME=$(uname) ARCH=$(uname -m) MONGO_VERSION=3.2.12 -NODE_VERSION=4.8.2 +NODE_VERSION=4.8.3 NPM_VERSION=4.5.0 if [ "$UNAME" == "Linux" ] ; then From f8bf1ae6eb37e88def597763751bf85a6fc48ea8 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 13:53:49 -0400 Subject: [PATCH 107/125] Bump $BUNDLE_VERSION to 4.8.11 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 6f753b7931..7b371a760f 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.10 +BUNDLE_VERSION=4.8.11 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 8364f813448bfd10457e63fe3a22d0142d248cd5 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 14:48:13 -0400 Subject: [PATCH 108/125] Include the dynamic-import package in new apps and packages. It's tempting to make the ecmascript package api.imply("dynamic-import"), but the dynamic-import package depends on the ddp package, which depends heavily on the ecmascript package, and I'm not sure how best to break that dependency cycle. --- tools/static-assets/skel-bare/.meteor/packages | 3 ++- tools/static-assets/skel-full/.meteor/packages | 3 ++- tools/static-assets/skel-pack/package.js | 1 + tools/static-assets/skel/.meteor/packages | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/static-assets/skel-bare/.meteor/packages b/tools/static-assets/skel-bare/.meteor/packages index 56a930a9ed..eaef440301 100644 --- a/tools/static-assets/skel-bare/.meteor/packages +++ b/tools/static-assets/skel-bare/.meteor/packages @@ -13,6 +13,7 @@ tracker # Meteor's client-side reactive programming library standard-minifier-css # CSS minifier run for production mode standard-minifier-js # JS minifier run for production mode -es5-shim # ECMAScript 5 compatibility for older browsers. +es5-shim # ECMAScript 5 compatibility for older browsers ecmascript # Enable ECMAScript2015+ syntax in app code +dynamic-import # Enable dynamic import(...) syntax and runtime shell-server # Server-side component of the `meteor shell` command diff --git a/tools/static-assets/skel-full/.meteor/packages b/tools/static-assets/skel-full/.meteor/packages index 75aaefb27e..45c1e58942 100644 --- a/tools/static-assets/skel-full/.meteor/packages +++ b/tools/static-assets/skel-full/.meteor/packages @@ -13,8 +13,9 @@ tracker # Meteor's client-side reactive programming library standard-minifier-css # CSS minifier run for production mode standard-minifier-js # JS minifier run for production mode -es5-shim # ECMAScript 5 compatibility for older browsers. +es5-shim # ECMAScript 5 compatibility for older browsers ecmascript # Enable ECMAScript2015+ syntax in app code +dynamic-import # Enable dynamic import(...) syntax and runtime kadira:flow-router # FlowRouter is a very simple router for Meteor kadira:blaze-layout # Layout manager for blaze (works well with FlowRouter) diff --git a/tools/static-assets/skel-pack/package.js b/tools/static-assets/skel-pack/package.js index d0bbaf2c14..87d09b4847 100644 --- a/tools/static-assets/skel-pack/package.js +++ b/tools/static-assets/skel-pack/package.js @@ -13,6 +13,7 @@ Package.describe({ Package.onUse(function(api) { ~cc~ api.versionsFrom('~release~'); api.use('ecmascript'); + api.use('dynamic-import'); api.mainModule('~fs-name~.js'); }); diff --git a/tools/static-assets/skel/.meteor/packages b/tools/static-assets/skel/.meteor/packages index 39fe93e662..d7c0f56593 100644 --- a/tools/static-assets/skel/.meteor/packages +++ b/tools/static-assets/skel/.meteor/packages @@ -13,8 +13,9 @@ tracker # Meteor's client-side reactive programming library standard-minifier-css # CSS minifier run for production mode standard-minifier-js # JS minifier run for production mode -es5-shim # ECMAScript 5 compatibility for older browsers. +es5-shim # ECMAScript 5 compatibility for older browsers ecmascript # Enable ECMAScript2015+ syntax in app code +dynamic-import # Enable dynamic import(...) syntax and runtime shell-server # Server-side component of the `meteor shell` command autopublish # Publish all data to the clients (for prototyping) From ee5638761e9c0ae78b5771e84bfb71c52178ddb5 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 14:53:41 -0400 Subject: [PATCH 109/125] Mention bundle size analysis in History.md. --- History.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/History.md b/History.md index d4800a9aaa..a5b4b199f4 100644 --- a/History.md +++ b/History.md @@ -25,6 +25,18 @@ * The `install` npm package has been upgraded to version 0.10.1. +* If you're using the `standard-minifier-js` Meteor package, as most + Meteor developers do, it will now produce a detailed analysis of package + and module sizes within your production `.js` bundle whenever you run + `meteor build` or `meteor run --production`. These data are served by + the application web server at the same URL as the minified `.js` bundle, + except with a `.stats.json` file extension instead of `.js`. If you're + using a different minifier plugin, and would like to support similar + functionality, refer to + [these](https://github.com/meteor/meteor/pull/8327/commits/084801237a8c288d99ec82b0fbc1c76bdf1aab16) + [commits](https://github.com/meteor/meteor/pull/8327/commits/1c8bc7353e9a8d526880634a58c506b423c4a55e) + for inspiration. + ## v1.4.4.2, 2017-05-02 * Node has been upgraded to version 4.8.2. From 75ada39092aaa152726511c10f42a816d205c1ea Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 15:21:42 -0400 Subject: [PATCH 110/125] Bump LINKER_CACHE_SALT and compiler.BUILT_BY for good measure. Recent updates to meteor-babel and reify make it particularly important to force recompilation of ECMAScript modules and package/app bundles. --- tools/isobuild/compiler-plugin.js | 2 +- tools/isobuild/compiler.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/isobuild/compiler-plugin.js b/tools/isobuild/compiler-plugin.js index 4c2925226e..10f4f3e031 100644 --- a/tools/isobuild/compiler-plugin.js +++ b/tools/isobuild/compiler-plugin.js @@ -62,7 +62,7 @@ import { isTestFilePath } from './test-files.js'; // Cache the (slightly post-processed) results of linker.fullLink. const CACHE_SIZE = process.env.METEOR_LINKER_CACHE_SIZE || 1024*1024*100; const CACHE_DEBUG = !! process.env.METEOR_TEST_PRINT_LINKER_CACHE_DEBUG; -const LINKER_CACHE_SALT = 15; // Increment this number to force relinking. +const LINKER_CACHE_SALT = 16; // Increment this number to force relinking. const LINKER_CACHE = new LRU({ max: CACHE_SIZE, // Cache is measured in bytes. We don't care about servePath. diff --git a/tools/isobuild/compiler.js b/tools/isobuild/compiler.js index c00f588617..befd61ebf7 100644 --- a/tools/isobuild/compiler.js +++ b/tools/isobuild/compiler.js @@ -34,7 +34,7 @@ var compiler = exports; // dependencies. (At least for now, packages only used in target creation (eg // minifiers) don't require you to update BUILT_BY, though you will need to quit // and rerun "meteor run".) -compiler.BUILT_BY = 'meteor/27'; +compiler.BUILT_BY = 'meteor/28'; // This is a list of all possible architectures that a build can target. (Client // is expanded into 'web.browser' and 'web.cordova') From 3b6a577ffb167af47396f243721aef028b1db70f Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 21:22:00 -0400 Subject: [PATCH 111/125] Fix typo in dynamic-import/client.js comment. --- packages/dynamic-import/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index 9d5f9593b9..a7120dca9c 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -12,7 +12,7 @@ Module.prototype.dynamicImport = function (id) { }); }; -// Called by Module.prototype.fetch if there are any missing dynamic +// Called by Module.prototype.prefetch if there are any missing dynamic // modules that need to be fetched. meteorInstall.fetch = function (ids) { var tree = Object.create(null); From 42c41901c53d2b0916f2ab5289596eeaa2d318f5 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 21:23:41 -0400 Subject: [PATCH 112/125] Call module.runSetters() after any meteor/tools modules load. --- tools/tool-env/install-runtime.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/tool-env/install-runtime.js b/tools/tool-env/install-runtime.js index a134327915..00178ef8a3 100644 --- a/tools/tool-env/install-runtime.js +++ b/tools/tool-env/install-runtime.js @@ -24,6 +24,19 @@ regenerator.async = function () { // add boilerplate at the top of every file. require("meteor-babel").defineHelpers(); +var Mp = module.constructor.prototype; +var moduleLoad = Mp.load; +Mp.load = function (filename) { + var result = moduleLoad.apply(this, arguments); + var runSetters = this.runSetters || this.runModuleSetters; + if (typeof runSetters === "function") { + // Make sure we call module.runSetters (or module.runModuleSetters, a + // legacy synonym) whenever a module finishes loading. + runSetters.call(this); + } + return result; +}; + // Installs source map support with a hook to add functions to look for // source maps in custom places. require('./source-map-retriever-stack.js'); From 7a54259c94b92a672911c52633c65815fe29124c Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 21:24:41 -0400 Subject: [PATCH 113/125] Revert "Include the dynamic-import package in new apps and packages." Partially reverts commit 8364f813448bfd10457e63fe3a22d0142d248cd5. This commit was causing self-test failures like the following: While selecting package versions: error: unknown package in top-level dependencies: dynamic-import I suspect these tests won't work until the dynamic-import package is published with a non-prerelease version. --- tools/static-assets/skel-bare/.meteor/packages | 1 - tools/static-assets/skel-full/.meteor/packages | 1 - tools/static-assets/skel-pack/package.js | 1 - tools/static-assets/skel/.meteor/packages | 1 - 4 files changed, 4 deletions(-) diff --git a/tools/static-assets/skel-bare/.meteor/packages b/tools/static-assets/skel-bare/.meteor/packages index eaef440301..1dacd59dda 100644 --- a/tools/static-assets/skel-bare/.meteor/packages +++ b/tools/static-assets/skel-bare/.meteor/packages @@ -15,5 +15,4 @@ standard-minifier-css # CSS minifier run for production mode standard-minifier-js # JS minifier run for production mode es5-shim # ECMAScript 5 compatibility for older browsers ecmascript # Enable ECMAScript2015+ syntax in app code -dynamic-import # Enable dynamic import(...) syntax and runtime shell-server # Server-side component of the `meteor shell` command diff --git a/tools/static-assets/skel-full/.meteor/packages b/tools/static-assets/skel-full/.meteor/packages index 45c1e58942..6f3d36015c 100644 --- a/tools/static-assets/skel-full/.meteor/packages +++ b/tools/static-assets/skel-full/.meteor/packages @@ -15,7 +15,6 @@ standard-minifier-css # CSS minifier run for production mode standard-minifier-js # JS minifier run for production mode es5-shim # ECMAScript 5 compatibility for older browsers ecmascript # Enable ECMAScript2015+ syntax in app code -dynamic-import # Enable dynamic import(...) syntax and runtime kadira:flow-router # FlowRouter is a very simple router for Meteor kadira:blaze-layout # Layout manager for blaze (works well with FlowRouter) diff --git a/tools/static-assets/skel-pack/package.js b/tools/static-assets/skel-pack/package.js index 87d09b4847..d0bbaf2c14 100644 --- a/tools/static-assets/skel-pack/package.js +++ b/tools/static-assets/skel-pack/package.js @@ -13,7 +13,6 @@ Package.describe({ Package.onUse(function(api) { ~cc~ api.versionsFrom('~release~'); api.use('ecmascript'); - api.use('dynamic-import'); api.mainModule('~fs-name~.js'); }); diff --git a/tools/static-assets/skel/.meteor/packages b/tools/static-assets/skel/.meteor/packages index d7c0f56593..18f8d45d89 100644 --- a/tools/static-assets/skel/.meteor/packages +++ b/tools/static-assets/skel/.meteor/packages @@ -15,7 +15,6 @@ standard-minifier-css # CSS minifier run for production mode standard-minifier-js # JS minifier run for production mode es5-shim # ECMAScript 5 compatibility for older browsers ecmascript # Enable ECMAScript2015+ syntax in app code -dynamic-import # Enable dynamic import(...) syntax and runtime shell-server # Server-side component of the `meteor shell` command autopublish # Publish all data to the clients (for prototyping) From 656fbeba9ba34e53682ce595d95a2af822313fa2 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 21:51:54 -0400 Subject: [PATCH 114/125] Upgrade meteor-babel to version 0.21.2 to enable class properties. --- History.md | 4 +++- .../.npm/package/npm-shrinkwrap.json | 16 +++++++++++++--- packages/babel-compiler/package.js | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index a5b4b199f4..ddad1870f7 100644 --- a/History.md +++ b/History.md @@ -11,7 +11,9 @@ information about how dynamic `import(...)` works in Meteor, and how to use it in your applications. -* The `meteor-babel` npm package has been upgraded to version 0.21.1. +* The `meteor-babel` npm package has been upgraded to version 0.21.2, + enabling the latest Reify compiler and the transform-class-properties + plugin, among other improvements. * The `reify` npm package has been upgraded to version 0.11.0, fixing [issue #8595](https://github.com/meteor/meteor/issues/8595) and diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index c6866fd16c..a88dedc6c0 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -199,6 +199,11 @@ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", "from": "babel-plugin-syntax-async-generators@>=6.13.0 <7.0.0" }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "from": "babel-plugin-syntax-class-properties@>=6.8.0 <7.0.0" + }, "babel-plugin-syntax-dynamic-import": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", @@ -224,6 +229,11 @@ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", "from": "babel-plugin-syntax-trailing-function-commas@>=6.22.0 <7.0.0" }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "from": "babel-plugin-transform-class-properties@>=6.24.1 <7.0.0" + }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", @@ -580,9 +590,9 @@ "from": "loose-envify@>=1.0.0 <2.0.0" }, "meteor-babel": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.21.1.tgz", - "from": "meteor-babel@0.21.1" + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.21.2.tgz", + "from": "meteor-babel@0.21.2" }, "meteor-babel-helpers": { "version": "0.0.3", diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index e6d14c7981..e0132914eb 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -10,7 +10,7 @@ Package.describe({ }); Npm.depends({ - 'meteor-babel': '0.21.1' + 'meteor-babel': '0.21.2' }); Package.onUse(function (api) { From d78fa46d06b9a3be678f1836bf37017c74132e24 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 22:20:59 -0400 Subject: [PATCH 115/125] Bump package versions for 1.5-beta.20 release. --- packages/babel-compiler/package.js | 2 +- packages/dynamic-import/package.js | 2 +- packages/ecmascript/package.js | 2 +- packages/facebook-oauth/package.js | 2 +- packages/localstorage/package.js | 2 +- packages/meteor-tool/package.js | 2 +- packages/minimongo/package.js | 2 +- packages/modules-runtime/package.js | 2 +- packages/modules/package.js | 2 +- packages/mongo/package.js | 2 +- packages/reactive-dict/package.js | 2 +- packages/standard-minifier-js/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index e0132914eb..1569b2f118 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,7 +6,7 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.19.1-beta.19' + version: '6.19.1-beta.20' }); Npm.depends({ diff --git a/packages/dynamic-import/package.js b/packages/dynamic-import/package.js index 94908b7c81..e7af46eab2 100644 --- a/packages/dynamic-import/package.js +++ b/packages/dynamic-import/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "dynamic-import", - version: "0.1.0-beta.19", + version: "0.1.0-beta.20", summary: "Support for module.dynamicImport(id).then(namespace => ...)", documentation: "README.md" }); diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index 28f837d339..463db14cc0 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.8.0-beta.19', + version: '0.8.0-beta.20', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); diff --git a/packages/facebook-oauth/package.js b/packages/facebook-oauth/package.js index e79740cd61..2d9a4d9c28 100644 --- a/packages/facebook-oauth/package.js +++ b/packages/facebook-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Facebook OAuth flow", - version: "1.3.1-beta.19" + version: "1.3.1-beta.20" }); Package.onUse(function(api) { diff --git a/packages/localstorage/package.js b/packages/localstorage/package.js index d8ed167141..8929f7ba57 100644 --- a/packages/localstorage/package.js +++ b/packages/localstorage/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Simulates local storage on IE 6,7 using userData", - version: "1.1.0-beta.19" + version: "1.1.0-beta.20" }); Package.onUse(function (api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 24df7a41f1..c2e197627a 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.5.0-beta.19' + version: '1.5.0-beta.20' }); Package.includeTool(); diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index 541e9ea468..e6f9ed5b7b 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.2.0-beta.19' + version: '1.2.0-beta.20' }); Package.onUse(function (api) { diff --git a/packages/modules-runtime/package.js b/packages/modules-runtime/package.js index 7ba33bfaa8..7ca843f823 100644 --- a/packages/modules-runtime/package.js +++ b/packages/modules-runtime/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules-runtime", - version: "0.8.0-beta.19", + version: "0.8.0-beta.20", summary: "CommonJS module system", git: "https://github.com/benjamn/install", documentation: "README.md" diff --git a/packages/modules/package.js b/packages/modules/package.js index c245ebdb3c..17b8f9c9e9 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules", - version: "0.9.0-beta.19", + version: "0.9.0-beta.20", summary: "CommonJS module system", documentation: "README.md" }); diff --git a/packages/mongo/package.js b/packages/mongo/package.js index bfc3b3034d..0ff9c14edc 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.1.18-beta.19' + version: '1.1.18-beta.20' }); Npm.depends({ diff --git a/packages/reactive-dict/package.js b/packages/reactive-dict/package.js index 215517b833..a75766091e 100644 --- a/packages/reactive-dict/package.js +++ b/packages/reactive-dict/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Reactive dictionary", - version: '1.1.9-beta.19' + version: '1.1.9-beta.20' }); Package.onUse(function (api) { diff --git a/packages/standard-minifier-js/package.js b/packages/standard-minifier-js/package.js index 8b9900cc8b..611288cf29 100644 --- a/packages/standard-minifier-js/package.js +++ b/packages/standard-minifier-js/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'standard-minifier-js', - version: '2.0.0', + version: '2.1.0-beta.20', summary: 'Standard javascript minifiers used with Meteor apps by default.', documentation: 'README.md', }); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index e51412b902..19054940e3 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5-beta.19", + "version": "1.5-beta.20", "recommended": false, "official": false, "description": "Meteor" From 5f8b52b2c21e56d28c45a70391242608e8c0ea4e Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 9 May 2017 22:35:39 -0400 Subject: [PATCH 116/125] Use module.watch instead of module.importSync in getNamespace. https://github.com/benjamn/reify/pull/159 --- packages/dynamic-import/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index a7120dca9c..a4bce902b8 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -141,7 +141,7 @@ function addToTree(tree, id, value) { function getNamespace(module, id) { var namespace = Object.create(null); - module.importSync(id, { + module.watch(module.require(id), { "*": function (value, name) { namespace[name] = value; } From 1af76603c6e51ce0f182a6108427e901347472f1 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 10 May 2017 11:02:50 -0400 Subject: [PATCH 117/125] Imply the dynamic-import package from the meteor-base package. Since it's relatively easy to remove/replace the meteor-base package, this should keep dynamic-import optional in principle, but also make sure it's installed in most apps without need for `meteor add dynamic-import`. I also considered implying the dynamic-import package from the ecmascript package, but that would have made it much harder to opt out, and created some nasty circular dependency problems. --- packages/meteor-base/package.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/meteor-base/package.js b/packages/meteor-base/package.js index cd962dfbc9..f3c9e0c21f 100644 --- a/packages/meteor-base/package.js +++ b/packages/meteor-base/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'meteor-base', - version: '1.0.4', + version: '1.1.0', // Brief, one-line summary of the package. summary: 'Packages that every Meteor app needs', // By default, Meteor will default to using README.md for documentation. @@ -25,6 +25,9 @@ Package.onUse(function(api) { 'ddp', 'livedata', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0. + // Runtime support for Meteor 1.5 dynamic import(...) syntax. + 'dynamic-import', + // Push code changes to the client and automatically reload the page 'hot-code-push' ]); From fba9e9dfe95bc4d1036cfe4407d6d7a23b6167ae Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 10 May 2017 11:31:39 -0400 Subject: [PATCH 118/125] Restrict the dynamic-import package to Meteor 1.5+ apps. --- packages/dynamic-import/package.js | 4 ++++ tools/isobuild/compiler.js | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/dynamic-import/package.js b/packages/dynamic-import/package.js index e7af46eab2..3e976b53b0 100644 --- a/packages/dynamic-import/package.js +++ b/packages/dynamic-import/package.js @@ -6,6 +6,10 @@ Package.describe({ }); Package.onUse(function (api) { + // Do not allow this package to be used in pre-Meteor 1.5 apps. + api.use("isobuild:dynamic-import@1.5.0"); + + // Modify browser policy only if browser-policy packages are used. api.use("browser-policy-content", { weak: true }); api.use("modules"); diff --git a/tools/isobuild/compiler.js b/tools/isobuild/compiler.js index befd61ebf7..6af9d217f5 100644 --- a/tools/isobuild/compiler.js +++ b/tools/isobuild/compiler.js @@ -1021,5 +1021,9 @@ export const KNOWN_ISOBUILD_FEATURE_PACKAGES = { // One scenario is a package depending on a Cordova plugin or version // that is only available on npm, which means downloading the plugin is not // supported on versions of Cordova below 5.0.0. - 'isobuild:cordova': ['5.4.0'] + 'isobuild:cordova': ['5.4.0'], + + // This package requires functionality introduced in meteor-tool@1.5.0 + // to enable dynamic module fetching via import(...). + 'isobuild:dynamic-import': ['1.5.0'], }; From b6694b2f5d1ba8f58ce20e56de68bef7487ca3ce Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 10 May 2017 11:57:37 -0400 Subject: [PATCH 119/125] Expose dynamic modules via HTTP, but do not load them eagerly. This allows fetching the compiled code of dynamic modules via HTTP, without generating