From 8b8622960b5fd5684da6d5f3b03a51937fceb0d3 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Wed, 6 Sep 2017 00:23:41 +0300 Subject: [PATCH 01/84] Replace Underscore methods with native ECMAScript. This removes `underscore` entirely from `allow-deny`. --- packages/allow-deny/allow-deny.js | 51 ++++++++++++++++++------------- packages/allow-deny/package.js | 1 - 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/packages/allow-deny/allow-deny.js b/packages/allow-deny/allow-deny.js index 819a4dfc59..6fb235d00e 100644 --- a/packages/allow-deny/allow-deny.js +++ b/packages/allow-deny/allow-deny.js @@ -2,6 +2,8 @@ /// Remote methods and access control. /// +const hasOwn = Object.prototype.hasOwnProperty; + // Restrict default mutators on collection. allow() and deny() take the // same options: // @@ -108,7 +110,7 @@ CollectionPrototype._defineMutationMethods = function(options) { if (self._connection && (self._connection === Meteor.server || Meteor.isClient)) { const m = {}; - _.each(['insert', 'update', 'remove'], function (method) { + ['insert', 'update', 'remove'].forEach((method) => { const methodName = self._prefix + method; if (options.useExisting) { @@ -122,7 +124,7 @@ CollectionPrototype._defineMutationMethods = function(options) { m[methodName] = function (/* ... */) { // All the methods do their own validation, instead of using check(). check(arguments, [Match.Any]); - const args = _.toArray(arguments); + const args = Array.from(arguments); try { // For an insert, if the client didn't specify an _id, generate one // now; because this uses DDP.randomStream, it will be consistent with @@ -136,7 +138,7 @@ CollectionPrototype._defineMutationMethods = function(options) { // between arbitrary client-specified _id fields and merely // client-controlled-via-randomSeed fields. let generatedId = null; - if (method === "insert" && !_.has(args[0], '_id')) { + if (method === "insert" && !hasOwn.call(args[0], '_id')) { generatedId = self._makeNewID(); } @@ -208,7 +210,9 @@ CollectionPrototype._updateFetch = function (fields) { if (!self._validators.fetchAllFields) { if (fields) { - self._validators.fetch = _.union(self._validators.fetch, fields); + self._validators.fetch = + // union + Array.from(new Set([...self._validators.fetch, ...fields])); } else { self._validators.fetchAllFields = true; // clear fetch just to make sure we don't accidentally read it @@ -230,13 +234,13 @@ CollectionPrototype._validatedInsert = function (userId, doc, // call user validators. // Any deny returns true means denied. - if (_.any(self._validators.insert.deny, function(validator) { + if (self._validators.insert.deny.some((validator) => { return validator(userId, docToValidate(validator, doc, generatedId)); })) { throw new Meteor.Error(403, "Access denied"); } // Any allow returns true means proceed. Throw error if they all fail. - if (_.all(self._validators.insert.allow, function(validator) { + if (self._validators.insert.allow.every((validator) => { return !validator(userId, docToValidate(validator, doc, generatedId)); })) { throw new Meteor.Error(403, "Access denied"); @@ -260,7 +264,7 @@ CollectionPrototype._validatedUpdate = function( check(mutator, Object); - options = _.clone(options) || {}; + options = Object.assign(Object.create(null), options); if (!LocalCollection._selectorIsIdPerhapsAsObject(selector)) throw new Error("validated update should be of a single ID"); @@ -275,26 +279,29 @@ CollectionPrototype._validatedUpdate = function( " update documents, not replace them. Use a Mongo update operator, such " + "as '$set'."; + const mutatorKeys = Object.keys(mutator); + // compute modified fields const fields = []; - if (_.isEmpty(mutator)) { + if (mutatorKeys.length === 0) { throw new Meteor.Error(403, noReplaceError); } - _.each(mutator, function (params, op) { + mutatorKeys.forEach((op) => { + const params = mutator[op]; if (op.charAt(0) !== '$') { throw new Meteor.Error(403, noReplaceError); - } else if (!_.has(ALLOWED_UPDATE_OPERATIONS, op)) { + } else if (!hasOwn.call(ALLOWED_UPDATE_OPERATIONS, op)) { throw new Meteor.Error( 403, "Access denied. Operator " + op + " not allowed in a restricted collection."); } else { - _.each(_.keys(params), function (field) { + Object.keys(params).forEach((field) => { // treat dotted fields as if they are replacing their // top-level part if (field.indexOf('.') !== -1) field = field.substring(0, field.indexOf('.')); // record the field we are trying to change - if (!_.contains(fields, field)) + if (!fields.includes(field)) fields.push(field); }); } @@ -303,7 +310,7 @@ CollectionPrototype._validatedUpdate = function( const findOptions = {transform: null}; if (!self._validators.fetchAllFields) { findOptions.fields = {}; - _.each(self._validators.fetch, function(fieldName) { + self._validators.fetch.forEach((fieldName) => { findOptions.fields[fieldName] = 1; }); } @@ -314,7 +321,7 @@ CollectionPrototype._validatedUpdate = function( // call user validators. // Any deny returns true means denied. - if (_.any(self._validators.update.deny, function(validator) { + if (self._validators.update.deny.some((validator) => { const factoriedDoc = transformDoc(validator, doc); return validator(userId, factoriedDoc, @@ -324,7 +331,7 @@ CollectionPrototype._validatedUpdate = function( throw new Meteor.Error(403, "Access denied"); } // Any allow returns true means proceed. Throw error if they all fail. - if (_.all(self._validators.update.allow, function(validator) { + if (self._validators.update.allow.every((validator) => { const factoriedDoc = transformDoc(validator, doc); return !validator(userId, factoriedDoc, @@ -364,7 +371,7 @@ CollectionPrototype._validatedRemove = function(userId, selector) { const findOptions = {transform: null}; if (!self._validators.fetchAllFields) { findOptions.fields = {}; - _.each(self._validators.fetch, function(fieldName) { + self._validators.fetch.forEach((fieldName) => { findOptions.fields[fieldName] = 1; }); } @@ -375,13 +382,13 @@ CollectionPrototype._validatedRemove = function(userId, selector) { // call user validators. // Any deny returns true means denied. - if (_.any(self._validators.remove.deny, function(validator) { + if (self._validators.remove.deny.some((validator) => { return validator(userId, transformDoc(validator, doc)); })) { throw new Meteor.Error(403, "Access denied"); } // Any allow returns true means proceed. Throw error if they all fail. - if (_.all(self._validators.remove.allow, function(validator) { + if (self._validators.remove.allow.every((validator) => { return !validator(userId, transformDoc(validator, doc)); })) { throw new Meteor.Error(403, "Access denied"); @@ -451,15 +458,15 @@ function docToValidate(validator, doc, generatedId) { function addValidator(collection, allowOrDeny, options) { // validate keys const VALID_KEYS = ['insert', 'update', 'remove', 'fetch', 'transform']; - _.each(_.keys(options), function (key) { - if (!_.contains(VALID_KEYS, key)) + Object.keys(options).forEach((key) => { + if (!VALID_KEYS.includes(key)) throw new Error(allowOrDeny + ": Invalid key: " + key); }); collection._restricted = true; - _.each(['insert', 'update', 'remove'], function (name) { - if (options.hasOwnProperty(name)) { + ['insert', 'update', 'remove'].forEach((name) => { + if (hasOwn.call(options, name)) { if (!(options[name] instanceof Function)) { throw new Error(allowOrDeny + ": Value for `" + name + "` must be a function"); } diff --git a/packages/allow-deny/package.js b/packages/allow-deny/package.js index 4f84375323..34dc7bda9a 100644 --- a/packages/allow-deny/package.js +++ b/packages/allow-deny/package.js @@ -13,7 +13,6 @@ Package.describe({ Package.onUse(function(api) { api.use([ 'ecmascript', - 'underscore', 'minimongo', // Just for LocalCollection.wrapTransform :[ 'check', 'ejson', From 174f3dc1353bcf831244e98eebdf882476ee98e6 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 12 Sep 2017 12:56:49 -0400 Subject: [PATCH 02/84] Avoid Array.from, Set, and spread elements when computing union. --- packages/allow-deny/allow-deny.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/allow-deny/allow-deny.js b/packages/allow-deny/allow-deny.js index 6fb235d00e..96684e35c3 100644 --- a/packages/allow-deny/allow-deny.js +++ b/packages/allow-deny/allow-deny.js @@ -210,9 +210,11 @@ CollectionPrototype._updateFetch = function (fields) { if (!self._validators.fetchAllFields) { if (fields) { - self._validators.fetch = - // union - Array.from(new Set([...self._validators.fetch, ...fields])); + const union = Object.create(null); + const add = names => names && names.forEach(name => union[name] = 1); + add(self._validators.fetch); + add(fields); + self._validators.fetch = Object.keys(union); } else { self._validators.fetchAllFields = true; // clear fetch just to make sure we don't accidentally read it From 8b87abe41a4edb92443dad90fc3d2e70e60a7554 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Wed, 13 Sep 2017 23:53:16 +0300 Subject: [PATCH 03/84] Bump allow-deny package patch version. --- packages/allow-deny/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/allow-deny/package.js b/packages/allow-deny/package.js index 34dc7bda9a..65f0afe4ee 100644 --- a/packages/allow-deny/package.js +++ b/packages/allow-deny/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'allow-deny', - version: '1.0.5', + version: '1.0.9', // Brief, one-line summary of the package. summary: 'Implements functionality for allow/deny and client-side db operations', // URL to the Git repository containing the source code for this package. From 7308d46a863cdc11ab98af711df095228bb1df02 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 14 Sep 2017 15:07:02 +0300 Subject: [PATCH 04/84] Avoid Array.prototype.includes. Array.prototype.includes was not available in older implementations and this avoids tighter version contraints and maximum compatibility. --- packages/allow-deny/allow-deny.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/allow-deny/allow-deny.js b/packages/allow-deny/allow-deny.js index 96684e35c3..9b5cb9ce20 100644 --- a/packages/allow-deny/allow-deny.js +++ b/packages/allow-deny/allow-deny.js @@ -284,7 +284,8 @@ CollectionPrototype._validatedUpdate = function( const mutatorKeys = Object.keys(mutator); // compute modified fields - const fields = []; + const modifiedFields = {}; + if (mutatorKeys.length === 0) { throw new Meteor.Error(403, noReplaceError); } @@ -303,12 +304,13 @@ CollectionPrototype._validatedUpdate = function( field = field.substring(0, field.indexOf('.')); // record the field we are trying to change - if (!fields.includes(field)) - fields.push(field); + modifiedFields[field] = true; }); } }); + const fields = Object.keys(modifiedFields); + const findOptions = {transform: null}; if (!self._validators.fetchAllFields) { findOptions.fields = {}; @@ -459,9 +461,9 @@ function docToValidate(validator, doc, generatedId) { function addValidator(collection, allowOrDeny, options) { // validate keys - const VALID_KEYS = ['insert', 'update', 'remove', 'fetch', 'transform']; + const validKeysRegEx = /^(?:insert|update|remove|fetch|transform)$/; Object.keys(options).forEach((key) => { - if (!VALID_KEYS.includes(key)) + if (!validKeysRegEx.test(key)) throw new Error(allowOrDeny + ": Invalid key: " + key); }); From 49cf456d05f3a50824a7c24a0c5b7c293470a72f Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 14 Sep 2017 15:12:24 +0300 Subject: [PATCH 05/84] Bump allow-deny package patch version. From 5cc99149d0ba15a9b9bf3a04c28574d6df5d28b4 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Mon, 25 Sep 2017 20:48:27 +0300 Subject: [PATCH 06/84] Bump package versions for 1.4.4.4-rc.0 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 531b6c0664..11b63bb0cc 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_3' + version: "1.4.4-4-rc.0" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 9f5fdbb490..358d96f1eb 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.3-rc.0", + "version": "1.4.4.4-rc.0", "recommended": false, "official": false, "description": "Meteor" From cb85625520a3bc63267717bdf3cffc08654c7c54 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 23 Oct 2017 18:57:47 -0400 Subject: [PATCH 07/84] Remove dev_bundle/.npm (-30MB due to .npm/_cacache). --- scripts/generate-dev-bundle.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate-dev-bundle.sh b/scripts/generate-dev-bundle.sh index 85a95af5b8..820cb60c65 100755 --- a/scripts/generate-dev-bundle.sh +++ b/scripts/generate-dev-bundle.sh @@ -171,7 +171,7 @@ echo BUNDLING cd "$DIR" echo "${BUNDLE_VERSION}" > .bundle_version.txt -rm -rf build CHANGELOG.md ChangeLog LICENSE README.md +rm -rf build CHANGELOG.md ChangeLog LICENSE README.md .npm tar czf "${CHECKOUT_DIR}/dev_bundle_${PLATFORM}_${BUNDLE_VERSION}.tar.gz" . From 8841080c9eaf5f390388ab7a12d700e2b4e15fda Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 24 Oct 2017 15:58:11 -0700 Subject: [PATCH 08/84] Bump $NODE_BUILD_NUMBER to 113 before rebuilding dev bundle. --- scripts/build-dev-bundle-common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 2fb80fec3a..2d2a7d4c77 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -10,7 +10,7 @@ NODE_VERSION=4.8.4 NPM_VERSION=4.6.1 # If we built Node from source on Jenkins, this is the build number. -NODE_BUILD_NUMBER=111 +NODE_BUILD_NUMBER=113 if [ "$UNAME" == "Linux" ] ; then if [ "$ARCH" != "i686" -a "$ARCH" != "x86_64" ] ; then From cc2608f4a05883fe5dff3ff5d4214123361ae90f Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 24 Oct 2017 15:46:27 -0700 Subject: [PATCH 09/84] Bump $BUNDLE_VERSION to 4.8.42 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 1e608a01c3..e36cb96f1d 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.41 +BUNDLE_VERSION=4.8.42 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 16a4bbab041d3a9d5637d1fedb57fb9b3fa2ec8e Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 24 Oct 2017 16:03:07 -0700 Subject: [PATCH 10/84] Bump $NODE_VERSION to 4.8.5 before rebuilding dev bundle. While the actual version included for Unix developers will be our own build at NODE_VERSION, this is important for the Windows version, since it is not being rebuilt by our Jenkins at the moment. --- scripts/build-dev-bundle-common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 2d2a7d4c77..6a74e0c7d0 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.15 -NODE_VERSION=4.8.4 +NODE_VERSION=4.8.5 NPM_VERSION=4.6.1 # If we built Node from source on Jenkins, this is the build number. From 6cee042b545ee7f74cbbf5b156c7e82561c5e73b Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 6 Oct 2017 18:38:12 -0400 Subject: [PATCH 11/84] Simplify checking/setting file.imported in ImportScanner#_scanFile. By checking and setting this property earlier, we can avoid scanning files more than once. --- tools/isobuild/import-scanner.js | 88 +++++++++++++++----------------- 1 file changed, 42 insertions(+), 46 deletions(-) diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index dcd26d956d..0301c4cf72 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -204,10 +204,11 @@ export default class ImportScanner { file.data = new Buffer(file.dataString, "utf8"); } - // Files that are not eagerly evaluated (lazy) will only be included - // in the bundle if they are actually imported. Files that are - // eagerly evaluated are effectively "imported" as entry points. - file.imported = ! file.lazy; + // This property can have values false, true, "dynamic" (which + // indicates that the file has been imported, but only dynamically), + // or "fake" (which indicates it is a temporary file that should + // never be returned from getOutputFiles). + file.imported = false; file.installPath = file.installPath || this._getInstallPath(absPath); @@ -353,8 +354,8 @@ export default class ImportScanner { scanImports() { this.outputFiles.forEach(file => { - if (! file.lazy || file.imported) { - this._scanFile(file, file.imported === "dynamic"); + if (! file.lazy) { + this._scanFile(file); } }); @@ -538,6 +539,36 @@ export default class ImportScanner { } _scanFile(file, forDynamicImport = false) { + if (file.imported === true) { + // If we've already scanned this file non-dynamically, then we don't + // need to scan it again. + return; + } + + if (forDynamicImport && + file.imported === "dynamic") { + // If we've already scanned this file dynamically, then we don't + // need to scan it dynamically again. + return; + } + + // Make sure file.imported is set to a truthy value, but allow values + // other than "dynamic" or true (e.g. "fake"). + file.imported = file.imported || ( + forDynamicImport ? "dynamic" : true + ); + + if (file.error) { + // Any errors reported to InputFile#error were saved but not + // reported at compilation time. Now that we know the file has been + // imported, it's time to report those errors. + buildmessage.error( + depFile.error.message, + depFile.error.info + ); + return; + } + const absPath = pathJoin(this.sourceRoot, file.sourcePath); try { @@ -582,45 +613,7 @@ export default class ImportScanner { } } - // Avoid scanning files that we've scanned before, but mark them - // as imported so we know to include them in the bundle if they - // are lazy. Eager files and files that we have imported before do - // not need to be scanned again. Lazy files that we have not - // imported before still need to be scanned, however. Note that - // alreadyScanned will be "dynamic" (which is truthy) if the file - // has only been scanned because of a dynamic import(...). - const alreadyScanned = ! depFile.lazy || depFile.imported; - - // Whether the file is eager or lazy, mark it as imported. For - // lazy files, this makes the difference between being included in - // or omitted from the bundle. For eager files, this just ensures - // we won't scan them again. If this scan began from a dynamic - // import(...), we set depFile.imported = "dynamic" unless it's - // already been set true. - depFile.imported = dynamic - ? depFile.imported || "dynamic" - : true; - - const needsToBeScanned = ! alreadyScanned || - // If the file has already been scanned, but only because of a - // dynamic import(...), then it needs to be scanned again, so that - // we mark it and its dependencies as non-dynamic. This will be - // cheaper than before because we've already computed depFile.deps. - (alreadyScanned === "dynamic" && - depFile.imported === true); - - if (needsToBeScanned) { - if (depFile.error) { - // Since this file is lazy, it might never have been imported, - // so any errors reported to InputFile#error were saved but - // not reported at compilation time. Now that we know the file - // has been imported, it's time to report those errors. - buildmessage.error(depFile.error.message, - depFile.error.info); - } else { - this._scanFile(depFile, dynamic); - } - } + this._scanFile(depFile, dynamic); return; } @@ -646,7 +639,7 @@ export default class ImportScanner { depFile.installPath = installPath; depFile.servePath = installPath; depFile.lazy = true; - depFile.imported = dynamic ? "dynamic" : true; + depFile.imported = false; // Append this file to the output array and record its index. this._addFile(absImportedPath, depFile); @@ -664,6 +657,9 @@ export default class ImportScanner { // still evaluate this module natively on the server. What we // really care about is watching the file for changes. ! shouldWatch(absImportedPath)) { + // Since we're not going to call this._scanFile(depFile, dynamic) + // below, this is our last chance to update depFile.imported. + depFile.imported = dynamic ? "dynamic" : true; return; } From 9ac6d60ba2244ec17b6f74b3829283ea795eb303 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 6 Oct 2017 18:53:32 -0400 Subject: [PATCH 12/84] Track all failed imports separately. Previously, if more than one module in a package tried and failed to import the same identifier, we would record information about only the last failed import. This was good enough for later attempting to resolve the failed import in other packges or the application's `node_modules` directory (a concept known as "peer dependencies"), but it sometimes discarded information about whether the failed imports were dynamic. In particular, if the last recorded failed import was a dynamic import, it could accidentally render the entire peer dependency tree dynamic. Although it's a bit more complicated than what we did before, I believe the simplest solution is for the ImportScanner to maintain a mapping from failed identifiers to lists of import information objects, rather than a single object, so that no information is lost. --- tools/isobuild/compiler-plugin.js | 67 ++++++++++-------- tools/isobuild/import-scanner.js | 109 ++++++++++++++++++------------ 2 files changed, 106 insertions(+), 70 deletions(-) diff --git a/tools/isobuild/compiler-plugin.js b/tools/isobuild/compiler-plugin.js index 1f18fbc8fa..cb52f25699 100644 --- a/tools/isobuild/compiler-plugin.js +++ b/tools/isobuild/compiler-plugin.js @@ -999,10 +999,13 @@ export class PackageSourceBatch { return true; }); - const allMissingNodeModules = Object.create(null); - // Records the subset of allMissingNodeModules that were successfully + // Map from module identifiers that previously could not be imported + // to lists of info objects describing the failed imports. + const allMissingModules = Object.create(null); + + // Records the subset of allMissingModules that were successfully // relocated to a source batch that could handle them. - const allRelocatedNodeModules = Object.create(null); + const allRelocatedModules = Object.create(null); const scannerMap = new Map; sourceBatches.forEach(batch => { @@ -1038,16 +1041,19 @@ export class PackageSourceBatch { if (batch.useMeteorInstall) { scanner.scanImports(); - _.extend(allMissingNodeModules, scanner.allMissingNodeModules); + ImportScanner.mergeMissing( + allMissingModules, + scanner.allMissingModules + ); } scannerMap.set(name, scanner); }); - function handleMissing(missingNodeModules) { + function handleMissing(missingModules) { const missingMap = new Map; - _.each(missingNodeModules, (info, id) => { + _.each(missingModules, (importInfoList, id) => { const parts = id.split("/"); let name = null; @@ -1079,39 +1085,36 @@ export class PackageSourceBatch { } if (! missingMap.has(name)) { - missingMap.set(name, {}); + missingMap.set(name, Object.create(null)); } - const missing = missingMap.get(name); - if (! _.has(missing, id) || - ! info.possiblySpurious) { - // Allow any non-spurious identifier to replace an existing - // possibly spurious identifier. - missing[id] = info; - } + ImportScanner.mergeMissing( + missingMap.get(name), + { [id]: importInfoList } + ); }); - const nextMissingNodeModules = Object.create(null); + const nextMissingModules = Object.create(null); - missingMap.forEach((ids, name) => { + missingMap.forEach((missing, name) => { const { newlyAdded, newlyMissing } = - scannerMap.get(name).addNodeModules(ids); - _.extend(allRelocatedNodeModules, newlyAdded); - _.extend(nextMissingNodeModules, newlyMissing); + scannerMap.get(name).scanMissingModules(missing); + ImportScanner.mergeMissing(allRelocatedModules, newlyAdded); + ImportScanner.mergeMissing(nextMissingModules, newlyMissing); }); - if (! _.isEmpty(nextMissingNodeModules)) { - handleMissing(nextMissingNodeModules); + if (! _.isEmpty(nextMissingModules)) { + handleMissing(nextMissingModules); } } - handleMissing(allMissingNodeModules); + handleMissing(allMissingModules); - _.each(allRelocatedNodeModules, (info, id) => { - delete allMissingNodeModules[id]; + Object.keys(allRelocatedModules).forEach(id => { + delete allMissingModules[id]; }); - this._warnAboutMissingModules(allMissingNodeModules); + this._warnAboutMissingModules(allMissingModules); scannerMap.forEach((scanner, name) => { const isApp = ! name; @@ -1151,11 +1154,17 @@ export class PackageSourceBatch { return map; } - static _warnAboutMissingModules(missingNodeModules) { + static _warnAboutMissingModules(missingModules) { const topLevelMissingIDs = {}; const warnings = []; - _.each(missingNodeModules, (info, id) => { + Object.keys(missingModules).forEach(id => { + // Issue at most one warning per module identifier, even if there + // are multiple parent modules that failed to import it. + missingModules[id].some(info => maybeWarn(id, info)); + }); + + function maybeWarn(id, info) { if (info.packageName) { // Silence warnings generated by Meteor packages, since package // authors can be trusted to test their packages, and may have @@ -1220,7 +1229,9 @@ export class PackageSourceBatch { warnings.push(` ${JSON.stringify(id)} in ${ info.parentPath} (${info.bundleArch})`); - }); + + return true; + } if (warnings.length > 0) { Console.rawWarn("\nUnable to resolve some modules:\n\n"); diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index 0301c4cf72..150de5aaea 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -119,7 +119,7 @@ export default class ImportScanner { this.nodeModulesPaths = nodeModulesPaths; this.watchSet = watchSet; this.absPathToOutputIndex = Object.create(null); - this.allMissingNodeModules = Object.create(null); + this.allMissingModules = Object.create(null); this.outputFiles = []; this.resolver = Resolver.getOrCreate({ @@ -339,7 +339,7 @@ export default class ImportScanner { // If either oldFile or newFile has been imported non-dynamically, // then oldFile.imported needs to be === true. Otherwise we simply set // oldFile.imported = oldFile.imported || newFile.imported, which - // could be either false, "dynamic", or "fake" (see addNodeModules). + // could be either false, "dynamic", or "fake" (see scanMissingModules). oldFile.imported = oldFile.imported === true || newFile.imported === true || @@ -362,20 +362,22 @@ export default class ImportScanner { return this; } - addNodeModules(identifiers) { - assert.ok(identifiers); - assert.ok(typeof identifiers === "object"); - assert.ok(! Array.isArray(identifiers)); + scanMissingModules(missingModules) { + assert.ok(missingModules); + assert.ok(typeof missingModules === "object"); + assert.ok(! Array.isArray(missingModules)); const newlyMissing = Object.create(null); const newlyAdded = Object.create(null); - if (! isEmpty(identifiers)) { - const previousAllMissingNodeModules = this.allMissingNodeModules; - this.allMissingNodeModules = newlyMissing; + if (! isEmpty(missingModules)) { + const previousAllMissingModules = this.allMissingModules; + this.allMissingModules = newlyMissing; - try { - this._scanFile({ + Object.keys(missingModules).forEach(id => { + // TODO Call this._scanFile fewer times in case missingModules[id] + // is a long and redundant list? + missingModules[id].forEach(importInfo => this._scanFile({ sourcePath: "fake.js", // It's important that the fake.js file itself never gets // scanned or bundled. See the _scanFile and getOutputFiles @@ -383,32 +385,33 @@ export default class ImportScanner { imported: "fake", lazy: true, // By specifying the .deps property of this fake file ahead of - // time, we can avoid calling findImportedModuleIdentifiers in the - // _scanFile method. - deps: identifiers, - }); + // time, we can avoid calling findImportedModuleIdentifiers in + // the _scanFile method. + deps: { [id]: importInfo } + })); + }); - } finally { - this.allMissingNodeModules = previousAllMissingNodeModules; + this.allMissingModules = previousAllMissingModules; - each(identifiers, (info, id) => { - if (! has(newlyMissing, id)) { - newlyAdded[id] = info; - } - }); + Object.keys(missingModules).forEach(id => { + if (! has(newlyMissing, id)) { + newlyAdded[id] = missingModules[id]; + } + }); - // Remove previously seen missing module identifiers from - // newlyMissing and merge the new identifiers back into - // this.allMissingNodeModules. - each(keys(newlyMissing), key => { - if (has(previousAllMissingNodeModules, key)) { - delete newlyMissing[key]; - } else { - previousAllMissingNodeModules[key] = - newlyMissing[key]; - } - }); - } + // Remove previously seen missing module identifiers from + // newlyMissing and merge the new identifiers back into + // this.allMissingModules. + Object.keys(newlyMissing).forEach(id => { + if (has(previousAllMissingModules, id)) { + delete newlyMissing[id]; + } else { + ImportScanner.mergeMissing( + previousAllMissingModules, + { [id]: newlyMissing[id] } + ); + } + }); } return { @@ -417,6 +420,30 @@ export default class ImportScanner { }; } + static mergeMissing(target, source) { + keys(source).forEach(id => { + const importInfoList = source[id]; + const pathToIndex = Object.create(null); + + if (! has(target, id)) { + target[id] = []; + } else { + target[id].forEach((info, index) => { + pathToIndex[info.parentPath] = index; + }); + } + + importInfoList.forEach(info => { + const index = pathToIndex[info.parentPath]; + if (typeof index === "number") { + target[id][index] = info; + } else { + target[id].push(info); + } + }); + }); + } + getOutputFiles() { // Return all installable output files that are either eager or // imported (statically or dynamically). @@ -900,18 +927,16 @@ export default class ImportScanner { // missing dependency so that we can include it in the app bundle. if (parentFile) { const missing = - parentFile.missingNodeModules || + parentFile.missingModules || Object.create(null); missing[id] = info; - parentFile.missingNodeModules = missing; + parentFile.missingModules = missing; } - if (! has(this.allMissingNodeModules, id) || - ! info.possiblySpurious) { - // Allow any non-spurious identifier to replace an existing - // possibly spurious identifier. - this.allMissingNodeModules[id] = info; - } + ImportScanner.mergeMissing( + this.allMissingModules, + { [id]: [info] } + ); } _addPkgJsonToOutput(pkgJsonPath, pkg, forDynamicImport = false) { From 4e778b6e17ba5ac6813ee0bd3a2610de5babb1b6 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 11 Sep 2017 16:42:06 -0400 Subject: [PATCH 13/84] Rename installPath property to absModuleId, and make absolute. The `installPath` property was always essentially an absolute module identifier that was simply missing the leading '/' character, so this commit acknowledges that role by renaming the property to `absModuleId` and adding the leading slash. --- tools/isobuild/compiler-plugin.js | 10 ++-- tools/isobuild/import-scanner.js | 81 +++++++++++++++++-------------- tools/isobuild/linker.js | 22 +++++---- 3 files changed, 64 insertions(+), 49 deletions(-) diff --git a/tools/isobuild/compiler-plugin.js b/tools/isobuild/compiler-plugin.js index cb52f25699..f164544092 100644 --- a/tools/isobuild/compiler-plugin.js +++ b/tools/isobuild/compiler-plugin.js @@ -8,6 +8,7 @@ var linker = require('./linker.js'); var util = require('util'); var _ = require('underscore'); var Profile = require('../tool-env/profile.js').Profile; +import assert from "assert"; import {sha1, readAndWatchFileWithHash} from '../fs/watch.js'; import LRU from 'lru-cache'; import {sourceMapLength} from '../utils/utils.js'; @@ -1124,11 +1125,12 @@ export class PackageSourceBatch { const appFilesWithoutNodeModules = []; outputFiles.forEach(file => { - const parts = file.installPath.split("/"); + const parts = file.absModuleId.split("/"); + assert.strictEqual(parts[0], ""); const nodeModulesIndex = parts.indexOf("node_modules"); - if (nodeModulesIndex === -1 || (nodeModulesIndex === 0 && - parts[1] === "meteor")) { + if (nodeModulesIndex === -1 || (nodeModulesIndex === 1 && + parts[2] === "meteor")) { appFilesWithoutNodeModules.push(file); } else { // This file is going to be installed in a node_modules @@ -1308,7 +1310,7 @@ export class PackageSourceBatch { files: jsResources.map((inputFile) => { fileHashes.push(inputFile.hash); return { - installPath: inputFile.installPath, + absModuleId: inputFile.absModuleId, sourceMap: !! inputFile.sourceMap, mainModule: inputFile.mainModule, imported: inputFile.imported, diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index 150de5aaea..0491a3352d 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -86,6 +86,14 @@ function canBeParsedAsPlainJS(dataString, hash) { return result; } +function stripLeadingSlash(path) { + if (path.charAt(0) === "/") { + return path.slice(1); + } + + return path; +} + // Map from SHA (which is already calculated, so free for us) // to the results of calling findImportedModuleIdentifiers. // Each entry is an array of strings, and this is a case where @@ -210,7 +218,7 @@ export default class ImportScanner { // never be returned from getOutputFiles). file.imported = false; - file.installPath = file.installPath || this._getInstallPath(absPath); + file.absModuleId = file.absModuleId || this._getAbsModuleId(absPath); if (! this._addFile(absPath, file)) { // Collisions can happen if a compiler plugin calls addJavaScript @@ -244,12 +252,12 @@ export default class ImportScanner { // to have the same .sourcePath but different .targetPaths. let sourceFile = this._getFile(absSourcePath); if (! sourceFile) { - const installPath = this._getInstallPath(absSourcePath); + const absModuleId = this._getAbsModuleId(absSourcePath); sourceFile = this._addFile(absSourcePath, { type: file.type, sourcePath: file.sourcePath, - servePath: installPath, - installPath, + servePath: stripLeadingSlash(absModuleId), + absModuleId, dataString: "", deps: {}, lazy: true, @@ -258,7 +266,7 @@ export default class ImportScanner { // Make sure the original file gets installed at the target path // instead of the source path. - file.installPath = this._getInstallPath(absTargetPath); + file.absModuleId = this._getAbsModuleId(absTargetPath); file.sourcePath = file.targetPath; const relativeId = this._getRelativeImportId( @@ -448,7 +456,7 @@ export default class ImportScanner { // Return all installable output files that are either eager or // imported (statically or dynamically). return this.outputFiles.filter(file => { - return file.installPath && + return file.absModuleId && (! file.lazy || file.imported === true || file.imported === "dynamic"); @@ -527,7 +535,7 @@ export default class ImportScanner { const packageJsonFile = this._addPkgJsonToOutput(path, pkg, forDynamicImport); - if (! parentFile.installPath) { + if (! parentFile.absModuleId) { // If parentFile is not installable, then we won't return it // from getOutputFiles, so we don't need to worry about // recording any parentFile.deps[id].helpers. @@ -535,8 +543,8 @@ export default class ImportScanner { } const relativeId = this._getRelativeImportId( - parentFile.installPath, - packageJsonFile.installPath + parentFile.absModuleId, + packageJsonFile.absModuleId ); // Although not explicitly imported, any package.json modules @@ -631,7 +639,7 @@ export default class ImportScanner { // If the module is an implicit package.json stub, update to the // explicit version now. if (depFile.jsonData && - depFile.installPath.endsWith("/package.json") && + depFile.absModuleId.endsWith("/package.json") && depFile.implicit === true) { const file = this._readModule(absImportedPath); if (file) { @@ -645,13 +653,13 @@ export default class ImportScanner { return; } - const installPath = this._getInstallPath(absImportedPath); - if (! installPath) { + const absModuleId = this._getAbsModuleId(absImportedPath); + if (! absModuleId) { // The given path cannot be installed on this architecture. return; } - info.installPath = installPath; + info.absModuleId = absModuleId; // If the module is not readable, _readModule may return // null. Otherwise it will return an object with .data, .dataString, @@ -663,8 +671,8 @@ export default class ImportScanner { depFile.type = "js"; // TODO Is this correct? depFile.sourcePath = pathRelative(this.sourceRoot, absImportedPath); - depFile.installPath = installPath; - depFile.servePath = installPath; + depFile.absModuleId = absModuleId; + depFile.servePath = stripLeadingSlash(absModuleId); depFile.lazy = true; depFile.imported = false; @@ -675,7 +683,7 @@ export default class ImportScanner { // handled natively by Node, so we don't need to build a // meteorInstall-style bundle beyond the entry-point module. if (! this.isWeb() && - depFile.installPath.startsWith("node_modules/") && + depFile.absModuleId.startsWith("/node_modules/") && // If optimistic functions care about this file, e.g. because it // resides in a linked npm package, then we should allow it to // be watched by including it in the server bundle by not @@ -770,13 +778,13 @@ export default class ImportScanner { return info; } - // Returns a relative path indicating where to install the given file - // via meteorInstall. May return undefined if the file should not be - // installed on the current architecture. - _getInstallPath(absPath) { + // Returns an absolute module identifier indicating where to install the + // given file via meteorInstall. May return undefined if the file should + // not be installed on the current architecture. + _getAbsModuleId(absPath) { let path = - this._getNodeModulesInstallPath(absPath) || - this._getSourceRootInstallPath(absPath); + this._getNodeModulesAbsModuleId(absPath) || + this._getSourceRootAbsModuleId(absPath); if (! path) { return; @@ -794,11 +802,11 @@ export default class ImportScanner { } // Install paths should always be delimited by /. - return convertToPosixPath(path); + return "/" + stripLeadingSlash(convertToPosixPath(path)); } - _getNodeModulesInstallPath(absPath) { - let installPath; + _getNodeModulesAbsModuleId(absPath) { + let absModuleId; this.nodeModulesPaths.some(path => { const relPathWithinNodeModules = pathRelative(path, absPath); @@ -810,24 +818,24 @@ export default class ImportScanner { // Install the module into the local node_modules directory within // this app or package. - return installPath = pathJoin( + return absModuleId = pathJoin( "node_modules", relPathWithinNodeModules ); }); - return installPath; + return absModuleId; } - _getSourceRootInstallPath(absPath) { - const installPath = pathRelative(this.sourceRoot, absPath); + _getSourceRootAbsModuleId(absPath) { + const absModuleId = pathRelative(this.sourceRoot, absPath); - if (installPath.startsWith("..")) { + if (absModuleId.startsWith("..")) { // absPath is not a subdirectory of this.sourceRoot. return; } - const dirs = this._splitPath(pathDirname(installPath)); + const dirs = this._splitPath(pathDirname(absModuleId)); const isApp = ! this.name; const bundlingForWeb = this.isWeb(); @@ -864,11 +872,11 @@ export default class ImportScanner { if (dir === "node_modules") { // Accept any file within a node_modules directory. - return installPath; + return absModuleId; } } - return installPath; + return absModuleId; } _splitPath(path) { @@ -961,6 +969,7 @@ export default class ImportScanner { }).join("")); const relPkgJsonPath = pathRelative(this.sourceRoot, pkgJsonPath); + const absModuleId = this._getAbsModuleId(pkgJsonPath); const pkgFile = { type: "js", // We represent the JSON module with JS. @@ -968,8 +977,8 @@ export default class ImportScanner { jsonData: pkg, deps: {}, // Avoid accidentally re-scanning this file. sourcePath: relPkgJsonPath, - installPath: this._getInstallPath(pkgJsonPath), - servePath: relPkgJsonPath, + absModuleId, + servePath: stripLeadingSlash(absModuleId), hash: sha1(data), lazy: true, imported: forDynamicImport ? "dynamic" : true, @@ -994,7 +1003,7 @@ export default class ImportScanner { } each(["_readFile", "_findImportedModuleIdentifiers", - "_getInstallPath"], funcName => { + "_getAbsModuleId"], funcName => { ImportScanner.prototype[funcName] = Profile( `ImportScanner#${funcName}`, ImportScanner.prototype[funcName]); }); diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index 5a7b09fa60..204b96f9ea 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -246,7 +246,7 @@ _.extend(Module.prototype, { } if (file.isDynamic()) { - const servePath = "dynamic/" + file.installPath; + const servePath = files.pathJoin("dynamic", file.absModuleId); const { code: source, map } = file.getPrelinkedOutput({ sourceWidth: sourceWidth, @@ -264,7 +264,7 @@ _.extend(Module.prototype, { const stubArray = file.deps.slice(0); - if (file.installPath.endsWith("/package.json") && + if (file.absModuleId.endsWith("/package.json") && file.jsonData) { const stub = {}; @@ -281,12 +281,12 @@ _.extend(Module.prototype, { stubArray.push(stub); } - addToTree(stubArray, file.installPath, tree); + addToTree(stubArray, file.absModuleId, 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. - addToTree(file, file.installPath, tree); + addToTree(file, file.absModuleId, tree); } }); @@ -420,7 +420,7 @@ _.extend(Module.prototype, { chunks.push( file.mainModule ? "\nvar " + exportsName + " = " : "\n", "require(", - JSON.stringify("./" + file.installPath), + JSON.stringify(file.absModuleId), ");" ); }); @@ -437,6 +437,10 @@ export function addToTree(value, path, tree) { const parts = path.split("/"); const lastIndex = parts.length - 1; parts.forEach((part, i) => { + if (part === "") { + return; + } + tree = _.has(tree, part) ? tree[part] : tree[part] = i < lastIndex ? {} : value; @@ -515,9 +519,9 @@ var File = function (inputFile, module) { self.sourcePath = inputFile.sourcePath; // Absolute module identifier to use when installing this file via - // meteorInstall. If the inputFile has no .installPath, then this file + // meteorInstall. If the inputFile has no .absModuleId, then this file // cannot be installed as a module. - self.installPath = inputFile.installPath || null; + self.absModuleId = inputFile.absModuleId || null; // the path where this file would prefer to be served if possible self.servePath = inputFile.servePath; @@ -575,8 +579,8 @@ _.extend(File.prototype, { computeAssignedVariables: Profile("linker File#computeAssignedVariables", function () { var self = this; - if (self.installPath) { - const parts = self.installPath.split("/"); + if (self.absModuleId) { + const parts = self.absModuleId.split("/"); const nmi = parts.indexOf("node_modules"); if (nmi >= 0 && parts[nmi + 1] !== "meteor") { // If this file is in a node_modules directory and is not part of From 1470bc841f45db71be1ab2c01fd5e94a0d738b81 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 6 Oct 2017 19:08:18 -0400 Subject: [PATCH 14/84] Remember whether parent module of failed import was dynamic. Fixes #9182. --- tools/isobuild/import-scanner.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index 0491a3352d..6c51fd0b6f 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -625,7 +625,9 @@ export default class ImportScanner { // browser (even though it works equally well on the server), so // it's better if forDynamicImport never becomes true on the server. const dynamic = this.isWebBrowser() && - (forDynamicImport || info.dynamic); + (forDynamicImport || + info.parentWasDynamic || + info.dynamic); const resolved = this._resolve(file, id, dynamic); if (! resolved) { @@ -919,6 +921,12 @@ export default class ImportScanner { bundleArch: this.bundleArch, possiblySpurious: false, dynamic: false, + // When we later attempt to resolve this id in the application's + // node_modules directory or in other packages, we need to remember + // if the parent module was imported dynamically, since that makes + // this import effectively dynamic, even if the parent module + // imported the given id with a static import or require. + parentWasDynamic: forDynamicImport, }; if (parentFile && @@ -926,6 +934,12 @@ export default class ImportScanner { has(parentFile.deps, id)) { const importInfo = parentFile.deps[id]; info.possiblySpurious = importInfo.possiblySpurious; + // Remember that this property only indicates whether or not the + // parent module used a dynamic import(...) to import this module. + // Even if info.dynamic is false (because the parent module used a + // static import or require for this import), this module may still + // be effectively dynamic if the parent was imported dynamically, as + // indicated by info.parentWasDynamic. info.dynamic = importInfo.dynamic; } From 202e913faa33e5e5ddad4677309a777f2e781ee6 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Sat, 7 Oct 2017 10:11:02 -0400 Subject: [PATCH 15/84] Call _scanFile far fewer times in ImportScanner#scanMissingModules. --- tools/isobuild/import-scanner.js | 64 +++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index 6c51fd0b6f..68653fbb25 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -43,6 +43,18 @@ const fakeFileStat = { } }; +// Used in ImportScanner#scanMissingModules. +const fakeScanFileOptions = { + // A temporary file that does not really exist and will never be added + // to scanner.outputFiles or returned by scanner.getOutputFiles. + sourcePath: "fake.js", + // It's important that the fake.js file itself never gets scanned or + // bundled. See the _scanFile and getOutputFiles methods for logic that + // deals with file.imported values. + imported: "fake", + lazy: true, +}; + // Default handlers for well-known file extensions. // Note that these function expect strings, not Buffer objects. const defaultExtensionHandlers = { @@ -383,20 +395,44 @@ export default class ImportScanner { this.allMissingModules = newlyMissing; Object.keys(missingModules).forEach(id => { - // TODO Call this._scanFile fewer times in case missingModules[id] - // is a long and redundant list? - missingModules[id].forEach(importInfo => this._scanFile({ - sourcePath: "fake.js", - // It's important that the fake.js file itself never gets - // scanned or bundled. See the _scanFile and getOutputFiles - // methods for logic that deals with file.imported values. - imported: "fake", - lazy: true, - // By specifying the .deps property of this fake file ahead of - // time, we can avoid calling findImportedModuleIdentifiers in - // the _scanFile method. - deps: { [id]: importInfo } - })); + let staticImportInfo = null; + let dynamicImportInfo = null; + + // Although it would be logically valid to call this._scanFile for + // each and every importInfo object, there can be a lot of them + // (hundreds, maybe thousands). The only relevant difference is + // whether the file is being scanned as a dynamic import or not, + // so we can get away with calling this._scanFile at most twice, + // with a representative importInfo object of each kind. + missingModules[id].some(importInfo => { + if (importInfo.parentWasDynamic || + importInfo.dynamic) { + dynamicImportInfo = dynamicImportInfo || importInfo; + } else { + staticImportInfo = staticImportInfo || importInfo; + } + + // Stop when/if both variables have been initialized. + return staticImportInfo && dynamicImportInfo; + }); + + if (staticImportInfo) { + this._scanFile({ + ...fakeScanFileOptions, + // By specifying the .deps property of this fake file ahead of + // time, we can avoid calling findImportedModuleIdentifiers in + // the _scanFile method, which is important because this file + // doesn't have a .data or .dataString property. + deps: { [id]: staticImportInfo } + }, false); // !forDynamicImport + } + + if (dynamicImportInfo) { + this._scanFile({ + ...fakeScanFileOptions, + deps: { [id]: dynamicImportInfo } + }, true); // forDynamicImport + } }); this.allMissingModules = previousAllMissingModules; From 3b7943f6318e427f4edeade0a44d2fc1a1591927 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Sat, 7 Oct 2017 14:10:37 -0400 Subject: [PATCH 16/84] Add more comments to recently-modified ImportScanner logic. --- tools/isobuild/import-scanner.js | 34 ++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index 68653fbb25..03a0ff79c9 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -439,6 +439,8 @@ export default class ImportScanner { Object.keys(missingModules).forEach(id => { if (! has(newlyMissing, id)) { + // We don't need to use ImportScanner.mergeMissing here because + // this is the first time newlyAdded[id] has been assigned. newlyAdded[id] = missingModules[id]; } }); @@ -464,6 +466,10 @@ export default class ImportScanner { }; } + // Helper for copying the properties of source into target, + // concatenating values (which must be arrays) if a property already + // exists. The array elements should be importInfo objects, and will be + // deduplicated according to their .parentPath properties. static mergeMissing(target, source) { keys(source).forEach(id => { const importInfoList = source[id]; @@ -472,18 +478,24 @@ export default class ImportScanner { if (! has(target, id)) { target[id] = []; } else { - target[id].forEach((info, index) => { - pathToIndex[info.parentPath] = index; + target[id].forEach((importInfo, index) => { + pathToIndex[importInfo.parentPath] = index; }); } - importInfoList.forEach(info => { - const index = pathToIndex[info.parentPath]; - if (typeof index === "number") { - target[id][index] = info; - } else { - target[id].push(info); + importInfoList.forEach(importInfo => { + const { parentPath } = importInfo; + if (typeof parentPath === "string") { + const index = pathToIndex[parentPath]; + if (typeof index === "number") { + // If an importInfo object with this .parentPath is already + // present in the target[id] array, replace it. + target[id][index] = importInfo; + return; + } } + + target[id].push(importInfo); }); }); } @@ -686,6 +698,9 @@ export default class ImportScanner { } } + // If depFile has already been scanned, this._scanFile will return + // immediately thanks to the depFile.imported-checking logic at + // the top of the method. this._scanFile(depFile, dynamic); return; @@ -712,6 +727,9 @@ export default class ImportScanner { depFile.absModuleId = absModuleId; depFile.servePath = stripLeadingSlash(absModuleId); depFile.lazy = true; + // Setting depFile.imported = false is necessary so that + // this._scanFile(depFile, dynamic) doesn't think the file has been + // scanned already and return immediately. depFile.imported = false; // Append this file to the output array and record its index. From c03a46f70fdf6ab59af53f0172f34a91f09f1a60 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 10 Oct 2017 14:52:15 -0400 Subject: [PATCH 17/84] Regression test for #9185 (fixed by #9187). --- tools/tests/apps/dynamic-import/package.json | 1 + .../packages/helper-package/import-peer.js | 1 + tools/tests/apps/dynamic-import/tests.js | 18 +++++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tools/tests/apps/dynamic-import/packages/helper-package/import-peer.js diff --git a/tools/tests/apps/dynamic-import/package.json b/tools/tests/apps/dynamic-import/package.json index 1a6a568e7c..dcd499275d 100644 --- a/tools/tests/apps/dynamic-import/package.json +++ b/tools/tests/apps/dynamic-import/package.json @@ -11,6 +11,7 @@ "babel-runtime": "^6.20.0", "meteor-node-stubs": "~0.2.4", "moment": "^2.17.1", + "optimism": "^0.3.3", "private": "^0.1.7", "react": "^15.4.2" } diff --git a/tools/tests/apps/dynamic-import/packages/helper-package/import-peer.js b/tools/tests/apps/dynamic-import/packages/helper-package/import-peer.js new file mode 100644 index 0000000000..b36427b5ca --- /dev/null +++ b/tools/tests/apps/dynamic-import/packages/helper-package/import-peer.js @@ -0,0 +1 @@ +export { wrap } from "optimism"; diff --git a/tools/tests/apps/dynamic-import/tests.js b/tools/tests/apps/dynamic-import/tests.js index 33646bf625..a04f11dcc4 100644 --- a/tools/tests/apps/dynamic-import/tests.js +++ b/tools/tests/apps/dynamic-import/tests.js @@ -209,10 +209,26 @@ describe("dynamic import(...)", function () { assert.strictEqual(version, null); } - import("meteor/user:colon-name/dynamic.js").then(dynamic => { + return import("meteor/user:colon-name/dynamic.js").then(dynamic => { assert.strictEqual(dynamic.name, expectedAbsId); }); }); + + it("should track dynamic peer imports from packages (#9187)", () => { + const version = require( + "meteor/dynamic-import/dynamic-versions.js" + ).get("/node_modules/optimism/lib/index.js"); + + if (Meteor.isClient) { + assert.strictEqual(typeof version, "string"); + } else { + assert.strictEqual(version, null); + } + + return import("meteor/helper-package/import-peer.js").then(m => { + assert.strictEqual(typeof m.wrap, "function"); + }); + }); }); function maybeClearDynamicImportCache() { From 6323a34d6a7cf84c87f5b82c4ae7428ac3178c79 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 23 Oct 2017 19:37:44 -0400 Subject: [PATCH 18/84] Adjust npm update notifier opt-out environment variable. https://github.com/zkat/npx/issues/98#issuecomment-316936135 https://www.npmjs.com/package/update-notifier#user-settings --- tools/cli/dev-bundle-bin-helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cli/dev-bundle-bin-helpers.js b/tools/cli/dev-bundle-bin-helpers.js index d0b36db9f4..19e7fcfe11 100644 --- a/tools/cli/dev-bundle-bin-helpers.js +++ b/tools/cli/dev-bundle-bin-helpers.js @@ -78,7 +78,7 @@ exports.getEnv = function (options) { var env = Object.create(process.env); // Make sure notifications to update npm aren't presented to the user. - env.NPM_CONFIG_NO_UPDATE_NOTIFIER = true; + env.NO_UPDATE_NOTIFIER = true; // Make sure `meteor npm install --global ...` installs into // dev_bundle/lib/node_modules by default. From 8dc1fc35123c28c13573c5af3c9d37313ac1042d Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 9 Oct 2017 09:48:23 -0400 Subject: [PATCH 19/84] Fix typo in ImportScanner#_scanFile. Introduced by 3faee05eede683dd14fa922464ef2ba0c081a051. cc @cpury @JanMP --- tools/isobuild/import-scanner.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index 03a0ff79c9..d930e6cbea 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -646,8 +646,8 @@ export default class ImportScanner { // reported at compilation time. Now that we know the file has been // imported, it's time to report those errors. buildmessage.error( - depFile.error.message, - depFile.error.info + file.error.message, + file.error.info ); return; } From e5211e48763cf9c0a44e36a0381a487bac68bbd1 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Fri, 27 Oct 2017 11:39:02 -0700 Subject: [PATCH 20/84] Bump package versions for 1.5.3-rc.0 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 4a5ba7e2a8..38841667cb 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.2_2" + version: "1.5.3-rc.0" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 0d65e4a5f9..93dbc89693 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5.2.2-rc.1", + "version": "1.5.3-rc.0", "recommended": false, "official": false, "description": "Meteor" From 9c62a55137a0d27796e6328a822dc08f586fbc7a Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Fri, 27 Oct 2017 14:47:06 -0700 Subject: [PATCH 21/84] Bump $NODE_BUILD_NUMBER to 116 before rebuilding dev bundle. --- scripts/build-dev-bundle-common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 6a74e0c7d0..068cde70af 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -10,7 +10,7 @@ NODE_VERSION=4.8.5 NPM_VERSION=4.6.1 # If we built Node from source on Jenkins, this is the build number. -NODE_BUILD_NUMBER=113 +NODE_BUILD_NUMBER=116 if [ "$UNAME" == "Linux" ] ; then if [ "$ARCH" != "i686" -a "$ARCH" != "x86_64" ] ; then From d6fc953ba66a26813f0b800057bbdc7331202cc9 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Fri, 27 Oct 2017 15:15:05 -0700 Subject: [PATCH 22/84] Bump $NODE_BUILD_NUMBER to 120 before rebuilding dev bundle. --- scripts/build-dev-bundle-common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 068cde70af..6073692997 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -10,7 +10,7 @@ NODE_VERSION=4.8.5 NPM_VERSION=4.6.1 # If we built Node from source on Jenkins, this is the build number. -NODE_BUILD_NUMBER=116 +NODE_BUILD_NUMBER=120 if [ "$UNAME" == "Linux" ] ; then if [ "$ARCH" != "i686" -a "$ARCH" != "x86_64" ] ; then From 1995c8d44522d9db31742dcd1428d5b2dc9274c9 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Fri, 27 Oct 2017 14:47:17 -0700 Subject: [PATCH 23/84] Bump $BUNDLE_VERSION to 4.8.43 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index e36cb96f1d..448bbca4ef 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.42 +BUNDLE_VERSION=4.8.43 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 55a6d1b50b785a5c8d6e70c17089875e97a3874f Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Sun, 8 Oct 2017 15:54:46 -0400 Subject: [PATCH 24/84] Revert "Rename installPath property to absModuleId, and make absolute." This reverts commit b9f0a54b396e76966364a6edcd99401287103e53. Though probably a good idea for the future, this change was not really necessary for Meteor 1.6, and probably too risky for a release candidate. --- tools/isobuild/compiler-plugin.js | 10 ++-- tools/isobuild/import-scanner.js | 81 ++++++++++++++----------------- tools/isobuild/linker.js | 22 ++++----- 3 files changed, 49 insertions(+), 64 deletions(-) diff --git a/tools/isobuild/compiler-plugin.js b/tools/isobuild/compiler-plugin.js index f164544092..cb52f25699 100644 --- a/tools/isobuild/compiler-plugin.js +++ b/tools/isobuild/compiler-plugin.js @@ -8,7 +8,6 @@ var linker = require('./linker.js'); var util = require('util'); var _ = require('underscore'); var Profile = require('../tool-env/profile.js').Profile; -import assert from "assert"; import {sha1, readAndWatchFileWithHash} from '../fs/watch.js'; import LRU from 'lru-cache'; import {sourceMapLength} from '../utils/utils.js'; @@ -1125,12 +1124,11 @@ export class PackageSourceBatch { const appFilesWithoutNodeModules = []; outputFiles.forEach(file => { - const parts = file.absModuleId.split("/"); - assert.strictEqual(parts[0], ""); + const parts = file.installPath.split("/"); const nodeModulesIndex = parts.indexOf("node_modules"); - if (nodeModulesIndex === -1 || (nodeModulesIndex === 1 && - parts[2] === "meteor")) { + if (nodeModulesIndex === -1 || (nodeModulesIndex === 0 && + parts[1] === "meteor")) { appFilesWithoutNodeModules.push(file); } else { // This file is going to be installed in a node_modules @@ -1310,7 +1308,7 @@ export class PackageSourceBatch { files: jsResources.map((inputFile) => { fileHashes.push(inputFile.hash); return { - absModuleId: inputFile.absModuleId, + installPath: inputFile.installPath, sourceMap: !! inputFile.sourceMap, mainModule: inputFile.mainModule, imported: inputFile.imported, diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index d930e6cbea..4d34d533bf 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -98,14 +98,6 @@ function canBeParsedAsPlainJS(dataString, hash) { return result; } -function stripLeadingSlash(path) { - if (path.charAt(0) === "/") { - return path.slice(1); - } - - return path; -} - // Map from SHA (which is already calculated, so free for us) // to the results of calling findImportedModuleIdentifiers. // Each entry is an array of strings, and this is a case where @@ -230,7 +222,7 @@ export default class ImportScanner { // never be returned from getOutputFiles). file.imported = false; - file.absModuleId = file.absModuleId || this._getAbsModuleId(absPath); + file.installPath = file.installPath || this._getInstallPath(absPath); if (! this._addFile(absPath, file)) { // Collisions can happen if a compiler plugin calls addJavaScript @@ -264,12 +256,12 @@ export default class ImportScanner { // to have the same .sourcePath but different .targetPaths. let sourceFile = this._getFile(absSourcePath); if (! sourceFile) { - const absModuleId = this._getAbsModuleId(absSourcePath); + const installPath = this._getInstallPath(absSourcePath); sourceFile = this._addFile(absSourcePath, { type: file.type, sourcePath: file.sourcePath, - servePath: stripLeadingSlash(absModuleId), - absModuleId, + servePath: installPath, + installPath, dataString: "", deps: {}, lazy: true, @@ -278,7 +270,7 @@ export default class ImportScanner { // Make sure the original file gets installed at the target path // instead of the source path. - file.absModuleId = this._getAbsModuleId(absTargetPath); + file.installPath = this._getInstallPath(absTargetPath); file.sourcePath = file.targetPath; const relativeId = this._getRelativeImportId( @@ -504,7 +496,7 @@ export default class ImportScanner { // Return all installable output files that are either eager or // imported (statically or dynamically). return this.outputFiles.filter(file => { - return file.absModuleId && + return file.installPath && (! file.lazy || file.imported === true || file.imported === "dynamic"); @@ -583,7 +575,7 @@ export default class ImportScanner { const packageJsonFile = this._addPkgJsonToOutput(path, pkg, forDynamicImport); - if (! parentFile.absModuleId) { + if (! parentFile.installPath) { // If parentFile is not installable, then we won't return it // from getOutputFiles, so we don't need to worry about // recording any parentFile.deps[id].helpers. @@ -591,8 +583,8 @@ export default class ImportScanner { } const relativeId = this._getRelativeImportId( - parentFile.absModuleId, - packageJsonFile.absModuleId + parentFile.installPath, + packageJsonFile.installPath ); // Although not explicitly imported, any package.json modules @@ -689,7 +681,7 @@ export default class ImportScanner { // If the module is an implicit package.json stub, update to the // explicit version now. if (depFile.jsonData && - depFile.absModuleId.endsWith("/package.json") && + depFile.installPath.endsWith("/package.json") && depFile.implicit === true) { const file = this._readModule(absImportedPath); if (file) { @@ -706,13 +698,13 @@ export default class ImportScanner { return; } - const absModuleId = this._getAbsModuleId(absImportedPath); - if (! absModuleId) { + const installPath = this._getInstallPath(absImportedPath); + if (! installPath) { // The given path cannot be installed on this architecture. return; } - info.absModuleId = absModuleId; + info.installPath = installPath; // If the module is not readable, _readModule may return // null. Otherwise it will return an object with .data, .dataString, @@ -724,8 +716,8 @@ export default class ImportScanner { depFile.type = "js"; // TODO Is this correct? depFile.sourcePath = pathRelative(this.sourceRoot, absImportedPath); - depFile.absModuleId = absModuleId; - depFile.servePath = stripLeadingSlash(absModuleId); + depFile.installPath = installPath; + depFile.servePath = installPath; depFile.lazy = true; // Setting depFile.imported = false is necessary so that // this._scanFile(depFile, dynamic) doesn't think the file has been @@ -739,7 +731,7 @@ export default class ImportScanner { // handled natively by Node, so we don't need to build a // meteorInstall-style bundle beyond the entry-point module. if (! this.isWeb() && - depFile.absModuleId.startsWith("/node_modules/") && + depFile.installPath.startsWith("node_modules/") && // If optimistic functions care about this file, e.g. because it // resides in a linked npm package, then we should allow it to // be watched by including it in the server bundle by not @@ -834,13 +826,13 @@ export default class ImportScanner { return info; } - // Returns an absolute module identifier indicating where to install the - // given file via meteorInstall. May return undefined if the file should - // not be installed on the current architecture. - _getAbsModuleId(absPath) { + // Returns a relative path indicating where to install the given file + // via meteorInstall. May return undefined if the file should not be + // installed on the current architecture. + _getInstallPath(absPath) { let path = - this._getNodeModulesAbsModuleId(absPath) || - this._getSourceRootAbsModuleId(absPath); + this._getNodeModulesInstallPath(absPath) || + this._getSourceRootInstallPath(absPath); if (! path) { return; @@ -858,11 +850,11 @@ export default class ImportScanner { } // Install paths should always be delimited by /. - return "/" + stripLeadingSlash(convertToPosixPath(path)); + return convertToPosixPath(path); } - _getNodeModulesAbsModuleId(absPath) { - let absModuleId; + _getNodeModulesInstallPath(absPath) { + let installPath; this.nodeModulesPaths.some(path => { const relPathWithinNodeModules = pathRelative(path, absPath); @@ -874,24 +866,24 @@ export default class ImportScanner { // Install the module into the local node_modules directory within // this app or package. - return absModuleId = pathJoin( + return installPath = pathJoin( "node_modules", relPathWithinNodeModules ); }); - return absModuleId; + return installPath; } - _getSourceRootAbsModuleId(absPath) { - const absModuleId = pathRelative(this.sourceRoot, absPath); + _getSourceRootInstallPath(absPath) { + const installPath = pathRelative(this.sourceRoot, absPath); - if (absModuleId.startsWith("..")) { + if (installPath.startsWith("..")) { // absPath is not a subdirectory of this.sourceRoot. return; } - const dirs = this._splitPath(pathDirname(absModuleId)); + const dirs = this._splitPath(pathDirname(installPath)); const isApp = ! this.name; const bundlingForWeb = this.isWeb(); @@ -928,11 +920,11 @@ export default class ImportScanner { if (dir === "node_modules") { // Accept any file within a node_modules directory. - return absModuleId; + return installPath; } } - return absModuleId; + return installPath; } _splitPath(path) { @@ -1037,7 +1029,6 @@ export default class ImportScanner { }).join("")); const relPkgJsonPath = pathRelative(this.sourceRoot, pkgJsonPath); - const absModuleId = this._getAbsModuleId(pkgJsonPath); const pkgFile = { type: "js", // We represent the JSON module with JS. @@ -1045,8 +1036,8 @@ export default class ImportScanner { jsonData: pkg, deps: {}, // Avoid accidentally re-scanning this file. sourcePath: relPkgJsonPath, - absModuleId, - servePath: stripLeadingSlash(absModuleId), + installPath: this._getInstallPath(pkgJsonPath), + servePath: relPkgJsonPath, hash: sha1(data), lazy: true, imported: forDynamicImport ? "dynamic" : true, @@ -1071,7 +1062,7 @@ export default class ImportScanner { } each(["_readFile", "_findImportedModuleIdentifiers", - "_getAbsModuleId"], funcName => { + "_getInstallPath"], funcName => { ImportScanner.prototype[funcName] = Profile( `ImportScanner#${funcName}`, ImportScanner.prototype[funcName]); }); diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index 204b96f9ea..5a7b09fa60 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -246,7 +246,7 @@ _.extend(Module.prototype, { } if (file.isDynamic()) { - const servePath = files.pathJoin("dynamic", file.absModuleId); + const servePath = "dynamic/" + file.installPath; const { code: source, map } = file.getPrelinkedOutput({ sourceWidth: sourceWidth, @@ -264,7 +264,7 @@ _.extend(Module.prototype, { const stubArray = file.deps.slice(0); - if (file.absModuleId.endsWith("/package.json") && + if (file.installPath.endsWith("/package.json") && file.jsonData) { const stub = {}; @@ -281,12 +281,12 @@ _.extend(Module.prototype, { stubArray.push(stub); } - addToTree(stubArray, file.absModuleId, tree); + addToTree(stubArray, 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. - addToTree(file, file.absModuleId, tree); + addToTree(file, file.installPath, tree); } }); @@ -420,7 +420,7 @@ _.extend(Module.prototype, { chunks.push( file.mainModule ? "\nvar " + exportsName + " = " : "\n", "require(", - JSON.stringify(file.absModuleId), + JSON.stringify("./" + file.installPath), ");" ); }); @@ -437,10 +437,6 @@ export function addToTree(value, path, tree) { const parts = path.split("/"); const lastIndex = parts.length - 1; parts.forEach((part, i) => { - if (part === "") { - return; - } - tree = _.has(tree, part) ? tree[part] : tree[part] = i < lastIndex ? {} : value; @@ -519,9 +515,9 @@ var File = function (inputFile, module) { self.sourcePath = inputFile.sourcePath; // Absolute module identifier to use when installing this file via - // meteorInstall. If the inputFile has no .absModuleId, then this file + // meteorInstall. If the inputFile has no .installPath, then this file // cannot be installed as a module. - self.absModuleId = inputFile.absModuleId || null; + self.installPath = inputFile.installPath || null; // the path where this file would prefer to be served if possible self.servePath = inputFile.servePath; @@ -579,8 +575,8 @@ _.extend(File.prototype, { computeAssignedVariables: Profile("linker File#computeAssignedVariables", function () { var self = this; - if (self.absModuleId) { - const parts = self.absModuleId.split("/"); + if (self.installPath) { + const parts = self.installPath.split("/"); const nmi = parts.indexOf("node_modules"); if (nmi >= 0 && parts[nmi + 1] !== "meteor") { // If this file is in a node_modules directory and is not part of From f2b800c92799bdf8de2cdf71966b9664207e89a4 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Sun, 8 Oct 2017 19:59:56 -0400 Subject: [PATCH 25/84] Remove target directory in files.rename to avoid Windows EPERM errors. These errors are especially harmful because they cause files.rename to fall back to copying rather than atomically renaming, which is both much slower and not even remotely atomic. --- tools/fs/files.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/fs/files.js b/tools/fs/files.js index 8c3789c5ae..5dd318c269 100644 --- a/tools/fs/files.js +++ b/tools/fs/files.js @@ -1755,15 +1755,21 @@ files.existsSync = function (path, callback) { }; if (files.isWindowsLikeFilesystem()) { - var rename = files.rename; + const rename = files.rename; files.rename = function (from, to) { - // retries are necessarily only on Windows, because the rename call can fail - // with EBUSY, which means the file is "busy" - var maxTries = 10; - var success = false; + // Retries are necessary only on Windows, because the rename call can + // fail with EBUSY, which means the file is in use. + let maxTries = 10; + let success = false; + const osTo = files.convertToOSPath(to); + while (! success && maxTries-- > 0) { try { + // Despite previous failures, the top-level destination directory + // may have been successfully created, so we must remove it to + // avoid moving the source file *into* the destination directory. + rimraf.sync(osTo); rename(from, to); success = true; } catch (err) { @@ -1772,6 +1778,7 @@ if (files.isWindowsLikeFilesystem()) { } } } + if (! success) { files.cp_r(from, to); files.rm_recursive(from); From 699768f39dfd8ae176b9a00a945f0e498053efb2 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 9 Oct 2017 16:45:08 -0400 Subject: [PATCH 26/84] Stop using file.imported to mark fake files in the ImportScanner. Using a Symbol ensures compiler plugins can't mark files fake accidentally (or maliciously) when calling inputFile.addJavaScript(options). --- tools/isobuild/import-scanner.js | 45 +++++++++++++++----------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index 4d34d533bf..c5d55eb3d6 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -43,17 +43,9 @@ const fakeFileStat = { } }; -// Used in ImportScanner#scanMissingModules. -const fakeScanFileOptions = { - // A temporary file that does not really exist and will never be added - // to scanner.outputFiles or returned by scanner.getOutputFiles. - sourcePath: "fake.js", - // It's important that the fake.js file itself never gets scanned or - // bundled. See the _scanFile and getOutputFiles methods for logic that - // deals with file.imported values. - imported: "fake", - lazy: true, -}; +// Symbol used by scanMissingModules to mark certain files as temporary, +// to prevent them from being added to scanner.outputFiles. +const fakeSymbol = Symbol("fake"); // Default handlers for well-known file extensions. // Note that these function expect strings, not Buffer objects. @@ -168,6 +160,11 @@ export default class ImportScanner { } _addFile(absPath, file) { + if (! file || file[fakeSymbol]) { + // Return file without adding it to this.outputFiles. + return file; + } + absPath = absPath.toLowerCase(); const old = this.absPathToOutputIndex[absPath]; @@ -217,9 +214,7 @@ export default class ImportScanner { } // This property can have values false, true, "dynamic" (which - // indicates that the file has been imported, but only dynamically), - // or "fake" (which indicates it is a temporary file that should - // never be returned from getOutputFiles). + // indicates that the file has been imported, but only dynamically). file.imported = false; file.installPath = file.installPath || this._getInstallPath(absPath); @@ -351,7 +346,7 @@ export default class ImportScanner { // If either oldFile or newFile has been imported non-dynamically, // then oldFile.imported needs to be === true. Otherwise we simply set // oldFile.imported = oldFile.imported || newFile.imported, which - // could be either false, "dynamic", or "fake" (see scanMissingModules). + // could be either "dynamic" or false. oldFile.imported = oldFile.imported === true || newFile.imported === true || @@ -410,7 +405,8 @@ export default class ImportScanner { if (staticImportInfo) { this._scanFile({ - ...fakeScanFileOptions, + sourcePath: "fake.js", + [fakeSymbol]: true, // By specifying the .deps property of this fake file ahead of // time, we can avoid calling findImportedModuleIdentifiers in // the _scanFile method, which is important because this file @@ -421,7 +417,8 @@ export default class ImportScanner { if (dynamicImportInfo) { this._scanFile({ - ...fakeScanFileOptions, + sourcePath: "fake.js", + [fakeSymbol]: true, deps: { [id]: dynamicImportInfo } }, true); // forDynamicImport } @@ -497,6 +494,7 @@ export default class ImportScanner { // imported (statically or dynamically). return this.outputFiles.filter(file => { return file.installPath && + ! file[fakeSymbol] && (! file.lazy || file.imported === true || file.imported === "dynamic"); @@ -627,11 +625,8 @@ export default class ImportScanner { return; } - // Make sure file.imported is set to a truthy value, but allow values - // other than "dynamic" or true (e.g. "fake"). - file.imported = file.imported || ( - forDynamicImport ? "dynamic" : true - ); + // Set file.imported to a truthy value (either "dynamic" or true). + file.imported = forDynamicImport ? "dynamic" : true; if (file.error) { // Any errors reported to InputFile#error were saved but not @@ -644,8 +639,6 @@ export default class ImportScanner { return; } - const absPath = pathJoin(this.sourceRoot, file.sourcePath); - try { file.deps = file.deps || this._findImportedModuleIdentifiers(file); } catch (e) { @@ -678,6 +671,10 @@ export default class ImportScanner { let depFile = this._getFile(absImportedPath); if (depFile) { + // We should never have stored a fake file in this.outputFiles, so + // it's surprising if depFile[fakeSymbol] is true. + assert.notStrictEqual(depFile[fakeSymbol], true); + // If the module is an implicit package.json stub, update to the // explicit version now. if (depFile.jsonData && From ddc490c66d33c5ebb9a6e2c6f05490d09f707f81 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 11 Oct 2017 15:09:55 -0400 Subject: [PATCH 27/84] Use module.watch live bindings to solve #9176. Further explanation / discussion: https://github.com/meteor/meteor/issues/9176#issuecomment-335913296 Another (complementary) solution to the same problem: #9190 --- tools/isobuild/import-scanner.js | 37 +++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/tools/isobuild/import-scanner.js b/tools/isobuild/import-scanner.js index c5d55eb3d6..5c07960b6c 100644 --- a/tools/isobuild/import-scanner.js +++ b/tools/isobuild/import-scanner.js @@ -260,6 +260,7 @@ export default class ImportScanner { dataString: "", deps: {}, lazy: true, + imported: false, }); } @@ -274,17 +275,33 @@ export default class ImportScanner { ); // Set the contents of the source module to import the target - // module(s). Note that module.exports will be set to the exports of - // the last target module. This is not perfect, but (1) it's better - // than trying to merge exports, (2) it does the right thing when - // there's only one target module, (3) the plugin author can easily - // control which file comes last, and (4) it's always possible to - // import the target modules individually. - sourceFile.dataString += "module.exports = require(" + - JSON.stringify(relativeId) + ");\n"; - sourceFile.data = new Buffer(sourceFile.dataString, "utf8"); + // module(s), combining their exports on the source module's exports + // object using the module.watch live binding system. This is better + // than `Object.assign(exports, require(relativeId))` because it + // allows the exports to change in the future, and better than + // `module.exports = require(relativeId)` because it preserves the + // original module.exports object, avoiding problems with circular + // dependencies (#9176, #9190). + // + // If there could be only one target module, we could do something + // less clever here (like using an identifier string alias), but + // unfortunately we have to tolerate the possibility of a compiler + // plugin calling inputFile.addJavaScript multiple times for the + // same source file (see discussion in #9176), with different target + // paths, code, laziness, etc. + sourceFile.dataString += [ + "module.watch(require(" + JSON.stringify(relativeId) + "), {", + ' "*": module.makeNsSetter()', + "});", + "" + ].join("\n"); + sourceFile.data = Buffer.from(sourceFile.dataString, "utf8"); sourceFile.hash = sha1(sourceFile.data); - sourceFile.deps[relativeId] = {}; + sourceFile.deps[relativeId] = { + installPath: file.installPath, + possiblySpurious: false, + dynamic: false + }; } } From b567fa0a39736561a84f1e74d100b08f0df782e7 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 12 Oct 2017 16:45:04 -0400 Subject: [PATCH 28/84] Allow asynchronous meteor command implementations. --- tools/cli/main.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/cli/main.js b/tools/cli/main.js index 7434ac66d0..79269b7afb 100644 --- a/tools/cli/main.js +++ b/tools/cli/main.js @@ -1480,7 +1480,10 @@ Fiber(function () { }); } - var ret = command.func(options, {rawOptions}); + var ret = Promise.resolve( + command.func(options, { rawOptions }) + ).await(); + } catch (e) { Console.enableProgressDisplay(false); From f73c7207e2886517133ca966c2e6c5836350e8fa Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 12 Oct 2017 16:45:12 -0400 Subject: [PATCH 29/84] Use files.rm_recursive_async to implement `meteor reset`. This should hopefully prevent ENOTEMPTY errors on Windows. --- tools/cli/commands.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/cli/commands.js b/tools/cli/commands.js index f01fc03f3a..7ffed6af7b 100644 --- a/tools/cli/commands.js +++ b/tools/cli/commands.js @@ -1265,10 +1265,11 @@ main.registerCommand({ return 1; } - var localDir = files.pathJoin(options.appDir, '.meteor', 'local'); - files.rm_recursive(localDir); - - Console.info("Project reset."); + return files.rm_recursive_async( + files.pathJoin(options.appDir, '.meteor', 'local') + ).then(() => { + Console.info("Project reset."); + }); }); /////////////////////////////////////////////////////////////////////////////// From b2db70a7276dc4a5e600767b426641ee0eeb9a3f Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 16 Oct 2017 13:19:02 -0400 Subject: [PATCH 30/84] Allow files.rm_recursive to yield whenever possible. A while back, for performance reasons, we disabled yielding for all files.* operations unless METEOR_DISABLE_FS_FIBERS was set to false. This was safe for almost all files.* operations, because most of them have a synchronous fs.*Sync version available. For a more complicated operation like files.rm_recursive, however, there is no synchronous or asynchronous counterpart in the fs.* namespace, so the safety of disabling fibers is not guaranteed. Lately, files.rm_recursive has become a major source of uncaught ENOTEMPTY errors on Windows, because rimraf.sync fails with that error, and we don't give files.rm_recursive_async a chance to delete the directory in a more persistent, forgiving manner. The only reason we haven't been falling back to files.rm_recursive_async is that YIELD_ALLOWED is false by default, so canYield() returns false. This commit distinguishes between canYield() and mayYield(), and uses canYield() in files.rm_recursive to determine whether it is technically safe to yield, regardless of YIELD_ALLOWED. Anyone who ever asked "Can I go to the bathroom?" in elementary school, only to be mercilessly rebuked with "I don't know, CAN YOU?" should understand the difference between these two functions. --- tools/fs/files.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/fs/files.js b/tools/fs/files.js index 5dd318c269..612fa13363 100644 --- a/tools/fs/files.js +++ b/tools/fs/files.js @@ -55,12 +55,15 @@ const YIELD_ALLOWED = !! ( ! JSON.parse(process.env.METEOR_DISABLE_FS_FIBERS)); function canYield() { - return YIELD_ALLOWED && - Fiber.current && + return Fiber.current && Fiber.yield && ! Fiber.yield.disallowed; } +function mayYield() { + return YIELD_ALLOWED && canYield(); +} + // given a predicate function and a starting path, traverse upwards // from the path until we find a path that satisfies the predicate. // @@ -303,8 +306,7 @@ files.rm_recursive = Profile("files.rm_recursive", (path) => { try { rimraf.sync(files.convertToOSPath(path)); } catch (e) { - if (e.code === "ENOTEMPTY" && - canYield()) { + if (e.code === "ENOTEMPTY" && canYield()) { files.rm_recursive_async(path).await(); return; } @@ -1561,7 +1563,7 @@ function wrapFsFunc(fsFuncName, pathArgIndices, options) { const dirty = options && options.dirty; const dirtyFn = typeof dirty === "function" ? dirty : null; - if (canYield() && + if (mayYield() && shouldBeSync && ! isQuickie) { const promise = new Promise((resolve, reject) => { From b7695d2e8b0ff3c54dbaf30f44cbd9a4050ce761 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 16 Oct 2017 13:55:16 -0400 Subject: [PATCH 31/84] Avoid creating symlinks in Builder#copyDirectory when forbidden. --- tools/isobuild/builder.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/isobuild/builder.js b/tools/isobuild/builder.js index a6d567aa80..b0bef4aa53 100644 --- a/tools/isobuild/builder.js +++ b/tools/isobuild/builder.js @@ -6,6 +6,7 @@ import {Profile} from '../tool-env/profile.js'; import { optimisticReadFile, optimisticReaddir, + optimisticStatOrNull, optimisticLStatOrNull, } from "../fs/optimistic.js"; @@ -555,7 +556,7 @@ Previous builder: ${previousBuilder.outputPath}, this builder: ${outputPath}` if (isDirectory) { walk(thisAbsFrom, thisRelTo, _currentRealRootDir); - } else if (fileStatus.isSymbolicLink()) { + } else if (symlink && fileStatus.isSymbolicLink()) { symlinkWithOverwrite( // Symbolic links pointing to relative external paths are less // portable than absolute links, so getExternalPath() is @@ -569,6 +570,13 @@ Previous builder: ${previousBuilder.outputPath}, this builder: ${outputPath}` this.usedAsFile[thisRelTo] = true; } else { + // Fall back to copying the file, but make sure it's really a + // file first, just in case it was a forbidden symbolic link. + fileStatus = optimisticStatOrNull(thisAbsFrom); + if (! (fileStatus && fileStatus.isFile())) { + return; + } + // XXX can't really optimize this copying without reading // the file into memory to calculate the hash. files.writeFile( From fe5479400e4c35f1ba8c2bc181666f6d54f0034a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 16 Oct 2017 14:07:11 -0400 Subject: [PATCH 32/84] Avoid calling files.stat(source) in symlinkWithOverwrite. This was dangerous because source is often a path relative to the old target file, whereas files.stat was interpreting source as a path relative to process.cwd(). Fixes #9203. --- tools/isobuild/builder.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/tools/isobuild/builder.js b/tools/isobuild/builder.js index b0bef4aa53..8f42208122 100644 --- a/tools/isobuild/builder.js +++ b/tools/isobuild/builder.js @@ -734,23 +734,19 @@ function atomicallyRewriteFile(path, data, options) { // create a symlink, overwriting the target link, file, or directory // if it exists function symlinkWithOverwrite(source, target) { - const args = [source, target]; - - if (process.platform === "win32") { - if (! files.stat(source).isDirectory()) { - throw new Error("symlink source must be a directory: " + source); - } - - args[2] = "junction"; - } - try { - files.symlink(...args); + files.symlink(source, target); } catch (e) { - if (e.code === 'EEXIST') { + if (e.code === "EEXIST") { // overwrite existing link, file, or directory files.rm_recursive(target); - files.symlink(...args); + files.symlink(source, target); + } else if (e.code === "EPERM" && + process.platform === "win32") { + files.rm_recursive(target); + // This will work only if source refers to a directory, but that's a + // chance worth taking. + files.symlink(source, target, "junction"); } else { throw e; } From afd556f93150c3c494d13cbb9cc849834dee7c0d Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 16 Oct 2017 14:57:02 -0400 Subject: [PATCH 33/84] Allow Builder#copyDirectory to re-create symlinks again. Commit 86ec7eb5db1ce13d0c27865fc6f432fd51241cf4 broke tests because we rely on symlinks even when the symlink option is false. --- tools/isobuild/builder.js | 45 +++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/tools/isobuild/builder.js b/tools/isobuild/builder.js index 8f42208122..310e5b3ba5 100644 --- a/tools/isobuild/builder.js +++ b/tools/isobuild/builder.js @@ -555,28 +555,32 @@ Previous builder: ${previousBuilder.outputPath}, this builder: ${outputPath}` if (isDirectory) { walk(thisAbsFrom, thisRelTo, _currentRealRootDir); + return; + } - } else if (symlink && fileStatus.isSymbolicLink()) { - symlinkWithOverwrite( - // Symbolic links pointing to relative external paths are less - // portable than absolute links, so getExternalPath() is - // preferred if it returns a path. - getExternalPath() || files.readlink(thisAbsFrom), - files.pathResolve(this.buildPath, thisRelTo) - ); + if (fileStatus.isSymbolicLink()) { + // Symbolic links pointing to relative external paths are less + // portable than absolute links, so getExternalPath() is + // preferred if it returns a path. + const linkSource = getExternalPath() || + files.readlink(thisAbsFrom); - // A symlink counts as a file, as far as "can you put something under - // it" goes. - this.usedAsFile[thisRelTo] = true; + const linkTarget = + files.pathResolve(this.buildPath, thisRelTo); - } else { - // Fall back to copying the file, but make sure it's really a - // file first, just in case it was a forbidden symbolic link. - fileStatus = optimisticStatOrNull(thisAbsFrom); - if (! (fileStatus && fileStatus.isFile())) { + if (symlinkIfPossible(linkSource, linkTarget)) { + // A symlink counts as a file, as far as "can you put + // something under it" goes. + this.usedAsFile[thisRelTo] = true; return; } + } + // Fall back to copying the file, but make sure it's really a file + // first, just in case it was a symbolic link to a directory that + // could not be created above. + fileStatus = optimisticStatOrNull(thisAbsFrom); + if (fileStatus && fileStatus.isFile()) { // XXX can't really optimize this copying without reading // the file into memory to calculate the hash. files.writeFile( @@ -731,6 +735,15 @@ function atomicallyRewriteFile(path, data, options) { } } +function symlinkIfPossible(source, target) { + try { + symlinkWithOverwrite(source, target); + return true; + } catch (e) { + return false; + } +} + // create a symlink, overwriting the target link, file, or directory // if it exists function symlinkWithOverwrite(source, target) { From c257183a55db9b2dec1e5b4964e69c390cf27eae Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 16 Oct 2017 17:59:52 -0400 Subject: [PATCH 34/84] Use files.rm_recursive_async to implement files.freeTempDir. --- tools/fs/files.js | 48 ++++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/tools/fs/files.js b/tools/fs/files.js index 612fa13363..401733cb31 100644 --- a/tools/fs/files.js +++ b/tools/fs/files.js @@ -640,7 +640,7 @@ var copyFileHelper = function (from, to, mode) { // directory. Only the current user is allowed to read or write the // files in the directory (or add files to it). The directory will // be cleaned up on exit. -var tempDirs = []; +const tempDirs = Object.create(null); files.mkdtemp = function (prefix) { var make = function () { prefix = prefix || 'mt-'; @@ -675,55 +675,43 @@ files.mkdtemp = function (prefix) { throw new Error("failed to make temporary directory in " + tmpDir); }; var dir = make(); - tempDirs.push(dir); + tempDirs[dir] = true; return dir; }; // Call this if you're done using a temporary directory. It will asynchronously // be deleted. -files.freeTempDir = function (tempDir) { - if (! _.contains(tempDirs, tempDir)) { - throw Error("not a tracked temp dir: " + tempDir); +files.freeTempDir = function (dir) { + if (! tempDirs[dir]) { + throw Error("not a tracked temp dir: " + dir); } + if (process.env.METEOR_SAVE_TMPDIRS) { return; } - setImmediate(function () { - // note: rm_recursive can yield, so it's possible that during this - // rm_recursive call, the onExit rm_recursive fires too. (Or it could even - // start firing before the setImmediate handler is called.) But it should be - // OK for there to be overlapping rm_recursive calls, since rm_recursive - // ignores all ENOENT calls. And we don't remove tempDir from tempDirs until - // it's done, so that if mid-way through this rm_recursive the onExit one - // fires, it still gets removed. - try { - files.rm_recursive(tempDir); - } catch (err) { - // Don't crash and print a stack trace because we failed to delete a temp - // directory. This happens sometimes on Windows and seems to be - // unavoidable. - console.log(err); - } + delete tempDirs[dir]; - tempDirs = _.without(tempDirs, tempDir); + // Attach a .catch handler so that any errors resulting from + // files.rm_recursive_async will not trigger an unhandled promise + // rejection warning. + return files.rm_recursive_async(dir).catch(error => { + console.log(error); }); }; if (! process.env.METEOR_SAVE_TMPDIRS) { cleanup.onExit(function (sig) { - _.each(tempDirs, function (tempDir) { + Object.keys(tempDirs).forEach(dir => { + delete tempDirs[dir]; try { - files.rm_recursive(tempDir); + files.rm_recursive(dir); } catch (err) { - // Don't crash and print a stack trace because we failed to delete a temp - // directory. This happens sometimes on Windows and seems to be - // unavoidable. - console.log(err); + // Don't crash and print a stack trace because we failed to delete + // a temp directory. This happens sometimes on Windows and seems + // to be unavoidable. } }); - - tempDirs = []; }); } From f9a9e9f2f92f7f47a6438953901eccc77911f228 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 17 Oct 2017 10:21:01 -0400 Subject: [PATCH 35/84] Another small improvement to temp directory removal logic. --- tools/fs/files.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/fs/files.js b/tools/fs/files.js index 401733cb31..eeb66b1669 100644 --- a/tools/fs/files.js +++ b/tools/fs/files.js @@ -690,12 +690,14 @@ files.freeTempDir = function (dir) { return; } - delete tempDirs[dir]; - - // Attach a .catch handler so that any errors resulting from - // files.rm_recursive_async will not trigger an unhandled promise - // rejection warning. - return files.rm_recursive_async(dir).catch(error => { + return files.rm_recursive_async(dir).then(() => { + // Delete tempDirs[dir] only when the removal finishes, so that the + // cleanup.onExit handler can attempt the removal synchronously if it + // fires in the meantime. + delete tempDirs[dir]; + }, error => { + // Leave tempDirs[dir] in place so the cleanup.onExit handler can try + // to delete it again when the process exits. console.log(error); }); }; From 9efe9e8b8021e0c40e2277baaa765b1065d16056 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 31 Oct 2017 11:21:02 -0700 Subject: [PATCH 36/84] Bump package versions for 1.5.3-rc.1 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 38841667cb..960268d2b6 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.3-rc.0" + version: "1.5.3-rc.1" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 93dbc89693..b4443b3b03 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5.3-rc.0", + "version": "1.5.3-rc.1", "recommended": false, "official": false, "description": "Meteor" From dff4325341b327ab0cd019acb854114a7ce84b57 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 17 Oct 2017 18:59:32 +0300 Subject: [PATCH 37/84] Basic Appveyor testing for Windows. This implements a first generation of Windows CI testing. Presently, this only runs valuable, hand-picked tests which have been known to work in the past, and whose failure would indicate a critical problem. A test which isn't passing doesn't mean that the feature being tested is not working. For example, the 'create' test fails ostentatiously, though the 'meteor create' command certainly works in practice. This points to problems some compatibility problems with the 'self-test' harness itself, some of which I'm aware of. Though, it likely will highlight some legitimate problems which Windows users experience too. There are a number of additional tests which should be enabled which likely pass already, and many more which are failing and we should fix. Additional tests can be added to the scripts/windows/appveyor/test.ps1 file as they've been deemed working. Altogether, this will take extensive work to achieve the same level of coverage our Unix test suite enjoy, but we've got to start somewhere! cc @benjamn --- appveyor.yml | 38 ++++++++++++++++++++++++++++ scripts/windows/appveyor/install.ps1 | 28 ++++++++++++++++++++ scripts/windows/appveyor/test.ps1 | 38 ++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 appveyor.yml create mode 100644 scripts/windows/appveyor/install.ps1 create mode 100644 scripts/windows/appveyor/test.ps1 diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000..ae24e9c82f --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,38 @@ +version: '{build}' +clone_folder: C:\projects\meteor +os: Visual Studio 2015 +environment: + METEOR_PRETTY_OUTPUT: 0 + SELF_TEST_TOOL_NODE_FLAGS: " " + TOOL_NODE_FLAGS: --expose-gc + TIMEOUT_SCALE_FACTOR: 8 + METEOR_HEADLESS: true + SELF_TEST_EXCLUDE: "\ + ^old cli tests|\ + ^minifiers can't register non-js|\ + ^minifiers: apps can't use|\ + ^compiler plugins - addAssets|\ + ^NULL-LEAVE-THIS-HERE-NULL$" +platform: + - x64 + - x86 + +matrix: + fast_finish: true + allow_failures: + - platform: x64 + - platform: x86 + +# We don't need the actual "build", just the tests. +build: off + +install: + - ps: C:\projects\meteor\scripts\windows\appveyor\install.ps1 + +test_script: + - ps: C:\projects\meteor\scripts\windows\appveyor\test.ps1 + +cache: + - dev_bundle -> meteor + - .babel-cache + - .meteor diff --git a/scripts/windows/appveyor/install.ps1 b/scripts/windows/appveyor/install.ps1 new file mode 100644 index 0000000000..1f854d184e --- /dev/null +++ b/scripts/windows/appveyor/install.ps1 @@ -0,0 +1,28 @@ +# Appveyor already sets $PLATFORM to exactly what we don't want, so +# we'll prepend it with 'windows_' if that seems to be the case. +If ($env:PLATFORM -Match '^x86|x64$') { + $env:PLATFORM = "windows_${env:PLATFORM}" +} + +$dirCheckout = (Get-Item $PSScriptRoot).parent.parent.parent.FullName +$meteorBat = Join-Path $dirCheckout 'meteor.bat' + +Write-Host "Updating submodules recursively..." -ForegroundColor Magenta +# Appveyor suggests -q flag for 'git submodule...' https://goo.gl/4TFAHm +& git.exe -C "$dirCheckout" submodule -q update --init --recursive + +Write-Host "Running 'meteor --get-ready'..." -ForegroundColor Magenta +# By redirecting error to host, we avoid a shocking/false error color, +# since --get-ready and --version can print (anything) to STDERR and +# PowerShell will interpret that as something being terribly wrong. +& "$meteorBat" --get-ready 2>&1 | Write-Host -ForegroundColor Green + +# This should no longer be necessary with Meteor 1.6, which will +# automatically install these dependencies when they're not found in the +# dev bundle, but for good measure, we'll install them ahead of time, +# and to also cover Meteor 1.5. +Write-Host "Installing test npm dependencies..." ` + -ForegroundColor Magenta +& "$meteorBat" npm install --prefix "${dirCheckout}\dev_bundle\lib" ` + phantomjs-prebuilt ` + browserstack-webdriver diff --git a/scripts/windows/appveyor/test.ps1 b/scripts/windows/appveyor/test.ps1 new file mode 100644 index 0000000000..ecd056a48f --- /dev/null +++ b/scripts/windows/appveyor/test.ps1 @@ -0,0 +1,38 @@ +# For now, we only have one script. +$jUnit = Join-Path $env:TEMP 'self-test-junit-0.xml' + +$tests = @( + 'modules - test app' + '^assets' + 'autoupdate' + 'dynamic import' +) -Join '|' + +Write-Host "Running: $tests" -ForegroundColor Yellow +Write-Host "Excluded: $env:SELF_TEST_EXCLUDE" -ForegroundColor Yellow + +.\meteor.bat self-test --junit "$jUnit" "$tests" --exclude "$env:SELF_TEST_EXCLUDE" '2>&1' +$selfTestExitCode = $LASTEXITCODE + +If ($selfTestExitCode -eq 0) { + Write-Host "Success!" -ForegroundColor Green +} else { + Write-Host "FAILURE! (Exit: $selfTestExitCode)" -ForegroundColor Red +} + +Write-Host "Uploading JUnit test results..." -ForegroundColor Magenta +$wc = New-Object 'System.Net.WebClient' +Get-ChildItem $env:TEMP 'self-test-junit-*.xml' | Foreach-Object { + Write-Host " - $($_.FullName)" -ForegroundColor Magenta + Write-Host " - as Artifact..." -ForegroundColor Magenta + Push-AppveyorArtifact $_.FullName + Write-Host " - as Test Results..." -ForegroundColor Magenta + $artifactPostUrl = ` + "https://ci.appveyor.com/api/testresults/junit/", + $env:APPVEYOR_JOB_ID -Join '' + $wc.UploadFile($artifactPostUrl, ($_.FullName)) +} + +If ($selfTestExitCode -ne 0) { + Exit $selfTestExitCode +} From 975e12828c17735cc3ac926ddcf7e2422fdecb45 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 17 Oct 2017 23:45:55 +0300 Subject: [PATCH 38/84] Use YAML config for Appveyor settings, rather than their UI. These take precedence over the UI, and I'm not sure the UI is taking effect at the moment. We don't need to build branches which start with 'dev-bundle-' since those dev bundles won't be built yet when the tests are kicked off. --- appveyor.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index ae24e9c82f..7ce4f07bb1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,14 @@ version: '{build}' + +branches: + except: + - /^dev-bundle-/ + +skip_branch_with_pr: true + clone_folder: C:\projects\meteor -os: Visual Studio 2015 +image: Visual Studio 2015 + environment: METEOR_PRETTY_OUTPUT: 0 SELF_TEST_TOOL_NODE_FLAGS: " " From 790871796c4588b9d1abcbe1d71f56fb7d9649d0 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 17 Oct 2017 23:34:37 +0300 Subject: [PATCH 39/84] Remove problematic Windows test, until it can be researched further. Though it was thought to be reliable when running through 'self-test' on Windows, it's yet to be seen how reliable. The worst thing that could come of adding Windows testing would be that we have test failures again after such a string of green checkmarks and confidence. Also, reordered. --- scripts/windows/appveyor/test.ps1 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/windows/appveyor/test.ps1 b/scripts/windows/appveyor/test.ps1 index ecd056a48f..2a6f2a817e 100644 --- a/scripts/windows/appveyor/test.ps1 +++ b/scripts/windows/appveyor/test.ps1 @@ -2,10 +2,9 @@ $jUnit = Join-Path $env:TEMP 'self-test-junit-0.xml' $tests = @( - 'modules - test app' '^assets' - 'autoupdate' - 'dynamic import' + '^autoupdate' + '^dynamic import' ) -Join '|' Write-Host "Running: $tests" -ForegroundColor Yellow From b0f624ae57a95f6cebcf39661a93cde77cfc31a8 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Mon, 23 Oct 2017 16:38:31 -0700 Subject: [PATCH 40/84] Throw an error when any external command fails during test preparation. Even with $ErrorActionPreference, PowerShell won't automatically fail when an external command fails with an error code. This explicitly checks those exit codes and throws an error when that occurs. Hopefully prevents false successes like that shown in this AppVeyor test run: https://goo.gl/xxRsF9. --- scripts/windows/appveyor/install.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/windows/appveyor/install.ps1 b/scripts/windows/appveyor/install.ps1 index 1f854d184e..edd5b66572 100644 --- a/scripts/windows/appveyor/install.ps1 +++ b/scripts/windows/appveyor/install.ps1 @@ -11,12 +11,20 @@ Write-Host "Updating submodules recursively..." -ForegroundColor Magenta # Appveyor suggests -q flag for 'git submodule...' https://goo.gl/4TFAHm & git.exe -C "$dirCheckout" submodule -q update --init --recursive +If ($LASTEXITCODE -ne 0) { + throw "Updating submodules failed." +} + Write-Host "Running 'meteor --get-ready'..." -ForegroundColor Magenta # By redirecting error to host, we avoid a shocking/false error color, # since --get-ready and --version can print (anything) to STDERR and # PowerShell will interpret that as something being terribly wrong. & "$meteorBat" --get-ready 2>&1 | Write-Host -ForegroundColor Green +If ($LASTEXITCODE -ne 0) { + throw "Running .\meteor --get-ready failed." +} + # This should no longer be necessary with Meteor 1.6, which will # automatically install these dependencies when they're not found in the # dev bundle, but for good measure, we'll install them ahead of time, @@ -26,3 +34,7 @@ Write-Host "Installing test npm dependencies..." ` & "$meteorBat" npm install --prefix "${dirCheckout}\dev_bundle\lib" ` phantomjs-prebuilt ` browserstack-webdriver + +If ($LASTEXITCODE -ne 0) { + throw "Installing npm dependencies required for testing has failed." +} From 5d8e5013fa7e8c36687b1b03701a36e02c0fe4fc Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Sat, 4 Nov 2017 10:13:20 +0200 Subject: [PATCH 41/84] Bump package versions for the official 1.5.3 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-official.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 960268d2b6..bfe7f800df 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.3-rc.1" + version: "1.5.3" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index 63150a788a..de80597835 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5.2.2", + "version": "1.5.3", "recommended": false, "official": true, "description": "The Official Meteor Distribution" From c2157bb4bb4b0891850e341ef48da98ac330b259 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Sat, 4 Nov 2017 13:56:29 +0200 Subject: [PATCH 42/84] Update History.md with miscellaneous changes in Meteor 1.5.3. --- History.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/History.md b/History.md index 9e44e78482..3d173e897d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,22 @@ +## v1.5.3, 2017-11-04 + +* Node has been upgraded to version 4.8.5, a recommended security + release: https://nodejs.org/en/blog/release/v4.8.5/. While it was + expected that Node 4.8.5 would also include our fix of a faulty + backport of garbage collection-related logic in V8, the timing + of this security release has caused that to be delayed until 4.8.6. + Therefore, this Node still includes our patch for this issue. + [Issue #8648](https://github.com/meteor/meteor/issues/8648) + +* Various backports from Meteor 1.6. Consult the + [1.5.3 pull-request](https://github.com/meteor/meteor/pull/9266) + for additional details, but issues include: + * Child imports of dynamically imported modules within packages + [#9182](https://github.com/meteor/meteor/issues/9182) + * Unresolved circular dependencies + [#9176](https://github.com/meteor/meteor/issues/9176) + * Improvements to Windows temporary directory handling. + ## v1.5.2.2, 2017-10-02 * Fixes a regression in 1.5.2.1 which resulted in the macOS firewall From 12f45e9ad61c1ed15b6d37dc8acb25054c325094 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Sat, 4 Nov 2017 20:11:48 +0200 Subject: [PATCH 43/84] Tweaks to History.md for 1.5.3. [ci skip] (Hopefully.) --- History.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index 3d173e897d..2115c65616 100644 --- a/History.md +++ b/History.md @@ -8,14 +8,14 @@ Therefore, this Node still includes our patch for this issue. [Issue #8648](https://github.com/meteor/meteor/issues/8648) -* Various backports from Meteor 1.6. Consult the - [1.5.3 pull-request](https://github.com/meteor/meteor/pull/9266) - for additional details, but issues include: - * Child imports of dynamically imported modules within packages +* Various backports from Meteor 1.6, as detailed in the + [PR for Meteor 1.5.3](https://github.com/meteor/meteor/pull/9266). + Briefly, these involve fixes for: + * Child imports of dynamically imported modules within packages. [#9182](https://github.com/meteor/meteor/issues/9182) - * Unresolved circular dependencies + * Unresolved circular dependencies. [#9176](https://github.com/meteor/meteor/issues/9176) - * Improvements to Windows temporary directory handling. + * Windows temporary directory handling. ## v1.5.2.2, 2017-10-02 From f2009e2fa6a748bc0f4efec4593aa0ad8f5fbcae Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 7 Nov 2017 19:52:31 +0200 Subject: [PATCH 44/84] Switch to official Node.js 4.8.6 and stop using a custom Meteor build. This puts Meteor back on the official release track of Node.js 4, rather than using its own custom build (from https://github.com/meteor/node/), which had previously been necessary to add the garbage collection fixes gained with https://github.com/nodejs/node/commit/751f1ac08ebf602968fc289615b9f0e553bb2572 and https://github.com/nodejs/node/commit/71f9cdf24197b34657a050cb455901994576f054, both of which are now officially included in Node.js 4.x as of 4.8.6. :tada: --- scripts/build-dev-bundle-common.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 6073692997..5857646f75 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -6,11 +6,11 @@ set -u UNAME=$(uname) ARCH=$(uname -m) MONGO_VERSION=3.2.15 -NODE_VERSION=4.8.5 +NODE_VERSION=4.8.6 NPM_VERSION=4.6.1 # If we built Node from source on Jenkins, this is the build number. -NODE_BUILD_NUMBER=120 +NODE_BUILD_NUMBER= if [ "$UNAME" == "Linux" ] ; then if [ "$ARCH" != "i686" -a "$ARCH" != "x86_64" ] ; then From ca31a84dbf8d54a49eb5543ed98f2eae7b7ce63d Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 7 Nov 2017 20:16:53 +0200 Subject: [PATCH 45/84] Only try to download $NODE_BUILD_NUMBER when defined. Alternatively, this was just failing when trying to download a file that was 404-ing. This just short-circuits before that inevitable failure. --- scripts/generate-dev-bundle.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/generate-dev-bundle.sh b/scripts/generate-dev-bundle.sh index 820cb60c65..50578ed1b0 100755 --- a/scripts/generate-dev-bundle.sh +++ b/scripts/generate-dev-bundle.sh @@ -28,6 +28,7 @@ extractNodeFromTarGz() { } downloadNodeFromS3() { + test -n "${NODE_BUILD_NUMBER}" || return 1 S3_HOST="s3.amazonaws.com/com.meteor.jenkins" S3_TGZ="node_${UNAME}_${ARCH}_v${NODE_VERSION}.tar.gz" NODE_URL="https://${S3_HOST}/dev-bundle-node-${NODE_BUILD_NUMBER}/${S3_TGZ}" From 10a518487165081677b9ea663af75574cf1f5387 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 7 Nov 2017 20:05:21 +0200 Subject: [PATCH 46/84] Bump $BUNDLE_VERSION to 4.8.44 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 448bbca4ef..71dd736df0 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.43 +BUNDLE_VERSION=4.8.44 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 6faa67be8f7e9878eab929f3b363622736b834de Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Tue, 7 Nov 2017 21:35:37 +0200 Subject: [PATCH 47/84] Bump package versions for 1.5.4-rc.0 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index bfe7f800df..d441b907a6 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.3" + version: "1.5.4-rc.0" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index b4443b3b03..4a1f821563 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5.3-rc.1", + "version": "1.5.4-rc.0", "recommended": false, "official": false, "description": "Meteor" From 77b13e99416a9ae23f4a011fe21e9d937b85aa6d Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Wed, 8 Nov 2017 22:18:14 +0200 Subject: [PATCH 48/84] Update History.md with changes in Meteor 1.5.4. --- History.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/History.md b/History.md index 2115c65616..32382de094 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,12 @@ +## v1.5.4, 2017-11-08 + +* Node has been updated to version 4.8.6. This release officially + includes our fix of a faulty backport of garbage collection-related + logic in V8 and ends Meteor's use of a custom Node with that patch. + In addition, it includes small OpenSSL updates as announced on the + Node blog: https://nodejs.org/en/blog/release/v4.8.6/. + [Issue #8648](https://github.com/meteor/meteor/issues/8648) + ## v1.5.3, 2017-11-04 * Node has been upgraded to version 4.8.5, a recommended security From 66e1a780a664bc04437805055c05e42c5ca435c6 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Wed, 8 Nov 2017 22:22:39 +0200 Subject: [PATCH 49/84] Bump package versions for 1.5.4 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-official.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index d441b907a6..19ea4363d8 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.4-rc.0" + version: "1.5.4" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index de80597835..024ef29517 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,7 +1,8 @@ { "track": "METEOR", - "version": "1.5.3", + "version": "1.5.4", "recommended": false, "official": true, + "patchFrom": ["1.5", "1.5.1", "1.5.2", "1.5.2.1", "1.5.2.2", "1.5.3"], "description": "The Official Meteor Distribution" } From 31f230e8546b17ab1499eb5020c6691b2aa08ef5 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 9 Nov 2017 00:28:01 +0200 Subject: [PATCH 50/84] Only run AppVeyor tests for Windows 64-bit, and not also 32-. AppVeyor does provide us quite a bit of value at no cost since we're open-source software, but with only a single container at our disposal under that plan, our build queue is often maxed-out for hours. Since most Meteor developers are using 64-bit platforms, the 64-bit tests provide the most value. Meteor doesn't have much (if any?) in the way of 32-bit/64-bit exceptions so any functionality difference would be at the OS level. Some day, we might bring this back. --- appveyor.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7ce4f07bb1..47dbafb91d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,13 +23,11 @@ environment: ^NULL-LEAVE-THIS-HERE-NULL$" platform: - x64 - - x86 matrix: fast_finish: true allow_failures: - platform: x64 - - platform: x86 # We don't need the actual "build", just the tests. build: off From 7f8ed5692ed5390bc6e2f4b7b63cae1036fb4410 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 13 Nov 2017 15:53:11 -0500 Subject: [PATCH 51/84] Shallow-clone inserted documents more reliably. In a previous commit, I changed doc = _.extend({}, doc); to avoid using underscore, thus: doc = { ...doc }; While this may seem harmless, it broke a few Mongo.Collection tests because _.extend copies *all* properties, both own and inherited, whereas object ...spread only copies own properties. However, the correct way to fix this problem is *not* to revert to the old behavior, since flattening the inherited properties of a document was never actually what we wanted. The old behavior was subtly broken, too. Instead, we need to create a new object with the same prototoype as the provided document, then shallow-copy the own properties. Any properties or methods inherited from the original prototype will then be available on the new object, even though they didn't get copied over. I've intentionally left some trivial formatting changes in this commit to remind myself which broken tests were fixed by this change. --- packages/mongo/collection.js | 14 ++++++++++---- packages/mongo/mongo_livedata_tests.js | 12 +++++++++--- packages/mongo/package.js | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/mongo/collection.js b/packages/mongo/collection.js index 6a1a6906a4..9793e4a57d 100644 --- a/packages/mongo/collection.js +++ b/packages/mongo/collection.js @@ -429,12 +429,18 @@ Mongo.Collection.prototype.insert = function insert(doc, callback) { throw new Error("insert requires an argument"); } - // Shallow-copy the document and possibly generate an ID - doc = _.extend({}, doc); + // Make a shallow clone of the document, preserving its prototype. + doc = Object.create( + Object.getPrototypeOf(doc), + Object.getOwnPropertyDescriptors(doc) + ); if ('_id' in doc) { - if (!doc._id || !(typeof doc._id === 'string' || doc._id instanceof Mongo.ObjectID)) { - throw new Error("Meteor requires document _id fields to be non-empty strings or ObjectIDs"); + if (! doc._id || + ! (typeof doc._id === 'string' || + doc._id instanceof Mongo.ObjectID)) { + throw new Error( + "Meteor requires document _id fields to be non-empty strings or ObjectIDs"); } } else { let generateId = true; diff --git a/packages/mongo/mongo_livedata_tests.js b/packages/mongo/mongo_livedata_tests.js index 932b98caca..98ef9955a2 100644 --- a/packages/mongo/mongo_livedata_tests.js +++ b/packages/mongo/mongo_livedata_tests.js @@ -1507,7 +1507,9 @@ testAsyncMulti('mongo-livedata - document with a custom type, ' + idGeneration, Meteor.call('createInsecureCollection', this.collectionName, collectionOptions); Meteor.subscribe('c-' + this.collectionName, expect()); } - }, function (test, expect) { + }, + + function (test, expect) { var self = this; self.coll = new Mongo.Collection(this.collectionName, collectionOptions); var docId; @@ -1525,13 +1527,17 @@ testAsyncMulti('mongo-livedata - document with a custom type, ' + idGeneration, test.isTrue(inColl); inColl && test.equal(inColl.d.speak(), "woof"); })); - }, function (test, expect) { + }, + + function (test, expect) { var self = this; self.coll.insert(new Dog("rover", "orange"), expect(function (err, id) { test.isTrue(err); test.isFalse(id); })); - }, function (test, expect) { + }, + + function (test, expect) { var self = this; self.coll.update( self.docId, new Dog("rover", "orange"), expect(function (err) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 59c5de29f7..bc7776f7ad 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.3.0' + version: '1.3.1' }); Npm.depends({ From 895f9d3b47d15abefee124b04c0b50897cb66efc Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 22 Nov 2017 11:11:53 -0500 Subject: [PATCH 52/84] Merge pull request #9398 from sebakerckhof/fix/stop-npm-wasting-all-my-time Don't update npm dependencies when it's not needed --- tools/isobuild/meteor-npm.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/isobuild/meteor-npm.js b/tools/isobuild/meteor-npm.js index ffed839430..f66944df6b 100644 --- a/tools/isobuild/meteor-npm.js +++ b/tools/isobuild/meteor-npm.js @@ -920,6 +920,11 @@ function getInstalledDependenciesTree(dir) { const pkgDir = files.pathJoin(nodeModulesDir, item); const pkgJsonPath = files.pathJoin(pkgDir, "package.json"); + if (item.startsWith("@")) { + Object.assign(result, ls(pkgDir)); + return; + } + let pkg; try { pkg = JSON.parse(files.readFile(pkgJsonPath)); @@ -927,7 +932,9 @@ function getInstalledDependenciesTree(dir) { if (! pkg) return; } - const info = result[item] = { + const name = pkg.name || item; + + const info = result[name] = { version: pkg.version }; @@ -1136,7 +1143,8 @@ var minimizeDependencyTree = function (tree) { var minimizeModule = function (module) { var version; if (module.resolved && - !module.resolved.match(/^https?:\/\/registry.npmjs.org\//)) { + !module.resolved.match(/^https?:\/\/registry.npmjs.org\//) && + !module.resolved.startsWith(process.env.NPM_CONFIG_REGISTRY)) { version = module.resolved; } else if (utils.isNpmUrl(module.from)) { version = module.from; From 534e0c635886ff1e7bbd58354cd71b4525e56c52 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 22 Nov 2017 13:12:31 -0500 Subject: [PATCH 53/84] Guard against undefined process.env.NPM_CONFIG_REGISTRY. https://github.com/meteor/meteor/pull/9398#discussion_r152610836 --- tools/isobuild/meteor-npm.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tools/isobuild/meteor-npm.js b/tools/isobuild/meteor-npm.js index f66944df6b..a52b93e10c 100644 --- a/tools/isobuild/meteor-npm.js +++ b/tools/isobuild/meteor-npm.js @@ -1052,7 +1052,7 @@ const installNpmModule = meteorNpm.installNpmModule = (name, version, dir) => { `${name} version ${version} is not available in the npm registry`); } else { buildmessage.error( - `couldn't install npm package ${name}@${version}: ${result.error}`); + `couldn\'t install npm package ${name}@${version}: ${result.error}`); } // Recover by returning false from updateDependencies @@ -1139,12 +1139,10 @@ function shrinkwrap(dir) { // Reduces a dependency tree (as read from a just-made npm-shrinkwrap.json or // from npm ls --json) to just the versions we want. Returns an object that does // not share state with its input -var minimizeDependencyTree = function (tree) { - var minimizeModule = function (module) { +function minimizeDependencyTree(tree) { + function minimizeModule(module) { var version; - if (module.resolved && - !module.resolved.match(/^https?:\/\/registry.npmjs.org\//) && - !module.resolved.startsWith(process.env.NPM_CONFIG_REGISTRY)) { + if (module.resolved && ! isUrlFromRegistry(module.resolved)) { version = module.resolved; } else if (utils.isNpmUrl(module.from)) { version = module.from; @@ -1160,14 +1158,22 @@ var minimizeDependencyTree = function (tree) { }); } return minimized; - }; + } var newTopLevelDependencies = {}; _.each(tree.dependencies, function (module, name) { newTopLevelDependencies[name] = minimizeModule(module); }); return {dependencies: newTopLevelDependencies}; -}; +} + +function isUrlFromRegistry(url) { + if (url.match(/^https?:\/\/registry.npmjs.org\//)) { + return true; + } + const NCR = process.env.NPM_CONFIG_REGISTRY; + return NCR && url.startsWith(NCR); +} var logUpdateDependencies = function (packageName, npmDependencies) { runLog.log(packageName + ': updating npm dependencies -- ' + From 04e645906c673eae4154d7f3cc11facf1cf8448d Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 22 Nov 2017 13:27:16 -0500 Subject: [PATCH 54/84] Update blaze submodule to latest master revision. --- packages/non-core/blaze | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/non-core/blaze b/packages/non-core/blaze index 7508438243..8f819731df 160000 --- a/packages/non-core/blaze +++ b/packages/non-core/blaze @@ -1 +1 @@ -Subproject commit 750843824397a6f8062a6b1dcc884cacbd3bef85 +Subproject commit 8f819731df1fce254825c236176cfa5acb2df869 From 8048510a959d8616c29827f3f3becf8053da7a6c Mon Sep 17 00:00:00 2001 From: James Burgess Date: Wed, 22 Nov 2017 19:21:49 +0300 Subject: [PATCH 55/84] Fix meteor test file matching patterns (#9339) * Adjust test filename RegExps to match Meteor guide. Fixes #9332. * Adjusted help text for --drive-package on meteor test. * Add integration tests for `meteor test` eager file loading. * Fix typo in selftest.forbid comment. * Improve test file eager load integration test coverage and clarity. --- tools/cli/help.txt | 5 +- tools/isobuild/test-files.js | 14 ++-- .../apps/test-eagerly-load/.meteor/.gitignore | 1 + .../apps/test-eagerly-load/.meteor/packages | 2 + .../apps/test-eagerly-load/.meteor/release | 1 + .../test-eagerly-load/imports/foo.app-test.js | 1 + .../test-eagerly-load/imports/foo.test.js | 1 + tools/tests/apps/test-eagerly-load/index.js | 1 + tools/tests/test-modes.js | 79 +++++++++++++++++++ tools/tool-testing/selftest.js | 2 +- 10 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 tools/tests/apps/test-eagerly-load/.meteor/.gitignore create mode 100644 tools/tests/apps/test-eagerly-load/.meteor/packages create mode 100644 tools/tests/apps/test-eagerly-load/.meteor/release create mode 100644 tools/tests/apps/test-eagerly-load/imports/foo.app-test.js create mode 100644 tools/tests/apps/test-eagerly-load/imports/foo.test.js create mode 100644 tools/tests/apps/test-eagerly-load/index.js diff --git a/tools/cli/help.txt b/tools/cli/help.txt index 56b6b6226b..9f26e61c68 100644 --- a/tools/cli/help.txt +++ b/tools/cli/help.txt @@ -615,9 +615,8 @@ Options: test app rebuild. --extra-packages Run with additional packages (comma separated, for example: --extra-packages "package-name1, package-name2@1.2.3") - --driver-package Name of the optional test driver package to use to run - tests and display results. For example: - --driver-package practicalmeteor:mocha + --driver-package Test driver package to use to run tests and display results. + For example: --driver-package meteortesting:mocha >>> test Test the application diff --git a/tools/isobuild/test-files.js b/tools/isobuild/test-files.js index 399dcedc7b..fe6dcbea70 100644 --- a/tools/isobuild/test-files.js +++ b/tools/isobuild/test-files.js @@ -4,14 +4,18 @@ import { pathSep } from '../fs/files'; // We have two things "tests" and "app-tests". export const TEST_FILENAME_REGEXPS = [ // "*.test[s].*" or "*.spec[s].*" - /\.tests?./, - /\.specs?./, + /\.test\./, + /\.tests\./, + /\.spec\./, + /\.specs\./, ]; export const APP_TEST_FILENAME_REGEXPS = [ - // "*.app-tests.*" or "*.app-specs.*" - /\.app-tests?./, - /\.app-specs?./, + // "*.app-test[s].*" or "*.app-spec[s].*" + /\.app-test\./, + /\.app-tests\./, + /\.app-spec\./, + /\.app-specs\./, ]; // Given a path to a file in an app (relative to the app root diff --git a/tools/tests/apps/test-eagerly-load/.meteor/.gitignore b/tools/tests/apps/test-eagerly-load/.meteor/.gitignore new file mode 100644 index 0000000000..4083037423 --- /dev/null +++ b/tools/tests/apps/test-eagerly-load/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/tools/tests/apps/test-eagerly-load/.meteor/packages b/tools/tests/apps/test-eagerly-load/.meteor/packages new file mode 100644 index 0000000000..6029687b3b --- /dev/null +++ b/tools/tests/apps/test-eagerly-load/.meteor/packages @@ -0,0 +1,2 @@ +meteor-base +standard-minifiers diff --git a/tools/tests/apps/test-eagerly-load/.meteor/release b/tools/tests/apps/test-eagerly-load/.meteor/release new file mode 100644 index 0000000000..621e94f0ec --- /dev/null +++ b/tools/tests/apps/test-eagerly-load/.meteor/release @@ -0,0 +1 @@ +none diff --git a/tools/tests/apps/test-eagerly-load/imports/foo.app-test.js b/tools/tests/apps/test-eagerly-load/imports/foo.app-test.js new file mode 100644 index 0000000000..ec7d86d00c --- /dev/null +++ b/tools/tests/apps/test-eagerly-load/imports/foo.app-test.js @@ -0,0 +1 @@ +console.log('foo.app-test.js'); diff --git a/tools/tests/apps/test-eagerly-load/imports/foo.test.js b/tools/tests/apps/test-eagerly-load/imports/foo.test.js new file mode 100644 index 0000000000..f5195d8a74 --- /dev/null +++ b/tools/tests/apps/test-eagerly-load/imports/foo.test.js @@ -0,0 +1 @@ +console.log('foo.test.js'); diff --git a/tools/tests/apps/test-eagerly-load/index.js b/tools/tests/apps/test-eagerly-load/index.js new file mode 100644 index 0000000000..ec0ffd5d47 --- /dev/null +++ b/tools/tests/apps/test-eagerly-load/index.js @@ -0,0 +1 @@ +console.log('index.js'); diff --git a/tools/tests/test-modes.js b/tools/tests/test-modes.js index b7bfa213e7..5782af7034 100644 --- a/tools/tests/test-modes.js +++ b/tools/tests/test-modes.js @@ -1,4 +1,6 @@ var selftest = require('../tool-testing/selftest.js'); +import { isTestFilePath } from '../isobuild/test-files'; +const expectEqual = selftest.expectEqual; var Sandbox = selftest.Sandbox; selftest.define("'meteor test --port' accepts/rejects proper values", function () { @@ -28,3 +30,80 @@ selftest.define("'meteor test --port' accepts/rejects proper values", function ( run.match('App running at: http://[::]:3700/'); run.stop(); }); + +selftest.define("'meteor test' eagerly loads correct files", () => { + // Unit tests for test file match regexps + expectEqual(isTestFilePath('/foo.test.js'), true); + expectEqual(isTestFilePath('/foo.tests.js'), true); + expectEqual(isTestFilePath('/foo.spec.js'), true); + expectEqual(isTestFilePath('/foo.specs.js'), true); + expectEqual(isTestFilePath('/foo.test.bar.js'), true); + expectEqual(isTestFilePath('/foo.tests.bar.js'), true); + expectEqual(isTestFilePath('/foo.spec.bar.js'), true); + expectEqual(isTestFilePath('/foo.specs.bar.js'), true); + expectEqual(isTestFilePath('/foo.app-test.js'), true); + expectEqual(isTestFilePath('/foo.app-tests.js'), true); + expectEqual(isTestFilePath('/foo.app-spec.js'), true); + expectEqual(isTestFilePath('/foo.app-specs.js'), true); + expectEqual(isTestFilePath('/foo.app-test.bar.js'), true); + expectEqual(isTestFilePath('/foo.app-tests.bar.js'), true); + expectEqual(isTestFilePath('/foo.app-spec.bar.js'), true); + expectEqual(isTestFilePath('/foo.app-specs.bar.js'), true); + + // Regression tests for #9332 + expectEqual(isTestFilePath('/foo.testify.js'), false); + expectEqual(isTestFilePath('/foo.retest.js'), false); + expectEqual(isTestFilePath('/foo.spectacular.js'), false); + expectEqual(isTestFilePath('/foo.respec.js'), false); + expectEqual(isTestFilePath('/foo.testify.bar.js'), false); + expectEqual(isTestFilePath('/foo.retest.bar.js'), false); + expectEqual(isTestFilePath('/foo.spectacular.bar.js'), false); + expectEqual(isTestFilePath('/foo.respec.bar.js'), false); + expectEqual(isTestFilePath('/foo.app-testify.js'), false); + expectEqual(isTestFilePath('/foo.reapp-test.js'), false); + expectEqual(isTestFilePath('/foo.app-spectacular.js'), false); + expectEqual(isTestFilePath('/foo.reapp-spec.js'), false); + expectEqual(isTestFilePath('/foo.app-testify.bar.js'), false); + expectEqual(isTestFilePath('/foo.reapp-test.bar.js'), false); + expectEqual(isTestFilePath('/foo.app-spectacular.bar.js'), false); + expectEqual(isTestFilePath('/foo.reapp-spec.bar.js'), false); + + // Integration tests for test file eager loading with `meteor test` and + // `meteor test --full-app` + const s = new Sandbox(); + let run; + + s.createApp('myapp', 'test-eagerly-load'); + s.cd('myapp'); + s.set(''); + + // `meteor` should load app files, but not test files or app-test files + run = s.run(); + run.waitSecs(120); + run.match('index.js'); + run.stop(); + run.forbid('foo.test.js'); + run.forbid('foo.app-test.js'); + + // `meteor test` should load test files, but not app files or app-test files + run = s.run('test', '--driver-package', 'tmeasday:acceptance-test-driver'); + run.waitSecs(120); + run.match('foo.test.js'); + run.stop(); + run.forbid('index.js'); + run.forbid('foo.app-test.js'); + + // `meteor test --full-app` should load both test files and app-test files, + // but not test files + run = s.run( + 'test', + '--driver-package', + 'tmeasday:acceptance-test-driver', + '--full-app', + ); + run.waitSecs(120); + run.match('foo.app-test.js'); + run.match('index.js'); + run.stop(); + run.forbid('foo.test.js'); +}) diff --git a/tools/tool-testing/selftest.js b/tools/tool-testing/selftest.js index c646450774..ea0fa2ea84 100644 --- a/tools/tool-testing/selftest.js +++ b/tools/tool-testing/selftest.js @@ -1386,7 +1386,7 @@ export class Run { // // Example: // run = s.run("--help"); - // run.expectExit(1); // <<-- improtant to actually run the command + // run.expectExit(1); // <<-- important to actually run the command // run.forbidErr("unwanted string"); // <<-- important to run **after** the // // command ran the process. forbid(pattern) { From 9eb733d6bdcf5e82a5185ed276b9406c3e2dd242 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Fri, 24 Nov 2017 11:35:42 -0500 Subject: [PATCH 56/84] Add os.windows.x86_64 to meteor build --architecture help (#9413) The `meteor build --architecture` help was missing `os.windows.x86_64`. This commit adds it in and also updates an out of date comment in the source that referred to there only being 3 allowed architectures. --- tools/cli/commands.js | 5 ++--- tools/cli/help.txt | 17 +++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tools/cli/commands.js b/tools/cli/commands.js index 5ca218d2fa..7da06c5536 100644 --- a/tools/cli/commands.js +++ b/tools/cli/commands.js @@ -908,9 +908,8 @@ var buildCommand = function (options) { // of the file, not a constant 'bundle' (a bit obnoxious for // machines, but worth it for humans) - // Error handling for options.architecture. We must pass in only one of three - // architectures. See archinfo.js for more information on what the - // architectures are, what they mean, et cetera. + // Error handling for options.architecture. See archinfo.js for more + // information on what the architectures are, what they mean, et cetera. if (options.architecture && !_.has(archinfo.VALID_ARCHITECTURES, options.architecture)) { showInvalidArchMsg(options.architecture); diff --git a/tools/cli/help.txt b/tools/cli/help.txt index 9f26e61c68..80f99c9770 100644 --- a/tools/cli/help.txt +++ b/tools/cli/help.txt @@ -386,13 +386,14 @@ Options: --architecture Builds the server for a different architecture than your developer machine's architecture. Valid architectures include os.osx.x86_64, os.linux.x86_64, os.linux.x86_32, - and os.windows.x86_32. Note: This option selects the - architecture of the binary-dependent Atmosphere packages - you would like bundled into your application, when those - packages were specifically published for multiple - architectures (i.e. with meteor publish-for-arch). If - your project doesn't use any Atmosphere packages that - have binary dependencies, --architecture has no effect. + os.windows.x86_32, and os.windows.x86_64. Note: This + option selects the architecture of the binary-dependent + Atmosphere packages you would like bundled into your + application, when those packages were specifically + published for multiple architectures (i.e. with meteor + publish-for-arch). If your project doesn't use any + Atmosphere packages that have binary dependencies, + --architecture has no effect. --allow-incompatible-update Allow packages in your project to be upgraded or downgraded to versions that are potentially incompatible with the current versions, if required to satisfy all @@ -615,7 +616,7 @@ Options: test app rebuild. --extra-packages Run with additional packages (comma separated, for example: --extra-packages "package-name1, package-name2@1.2.3") - --driver-package Test driver package to use to run tests and display results. + --driver-package Test driver package to use to run tests and display results. For example: --driver-package meteortesting:mocha >>> test From 308692418be60eb37b3d5cedb4decb6b6be1b9e1 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 17:46:10 -0500 Subject: [PATCH 57/84] Upgrade Node to version 8.9.2. https://nodejs.org/en/blog/release/v8.9.2/ --- History.md | 4 ++++ scripts/build-dev-bundle-common.sh | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 00d64c1265..8555d6535e 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,9 @@ ## v.NEXT +## v1.6.0.1, 2017-12-08 + +* Node has been upgraded to version 8.9.2. + ## v1.6, 2017-10-30 * Node.js has been upgraded to version 8.8.1, which will be entering diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 9c65745ac8..0819163ef3 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -5,7 +5,7 @@ set -u UNAME=$(uname) ARCH=$(uname -m) -NODE_VERSION=8.8.1 +NODE_VERSION=8.9.2 MONGO_VERSION_64BIT=3.2.15 MONGO_VERSION_32BIT=3.2.15 NPM_VERSION=5.4.2 From 3ff79472a065441ccd1996eda031c4a64e50d95d Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 17:53:45 -0500 Subject: [PATCH 58/84] Upgrade npm to version 5.5.1. http://blog.npmjs.org/post/166044150500/v550-2017-10-04 --- History.md | 2 ++ scripts/build-dev-bundle-common.sh | 2 +- scripts/dev-bundle-tool-package.js | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 8555d6535e..f148b27c1b 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,8 @@ * Node has been upgraded to version 8.9.2. +* The `npm` package has ben upgraded to version 5.5.1. + ## v1.6, 2017-10-30 * Node.js has been upgraded to version 8.8.1, which will be entering diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 0819163ef3..e8623ece18 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -8,7 +8,7 @@ ARCH=$(uname -m) NODE_VERSION=8.9.2 MONGO_VERSION_64BIT=3.2.15 MONGO_VERSION_32BIT=3.2.15 -NPM_VERSION=5.4.2 +NPM_VERSION=5.5.1 # If we built Node from source on Jenkins, this is the build number. NODE_BUILD_NUMBER=111 diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index fdde521a2d..21f68a38cf 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: "5.4.2", + npm: "5.5.1", pacote: "https://github.com/meteor/pacote/tarball/4e58fa55e2a0ba7dc75b26ff5273730d98335a85", "node-gyp": "3.6.2", "node-pre-gyp": "0.6.36", From 5d4e480d209e30852a3892bc4f142083e43c5097 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 18:07:30 -0500 Subject: [PATCH 59/84] Bump $BUNDLE_VERSION to 8.9.6 before rebuilding dev bundle. Versions 8.9.0-5 had already been used on branch release-1.6.1. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 8c40c4bd26..2846f6dea1 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=8.8.1 +BUNDLE_VERSION=8.9.6 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From bd91cbef871fa7144e112d4407fb2ba8a903f93c Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 18:43:39 -0500 Subject: [PATCH 60/84] Add @babel/runtime to dev bundle and update npm dependencies. These are the same versions currently on release-1.6.1. --- scripts/dev-bundle-tool-package.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 21f68a38cf..fbbaac20bd 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -12,15 +12,18 @@ var packageJson = { // 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: "5.5.1", - pacote: "https://github.com/meteor/pacote/tarball/4e58fa55e2a0ba7dc75b26ff5273730d98335a85", + pacote: "https://github.com/meteor/pacote/tarball/dea6a20a68057237a498f6c047e9b3ecf5df749d", "node-gyp": "3.6.2", "node-pre-gyp": "0.6.36", - "meteor-babel": "7.0.0-beta.3-1", + "meteor-babel": "7.0.0-beta.34-1", "meteor-promise": "0.8.6", promise: "8.0.1", - reify: "0.12.3", + reify: "0.13.1", fibers: "2.0.0", - // So that Babel 6 can emit require("babel-runtime/helpers/...") calls. + // So that Babel can emit require("@babel/runtime/helpers/...") calls. + "@babel/runtime": "7.0.0-beta.34", + // For backwards compatibility with isopackets that still depend on + // babel-runtime rather than @babel/runtime. "babel-runtime": "7.0.0-beta.3", // 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 From 1139c74d6368ee1c7c9eb1d061e707f01e16c362 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 18:44:36 -0500 Subject: [PATCH 61/84] Bump $BUNDLE_VERSION to 8.9.7 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 2846f6dea1..5c624c58d4 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=8.9.6 +BUNDLE_VERSION=8.9.7 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From e49c632316cad45d135aee7837d9cd84ee40dd5b Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 18:53:27 -0500 Subject: [PATCH 62/84] Bump package versions for 1.6.0.1-beta.0 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 2d2fcb5841..45f1de0e00 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.6.0' + version: '1.6.0-1-beta.0' }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 1036283268..33f26ac959 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,7 +1,7 @@ { - "track": "METEOR", - "version": "1.6-rc.18", - "recommended": false, - "official": false, - "description": "Meteor" + "track": "METEOR", + "version": "1.6.0.1-beta.0", + "recommended": false, + "official": false, + "description": "Meteor" } From 58bdfe024d5f0da2a26153638f56f85ff0cdb002 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 13 Nov 2017 15:53:11 -0500 Subject: [PATCH 63/84] Shallow-clone inserted documents more reliably. In a previous commit, I changed doc = _.extend({}, doc); to avoid using underscore, thus: doc = { ...doc }; While this may seem harmless, it broke a few Mongo.Collection tests because _.extend copies *all* properties, both own and inherited, whereas object ...spread only copies own properties. However, the correct way to fix this problem is *not* to revert to the old behavior, since flattening the inherited properties of a document was never actually what we wanted. The old behavior was subtly broken, too. Instead, we need to create a new object with the same prototoype as the provided document, then shallow-copy the own properties. Any properties or methods inherited from the original prototype will then be available on the new object, even though they didn't get copied over. I've intentionally left some trivial formatting changes in this commit to remind myself which broken tests were fixed by this change. --- packages/mongo/collection.js | 14 ++++++++++---- packages/mongo/mongo_livedata_tests.js | 12 +++++++++--- packages/mongo/package.js | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/mongo/collection.js b/packages/mongo/collection.js index 6a1a6906a4..9793e4a57d 100644 --- a/packages/mongo/collection.js +++ b/packages/mongo/collection.js @@ -429,12 +429,18 @@ Mongo.Collection.prototype.insert = function insert(doc, callback) { throw new Error("insert requires an argument"); } - // Shallow-copy the document and possibly generate an ID - doc = _.extend({}, doc); + // Make a shallow clone of the document, preserving its prototype. + doc = Object.create( + Object.getPrototypeOf(doc), + Object.getOwnPropertyDescriptors(doc) + ); if ('_id' in doc) { - if (!doc._id || !(typeof doc._id === 'string' || doc._id instanceof Mongo.ObjectID)) { - throw new Error("Meteor requires document _id fields to be non-empty strings or ObjectIDs"); + if (! doc._id || + ! (typeof doc._id === 'string' || + doc._id instanceof Mongo.ObjectID)) { + throw new Error( + "Meteor requires document _id fields to be non-empty strings or ObjectIDs"); } } else { let generateId = true; diff --git a/packages/mongo/mongo_livedata_tests.js b/packages/mongo/mongo_livedata_tests.js index 932b98caca..98ef9955a2 100644 --- a/packages/mongo/mongo_livedata_tests.js +++ b/packages/mongo/mongo_livedata_tests.js @@ -1507,7 +1507,9 @@ testAsyncMulti('mongo-livedata - document with a custom type, ' + idGeneration, Meteor.call('createInsecureCollection', this.collectionName, collectionOptions); Meteor.subscribe('c-' + this.collectionName, expect()); } - }, function (test, expect) { + }, + + function (test, expect) { var self = this; self.coll = new Mongo.Collection(this.collectionName, collectionOptions); var docId; @@ -1525,13 +1527,17 @@ testAsyncMulti('mongo-livedata - document with a custom type, ' + idGeneration, test.isTrue(inColl); inColl && test.equal(inColl.d.speak(), "woof"); })); - }, function (test, expect) { + }, + + function (test, expect) { var self = this; self.coll.insert(new Dog("rover", "orange"), expect(function (err, id) { test.isTrue(err); test.isFalse(id); })); - }, function (test, expect) { + }, + + function (test, expect) { var self = this; self.coll.update( self.docId, new Dog("rover", "orange"), expect(function (err) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 85c5a094fd..a765a8052f 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.2.2' + version: '1.2.3' }); Npm.depends({ From 9c53e186d4ab1dec0dd8f9c979c36e3df8b6d064 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 13 Nov 2017 15:53:11 -0500 Subject: [PATCH 64/84] Shallow-clone inserted documents more reliably. In a previous commit, I changed doc = _.extend({}, doc); to avoid using underscore, thus: doc = { ...doc }; While this may seem harmless, it broke a few Mongo.Collection tests because _.extend copies *all* properties, both own and inherited, whereas object ...spread only copies own properties. However, the correct way to fix this problem is *not* to revert to the old behavior, since flattening the inherited properties of a document was never actually what we wanted. The old behavior was subtly broken, too. Instead, we need to create a new object with the same prototoype as the provided document, then shallow-copy the own properties. Any properties or methods inherited from the original prototype will then be available on the new object, even though they didn't get copied over. I've intentionally left some trivial formatting changes in this commit to remind myself which broken tests were fixed by this change. --- packages/mongo/collection.js | 14 ++++++++++---- packages/mongo/mongo_livedata_tests.js | 12 +++++++++--- packages/mongo/package.js | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/mongo/collection.js b/packages/mongo/collection.js index 000e84e850..155e3e5a58 100644 --- a/packages/mongo/collection.js +++ b/packages/mongo/collection.js @@ -468,12 +468,18 @@ Mongo.Collection.prototype.insert = function insert(doc, callback) { throw new Error("insert requires an argument"); } - // Shallow-copy the document and possibly generate an ID - doc = _.extend({}, doc); + // Make a shallow clone of the document, preserving its prototype. + doc = Object.create( + Object.getPrototypeOf(doc), + Object.getOwnPropertyDescriptors(doc) + ); if ('_id' in doc) { - if (!doc._id || !(typeof doc._id === 'string' || doc._id instanceof Mongo.ObjectID)) { - throw new Error("Meteor requires document _id fields to be non-empty strings or ObjectIDs"); + if (! doc._id || + ! (typeof doc._id === 'string' || + doc._id instanceof Mongo.ObjectID)) { + throw new Error( + "Meteor requires document _id fields to be non-empty strings or ObjectIDs"); } } else { let generateId = true; diff --git a/packages/mongo/mongo_livedata_tests.js b/packages/mongo/mongo_livedata_tests.js index 09759f0097..5d2bfdaec8 100644 --- a/packages/mongo/mongo_livedata_tests.js +++ b/packages/mongo/mongo_livedata_tests.js @@ -1484,7 +1484,9 @@ testAsyncMulti('mongo-livedata - document with a custom type, ' + idGeneration, Meteor.call('createInsecureCollection', this.collectionName, collectionOptions); Meteor.subscribe('c-' + this.collectionName, expect()); } - }, function (test, expect) { + }, + + function (test, expect) { var self = this; self.coll = new Mongo.Collection(this.collectionName, collectionOptions); var docId; @@ -1502,13 +1504,17 @@ testAsyncMulti('mongo-livedata - document with a custom type, ' + idGeneration, test.isTrue(inColl); inColl && test.equal(inColl.d.speak(), "woof"); })); - }, function (test, expect) { + }, + + function (test, expect) { var self = this; self.coll.insert(new Dog("rover", "orange"), expect(function (err, id) { test.isTrue(err); test.isFalse(id); })); - }, function (test, expect) { + }, + + function (test, expect) { var self = this; self.coll.update( self.docId, new Dog("rover", "orange"), expect(function (err) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 0c442d6e42..bb9a4dcb06 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.23' }); Npm.depends({ From cfd4cc4d9c3a135fa1cd80d1c63aada8fdcd3633 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 19:52:43 -0500 Subject: [PATCH 65/84] Bump $BUNDLE_VERSION to 4.8.45 before rebuilding dev bundle. This dev bundle version bump is just to make sure nothing significant has changed about transitive node_modules dependencies since last time, before we bump the Node version for the 1.5.4.1 release. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 71dd736df0..85b7bdf65d 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.44 +BUNDLE_VERSION=4.8.45 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 6c7531de460b55c7e7a8925858f3e9ffd097b884 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 20:16:28 -0500 Subject: [PATCH 66/84] Update expected dev bundle tarball count from 4 to 5. --- scripts/admin/copy-dev-bundle-from-jenkins.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/admin/copy-dev-bundle-from-jenkins.sh b/scripts/admin/copy-dev-bundle-from-jenkins.sh index af7cb75829..44a9b702e4 100755 --- a/scripts/admin/copy-dev-bundle-from-jenkins.sh +++ b/scripts/admin/copy-dev-bundle-from-jenkins.sh @@ -39,7 +39,7 @@ echo Found build $DIRNAME trap "echo Found surprising number of tarballs." EXIT # Check to make sure the proper number of each kind of file is there. aws s3 ls s3://com.meteor.jenkins/$DIRNAME/ | \ - perl -nle 'if (/\.tar\.gz/) { ++$TAR } else { die "something weird" } END { exit !($TAR == 4) }' + perl -nle 'if (/\.tar\.gz/) { ++$TAR } else { die "something weird" } END { exit !($TAR == 5) }' trap - EXIT From 7d9ee28efc43937e125a13de0feb797eb4e7b465 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 20:16:44 -0500 Subject: [PATCH 67/84] Bump package versions for 1.5.4.1-beta.0 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 19ea4363d8..4718dbc6b7 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.4" + version: "1.5.4-1-beta.0" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 4a1f821563..aa36a70d17 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,7 +1,7 @@ { - "track": "METEOR", - "version": "1.5.4-rc.0", - "recommended": false, - "official": false, - "description": "Meteor" + "track": "METEOR", + "version": "1.5.4.1-beta.0", + "recommended": false, + "official": false, + "description": "Meteor" } From 026b2983142bd17b1e6e0a4dc732fdada77906c9 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 20:23:09 -0500 Subject: [PATCH 68/84] Upgrade Node to version 4.8.6. https://nodejs.org/en/blog/release/v4.8.6/ --- History.md | 4 ++++ scripts/build-dev-bundle-common.sh | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0eff27a71a..a320906a86 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,9 @@ ## v.NEXT +## v1.4.4.5, 2017-12-08 + +* Node has been upgraded to version 4.8.6. + ## v1.4.4.3, 2017-05-22 * Node has been upgraded to version 4.8.3. diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index da0f8253f9..c792ea6167 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.3 +NODE_VERSION=4.8.6 NPM_VERSION=4.5.0 if [ "$UNAME" == "Linux" ] ; then From e5b8c431e3eb5f1f5122f60141aacabc177bb03c Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 20:23:58 -0500 Subject: [PATCH 69/84] Bump $BUNDLE_VERSION to 4.7.28 before rebuilding dev bundle. These Node and dev bundle version bumps are just to make sure nothing significant has changed since last time, before we bump the Node version again for the 1.4.4.5 release. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 500777dcdd..eee56ab784 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.7.27 +BUNDLE_VERSION=4.7.28 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 2594470e07582763eaa299893dc4dc2ca8fe6f63 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 20:39:55 -0500 Subject: [PATCH 70/84] Avoid using Object.getOwnPropertyDescriptors to clone inserted documents. --- packages/mongo/collection.js | 6 +++--- packages/mongo/package.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/mongo/collection.js b/packages/mongo/collection.js index 155e3e5a58..68d1f167f0 100644 --- a/packages/mongo/collection.js +++ b/packages/mongo/collection.js @@ -469,9 +469,9 @@ Mongo.Collection.prototype.insert = function insert(doc, callback) { } // Make a shallow clone of the document, preserving its prototype. - doc = Object.create( - Object.getPrototypeOf(doc), - Object.getOwnPropertyDescriptors(doc) + doc = Object.assign( + Object.create(Object.getPrototypeOf(doc)), + doc ); if ('_id' in doc) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index bb9a4dcb06..2636cd18db 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.23' + version: '1.1.24' }); Npm.depends({ From 0b89e7a23598d48e19dda3be3804f6e660a51696 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 20:45:37 -0500 Subject: [PATCH 71/84] Bump package versions for 1.4.4.5-beta.0 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 11b63bb0cc..f2b757d0b5 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-4-rc.0" + version: "1.4.4-5-beta.0" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 358d96f1eb..05d498e754 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.4-rc.0", + "version": "1.4.4.5-beta.0", "recommended": false, "official": false, "description": "Meteor" From 40787c1a51a21eba9f99b2a671ed91386dd0dd76 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 7 Dec 2017 20:16:28 -0500 Subject: [PATCH 72/84] Update expected dev bundle tarball count from 4 to 5. --- scripts/admin/copy-dev-bundle-from-jenkins.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/admin/copy-dev-bundle-from-jenkins.sh b/scripts/admin/copy-dev-bundle-from-jenkins.sh index af7cb75829..44a9b702e4 100755 --- a/scripts/admin/copy-dev-bundle-from-jenkins.sh +++ b/scripts/admin/copy-dev-bundle-from-jenkins.sh @@ -39,7 +39,7 @@ echo Found build $DIRNAME trap "echo Found surprising number of tarballs." EXIT # Check to make sure the proper number of each kind of file is there. aws s3 ls s3://com.meteor.jenkins/$DIRNAME/ | \ - perl -nle 'if (/\.tar\.gz/) { ++$TAR } else { die "something weird" } END { exit !($TAR == 4) }' + perl -nle 'if (/\.tar\.gz/) { ++$TAR } else { die "something weird" } END { exit !($TAR == 5) }' trap - EXIT From dfd8511e4eaf6c160e4aefa3ed44890a7e76e365 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 11:47:53 -0500 Subject: [PATCH 73/84] Upgrade Node to version 8.9.3. https://nodejs.org/en/blog/release/v8.9.3/ https://nodejs.org/en/blog/vulnerability/december-2017-security-releases/ --- History.md | 4 +++- scripts/build-dev-bundle-common.sh | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index f148b27c1b..0f2276dd4d 100644 --- a/History.md +++ b/History.md @@ -2,7 +2,9 @@ ## v1.6.0.1, 2017-12-08 -* Node has been upgraded to version 8.9.2. +* Node has been upgraded to version + [8.9.3](https://nodejs.org/en/blog/release/v8.9.3/), an important + [security release](https://nodejs.org/en/blog/vulnerability/december-2017-security-releases/). * The `npm` package has ben upgraded to version 5.5.1. diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index e8623ece18..920f3b5afb 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -5,7 +5,7 @@ set -u UNAME=$(uname) ARCH=$(uname -m) -NODE_VERSION=8.9.2 +NODE_VERSION=8.9.3 MONGO_VERSION_64BIT=3.2.15 MONGO_VERSION_32BIT=3.2.15 NPM_VERSION=5.5.1 From ea9f9697744a5320389d27913dac5fb8580a3d03 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 11:48:39 -0500 Subject: [PATCH 74/84] Bump $BUNDLE_VERSION to 8.9.8 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 5c624c58d4..5d31dae2ec 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=8.9.7 +BUNDLE_VERSION=8.9.8 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 9e4010a1ba188aa999107115a54bbbf0708e4588 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 11:52:52 -0500 Subject: [PATCH 75/84] Upgrade Node to version 4.9.7. https://nodejs.org/en/blog/release/v4.9.7/ https://nodejs.org/en/blog/vulnerability/december-2017-security-releases/ --- History.md | 6 ++++++ scripts/build-dev-bundle-common.sh | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 32382de094..049290c067 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +## v1.5.4.1, 2017-12-08 + +* Node has been upgraded to version + [4.8.7](https://nodejs.org/en/blog/release/v4.8.7/), an important + [security release](https://nodejs.org/en/blog/vulnerability/december-2017-security-releases/). + ## v1.5.4, 2017-11-08 * Node has been updated to version 4.8.6. This release officially diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 5857646f75..a794ec8e9d 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.15 -NODE_VERSION=4.8.6 +NODE_VERSION=4.8.7 NPM_VERSION=4.6.1 # If we built Node from source on Jenkins, this is the build number. From 062fcad856543cbf62915b5f8a5a52a54c8cb37a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 11:53:47 -0500 Subject: [PATCH 76/84] Bump $BUNDLE_VERSION to 4.8.46 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index 85b7bdf65d..b56a22bb35 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.8.45 +BUNDLE_VERSION=4.8.46 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From feb68df4d686af748174370a2314a9c744a07421 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 12:10:11 -0500 Subject: [PATCH 77/84] Bump package versions for 1.6.0.1-rc.0 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 45f1de0e00..9e56fab39a 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.6.0-1-beta.0' + version: '1.6.0-1-rc.0' }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 33f26ac959..c1e7ed8a88 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.6.0.1-beta.0", + "version": "1.6.0.1-rc.0", "recommended": false, "official": false, "description": "Meteor" From 44ade416b1af38d51397a0af76b76e1986af02a8 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 12:40:28 -0500 Subject: [PATCH 78/84] Bump package versions for 1.5.4.1-rc.0 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 4718dbc6b7..a0e083e0b6 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.4-1-beta.0" + version: "1.5.4-1-rc.0" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index aa36a70d17..39b481e41d 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5.4.1-beta.0", + "version": "1.5.4.1-rc.0", "recommended": false, "official": false, "description": "Meteor" From a436fde10968216d2fd1fb425c1ded7997ca7ffc Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 13:35:15 -0500 Subject: [PATCH 79/84] Bump package versions for the official 1.5.4.1 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-official.json | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index a0e083e0b6..e53a9a475e 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.4-1-rc.0" + version: "1.5.4_1" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index 024ef29517..99fafed4a7 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,8 +1,16 @@ { "track": "METEOR", - "version": "1.5.4", + "version": "1.5.4.1", "recommended": false, "official": true, - "patchFrom": ["1.5", "1.5.1", "1.5.2", "1.5.2.1", "1.5.2.2", "1.5.3"], + "patchFrom": [ + "1.5", + "1.5.1", + "1.5.2", + "1.5.2.1", + "1.5.2.2", + "1.5.3", + "1.5.4" + ], "description": "The Official Meteor Distribution" } From 5533aa7ce86f8cbeb8e770ebeb9fb5909b399b1f Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 14:19:21 -0500 Subject: [PATCH 80/84] Bump package versions for the official 1.6.0.1 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-official.json | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 9e56fab39a..be828ee23c 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.6.0-1-rc.0' + version: '1.6.0_1' }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index a45e446e7c..45bbf461f9 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,7 +1,10 @@ { "track": "METEOR", - "version": "1.6", + "version": "1.6.0.1", "recommended": false, "official": true, + "patchFrom": [ + "1.6" + ], "description": "The Official Meteor Distribution" } From 04ca53a9589b9d1926400c062f9db809cc066be3 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 14:31:56 -0500 Subject: [PATCH 81/84] Fix typo in History.md. --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 0f2276dd4d..c0a1da31b2 100644 --- a/History.md +++ b/History.md @@ -6,7 +6,7 @@ [8.9.3](https://nodejs.org/en/blog/release/v8.9.3/), an important [security release](https://nodejs.org/en/blog/vulnerability/december-2017-security-releases/). -* The `npm` package has ben upgraded to version 5.5.1. +* The `npm` package has been upgraded to version 5.5.1. ## v1.6, 2017-10-30 From 2d8f006ce0220409ac2bb7b8d33c913e431143b7 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 16:05:39 -0500 Subject: [PATCH 82/84] Upgrade Node to version 4.9.7. https://nodejs.org/en/blog/release/v4.9.7/ https://nodejs.org/en/blog/vulnerability/december-2017-security-releases/ --- History.md | 4 +++- scripts/build-dev-bundle-common.sh | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index a320906a86..47656189af 100644 --- a/History.md +++ b/History.md @@ -2,7 +2,9 @@ ## v1.4.4.5, 2017-12-08 -* Node has been upgraded to version 4.8.6. +* Node has been upgraded to version + [4.8.7](https://nodejs.org/en/blog/release/v4.8.7/), an important + [security release](https://nodejs.org/en/blog/vulnerability/december-2017-security-releases/). ## v1.4.4.3, 2017-05-22 diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index c792ea6167..faa57709ae 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.6 +NODE_VERSION=4.8.7 NPM_VERSION=4.5.0 if [ "$UNAME" == "Linux" ] ; then From 5ffa98e32705606489202888223455bc6e3ab71a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 16:06:19 -0500 Subject: [PATCH 83/84] Bump $BUNDLE_VERSION to 4.7.29 before rebuilding dev bundle. --- meteor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor b/meteor index eee56ab784..c1f3ab8755 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=4.7.28 +BUNDLE_VERSION=4.7.29 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. From 80d46d2e1834fd80e59f2f554dba9f6aef6385c3 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Dec 2017 16:36:06 -0500 Subject: [PATCH 84/84] Bump package versions for the official 1.4.4.5 release. --- packages/meteor-tool/package.js | 2 +- scripts/admin/meteor-release-official.json | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index f2b757d0b5..9520d920e3 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-5-beta.0" + version: "1.4.4_5" }); Package.includeTool(); diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index d1e963fd87..54d7e1b18b 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,8 +1,24 @@ { "track": "METEOR", - "version": "1.4.4.3", + "version": "1.4.4.5", "recommended": false, "official": true, - "patchFrom": ["1.4.4.2"], + "patchFrom": [ + "1.4", + "1.4.0.1", + "1.4.1", + "1.4.1.1", + "1.4.1.2", + "1.4.1.3", + "1.4.2", + "1.4.2.1", + "1.4.2.3", + "1.4.2.7", + "1.4.3.1", + "1.4.3.2", + "1.4.4.1", + "1.4.4.3", + "1.4.4.4" + ], "description": "The Official Meteor Distribution" }