205 lines
17 KiB
JavaScript
205 lines
17 KiB
JavaScript
|
//////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// This is a generated file. You can view the original //
|
||
|
// source in your browser if your browser supports source maps. //
|
||
|
// //
|
||
|
// If you are using Chrome, open the Developer Tools and click the gear //
|
||
|
// icon in its lower right corner. In the General Settings panel, turn //
|
||
|
// on 'Enable source maps'. //
|
||
|
// //
|
||
|
// If you are using Firefox 23, go to `about:config` and set the //
|
||
|
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||
|
// (The preference should be on by default in Firefox 24; versions //
|
||
|
// older than 23 do not support source maps.) //
|
||
|
// //
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
(function () {
|
||
|
|
||
|
/* Imports */
|
||
|
var Meteor = Package.meteor.Meteor;
|
||
|
var Tracker = Package.tracker.Tracker;
|
||
|
var Deps = Package.tracker.Deps;
|
||
|
var Retry = Package.retry.Retry;
|
||
|
var DDP = Package.ddp.DDP;
|
||
|
var Mongo = Package.mongo.Mongo;
|
||
|
var _ = Package.underscore._;
|
||
|
|
||
|
/* Package-scope variables */
|
||
|
var Autoupdate, ClientVersions;
|
||
|
|
||
|
(function () {
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// packages/autoupdate/autoupdate_client.js //
|
||
|
// //
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Subscribe to the `meteor_autoupdate_clientVersions` collection, // 1
|
||
|
// which contains the set of acceptable client versions. // 2
|
||
|
// // 3
|
||
|
// A "hard code push" occurs when the running client version is not in // 4
|
||
|
// the set of acceptable client versions (or the server updates the // 5
|
||
|
// collection, there is a published client version marked `current` and // 6
|
||
|
// the running client version is no longer in the set). // 7
|
||
|
// // 8
|
||
|
// When the `reload` package is loaded, a hard code push causes // 9
|
||
|
// the browser to reload, so that it will load the latest client // 10
|
||
|
// version from the server. // 11
|
||
|
// // 12
|
||
|
// A "soft code push" represents the situation when the running client // 13
|
||
|
// version is in the set of acceptable versions, but there is a newer // 14
|
||
|
// version available on the server. // 15
|
||
|
// // 16
|
||
|
// `Autoupdate.newClientAvailable` is a reactive data source which // 17
|
||
|
// becomes `true` if there is a new version of the client is available on // 18
|
||
|
// the server. // 19
|
||
|
// // 20
|
||
|
// This package doesn't implement a soft code reload process itself, // 21
|
||
|
// but `newClientAvailable` could be used for example to display a // 22
|
||
|
// "click to reload" link to the user. // 23
|
||
|
// 24
|
||
|
// The client version of the client code currently running in the // 25
|
||
|
// browser. // 26
|
||
|
var autoupdateVersion = __meteor_runtime_config__.autoupdateVersion || "unknown"; // 27
|
||
|
var autoupdateVersionRefreshable = // 28
|
||
|
__meteor_runtime_config__.autoupdateVersionRefreshable || "unknown"; // 29
|
||
|
// 30
|
||
|
// The collection of acceptable client versions. // 31
|
||
|
ClientVersions = new Mongo.Collection("meteor_autoupdate_clientVersions"); // 32
|
||
|
// 33
|
||
|
Autoupdate = {}; // 34
|
||
|
// 35
|
||
|
Autoupdate.newClientAvailable = function () { // 36
|
||
|
return !! ClientVersions.findOne({ // 37
|
||
|
_id: "version", // 38
|
||
|
version: {$ne: autoupdateVersion} }) || // 39
|
||
|
!! ClientVersions.findOne({ // 40
|
||
|
_id: "version-refreshable", // 41
|
||
|
version: {$ne: autoupdateVersionRefreshable} }); // 42
|
||
|
}; // 43
|
||
|
// 44
|
||
|
var knownToSupportCssOnLoad = false; // 45
|
||
|
// 46
|
||
|
var retry = new Retry({ // 47
|
||
|
// Unlike the stream reconnect use of Retry, which we want to be instant // 48
|
||
|
// in normal operation, this is a wacky failure. We don't want to retry // 49
|
||
|
// right away, we can start slowly. // 50
|
||
|
// // 51
|
||
|
// A better way than timeconstants here might be to use the knowledge // 52
|
||
|
// of when we reconnect to help trigger these retries. Typically, the // 53
|
||
|
// server fixing code will result in a restart and reconnect, but // 54
|
||
|
// potentially the subscription could have a transient error. // 55
|
||
|
minCount: 0, // don't do any immediate retries // 56
|
||
|
baseTimeout: 30*1000 // start with 30s // 57
|
||
|
}); // 58
|
||
|
var failures = 0; // 59
|
||
|
// 60
|
||
|
Autoupdate._retrySubscription = function () { // 61
|
||
|
Meteor.subscribe("meteor_autoupdate_clientVersions", { // 62
|
||
|
onError: function (error) { // 63
|
||
|
Meteor._debug("autoupdate subscription failed:", error); // 64
|
||
|
failures++; // 65
|
||
|
retry.retryLater(failures, function () { // 66
|
||
|
// Just retry making the subscription, don't reload the whole // 67
|
||
|
// page. While reloading would catch more cases (for example, // 68
|
||
|
// the server went back a version and is now doing old-style hot // 69
|
||
|
// code push), it would also be more prone to reload loops, // 70
|
||
|
// which look really bad to the user. Just retrying the // 71
|
||
|
// subscription over DDP means it is at least possible to fix by // 72
|
||
|
// updating the server. // 73
|
||
|
Autoupdate._retrySubscription(); // 74
|
||
|
}); // 75
|
||
|
}, // 76
|
||
|
onReady: function () { // 77
|
||
|
if (Package.reload) { // 78
|
||
|
var checkNewVersionDocument = function (doc) { // 79
|
||
|
var self = this; // 80
|
||
|
if (doc._id === 'version-refreshable' && // 81
|
||
|
doc.version !== autoupdateVersionRefreshable) { // 82
|
||
|
autoupdateVersionRefreshable = doc.version; // 83
|
||
|
// Switch out old css links for the new css links. Inspired by: // 84
|
||
|
// https://github.com/guard/guard-livereload/blob/master/js/livereload.js#L710 // 85
|
||
|
var newCss = (doc.assets && doc.assets.allCss) || []; // 86
|
||
|
var oldLinks = []; // 87
|
||
|
_.each(document.getElementsByTagName('link'), function (link) { // 88
|
||
|
if (link.className === '__meteor-css__') { // 89
|
||
|
oldLinks.push(link); // 90
|
||
|
} // 91
|
||
|
}); // 92
|
||
|
// 93
|
||
|
var waitUntilCssLoads = function (link, callback) { // 94
|
||
|
var executeCallback = _.once(callback); // 95
|
||
|
link.onload = function () { // 96
|
||
|
knownToSupportCssOnLoad = true; // 97
|
||
|
executeCallback(); // 98
|
||
|
}; // 99
|
||
|
if (! knownToSupportCssOnLoad) { // 100
|
||
|
var id = Meteor.setInterval(function () { // 101
|
||
|
if (link.sheet) { // 102
|
||
|
executeCallback(); // 103
|
||
|
Meteor.clearInterval(id); // 104
|
||
|
} // 105
|
||
|
}, 50); // 106
|
||
|
} // 107
|
||
|
}; // 108
|
||
|
// 109
|
||
|
var removeOldLinks = _.after(newCss.length, function () { // 110
|
||
|
_.each(oldLinks, function (oldLink) { // 111
|
||
|
oldLink.parentNode.removeChild(oldLink); // 112
|
||
|
}); // 113
|
||
|
}); // 114
|
||
|
// 115
|
||
|
var attachStylesheetLink = function (newLink) { // 116
|
||
|
document.getElementsByTagName("head").item(0).appendChild(newLink); // 117
|
||
|
// 118
|
||
|
waitUntilCssLoads(newLink, function () { // 119
|
||
|
Meteor.setTimeout(removeOldLinks, 200); // 120
|
||
|
}); // 121
|
||
|
}; // 122
|
||
|
// 123
|
||
|
if (newCss.length !== 0) { // 124
|
||
|
_.each(newCss, function (css) { // 125
|
||
|
var newLink = document.createElement("link"); // 126
|
||
|
newLink.setAttribute("rel", "stylesheet"); // 127
|
||
|
newLink.setAttribute("type", "text/css"); // 128
|
||
|
newLink.setAttribute("class", "__meteor-css__"); // 129
|
||
|
newLink.setAttribute("href", Meteor._relativeToSiteRootUrl(css.url)); // 130
|
||
|
attachStylesheetLink(newLink); // 131
|
||
|
}); // 132
|
||
|
} else { // 133
|
||
|
removeOldLinks(); // 134
|
||
|
} // 135
|
||
|
// 136
|
||
|
} // 137
|
||
|
else if (doc._id === 'version' && doc.version !== autoupdateVersion) { // 138
|
||
|
handle && handle.stop(); // 139
|
||
|
Package.reload.Reload._reload(); // 140
|
||
|
} // 141
|
||
|
}; // 142
|
||
|
// 143
|
||
|
var handle = ClientVersions.find().observe({ // 144
|
||
|
added: checkNewVersionDocument, // 145
|
||
|
changed: checkNewVersionDocument // 146
|
||
|
}); // 147
|
||
|
} // 148
|
||
|
} // 149
|
||
|
}); // 150
|
||
|
}; // 151
|
||
|
Autoupdate._retrySubscription(); // 152
|
||
|
// 153
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
}).call(this);
|
||
|
|
||
|
|
||
|
/* Exports */
|
||
|
if (typeof Package === 'undefined') Package = {};
|
||
|
Package.autoupdate = {
|
||
|
Autoupdate: Autoupdate
|
||
|
};
|
||
|
|
||
|
})();
|