1350 lines
45 KiB
JavaScript
1350 lines
45 KiB
JavaScript
//////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// This is a generated file. You can view the original //
|
|
// source in your browser if your browser supports source maps. //
|
|
// Source maps are supported by all recent versions of Chrome, Safari, //
|
|
// and Firefox, and by Internet Explorer 11. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
(function () {
|
|
|
|
/* Package-scope variables */
|
|
var global, meteorEnv, Meteor;
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/global.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Export a reliable global object for all Meteor code.
|
|
global = this;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/client_environment.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
var config = __meteor_runtime_config__;
|
|
meteorEnv = config.meteorEnv;
|
|
|
|
/**
|
|
* @summary The Meteor namespace
|
|
* @namespace Meteor
|
|
*/
|
|
Meteor = {
|
|
/**
|
|
* @summary Boolean variable. True if running in production environment.
|
|
* @locus Anywhere
|
|
* @static
|
|
* @type {Boolean}
|
|
*/
|
|
isProduction: meteorEnv.NODE_ENV === "production",
|
|
|
|
/**
|
|
* @summary Boolean variable. True if running in development environment.
|
|
* @locus Anywhere
|
|
* @static
|
|
* @type {Boolean}
|
|
*/
|
|
isDevelopment: meteorEnv.NODE_ENV !== "production",
|
|
|
|
/**
|
|
* @summary Boolean variable. True if running in client environment.
|
|
* @locus Anywhere
|
|
* @static
|
|
* @type {Boolean}
|
|
*/
|
|
isClient: true,
|
|
|
|
/**
|
|
* @summary Boolean variable. True if running in server environment.
|
|
* @locus Anywhere
|
|
* @static
|
|
* @type {Boolean}
|
|
*/
|
|
isServer: false,
|
|
|
|
/**
|
|
* @summary Boolean variable. True if running in Cordova environment.
|
|
* @locus Anywhere
|
|
* @static
|
|
* @type {Boolean}
|
|
*/
|
|
isCordova: false,
|
|
|
|
/**
|
|
* @summary Boolean variable. True if running in a "modern" JS
|
|
* environment, as determined by the `modern` package.
|
|
* @locus Anywhere
|
|
* @static
|
|
* @type {Boolean}
|
|
*/
|
|
isModern: config.isModern
|
|
};
|
|
|
|
if (config.PUBLIC_SETTINGS) {
|
|
/**
|
|
* @summary `Meteor.settings` contains deployment-specific configuration options. You can initialize settings by passing the `--settings` option (which takes the name of a file containing JSON data) to `meteor run` or `meteor deploy`. When running your server directly (e.g. from a bundle), you instead specify settings by putting the JSON directly into the `METEOR_SETTINGS` environment variable. If the settings object contains a key named `public`, then `Meteor.settings.public` will be available on the client as well as the server. All other properties of `Meteor.settings` are only defined on the server. You can rely on `Meteor.settings` and `Meteor.settings.public` being defined objects (not undefined) on both client and server even if there are no settings specified. Changes to `Meteor.settings.public` at runtime will be picked up by new client connections.
|
|
* @locus Anywhere
|
|
* @type {Object}
|
|
*/
|
|
Meteor.settings = {
|
|
"public": config.PUBLIC_SETTINGS
|
|
};
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/define-package.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
function PackageRegistry() {
|
|
this._promiseInfoMap = Object.create(null);
|
|
}
|
|
|
|
var PRp = PackageRegistry.prototype;
|
|
|
|
// Set global.Package[name] = pkg || {}. If additional arguments are
|
|
// supplied, their keys will be copied into pkg if not already present.
|
|
// This method is defined on the prototype of global.Package so that it
|
|
// will not be included in Object.keys(Package).
|
|
PRp._define = function definePackage(name, pkg) {
|
|
pkg = pkg || {};
|
|
|
|
var argc = arguments.length;
|
|
for (var i = 2; i < argc; ++i) {
|
|
var arg = arguments[i];
|
|
for (var s in arg) {
|
|
if (! (s in pkg)) {
|
|
pkg[s] = arg[s];
|
|
}
|
|
}
|
|
}
|
|
|
|
this[name] = pkg;
|
|
|
|
var info = this._promiseInfoMap[name];
|
|
if (info) {
|
|
info.resolve(pkg);
|
|
}
|
|
|
|
return pkg;
|
|
};
|
|
|
|
PRp._has = function has(name) {
|
|
return Object.prototype.hasOwnProperty.call(this, name);
|
|
};
|
|
|
|
// Returns a Promise that will resolve to the exports of the named
|
|
// package, or be rejected if the package is not installed.
|
|
PRp._promise = function promise(name) {
|
|
var self = this;
|
|
var info = self._promiseInfoMap[name];
|
|
|
|
if (! info) {
|
|
info = self._promiseInfoMap[name] = {};
|
|
info.promise = new Promise(function (resolve, reject) {
|
|
info.resolve = resolve;
|
|
if (self._has(name)) {
|
|
resolve(self[name]);
|
|
} else {
|
|
Meteor.startup(function () {
|
|
if (! self._has(name)) {
|
|
reject(new Error("Package " + name + " not installed"));
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
return info.promise;
|
|
};
|
|
|
|
// Initialize the Package namespace used by all Meteor packages.
|
|
global.Package = new PackageRegistry();
|
|
|
|
if (typeof exports === "object") {
|
|
// This code is also used by meteor/tools/isobuild/bundler.js.
|
|
exports.PackageRegistry = PackageRegistry;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/helpers.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
if (Meteor.isServer)
|
|
var Future = Npm.require('fibers/future');
|
|
|
|
if (typeof __meteor_runtime_config__ === 'object' &&
|
|
__meteor_runtime_config__.meteorRelease) {
|
|
/**
|
|
* @summary `Meteor.release` is a string containing the name of the [release](#meteorupdate) with which the project was built (for example, `"1.2.3"`). It is `undefined` if the project was built using a git checkout of Meteor.
|
|
* @locus Anywhere
|
|
* @type {String}
|
|
*/
|
|
Meteor.release = __meteor_runtime_config__.meteorRelease;
|
|
}
|
|
|
|
// XXX find a better home for these? Ideally they would be _.get,
|
|
// _.ensure, _.delete..
|
|
|
|
// _get(a,b,c,d) returns a[b][c][d], or else undefined if a[b] or
|
|
// a[b][c] doesn't exist.
|
|
//
|
|
Meteor._get = function (obj /*, arguments */) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
if (!(arguments[i] in obj))
|
|
return undefined;
|
|
obj = obj[arguments[i]];
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
// _ensure(a,b,c,d) ensures that a[b][c][d] exists. If it does not,
|
|
// it is created and set to {}. Either way, it is returned.
|
|
//
|
|
Meteor._ensure = function (obj /*, arguments */) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var key = arguments[i];
|
|
if (!(key in obj))
|
|
obj[key] = {};
|
|
obj = obj[key];
|
|
}
|
|
|
|
return obj;
|
|
};
|
|
|
|
// _delete(a, b, c, d) deletes a[b][c][d], then a[b][c] unless it
|
|
// isn't empty, then a[b] unless it isn't empty.
|
|
//
|
|
Meteor._delete = function (obj /*, arguments */) {
|
|
var stack = [obj];
|
|
var leaf = true;
|
|
for (var i = 1; i < arguments.length - 1; i++) {
|
|
var key = arguments[i];
|
|
if (!(key in obj)) {
|
|
leaf = false;
|
|
break;
|
|
}
|
|
obj = obj[key];
|
|
if (typeof obj !== "object")
|
|
break;
|
|
stack.push(obj);
|
|
}
|
|
|
|
for (var i = stack.length - 1; i >= 0; i--) {
|
|
var key = arguments[i+1];
|
|
|
|
if (leaf)
|
|
leaf = false;
|
|
else
|
|
for (var other in stack[i][key])
|
|
return; // not empty -- we're done
|
|
|
|
delete stack[i][key];
|
|
}
|
|
};
|
|
|
|
// wrapAsync can wrap any function that takes some number of arguments that
|
|
// can't be undefined, followed by some optional arguments, where the callback
|
|
// is the last optional argument.
|
|
// e.g. fs.readFile(pathname, [callback]),
|
|
// fs.open(pathname, flags, [mode], [callback])
|
|
// For maximum effectiveness and least confusion, wrapAsync should be used on
|
|
// functions where the callback is the only argument of type Function.
|
|
|
|
/**
|
|
* @memberOf Meteor
|
|
* @summary Wrap a function that takes a callback function as its final parameter. The signature of the callback of the wrapped function should be `function(error, result){}`. On the server, the wrapped function can be used either synchronously (without passing a callback) or asynchronously (when a callback is passed). On the client, a callback is always required; errors will be logged if there is no callback. If a callback is provided, the environment captured when the original function was called will be restored in the callback.
|
|
* @locus Anywhere
|
|
* @param {Function} func A function that takes a callback as its final parameter
|
|
* @param {Object} [context] Optional `this` object against which the original function will be invoked
|
|
*/
|
|
Meteor.wrapAsync = function (fn, context) {
|
|
return function (/* arguments */) {
|
|
var self = context || this;
|
|
var newArgs = Array.prototype.slice.call(arguments);
|
|
var callback;
|
|
|
|
for (var i = newArgs.length - 1; i >= 0; --i) {
|
|
var arg = newArgs[i];
|
|
var type = typeof arg;
|
|
if (type !== "undefined") {
|
|
if (type === "function") {
|
|
callback = arg;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (! callback) {
|
|
if (Meteor.isClient) {
|
|
callback = logErr;
|
|
} else {
|
|
var fut = new Future();
|
|
callback = fut.resolver();
|
|
}
|
|
++i; // Insert the callback just after arg.
|
|
}
|
|
|
|
newArgs[i] = Meteor.bindEnvironment(callback);
|
|
var result = fn.apply(self, newArgs);
|
|
return fut ? fut.wait() : result;
|
|
};
|
|
};
|
|
|
|
// Sets child's prototype to a new object whose prototype is parent's
|
|
// prototype. Used as:
|
|
// Meteor._inherits(ClassB, ClassA).
|
|
// _.extend(ClassB.prototype, { ... })
|
|
// Inspired by CoffeeScript's `extend` and Google Closure's `goog.inherits`.
|
|
var hasOwn = Object.prototype.hasOwnProperty;
|
|
Meteor._inherits = function (Child, Parent) {
|
|
// copy Parent static properties
|
|
for (var key in Parent) {
|
|
// make sure we only copy hasOwnProperty properties vs. prototype
|
|
// properties
|
|
if (hasOwn.call(Parent, key)) {
|
|
Child[key] = Parent[key];
|
|
}
|
|
}
|
|
|
|
// a middle member of prototype chain: takes the prototype from the Parent
|
|
var Middle = function () {
|
|
this.constructor = Child;
|
|
};
|
|
Middle.prototype = Parent.prototype;
|
|
Child.prototype = new Middle();
|
|
Child.__super__ = Parent.prototype;
|
|
return Child;
|
|
};
|
|
|
|
var warnedAboutWrapAsync = false;
|
|
|
|
/**
|
|
* @deprecated in 0.9.3
|
|
*/
|
|
Meteor._wrapAsync = function(fn, context) {
|
|
if (! warnedAboutWrapAsync) {
|
|
Meteor._debug("Meteor._wrapAsync has been renamed to Meteor.wrapAsync");
|
|
warnedAboutWrapAsync = true;
|
|
}
|
|
return Meteor.wrapAsync.apply(Meteor, arguments);
|
|
};
|
|
|
|
function logErr(err) {
|
|
if (err) {
|
|
return Meteor._debug(
|
|
"Exception in callback of async function",
|
|
err
|
|
);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/setimmediate.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Chooses one of three setImmediate implementations:
|
|
//
|
|
// * Native setImmediate (IE 10, Node 0.9+)
|
|
//
|
|
// * postMessage (many browsers)
|
|
//
|
|
// * setTimeout (fallback)
|
|
//
|
|
// The postMessage implementation is based on
|
|
// https://github.com/NobleJS/setImmediate/tree/1.0.1
|
|
//
|
|
// Don't use `nextTick` for Node since it runs its callbacks before
|
|
// I/O, which is stricter than we're looking for.
|
|
//
|
|
// Not installed as a polyfill, as our public API is `Meteor.defer`.
|
|
// Since we're not trying to be a polyfill, we have some
|
|
// simplifications:
|
|
//
|
|
// If one invocation of a setImmediate callback pauses itself by a
|
|
// call to alert/prompt/showModelDialog, the NobleJS polyfill
|
|
// implementation ensured that no setImmedate callback would run until
|
|
// the first invocation completed. While correct per the spec, what it
|
|
// would mean for us in practice is that any reactive updates relying
|
|
// on Meteor.defer would be hung in the main window until the modal
|
|
// dialog was dismissed. Thus we only ensure that a setImmediate
|
|
// function is called in a later event loop.
|
|
//
|
|
// We don't need to support using a string to be eval'ed for the
|
|
// callback, arguments to the function, or clearImmediate.
|
|
|
|
"use strict";
|
|
|
|
var global = this;
|
|
|
|
|
|
// IE 10, Node >= 9.1
|
|
|
|
function useSetImmediate() {
|
|
if (! global.setImmediate)
|
|
return null;
|
|
else {
|
|
var setImmediate = function (fn) {
|
|
global.setImmediate(fn);
|
|
};
|
|
setImmediate.implementation = 'setImmediate';
|
|
return setImmediate;
|
|
}
|
|
}
|
|
|
|
|
|
// Android 2.3.6, Chrome 26, Firefox 20, IE 8-9, iOS 5.1.1 Safari
|
|
|
|
function usePostMessage() {
|
|
// The test against `importScripts` prevents this implementation
|
|
// from being installed inside a web worker, where
|
|
// `global.postMessage` means something completely different and
|
|
// can't be used for this purpose.
|
|
|
|
if (!global.postMessage || global.importScripts) {
|
|
return null;
|
|
}
|
|
|
|
// Avoid synchronous post message implementations.
|
|
|
|
var postMessageIsAsynchronous = true;
|
|
var oldOnMessage = global.onmessage;
|
|
global.onmessage = function () {
|
|
postMessageIsAsynchronous = false;
|
|
};
|
|
global.postMessage("", "*");
|
|
global.onmessage = oldOnMessage;
|
|
|
|
if (! postMessageIsAsynchronous)
|
|
return null;
|
|
|
|
var funcIndex = 0;
|
|
var funcs = {};
|
|
|
|
// Installs an event handler on `global` for the `message` event: see
|
|
// * https://developer.mozilla.org/en/DOM/window.postMessage
|
|
// * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
|
|
|
|
// XXX use Random.id() here?
|
|
var MESSAGE_PREFIX = "Meteor._setImmediate." + Math.random() + '.';
|
|
|
|
function isStringAndStartsWith(string, putativeStart) {
|
|
return (typeof string === "string" &&
|
|
string.substring(0, putativeStart.length) === putativeStart);
|
|
}
|
|
|
|
function onGlobalMessage(event) {
|
|
// This will catch all incoming messages (even from other
|
|
// windows!), so we need to try reasonably hard to avoid letting
|
|
// anyone else trick us into firing off. We test the origin is
|
|
// still this window, and that a (randomly generated)
|
|
// unpredictable identifying prefix is present.
|
|
if (event.source === global &&
|
|
isStringAndStartsWith(event.data, MESSAGE_PREFIX)) {
|
|
var index = event.data.substring(MESSAGE_PREFIX.length);
|
|
try {
|
|
if (funcs[index])
|
|
funcs[index]();
|
|
}
|
|
finally {
|
|
delete funcs[index];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (global.addEventListener) {
|
|
global.addEventListener("message", onGlobalMessage, false);
|
|
} else {
|
|
global.attachEvent("onmessage", onGlobalMessage);
|
|
}
|
|
|
|
var setImmediate = function (fn) {
|
|
// Make `global` post a message to itself with the handle and
|
|
// identifying prefix, thus asynchronously invoking our
|
|
// onGlobalMessage listener above.
|
|
++funcIndex;
|
|
funcs[funcIndex] = fn;
|
|
global.postMessage(MESSAGE_PREFIX + funcIndex, "*");
|
|
};
|
|
setImmediate.implementation = 'postMessage';
|
|
return setImmediate;
|
|
}
|
|
|
|
|
|
function useTimeout() {
|
|
var setImmediate = function (fn) {
|
|
global.setTimeout(fn, 0);
|
|
};
|
|
setImmediate.implementation = 'setTimeout';
|
|
return setImmediate;
|
|
}
|
|
|
|
|
|
Meteor._setImmediate =
|
|
useSetImmediate() ||
|
|
usePostMessage() ||
|
|
useTimeout();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/timers.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
function withoutInvocation(f) {
|
|
if (Package.ddp) {
|
|
var DDP = Package.ddp.DDP;
|
|
var CurrentInvocation =
|
|
DDP._CurrentMethodInvocation ||
|
|
// For backwards compatibility, as explained in this issue:
|
|
// https://github.com/meteor/meteor/issues/8947
|
|
DDP._CurrentInvocation;
|
|
|
|
var invocation = CurrentInvocation.get();
|
|
if (invocation && invocation.isSimulation) {
|
|
throw new Error("Can't set timers inside simulations");
|
|
}
|
|
|
|
return function () {
|
|
CurrentInvocation.withValue(null, f);
|
|
};
|
|
} else {
|
|
return f;
|
|
}
|
|
}
|
|
|
|
function bindAndCatch(context, f) {
|
|
return Meteor.bindEnvironment(withoutInvocation(f), context);
|
|
}
|
|
|
|
// Meteor.setTimeout and Meteor.setInterval callbacks scheduled
|
|
// inside a server method are not part of the method invocation and
|
|
// should clear out the CurrentMethodInvocation environment variable.
|
|
|
|
/**
|
|
* @memberOf Meteor
|
|
* @summary Call a function in the future after waiting for a specified delay.
|
|
* @locus Anywhere
|
|
* @param {Function} func The function to run
|
|
* @param {Number} delay Number of milliseconds to wait before calling function
|
|
*/
|
|
Meteor.setTimeout = function (f, duration) {
|
|
return setTimeout(bindAndCatch("setTimeout callback", f), duration);
|
|
};
|
|
|
|
/**
|
|
* @memberOf Meteor
|
|
* @summary Call a function repeatedly, with a time delay between calls.
|
|
* @locus Anywhere
|
|
* @param {Function} func The function to run
|
|
* @param {Number} delay Number of milliseconds to wait between each function call.
|
|
*/
|
|
Meteor.setInterval = function (f, duration) {
|
|
return setInterval(bindAndCatch("setInterval callback", f), duration);
|
|
};
|
|
|
|
/**
|
|
* @memberOf Meteor
|
|
* @summary Cancel a repeating function call scheduled by `Meteor.setInterval`.
|
|
* @locus Anywhere
|
|
* @param {Object} id The handle returned by `Meteor.setInterval`
|
|
*/
|
|
Meteor.clearInterval = function(x) {
|
|
return clearInterval(x);
|
|
};
|
|
|
|
/**
|
|
* @memberOf Meteor
|
|
* @summary Cancel a function call scheduled by `Meteor.setTimeout`.
|
|
* @locus Anywhere
|
|
* @param {Object} id The handle returned by `Meteor.setTimeout`
|
|
*/
|
|
Meteor.clearTimeout = function(x) {
|
|
return clearTimeout(x);
|
|
};
|
|
|
|
// XXX consider making this guarantee ordering of defer'd callbacks, like
|
|
// Tracker.afterFlush or Node's nextTick (in practice). Then tests can do:
|
|
// callSomethingThatDefersSomeWork();
|
|
// Meteor.defer(expect(somethingThatValidatesThatTheWorkHappened));
|
|
|
|
/**
|
|
* @memberOf Meteor
|
|
* @summary Defer execution of a function to run asynchronously in the background (similar to `Meteor.setTimeout(func, 0)`.
|
|
* @locus Anywhere
|
|
* @param {Function} func The function to run
|
|
*/
|
|
Meteor.defer = function (f) {
|
|
Meteor._setImmediate(bindAndCatch("defer callback", f));
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/errors.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Makes an error subclass which properly contains a stack trace in most
|
|
// environments. constructor can set fields on `this` (and should probably set
|
|
// `message`, which is what gets displayed at the top of a stack trace).
|
|
//
|
|
Meteor.makeErrorType = function (name, constructor) {
|
|
var errorClass = function (/*arguments*/) {
|
|
// Ensure we get a proper stack trace in most Javascript environments
|
|
if (Error.captureStackTrace) {
|
|
// V8 environments (Chrome and Node.js)
|
|
Error.captureStackTrace(this, errorClass);
|
|
} else {
|
|
// Borrow the .stack property of a native Error object.
|
|
this.stack = new Error().stack;
|
|
}
|
|
// Safari magically works.
|
|
|
|
constructor.apply(this, arguments);
|
|
|
|
this.errorType = name;
|
|
};
|
|
|
|
Meteor._inherits(errorClass, Error);
|
|
|
|
return errorClass;
|
|
};
|
|
|
|
// This should probably be in the livedata package, but we don't want
|
|
// to require you to use the livedata package to get it. Eventually we
|
|
// should probably rename it to DDP.Error and put it back in the
|
|
// 'livedata' package (which we should rename to 'ddp' also.)
|
|
//
|
|
// Note: The DDP server assumes that Meteor.Error EJSON-serializes as an object
|
|
// containing 'error' and optionally 'reason' and 'details'.
|
|
// The DDP client manually puts these into Meteor.Error objects. (We don't use
|
|
// EJSON.addType here because the type is determined by location in the
|
|
// protocol, not text on the wire.)
|
|
|
|
/**
|
|
* @summary This class represents a symbolic error thrown by a method.
|
|
* @locus Anywhere
|
|
* @class
|
|
* @param {String} error A string code uniquely identifying this kind of error.
|
|
* This string should be used by callers of the method to determine the
|
|
* appropriate action to take, instead of attempting to parse the reason
|
|
* or details fields. For example:
|
|
*
|
|
* ```
|
|
* // on the server, pick a code unique to this error
|
|
* // the reason field should be a useful debug message
|
|
* throw new Meteor.Error("logged-out",
|
|
* "The user must be logged in to post a comment.");
|
|
*
|
|
* // on the client
|
|
* Meteor.call("methodName", function (error) {
|
|
* // identify the error
|
|
* if (error && error.error === "logged-out") {
|
|
* // show a nice error message
|
|
* Session.set("errorMessage", "Please log in to post a comment.");
|
|
* }
|
|
* });
|
|
* ```
|
|
*
|
|
* For legacy reasons, some built-in Meteor functions such as `check` throw
|
|
* errors with a number in this field.
|
|
*
|
|
* @param {String} [reason] Optional. A short human-readable summary of the
|
|
* error, like 'Not Found'.
|
|
* @param {String} [details] Optional. Additional information about the error,
|
|
* like a textual stack trace.
|
|
*/
|
|
Meteor.Error = Meteor.makeErrorType(
|
|
"Meteor.Error",
|
|
function (error, reason, details) {
|
|
var self = this;
|
|
|
|
// Newer versions of DDP use this property to signify that an error
|
|
// can be sent back and reconstructed on the calling client.
|
|
self.isClientSafe = true;
|
|
|
|
// String code uniquely identifying this kind of error.
|
|
self.error = error;
|
|
|
|
// Optional: A short human-readable summary of the error. Not
|
|
// intended to be shown to end users, just developers. ("Not Found",
|
|
// "Internal Server Error")
|
|
self.reason = reason;
|
|
|
|
// Optional: Additional information about the error, say for
|
|
// debugging. It might be a (textual) stack trace if the server is
|
|
// willing to provide one. The corresponding thing in HTTP would be
|
|
// the body of a 404 or 500 response. (The difference is that we
|
|
// never expect this to be shown to end users, only developers, so
|
|
// it doesn't need to be pretty.)
|
|
self.details = details;
|
|
|
|
// This is what gets displayed at the top of a stack trace. Current
|
|
// format is "[404]" (if no reason is set) or "File not found [404]"
|
|
if (self.reason)
|
|
self.message = self.reason + ' [' + self.error + ']';
|
|
else
|
|
self.message = '[' + self.error + ']';
|
|
});
|
|
|
|
// Meteor.Error is basically data and is sent over DDP, so you should be able to
|
|
// properly EJSON-clone it. This is especially important because if a
|
|
// Meteor.Error is thrown through a Future, the error, reason, and details
|
|
// properties become non-enumerable so a standard Object clone won't preserve
|
|
// them and they will be lost from DDP.
|
|
Meteor.Error.prototype.clone = function () {
|
|
var self = this;
|
|
return new Meteor.Error(self.error, self.reason, self.details);
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/fiber_stubs_client.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// This file is a partial analogue to fiber_helpers.js, which allows the client
|
|
// to use a queue too, and also to call noYieldsAllowed.
|
|
|
|
// The client has no ability to yield, so noYieldsAllowed is a noop.
|
|
//
|
|
Meteor._noYieldsAllowed = function (f) {
|
|
return f();
|
|
};
|
|
|
|
// An even simpler queue of tasks than the fiber-enabled one. This one just
|
|
// runs all the tasks when you call runTask or flush, synchronously.
|
|
//
|
|
Meteor._SynchronousQueue = function () {
|
|
var self = this;
|
|
self._tasks = [];
|
|
self._running = false;
|
|
self._runTimeout = null;
|
|
};
|
|
|
|
var SQp = Meteor._SynchronousQueue.prototype;
|
|
|
|
SQp.runTask = function (task) {
|
|
var self = this;
|
|
if (!self.safeToRunTask())
|
|
throw new Error("Could not synchronously run a task from a running task");
|
|
self._tasks.push(task);
|
|
var tasks = self._tasks;
|
|
self._tasks = [];
|
|
self._running = true;
|
|
|
|
if (self._runTimeout) {
|
|
// Since we're going to drain the queue, we can forget about the timeout
|
|
// which tries to run it. (But if one of our tasks queues something else,
|
|
// the timeout will be correctly re-created.)
|
|
clearTimeout(self._runTimeout);
|
|
self._runTimeout = null;
|
|
}
|
|
|
|
try {
|
|
while (tasks.length > 0) {
|
|
var t = tasks.shift();
|
|
try {
|
|
t();
|
|
} catch (e) {
|
|
if (tasks.length === 0) {
|
|
// this was the last task, that is, the one we're calling runTask
|
|
// for.
|
|
throw e;
|
|
}
|
|
Meteor._debug("Exception in queued task", e);
|
|
}
|
|
}
|
|
} finally {
|
|
self._running = false;
|
|
}
|
|
};
|
|
|
|
SQp.queueTask = function (task) {
|
|
var self = this;
|
|
self._tasks.push(task);
|
|
// Intentionally not using Meteor.setTimeout, because it doesn't like runing
|
|
// in stubs for now.
|
|
if (!self._runTimeout) {
|
|
self._runTimeout = setTimeout(function () {
|
|
return self.flush.apply(self, arguments);
|
|
}, 0);
|
|
}
|
|
};
|
|
|
|
SQp.flush = function () {
|
|
var self = this;
|
|
self.runTask(function () {});
|
|
};
|
|
|
|
SQp.drain = function () {
|
|
var self = this;
|
|
if (!self.safeToRunTask()) {
|
|
return;
|
|
}
|
|
while (self._tasks.length > 0) {
|
|
self.flush();
|
|
}
|
|
};
|
|
|
|
SQp.safeToRunTask = function () {
|
|
var self = this;
|
|
return !self._running;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/startup_client.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
var callbackQueue = [];
|
|
var isLoadingCompleted = false;
|
|
var isReady = false;
|
|
|
|
// Keeps track of how many events to wait for in addition to loading completing,
|
|
// before we're considered ready.
|
|
var readyHoldsCount = 0;
|
|
|
|
var holdReady = function () {
|
|
readyHoldsCount++;
|
|
}
|
|
|
|
var releaseReadyHold = function () {
|
|
readyHoldsCount--;
|
|
maybeReady();
|
|
}
|
|
|
|
var maybeReady = function () {
|
|
if (isReady || !isLoadingCompleted || readyHoldsCount > 0)
|
|
return;
|
|
|
|
isReady = true;
|
|
|
|
// Run startup callbacks
|
|
while (callbackQueue.length)
|
|
(callbackQueue.shift())();
|
|
|
|
if (Meteor.isCordova) {
|
|
// Notify the WebAppLocalServer plugin that startup was completed successfully,
|
|
// so we can roll back faulty versions if this doesn't happen
|
|
WebAppLocalServer.startupDidComplete();
|
|
}
|
|
};
|
|
|
|
var loadingCompleted = function () {
|
|
if (!isLoadingCompleted) {
|
|
isLoadingCompleted = true;
|
|
maybeReady();
|
|
}
|
|
}
|
|
|
|
if (Meteor.isCordova) {
|
|
holdReady();
|
|
document.addEventListener('deviceready', releaseReadyHold, false);
|
|
}
|
|
|
|
if (document.readyState === 'complete' || document.readyState === 'loaded') {
|
|
// Loading has completed,
|
|
// but allow other scripts the opportunity to hold ready
|
|
window.setTimeout(loadingCompleted);
|
|
} else { // Attach event listeners to wait for loading to complete
|
|
if (document.addEventListener) {
|
|
document.addEventListener('DOMContentLoaded', loadingCompleted, false);
|
|
window.addEventListener('load', loadingCompleted, false);
|
|
} else { // Use IE event model for < IE9
|
|
document.attachEvent('onreadystatechange', function () {
|
|
if (document.readyState === "complete") {
|
|
loadingCompleted();
|
|
}
|
|
});
|
|
window.attachEvent('load', loadingCompleted);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @summary Run code when a client or a server starts.
|
|
* @locus Anywhere
|
|
* @param {Function} func A function to run on startup.
|
|
*/
|
|
Meteor.startup = function (callback) {
|
|
// Fix for < IE9, see http://javascript.nwbox.com/IEContentLoaded/
|
|
var doScroll = !document.addEventListener &&
|
|
document.documentElement.doScroll;
|
|
|
|
if (!doScroll || window !== top) {
|
|
if (isReady)
|
|
callback();
|
|
else
|
|
callbackQueue.push(callback);
|
|
} else {
|
|
try { doScroll('left'); }
|
|
catch (error) {
|
|
setTimeout(function () { Meteor.startup(callback); }, 50);
|
|
return;
|
|
};
|
|
callback();
|
|
}
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/debug.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
var suppress = 0;
|
|
|
|
// replacement for console.log. This is a temporary API. We should
|
|
// provide a real logging API soon (possibly just a polyfill for
|
|
// console?)
|
|
//
|
|
// NOTE: this is used on the server to print the warning about
|
|
// having autopublish enabled when you probably meant to turn it
|
|
// off. it's not really the proper use of something called
|
|
// _debug. the intent is for this message to go to the terminal and
|
|
// be very visible. if you change _debug to go someplace else, etc,
|
|
// please fix the autopublish code to do something reasonable.
|
|
//
|
|
Meteor._debug = function (/* arguments */) {
|
|
if (suppress) {
|
|
suppress--;
|
|
return;
|
|
}
|
|
if (typeof console !== 'undefined' &&
|
|
typeof console.log !== 'undefined') {
|
|
if (arguments.length == 0) { // IE Companion breaks otherwise
|
|
// IE10 PP4 requires at least one argument
|
|
console.log('');
|
|
} else {
|
|
// IE doesn't have console.log.apply, it's not a real Object.
|
|
// http://stackoverflow.com/questions/5538972/console-log-apply-not-working-in-ie9
|
|
// http://patik.com/blog/complete-cross-browser-console-log/
|
|
if (typeof console.log.apply === "function") {
|
|
// Most browsers
|
|
|
|
// Chrome and Safari only hyperlink URLs to source files in first argument of
|
|
// console.log, so try to call it with one argument if possible.
|
|
// Approach taken here: If all arguments are strings, join them on space.
|
|
// See https://github.com/meteor/meteor/pull/732#issuecomment-13975991
|
|
var allArgumentsOfTypeString = true;
|
|
for (var i = 0; i < arguments.length; i++)
|
|
if (typeof arguments[i] !== "string")
|
|
allArgumentsOfTypeString = false;
|
|
|
|
if (allArgumentsOfTypeString)
|
|
console.log.apply(console, [Array.prototype.join.call(arguments, " ")]);
|
|
else
|
|
console.log.apply(console, arguments);
|
|
|
|
} else if (typeof Function.prototype.bind === "function") {
|
|
// IE9
|
|
var log = Function.prototype.bind.call(console.log, console);
|
|
log.apply(console, arguments);
|
|
} else {
|
|
// IE8
|
|
Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Suppress the next 'count' Meteor._debug messsages. Use this to
|
|
// stop tests from spamming the console.
|
|
//
|
|
Meteor._suppress_log = function (count) {
|
|
suppress += count;
|
|
};
|
|
|
|
Meteor._suppressed_log_expected = function () {
|
|
return suppress !== 0;
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/string_utils.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Like Perl's quotemeta: quotes all regexp metacharacters.
|
|
// Code taken from
|
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
|
Meteor._escapeRegExp = function (string) {
|
|
return String(string).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/test_environment.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
var TEST_METADATA_STR;
|
|
if (Meteor.isClient) {
|
|
TEST_METADATA_STR = meteorEnv.TEST_METADATA;
|
|
} else {
|
|
TEST_METADATA_STR = process.env.TEST_METADATA;
|
|
}
|
|
|
|
var TEST_METADATA = JSON.parse(TEST_METADATA_STR || "{}");
|
|
var testDriverPackageName = TEST_METADATA.driverPackage;
|
|
|
|
// Note that if we are in test-packages mode neither of these will be set,
|
|
// but we will have a test driver package
|
|
Meteor.isTest = !!TEST_METADATA.isTest;
|
|
Meteor.isAppTest = !!TEST_METADATA.isAppTest;
|
|
Meteor.isPackageTest = !!testDriverPackageName && !Meteor.isTest && !Meteor.isAppTest;
|
|
|
|
if (typeof testDriverPackageName === "string") {
|
|
Meteor.startup(function() {
|
|
var testDriverPackage = Package[testDriverPackageName];
|
|
if (! testDriverPackage) {
|
|
throw new Error("Can't find test driver package: " + testDriverPackageName);
|
|
}
|
|
|
|
// On the client, the test driver *must* define `runTests`
|
|
if (Meteor.isClient) {
|
|
if (typeof testDriverPackage.runTests !== "function") {
|
|
throw new Error("Test driver package " + testDriverPackageName
|
|
+ " missing `runTests` export");
|
|
}
|
|
testDriverPackage.runTests();
|
|
} else {
|
|
// The server can optionally define `start`
|
|
if (typeof testDriverPackage.start === "function") {
|
|
testDriverPackage.start();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/dynamics_browser.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Simple implementation of dynamic scoping, for use in browsers
|
|
|
|
var nextSlot = 0;
|
|
var currentValues = [];
|
|
|
|
Meteor.EnvironmentVariable = function () {
|
|
this.slot = nextSlot++;
|
|
};
|
|
|
|
var EVp = Meteor.EnvironmentVariable.prototype;
|
|
|
|
EVp.get = function () {
|
|
return currentValues[this.slot];
|
|
};
|
|
|
|
EVp.getOrNullIfOutsideFiber = function () {
|
|
return this.get();
|
|
};
|
|
|
|
EVp.withValue = function (value, func) {
|
|
var saved = currentValues[this.slot];
|
|
try {
|
|
currentValues[this.slot] = value;
|
|
var ret = func();
|
|
} finally {
|
|
currentValues[this.slot] = saved;
|
|
}
|
|
return ret;
|
|
};
|
|
|
|
Meteor.bindEnvironment = function (func, onException, _this) {
|
|
// needed in order to be able to create closures inside func and
|
|
// have the closed variables not change back to their original
|
|
// values
|
|
var boundValues = currentValues.slice();
|
|
|
|
if (!onException || typeof(onException) === 'string') {
|
|
var description = onException || "callback of async function";
|
|
onException = function (error) {
|
|
Meteor._debug(
|
|
"Exception in " + description + ":",
|
|
error
|
|
);
|
|
};
|
|
}
|
|
|
|
return function (/* arguments */) {
|
|
var savedValues = currentValues;
|
|
try {
|
|
currentValues = boundValues;
|
|
var ret = func.apply(_this, arguments);
|
|
} catch (e) {
|
|
// note: callback-hook currently relies on the fact that if onException
|
|
// throws in the browser, the wrapped call throws.
|
|
onException(e);
|
|
} finally {
|
|
currentValues = savedValues;
|
|
}
|
|
return ret;
|
|
};
|
|
};
|
|
|
|
Meteor._nodeCodeMustBeInFiber = function () {
|
|
// no-op on browser
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteor/url_common.js //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
/**
|
|
* @summary Generate an absolute URL pointing to the application. The server reads from the `ROOT_URL` environment variable to determine where it is running. This is taken care of automatically for apps deployed to Galaxy, but must be provided when using `meteor build`.
|
|
* @locus Anywhere
|
|
* @param {String} [path] A path to append to the root URL. Do not include a leading "`/`".
|
|
* @param {Object} [options]
|
|
* @param {Boolean} options.secure Create an HTTPS URL.
|
|
* @param {Boolean} options.replaceLocalhost Replace localhost with 127.0.0.1. Useful for services that don't recognize localhost as a domain name.
|
|
* @param {String} options.rootUrl Override the default ROOT_URL from the server environment. For example: "`http://foo.example.com`"
|
|
*/
|
|
Meteor.absoluteUrl = function (path, options) {
|
|
// path is optional
|
|
if (!options && typeof path === 'object') {
|
|
options = path;
|
|
path = undefined;
|
|
}
|
|
// merge options with defaults
|
|
options = Object.assign({}, Meteor.absoluteUrl.defaultOptions, options || {});
|
|
|
|
var url = options.rootUrl;
|
|
if (!url)
|
|
throw new Error("Must pass options.rootUrl or set ROOT_URL in the server environment");
|
|
|
|
if (!/^http[s]?:\/\//i.test(url)) // url starts with 'http://' or 'https://'
|
|
url = 'http://' + url; // we will later fix to https if options.secure is set
|
|
|
|
if (! url.endsWith("/")) {
|
|
url += "/";
|
|
}
|
|
|
|
if (path) {
|
|
// join url and path with a / separator
|
|
while (path.startsWith("/")) {
|
|
path = path.slice(1);
|
|
}
|
|
url += path;
|
|
}
|
|
|
|
// turn http to https if secure option is set, and we're not talking
|
|
// to localhost.
|
|
if (options.secure &&
|
|
/^http:/.test(url) && // url starts with 'http:'
|
|
!/http:\/\/localhost[:\/]/.test(url) && // doesn't match localhost
|
|
!/http:\/\/127\.0\.0\.1[:\/]/.test(url)) // or 127.0.0.1
|
|
url = url.replace(/^http:/, 'https:');
|
|
|
|
if (options.replaceLocalhost)
|
|
url = url.replace(/^http:\/\/localhost([:\/].*)/, 'http://127.0.0.1$1');
|
|
|
|
return url;
|
|
};
|
|
|
|
// allow later packages to override default options
|
|
var defaultOptions = Meteor.absoluteUrl.defaultOptions = {};
|
|
|
|
// available only in a browser environment
|
|
var location = typeof window === "object" && window.location;
|
|
|
|
if (typeof __meteor_runtime_config__ === "object" &&
|
|
__meteor_runtime_config__.ROOT_URL) {
|
|
defaultOptions.rootUrl = __meteor_runtime_config__.ROOT_URL;
|
|
} else if (location &&
|
|
location.protocol &&
|
|
location.host) {
|
|
defaultOptions.rootUrl = location.protocol + "//" + location.host;
|
|
}
|
|
|
|
// Make absolute URLs use HTTPS by default if the current window.location
|
|
// uses HTTPS. Since this is just a default, it can be overridden by
|
|
// passing { secure: false } if necessary.
|
|
if (location &&
|
|
location.protocol === "https:") {
|
|
defaultOptions.secure = true;
|
|
}
|
|
|
|
Meteor._relativeToSiteRootUrl = function (link) {
|
|
if (typeof __meteor_runtime_config__ === "object" &&
|
|
link.substr(0, 1) === "/")
|
|
link = (__meteor_runtime_config__.ROOT_URL_PATH_PREFIX || "") + link;
|
|
return link;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
/* Exports */
|
|
Package._define("meteor", {
|
|
Meteor: Meteor,
|
|
global: global,
|
|
meteorEnv: meteorEnv
|
|
});
|
|
|
|
})();
|