diff --git a/admin/spark-standalone.sh b/admin/spark-standalone.sh
index 7392ff7305..eb248cd040 100755
--- a/admin/spark-standalone.sh
+++ b/admin/spark-standalone.sh
@@ -9,7 +9,7 @@ PACKAGES_DIR=`dirname $0`/../packages
echo 'Meteor = {};'
cat $PACKAGES_DIR/underscore/underscore.js
cat $PACKAGES_DIR/logging/logging.js
-cat $PACKAGES_DIR/uuid/uuid.js
+cat $PACKAGES_DIR/random/random.js
cat $PACKAGES_DIR/deps/deps.js
cat $PACKAGES_DIR/deps/deps-utils.js
cat $PACKAGES_DIR/liverange/liverange.js
diff --git a/docs/client/api.html b/docs/client/api.html
index 70fd14c291..12d79e84b6 100644
--- a/docs/client/api.html
+++ b/docs/client/api.html
@@ -1034,25 +1034,6 @@ Example:
// After five seconds, stop keeping the count.
setTimeout(function () {handle.stop();}, 5000);
-{{> api_box id}}
-
-This returns a random text string such as ``"Jjwjg6gouWLXhMGKW"``
-that is likely to be unique in the whole world.
-
-Currently Meteor uses this function to generate `_id` fields for new Mongo
-documents by default. If your database requires native binary Mongo IDs instead,
-pass `"MONGO"` as the `idGeneration` option to
-[`Meteor.Collection`](#meteor_collection).
-
-
-{{#note}}
-
-In the current implementation, the returned string is derived from a
-pseudorandom number generator. The IDs generated definitely are not random
-enough to be used for cryptographic or security purposes.
-
-{{/note}}
-
{{> api_box collection_object_id}}
`Meteor.Collection.ObjectID` follows the same API as the [Node MongoDB driver
@@ -1500,7 +1481,7 @@ Example:
// Support for playing D&D: Roll 3d6 for dexterity
Accounts.onCreateUser(function(options, user) {
- var d6 = function () { return Math.floor(Math.random() * 6) + 1; };
+ var d6 = function () { return Math.floor(Random.fraction() * 6) + 1; };
user.dexterity = d6() + d6() + d6();
// We still want the default hook's 'profile' behavior.
if (options.profile)
diff --git a/docs/client/api.js b/docs/client/api.js
index 00c7dfb5a8..5f2ba48dda 100644
--- a/docs/client/api.js
+++ b/docs/client/api.js
@@ -684,7 +684,7 @@ Template.api.cursor_observe_changes = {
Template.api.id = {
id: "meteor_id",
- name: "Meteor.id()",
+ name: "Random.id()",
locus: "Anywhere",
descr: ["Return a unique identifier."],
args: [ ]
diff --git a/docs/client/docs.js b/docs/client/docs.js
index 4dee50fc1e..6587d7fcd4 100644
--- a/docs/client/docs.js
+++ b/docs/client/docs.js
@@ -151,7 +151,6 @@ var toc = [
{instance: "cursor", name: "observeChanges", id: "observe_changes"}
],
{type: "spacer"},
- "Meteor.id",
{name: "Meteor.Collection.ObjectID", id: "collection_object_id"},
{type: "spacer"},
{name: "Selectors", style: "noncode"},
@@ -295,6 +294,7 @@ var toc = [
"force-ssl",
"jquery",
"less",
+ "random",
"spiderable",
"stylus",
"showdown",
diff --git a/docs/client/packages.html b/docs/client/packages.html
index 6cf66ae559..adfd08f2b8 100644
--- a/docs/client/packages.html
+++ b/docs/client/packages.html
@@ -25,6 +25,7 @@ and removed with:
{{> pkg_force_ssl}}
{{> pkg_jquery}}
{{> pkg_less}}
+{{> pkg_random}}
{{> pkg_spiderable}}
{{> pkg_stylus}}
{{> pkg_showdown}}
diff --git a/docs/client/packages/random.html b/docs/client/packages/random.html
new file mode 100644
index 0000000000..4ad9c75c58
--- /dev/null
+++ b/docs/client/packages/random.html
@@ -0,0 +1,34 @@
+
+{{#better_markdown}}
+## `random`
+
+The `random` package provides several random-number utilities, using a
+random-number generator whose implementation does not depend on the particular
+browser.
+
+
+{{#dtdd "Random.id()"}}
+Returns a unique identifier, such as `"Jjwjg6gouWLXhMGKW"`, that is likely to
+be unique in the whole world.
+{{/dtdd}}
+
+{{#dtdd "Random.fraction()"}}
+Returns a number between 0 and 1, like `Math.random`.
+{{/dtdd}}
+
+{{#dtdd "Random.choice(arrayOrString)"}}
+Returns a random element of the given array or string.
+{{/dtdd}}
+
+{{#dtdd "Random.hexString(n)"}}
+Returns a random string of `n` hexadecimal digits.
+{{/dtdd}}
+
+
+{{#note}}
+In the current implementation, random values do not come from a
+cryptographically strong pseudorandom number generator. Future releases will
+improve this, particularly on the server.
+{{/note}}
+{{/better_markdown}}
+
diff --git a/examples/leaderboard/.meteor/packages b/examples/leaderboard/.meteor/packages
index 2ca3c152a4..bd558a2ce0 100644
--- a/examples/leaderboard/.meteor/packages
+++ b/examples/leaderboard/.meteor/packages
@@ -6,3 +6,4 @@
autopublish
insecure
preserve-inputs
+random
diff --git a/examples/leaderboard/leaderboard.js b/examples/leaderboard/leaderboard.js
index d75006046c..1013e28189 100644
--- a/examples/leaderboard/leaderboard.js
+++ b/examples/leaderboard/leaderboard.js
@@ -41,7 +41,7 @@ if (Meteor.isServer) {
"Nikola Tesla",
"Claude Shannon"];
for (var i = 0; i < names.length; i++)
- Players.insert({name: names[i], score: Math.floor(Math.random()*10)*5});
+ Players.insert({name: names[i], score: Math.floor(Random.fraction()*10)*5});
}
});
}
diff --git a/examples/other/quiescence/.meteor/packages b/examples/other/quiescence/.meteor/packages
index b205e40610..19052c13e7 100644
--- a/examples/other/quiescence/.meteor/packages
+++ b/examples/other/quiescence/.meteor/packages
@@ -5,3 +5,4 @@
insecure
preserve-inputs
+random
diff --git a/examples/other/quiescence/quiescence.js b/examples/other/quiescence/quiescence.js
index 46a1f6614a..a86cec8fe5 100644
--- a/examples/other/quiescence/quiescence.js
+++ b/examples/other/quiescence/quiescence.js
@@ -69,7 +69,7 @@ if (Meteor.isServer) {
};
Template.updated.events({
'click #update-button': function () {
- var num = Math.round(Math.random()*100);
+ var num = Math.round(Random.fraction()*100);
Meteor.call('setMagic', num);
}
});
diff --git a/examples/other/template-demo/client/template-demo.js b/examples/other/template-demo/client/template-demo.js
index 7959a9ca2c..0407ec425f 100644
--- a/examples/other/template-demo/client/template-demo.js
+++ b/examples/other/template-demo/client/template-demo.js
@@ -150,12 +150,12 @@ Template.circles.events({
Session.set("selectedCircle:" + this.group, evt.currentTarget.id);
},
'click .add': function () {
- Circles.insert({x: Meteor.random(), y: Meteor.random(),
- r: Meteor.random() * .1 + .02,
+ Circles.insert({x: Random.fraction(), y: Random.fraction(),
+ r: Random.fraction() * .1 + .02,
color: {
- r: Meteor.random(),
- g: Meteor.random(),
- b: Meteor.random()
+ r: Random.fraction(),
+ g: Random.fraction(),
+ b: Random.fraction()
},
group: this.group
});
@@ -171,7 +171,7 @@ Template.circles.events({
Circles.find({group: this.group}).forEach(function (r) {
Circles.update(r._id, {
$set: {
- x: Meteor.random(), y: Meteor.random(), r: Meteor.random() * .1 + .02
+ x: Random.fraction(), y: Random.fraction(), r: Random.fraction() * .1 + .02
}
});
});
diff --git a/examples/unfinished/accounts-ui-viewer/accounts-ui-viewer.js b/examples/unfinished/accounts-ui-viewer/accounts-ui-viewer.js
index 28a86e9d74..eb1b306d39 100644
--- a/examples/unfinished/accounts-ui-viewer/accounts-ui-viewer.js
+++ b/examples/unfinished/accounts-ui-viewer/accounts-ui-viewer.js
@@ -26,7 +26,7 @@ if (Meteor.isClient) {
} else {
// make sure we have a username
Meteor.users.update(Meteor.userId(),
- { $set: { username: Meteor.uuid() }});
+ { $set: { username: Random.id() }});
}
}
} else if (key === "signupFields") {
@@ -116,7 +116,7 @@ if (Meteor.isClient) {
var fakeLogin = function (callback) {
Accounts.createUser(
- {username: Meteor.uuid(),
+ {username: Random.id(),
password: "password",
profile: { name: "Joe Schmoe" }},
function () {
diff --git a/examples/unfinished/benchmark/.meteor/packages b/examples/unfinished/benchmark/.meteor/packages
index 0d8b60823c..233dc66a33 100644
--- a/examples/unfinished/benchmark/.meteor/packages
+++ b/examples/unfinished/benchmark/.meteor/packages
@@ -6,3 +6,4 @@
insecure
preserve-inputs
bootstrap
+random
diff --git a/examples/unfinished/benchmark/benchmark.js b/examples/unfinished/benchmark/benchmark.js
index 6f323a5def..db76523e47 100644
--- a/examples/unfinished/benchmark/benchmark.js
+++ b/examples/unfinished/benchmark/benchmark.js
@@ -16,7 +16,7 @@ if (Meteor.isServer) {
//////////////////////////////
var random = function (n) {
- return Math.floor(Math.random() * n);
+ return Math.floor(Random.fraction() * n);
};
var randomChars =
@@ -25,13 +25,13 @@ var randomString = function (length) {
// XXX make more efficient
var ret = '';
_.times(length, function () {
- ret += randomChars[random(randomChars.length)];
+ ret += Random.choice(randomChars);
});
return ret;
};
var pickCollection = function () {
- return Collections[random(Collections.length)];
+ return Random.choice(Collections);
};
var generateDoc = function () {
@@ -123,7 +123,7 @@ if (Meteor.isClient) {
Meteor.setInterval(function () {
var C = pickCollection();
var docs = C.find({}).fetch();
- var doc = docs[random(docs.length)];
+ var doc = Random.choice(docs);
if (doc)
C.remove(doc._id);
}, 1000 / PARAMS.removesPerSecond);
@@ -133,7 +133,7 @@ if (Meteor.isClient) {
Meteor.setInterval(function () {
var C = pickCollection();
var docs = C.find({}).fetch();
- var doc = docs[random(docs.length)];
+ var doc = Random.choice(docs);
if (doc) {
var field = 'Field' + random(PARAMS.documentNumFields);
var modifer = {};
diff --git a/examples/wordplay/model.js b/examples/wordplay/model.js
index 04b0188abf..7aca086fec 100644
--- a/examples/wordplay/model.js
+++ b/examples/wordplay/model.js
@@ -44,7 +44,7 @@ var new_board = function () {
// pick random letter from each die
for (i = 0; i < 16; i += 1) {
- board[i] = DICE[i].split('')[Math.floor(Math.random() * 6)];
+ board[i] = Random.choice(DICE[i]);
}
// knuth shuffle
diff --git a/packages/accounts-base/accounts_server.js b/packages/accounts-base/accounts_server.js
index d38777c801..3e621979e0 100644
--- a/packages/accounts-base/accounts_server.js
+++ b/packages/accounts-base/accounts_server.js
@@ -57,7 +57,7 @@
// support reconnecting using a meteor login token
Accounts._generateStampedLoginToken = function () {
- return {token: Meteor.uuid(), when: +(new Date)};
+ return {token: Random.id(), when: +(new Date)};
};
Accounts.registerLoginHandler(function(options) {
diff --git a/packages/accounts-base/accounts_tests.js b/packages/accounts-base/accounts_tests.js
index 01ba4e1a21..fc0759acf4 100644
--- a/packages/accounts-base/accounts_tests.js
+++ b/packages/accounts-base/accounts_tests.js
@@ -8,7 +8,7 @@ Tinytest.add('accounts - config validates keys', function (test) {
});
Tinytest.add('accounts - updateOrCreateUserFromExternalService - Facebook', function (test) {
- var facebookId = Meteor.uuid();
+ var facebookId = Random.id();
// create an account with facebook
var uid1 = Accounts.updateOrCreateUserFromExternalService(
@@ -38,8 +38,8 @@ Tinytest.add('accounts - updateOrCreateUserFromExternalService - Facebook', func
});
Tinytest.add('accounts - updateOrCreateUserFromExternalService - Weibo', function (test) {
- var weiboId1 = Meteor.uuid();
- var weiboId2 = Meteor.uuid();
+ var weiboId1 = Random.id();
+ var weiboId2 = Random.id();
// users that have different service ids get different users
uid1 = Accounts.updateOrCreateUserFromExternalService(
@@ -85,7 +85,7 @@ Tinytest.add('accounts - updateOrCreateUserFromExternalService - Twitter', funct
Tinytest.add('accounts - insertUserDoc username', function (test) {
var userIn = {
- username: Meteor.uuid()
+ username: Random.id()
};
// user does not already exist. create a user object with fields set.
@@ -113,9 +113,9 @@ Tinytest.add('accounts - insertUserDoc username', function (test) {
});
Tinytest.add('accounts - insertUserDoc email', function (test) {
- var email1 = Meteor.uuid();
- var email2 = Meteor.uuid();
- var email3 = Meteor.uuid();
+ var email1 = Random.id();
+ var email2 = Random.id();
+ var email3 = Random.id();
var userIn = {
emails: [{address: email1, verified: false},
{address: email2, verified: true}]
diff --git a/packages/accounts-base/localstorage_token.js b/packages/accounts-base/localstorage_token.js
index 9ee0a61fda..7446b7aa3d 100644
--- a/packages/accounts-base/localstorage_token.js
+++ b/packages/accounts-base/localstorage_token.js
@@ -7,8 +7,8 @@
// logging in and out, to protect multiple tabs running the same tests
// simultaneously from interfering with each others' localStorage.
Accounts._isolateLoginTokenForTest = function () {
- loginTokenKey = loginTokenKey + Meteor.uuid();
- userIdKey = userIdKey + Meteor.uuid();
+ loginTokenKey = loginTokenKey + Random.id();
+ userIdKey = userIdKey + Random.id();
};
Accounts._storeLoginToken = function(userId, token) {
diff --git a/packages/accounts-facebook/facebook_client.js b/packages/accounts-facebook/facebook_client.js
index caca4c0961..42f462276f 100644
--- a/packages/accounts-facebook/facebook_client.js
+++ b/packages/accounts-facebook/facebook_client.js
@@ -12,7 +12,7 @@
return;
}
- var state = Meteor.uuid();
+ var state = Random.id();
var mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
var display = mobile ? 'touch' : 'popup';
diff --git a/packages/accounts-github/github_client.js b/packages/accounts-github/github_client.js
index c16db9680d..9943b5689a 100644
--- a/packages/accounts-github/github_client.js
+++ b/packages/accounts-github/github_client.js
@@ -11,7 +11,7 @@
callback && callback(new Accounts.ConfigError("Service not configured"));
return;
}
- var state = Meteor.uuid();
+ var state = Random.id();
var scope = (options && options.requestPermissions) || [];
var flatScope = _.map(scope, encodeURIComponent).join('+');
diff --git a/packages/accounts-google/google_client.js b/packages/accounts-google/google_client.js
index bfcd83f605..b4c68d6f56 100644
--- a/packages/accounts-google/google_client.js
+++ b/packages/accounts-google/google_client.js
@@ -12,7 +12,7 @@
return;
}
- var state = Meteor.uuid();
+ var state = Random.id();
// always need this to get user id from google.
var requiredScope = ['https://www.googleapis.com/auth/userinfo.profile'];
diff --git a/packages/accounts-oauth1-helper/oauth1_binding.js b/packages/accounts-oauth1-helper/oauth1_binding.js
index 0497dbe46d..70d24c4b35 100644
--- a/packages/accounts-oauth1-helper/oauth1_binding.js
+++ b/packages/accounts-oauth1-helper/oauth1_binding.js
@@ -78,7 +78,7 @@ OAuth1Binding.prototype._buildHeader = function(headers) {
var self = this;
return _.extend({
oauth_consumer_key: self._consumerKey,
- oauth_nonce: Meteor.uuid().replace(/\W/g, ''),
+ oauth_nonce: Random.id().replace(/\W/g, ''),
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: (new Date().valueOf()/1000).toFixed().toString(),
oauth_version: '1.0'
diff --git a/packages/accounts-oauth1-helper/oauth1_tests.js b/packages/accounts-oauth1-helper/oauth1_tests.js
index d0688ebb89..88c5cc90b5 100644
--- a/packages/accounts-oauth1-helper/oauth1_tests.js
+++ b/packages/accounts-oauth1-helper/oauth1_tests.js
@@ -1,11 +1,11 @@
Tinytest.add("oauth1 - loginResultForState is stored", function (test) {
var http = __meteor_bootstrap__.require('http');
- var twitterfooId = Meteor.uuid();
- var twitterfooName = 'nickname' + Meteor.uuid();
- var twitterfooAccessToken = Meteor.uuid();
- var twitterfooAccessTokenSecret = Meteor.uuid();
- var state = Meteor.uuid();
+ var twitterfooId = Random.id();
+ var twitterfooName = 'nickname' + Random.id();
+ var twitterfooAccessToken = Random.id();
+ var twitterfooAccessTokenSecret = Random.id();
+ var state = Random.id();
OAuth1Binding.prototype.prepareRequestToken = function() {};
OAuth1Binding.prototype.prepareAccessToken = function() {
@@ -70,11 +70,11 @@ Tinytest.add("oauth1 - loginResultForState is stored", function (test) {
Tinytest.add("oauth1 - error in user creation", function (test) {
var http = __meteor_bootstrap__.require('http');
- var state = Meteor.uuid();
- var twitterfailId = Meteor.uuid();
- var twitterfailName = 'nickname' + Meteor.uuid();
- var twitterfailAccessToken = Meteor.uuid();
- var twitterfailAccessTokenSecret = Meteor.uuid();
+ var state = Random.id();
+ var twitterfailId = Random.id();
+ var twitterfailName = 'nickname' + Random.id();
+ var twitterfailAccessToken = Random.id();
+ var twitterfailAccessTokenSecret = Random.id();
if (!Accounts.loginServiceConfiguration.findOne({service: 'twitterfail'}))
Accounts.loginServiceConfiguration.insert({service: 'twitterfail'});
diff --git a/packages/accounts-oauth2-helper/oauth2_tests.js b/packages/accounts-oauth2-helper/oauth2_tests.js
index 206e509669..3d679b6a7a 100644
--- a/packages/accounts-oauth2-helper/oauth2_tests.js
+++ b/packages/accounts-oauth2-helper/oauth2_tests.js
@@ -1,7 +1,7 @@
Tinytest.add("oauth2 - loginResultForState is stored", function (test) {
var http = __meteor_bootstrap__.require('http');
- var foobookId = Meteor.uuid();
- var state = Meteor.uuid();
+ var foobookId = Random.id();
+ var state = Random.id();
if (!Accounts.loginServiceConfiguration.findOne({service: 'foobook'}))
Accounts.loginServiceConfiguration.insert({service: 'foobook'});
@@ -42,8 +42,8 @@ Tinytest.add("oauth2 - loginResultForState is stored", function (test) {
Tinytest.add("oauth2 - error in user creation", function (test) {
var http = __meteor_bootstrap__.require('http');
- var state = Meteor.uuid();
- var failbookId = Meteor.uuid();
+ var state = Random.id();
+ var failbookId = Random.id();
if (!Accounts.loginServiceConfiguration.findOne({service: 'failbook'}))
Accounts.loginServiceConfiguration.insert({service: 'failbook'});
diff --git a/packages/accounts-password/email_tests.js b/packages/accounts-password/email_tests.js
index 97d555e749..5798518259 100644
--- a/packages/accounts-password/email_tests.js
+++ b/packages/accounts-password/email_tests.js
@@ -15,7 +15,7 @@
testAsyncMulti("accounts emails - reset password flow", [
function (test, expect) {
- email1 = Meteor.uuid() + "-intercept@example.com";
+ email1 = Random.id() + "-intercept@example.com";
Accounts.createUser({email: email1, password: 'foobar'},
expect(function (error) {
test.equal(error, undefined);
@@ -87,8 +87,8 @@
testAsyncMulti("accounts emails - verify email flow", [
function (test, expect) {
- email2 = Meteor.uuid() + "-intercept@example.com";
- email3 = Meteor.uuid() + "-intercept@example.com";
+ email2 = Random.id() + "-intercept@example.com";
+ email3 = Random.id() + "-intercept@example.com";
Accounts.createUser(
{email: email2, password: 'foobar'},
loggedIn(test, expect));
@@ -171,7 +171,7 @@
testAsyncMulti("accounts emails - enroll account flow", [
function (test, expect) {
- email4 = Meteor.uuid() + "-intercept@example.com";
+ email4 = Random.id() + "-intercept@example.com";
Meteor.call("createUserOnServer", email4,
expect(function (error, result) {
test.isFalse(error);
diff --git a/packages/accounts-password/password_server.js b/packages/accounts-password/password_server.js
index 968df3e5ec..f48e2de906 100644
--- a/packages/accounts-password/password_server.js
+++ b/packages/accounts-password/password_server.js
@@ -23,8 +23,8 @@
// user: either {username: (username)}, {email: (email)}, or {id: (userId)}
// A: hex encoded int. the client's public key for this exchange
// @returns {Object} with fields:
- // identiy: string uuid
- // salt: string uuid
+ // identity: random string ID
+ // salt: random string ID
// B: hex encoded int. server's public key for this exchange
beginPasswordExchange: function (request) {
var selector = selectorFromUserQuery(request.user);
@@ -191,7 +191,7 @@
if (!email || !_.contains(_.pluck(user.emails || [], 'address'), email))
throw new Error("No such email for user.");
- var token = Meteor.uuid();
+ var token = Random.id();
var when = +(new Date);
Meteor.users.update(userId, {$set: {
"services.password.reset": {
@@ -233,7 +233,7 @@
var tokenRecord = {
- token: Meteor.uuid(),
+ token: Random.id(),
address: address,
when: +(new Date)};
Meteor.users.update(
@@ -268,7 +268,7 @@
throw new Error("No such email for user.");
- var token = Meteor.uuid();
+ var token = Random.id();
var when = +(new Date);
Meteor.users.update(userId, {$set: {
"services.password.reset": {
diff --git a/packages/accounts-password/password_tests.js b/packages/accounts-password/password_tests.js
index 4f79bb04ab..f5ad41eaf0 100644
--- a/packages/accounts-password/password_tests.js
+++ b/packages/accounts-password/password_tests.js
@@ -28,11 +28,11 @@ if (Meteor.isClient) (function () {
testAsyncMulti("passwords - long series", [
function (test, expect) {
- username = Meteor.uuid();
- username2 = Meteor.uuid();
- username3 = Meteor.uuid();
+ username = Random.id();
+ username2 = Random.id();
+ username3 = Random.id();
// use -intercept so that we don't print to the console
- email = Meteor.uuid() + '-intercept@example.com';
+ email = Random.id() + '-intercept@example.com';
password = 'password';
password2 = 'password2';
password3 = 'password3';
@@ -227,7 +227,7 @@ if (Meteor.isServer) (function () {
Tinytest.add(
'passwords - createUser hooks',
function (test) {
- var email = Meteor.uuid() + '@example.com';
+ var email = Random.id() + '@example.com';
test.throws(function () {
// should fail the new user validators
Accounts.createUser({email: email, profile: {invalid: true}});
@@ -249,7 +249,7 @@ if (Meteor.isServer) (function () {
Tinytest.add(
'passwords - setPassword',
function (test) {
- var username = Meteor.uuid();
+ var username = Random.id();
var userId = Accounts.createUser({username: username});
diff --git a/packages/accounts-twitter/twitter_client.js b/packages/accounts-twitter/twitter_client.js
index a9fd891a17..0d96ddcf9b 100644
--- a/packages/accounts-twitter/twitter_client.js
+++ b/packages/accounts-twitter/twitter_client.js
@@ -13,7 +13,7 @@
return;
}
- var state = Meteor.uuid();
+ var state = Random.id();
// We need to keep state across the next two 'steps' so we're adding
// a state parameter to the url and the callback url that we'll be returned
// to by oauth provider
diff --git a/packages/accounts-weibo/weibo_client.js b/packages/accounts-weibo/weibo_client.js
index a4b5258383..f5d221e143 100644
--- a/packages/accounts-weibo/weibo_client.js
+++ b/packages/accounts-weibo/weibo_client.js
@@ -13,7 +13,7 @@
return;
}
- var state = Meteor.uuid();
+ var state = Random.id();
// XXX need to support configuring access_type and scope
var loginUrl =
'https://api.weibo.com/oauth2/authorize' +
diff --git a/packages/http/httpcall_tests.js b/packages/http/httpcall_tests.js
index 55348f075f..4e5d99cdac 100644
--- a/packages/http/httpcall_tests.js
+++ b/packages/http/httpcall_tests.js
@@ -98,7 +98,7 @@ testAsyncMulti("httpcall - timeout", [
// Should time out
Meteor.http.call(
- "GET", url_prefix()+"/slow-"+Meteor.uuid(),
+ "GET", url_prefix()+"/slow-"+Random.id(),
{ timeout: 500 },
expect(function(error, result) {
test.isTrue(error);
@@ -107,7 +107,7 @@ testAsyncMulti("httpcall - timeout", [
// Should not time out
Meteor.http.call(
- "GET", url_prefix()+"/foo-"+Meteor.uuid(),
+ "GET", url_prefix()+"/foo-"+Random.id(),
{ timeout: 2000 },
expect(function(error, result) {
test.isFalse(error);
@@ -254,7 +254,7 @@ testAsyncMulti("httpcall - http auth", [
// uses cached credentials even if we supply different ones:
// https://bugzilla.mozilla.org/show_bug.cgi?id=654348
var password = 'rocks';
- //var password = Meteor.uuid().replace(/[^0-9a-zA-Z]/g, '');
+ //var password = Random.id().replace(/[^0-9a-zA-Z]/g, '');
Meteor.http.call(
"GET", url_prefix()+"/login?"+password,
{ auth: "meteor:"+password },
diff --git a/packages/livedata/livedata_connection.js b/packages/livedata/livedata_connection.js
index c7b4020b5c..9d62beed59 100644
--- a/packages/livedata/livedata_connection.js
+++ b/packages/livedata/livedata_connection.js
@@ -469,7 +469,7 @@ _.extend(Meteor._LivedataConnection.prototype, {
}
} else {
// New sub! Generate an id, save it locally, and send message.
- id = Meteor.uuid();
+ id = Random.id();
self._subscriptions[id] = {
id: id,
name: name,
diff --git a/packages/livedata/livedata_connection_tests.js b/packages/livedata/livedata_connection_tests.js
index c5e2f571c6..d3ae5187b2 100644
--- a/packages/livedata/livedata_connection_tests.js
+++ b/packages/livedata/livedata_connection_tests.js
@@ -74,7 +74,7 @@ Tinytest.add("livedata stub - receive data", function (test) {
startAndConnect(test, stream);
// data comes in for unknown collection.
- var coll_name = Meteor.uuid();
+ var coll_name = Random.id();
stream.receive({msg: 'added', collection: coll_name, id: '1234',
fields: {a: 1}});
// break throught the black box and test internal state
@@ -294,7 +294,7 @@ Tinytest.add("livedata stub - methods", function (test) {
startAndConnect(test, stream);
- var collName = Meteor.uuid();
+ var collName = Random.id();
var coll = new Meteor.Collection(collName, {manager: conn});
// setup method
@@ -436,7 +436,7 @@ Tinytest.add("livedata stub - methods calling methods", function (test) {
startAndConnect(test, stream);
- var coll_name = Meteor.uuid();
+ var coll_name = Random.id();
var coll = new Meteor.Collection(coll_name, {manager: conn});
// setup methods
@@ -521,7 +521,7 @@ Tinytest.add("livedata stub - reconnect", function (test) {
startAndConnect(test, stream);
- var collName = Meteor.uuid();
+ var collName = Random.id();
var coll = new Meteor.Collection(collName, {manager: conn});
var o = observeCursor(test, coll.find());
@@ -646,7 +646,7 @@ Tinytest.add("livedata stub - reconnect method which only got result", function
var conn = newConnection(stream);
startAndConnect(test, stream);
- var collName = Meteor.uuid();
+ var collName = Random.id();
var coll = new Meteor.Collection(collName, {manager: conn});
var o = observeCursor(test, coll.find());
@@ -819,7 +819,7 @@ Tinytest.add("livedata stub - reconnect method which only got data", function (t
var conn = newConnection(stream);
startAndConnect(test, stream);
- var collName = Meteor.uuid();
+ var collName = Random.id();
var coll = new Meteor.Collection(collName, {manager: conn});
var o = observeCursor(test, coll.find());
@@ -906,7 +906,7 @@ Tinytest.add("livedata stub - multiple stubs same doc", function (test) {
var conn = newConnection(stream);
startAndConnect(test, stream);
- var collName = Meteor.uuid();
+ var collName = Random.id();
var coll = new Meteor.Collection(collName, {manager: conn});
var o = observeCursor(test, coll.find());
@@ -991,7 +991,7 @@ Tinytest.add("livedata stub - unsent methods don't block quiescence", function (
var conn = newConnection(stream);
startAndConnect(test, stream);
- var collName = Meteor.uuid();
+ var collName = Random.id();
var coll = new Meteor.Collection(collName, {manager: conn});
conn.methods({
@@ -1067,7 +1067,7 @@ Tinytest.add("livedata connection - two wait methods", function (test) {
var conn = newConnection(stream);
startAndConnect(test, stream);
- var collName = Meteor.uuid();
+ var collName = Random.id();
var coll = new Meteor.Collection(collName, {manager: conn});
// setup method
@@ -1320,7 +1320,7 @@ Tinytest.add("livedata connection - onReconnect with sent messages", function(te
params: ['login'], id: '*'});
// we connect.
- stream.receive({msg: 'connected', session: Meteor.uuid()});
+ stream.receive({msg: 'connected', session: Random.id()});
test.length(stream.sent, 0);
// login got result (but not yet data)
@@ -1446,7 +1446,7 @@ Tinytest.add("livedata stub - stubs before connected", function (test) {
var stream = new Meteor._StubStream();
var conn = newConnection(stream);
- var collName = Meteor.uuid();
+ var collName = Random.id();
var coll = new Meteor.Collection(collName, {manager: conn});
// Start and send "connect", but DON'T get 'connected' quite yet.
diff --git a/packages/livedata/livedata_server.js b/packages/livedata/livedata_server.js
index ab969be6af..4409df1f62 100644
--- a/packages/livedata/livedata_server.js
+++ b/packages/livedata/livedata_server.js
@@ -201,7 +201,7 @@ _.extend(Meteor._SessionCollectionView.prototype, {
Meteor._LivedataSession = function (server, version) {
var self = this;
- self.id = Meteor.uuid();
+ self.id = Random.id();
self.server = server;
self.version = version;
@@ -772,7 +772,7 @@ Meteor._LivedataSubscription = function (
if (self._subscriptionId) {
self._subscriptionHandle = 'N' + self._subscriptionId;
} else {
- self._subscriptionHandle = 'U' + Meteor.id();
+ self._subscriptionHandle = 'U' + Random.id();
}
// has _deactivate been called?
diff --git a/packages/livedata/livedata_test_service.js b/packages/livedata/livedata_test_service.js
index 740af62335..322cc5b504 100644
--- a/packages/livedata/livedata_test_service.js
+++ b/packages/livedata/livedata_test_service.js
@@ -244,7 +244,7 @@ if (Meteor.isServer) {
// First add a random item, which should be cleaned up. We use ready/onReady
// to make sure that the second test block is only called after the added is
// processed, so that there's any chance of the coll.find().count() failing.
- sub.added(collName, Meteor.id(), {foo: 42});
+ sub.added(collName, Random.id(), {foo: 42});
sub.ready();
if (options.stopInHandler) {
diff --git a/packages/livedata/livedata_tests.js b/packages/livedata/livedata_tests.js
index 62c73bbac6..c10d87646e 100644
--- a/packages/livedata/livedata_tests.js
+++ b/packages/livedata/livedata_tests.js
@@ -45,7 +45,7 @@ if (Meteor.isServer) {
}
Tinytest.add("livedata - methods with colliding names", function (test) {
- var x = LocalCollection.uuid();
+ var x = Random.id();
var m = {};
m[x] = function () {};
Meteor.methods(m);
@@ -137,7 +137,7 @@ testAsyncMulti("livedata - basic method invocation", [
function (test, expect) {
if (Meteor.isClient) {
// For test isolation
- var token = Meteor.uuid();
+ var token = Random.id();
Meteor.apply(
"delayedTrue", [token], {wait: false}, expect(function(err, res) {
test.equal(res, false);
@@ -149,7 +149,7 @@ testAsyncMulti("livedata - basic method invocation", [
// test that `wait: true` is respected
function(test, expect) {
if (Meteor.isClient) {
- var token = Meteor.uuid();
+ var token = Random.id();
Meteor.apply(
"delayedTrue", [token], {wait: true}, expect(function(err, res) {
test.equal(res, true);
@@ -378,7 +378,7 @@ if (Meteor.isClient) {
undoEavesdrop();
});
}, function(test, expect) {
- var key = Meteor.uuid();
+ var key = Random.id();
Meteor.subscribe("recordUserIdOnStop", key);
Meteor.apply("setUserId", [100], {wait: true}, expect(function () {}));
Meteor.apply("setUserId", [101], {wait: true}, expect(function () {}));
@@ -401,7 +401,7 @@ if (Meteor.isClient) {
testAsyncMulti("livedata - overlapping universal subs", [
function (test, expect) {
var coll = new Meteor.Collection("overlappingUniversalSubs");
- var token = Meteor.uuid();
+ var token = Random.id();
test.isFalse(coll.findOne(token));
Meteor.call("testOverlappingSubs", token, expect(function (err) {
test.isFalse(err);
@@ -413,7 +413,7 @@ if (Meteor.isClient) {
testAsyncMulti("livedata - runtime universal sub creation", [
function (test, expect) {
var coll = new Meteor.Collection("runtimeSubCreation");
- var token = Meteor.uuid();
+ var token = Random.id();
test.isFalse(coll.findOne(token));
Meteor.call("runtimeUniversalSubCreation", token, expect(function (err) {
test.isFalse(err);
@@ -436,7 +436,7 @@ if (Meteor.isClient) {
// conn._subscriptions is empty.
var conn = new Meteor._LivedataConnection('/',
{reloadWithOutstanding: true});
- var collName = Meteor.id();
+ var collName = Random.id();
var coll = new Meteor.Collection(collName, {manager: conn});
var errorFromRerun;
var gotErrorFromStopper = false;
diff --git a/packages/livedata/package.js b/packages/livedata/package.js
index bfa72cc69b..8563defe91 100644
--- a/packages/livedata/package.js
+++ b/packages/livedata/package.js
@@ -4,7 +4,7 @@ Package.describe({
});
Package.on_use(function (api) {
- api.use(['stream', 'uuid']);
+ api.use(['stream', 'random']);
api.use(['ejson', 'json', 'underscore', 'deps', 'logging'], ['client', 'server']);
// livedata_connection.js uses a Minimongo collection internally to
diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js
index 7b52f48c0c..6bbd84a331 100644
--- a/packages/minimongo/minimongo.js
+++ b/packages/minimongo/minimongo.js
@@ -375,7 +375,7 @@ LocalCollection.prototype.insert = function (doc) {
// if you really want to use ObjectIDs, set this global.
// Meteor.Collection specifies its own ids and does not use this code.
doc._id = LocalCollection._useOID ? new LocalCollection._ObjectID()
- : LocalCollection.id();
+ : Random.id();
}
var id = LocalCollection._idStringify(doc._id);
diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js
index 32d10cb4e1..0fe9d0b49d 100644
--- a/packages/minimongo/minimongo_tests.js
+++ b/packages/minimongo/minimongo_tests.js
@@ -1208,7 +1208,7 @@ Tinytest.add("minimongo - observe ordered", function (test) {
// test stop
handle.stop();
- var idA2 = LocalCollection.id();
+ var idA2 = Random.id();
c.insert({_id: idA2, a:2});
test.equal(operations.shift(), undefined);
diff --git a/packages/minimongo/objectid.js b/packages/minimongo/objectid.js
index 2cd6682e61..90d259dd11 100644
--- a/packages/minimongo/objectid.js
+++ b/packages/minimongo/objectid.js
@@ -18,7 +18,7 @@ LocalCollection._ObjectID = function (hexString) {
// meant to work with _.isEqual(), which relies on structural equality
self._str = hexString;
} else {
- self._str = LocalCollection._randomHexString(24);
+ self._str = Random.hexString(24);
}
};
diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js
index 7b88f59b3c..c7ee043b58 100644
--- a/packages/minimongo/package.js
+++ b/packages/minimongo/package.js
@@ -8,11 +8,10 @@ Package.on_use(function (api, where) {
// It would be sort of nice if minimongo didn't depend on
// underscore, so we could ship it separately.
- api.use(['underscore', 'json', 'ejson', 'ordered-dict'], where);
+ api.use(['underscore', 'json', 'ejson', 'ordered-dict', 'random'], where);
api.add_files([
'minimongo.js',
'selector.js',
- 'uuid.js',
'modify.js',
'diff.js',
'objectid.js'
diff --git a/packages/minimongo/uuid.js b/packages/minimongo/uuid.js
deleted file mode 100644
index dab9dd8fe5..0000000000
--- a/packages/minimongo/uuid.js
+++ /dev/null
@@ -1,171 +0,0 @@
-// XXX dups packages/uuid/uuid.js
-
-// LocalCollection.random() -- known good PRNG, replaces Math.random()
-// LocalCollection.uuid() -- returns RFC 4122 v4 UUID.
-
-// see http://baagoe.org/en/wiki/Better_random_numbers_for_javascript
-// for a full discussion and Alea implementation.
-
-// Copyright (C) 2010 by Johannes Baagøe
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use, copy,
-// modify, merge, publish, distribute, sublicense, and/or sell copies
-// of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-(function() {
-
-var HEX_DIGITS = "0123456789abcdef";
-var UNMISTAKABLE_CHARS = "23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz";
-
-LocalCollection._Alea = function () {
- function Mash() {
- var n = 0xefc8249d;
-
- var mash = function(data) {
- data = data.toString();
- for (var i = 0; i < data.length; i++) {
- n += data.charCodeAt(i);
- var h = 0.02519603282416938 * n;
- n = h >>> 0;
- h -= n;
- h *= n;
- n = h >>> 0;
- h -= n;
- n += h * 0x100000000; // 2^32
- }
- return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
- };
-
- mash.version = 'Mash 0.9';
- return mash;
- }
-
- return (function (args) {
- var s0 = 0;
- var s1 = 0;
- var s2 = 0;
- var c = 1;
-
- if (args.length == 0) {
- args = [+new Date];
- }
- var mash = Mash();
- s0 = mash(' ');
- s1 = mash(' ');
- s2 = mash(' ');
-
- for (var i = 0; i < args.length; i++) {
- s0 -= mash(args[i]);
- if (s0 < 0) {
- s0 += 1;
- }
- s1 -= mash(args[i]);
- if (s1 < 0) {
- s1 += 1;
- }
- s2 -= mash(args[i]);
- if (s2 < 0) {
- s2 += 1;
- }
- }
- mash = null;
-
- var random = function() {
- var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
- s0 = s1;
- s1 = s2;
- return s2 = t - (c = t | 0);
- };
- random.uint32 = function() {
- return random() * 0x100000000; // 2^32
- };
- random.fract53 = function() {
- return random() +
- (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
- };
- random.version = 'Alea 0.9';
- random.args = args;
- return random;
-
- } (Array.prototype.slice.call(arguments)));
-}
-
-// instantiate RNG. Heuristically collect entropy from various sources
-
-// client sources
-var height = (typeof window !== 'undefined' && window.innerHeight) ||
- (typeof document !== 'undefined'
- && document.documentElement
- && document.documentElement.clientHeight) ||
- (typeof document !== 'undefined'
- && document.body
- && document.body.clientHeight) ||
- 1;
-
-var width = (typeof window !== 'undefined' && window.innerWidth) ||
- (typeof document !== 'undefined'
- && document.documentElement
- && document.documentElement.clientWidth) ||
- (typeof document !== 'undefined'
- && document.body
- && document.body.clientWidth) ||
- 1;
-
-var agent = (typeof navigator !== 'undefined' && navigator.userAgent) || "";
-
-// server sources
-var pid = (typeof process !== 'undefined' && process.pid) || 1;
-
-LocalCollection.random = new LocalCollection._Alea([
- new Date(), height, width, agent, pid, Math.random()]);
-
-LocalCollection._randomHexString = function (len) {
- var digits = [];
- for (var i = 0; i < len; i++) {
- digits[i] = HEX_DIGITS.substr(Math.floor(LocalCollection.random() * 0x10),
- 1);
- }
- return digits.join("");
-};
-
-// RFC 4122 v4 UUID.
-LocalCollection.uuid = function () {
- var s = [];
- for (var i = 0; i < 36; i++) {
- s[i] = HEX_DIGITS.substr(Math.floor(LocalCollection.random() * 0x10), 1);
- }
- s[14] = "4";
- s[19] = HEX_DIGITS.substr((parseInt(s[19],16) & 0x3) | 0x8, 1);
- s[8] = s[13] = s[18] = s[23] = "-";
-
- var uuid = s.join("");
- return uuid;
-};
-
-LocalCollection.id = function() {
- var digits = [];
- var base = UNMISTAKABLE_CHARS.length;
- // Length of 17 preserves around 96 bits of entropy, which is the
- // amount of state in our PRNG
- for (var i = 0; i < 17; i++) {
- digits[i] = UNMISTAKABLE_CHARS.substr(Math.floor(LocalCollection.random() * base), 1);
- }
- return digits.join("");
-};
-
-})();
diff --git a/packages/mongo-livedata/collection.js b/packages/mongo-livedata/collection.js
index 11c245645e..45ecd1ae62 100644
--- a/packages/mongo-livedata/collection.js
+++ b/packages/mongo-livedata/collection.js
@@ -28,7 +28,7 @@ Meteor.Collection = function (name, options) {
case 'STRING':
default:
self._makeNewID = function () {
- return LocalCollection.id();
+ return Random.id();
};
break;
}
@@ -201,7 +201,7 @@ Meteor.Collection._rewriteSelector = function (selector) {
if (!selector || (('_id' in selector) && !selector._id))
// can't match anything
- return {_id: LocalCollection.id()};
+ return {_id: Random.id()};
var ret = {};
_.each(selector, function (value, key) {
diff --git a/packages/mongo-livedata/mongo_livedata_tests.js b/packages/mongo-livedata/mongo_livedata_tests.js
index 7fdea4728d..097452c71d 100644
--- a/packages/mongo-livedata/mongo_livedata_tests.js
+++ b/packages/mongo-livedata/mongo_livedata_tests.js
@@ -229,8 +229,8 @@ Tinytest.addAsync("mongo-livedata - fuzz test, " + idGeneration, function(test,
// Use non-deterministic randomness so we can have a shorter fuzz
// test (fewer iterations). For deterministic (fully seeded)
- // randomness, remove the call to Math.random().
- var seededRandom = new SeededRandom("foobard" + Math.random());
+ // randomness, remove the call to Random.fraction().
+ var seededRandom = new SeededRandom("foobard" + Random.fraction());
// Random integer in [0,n)
var rnd = function (n) {
return seededRandom.nextIntBetween(0, n-1);
@@ -545,7 +545,7 @@ if (Meteor.isServer) {
testAsyncMulti('mongo-livedata - rewrite selector, ' + idGeneration, [
function (test, expect) {
- var collectionName = Meteor.uuid();
+ var collectionName = Random.id();
if (Meteor.isClient) {
Meteor.call('createInsecureCollection', collectionName, collectionOptions);
Meteor.subscribe('c-' + collectionName);
@@ -583,7 +583,7 @@ testAsyncMulti('mongo-livedata - rewrite selector, ' + idGeneration, [
testAsyncMulti('mongo-livedata - empty documents, ' + idGeneration, [
function (test, expect) {
- var collectionName = Meteor.uuid();
+ var collectionName = Random.id();
if (Meteor.isClient) {
Meteor.call('createInsecureCollection', collectionName);
Meteor.subscribe('c-' + collectionName);
@@ -604,7 +604,7 @@ testAsyncMulti('mongo-livedata - empty documents, ' + idGeneration, [
testAsyncMulti('mongo-livedata - document with a date, ' + idGeneration, [
function (test, expect) {
- var collectionName = Meteor.uuid();
+ var collectionName = Random.id();
if (Meteor.isClient) {
Meteor.call('createInsecureCollection', collectionName, collectionOptions);
Meteor.subscribe('c-' + collectionName);
@@ -633,7 +633,7 @@ testAsyncMulti('mongo-livedata - document with binary data, ' + idGeneration, [
"dCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdl" +
"bmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9y" +
"dCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=");
- var collectionName = Meteor.uuid();
+ var collectionName = Random.id();
if (Meteor.isClient) {
Meteor.call('createInsecureCollection', collectionName, collectionOptions);
Meteor.subscribe('c-' + collectionName);
@@ -658,7 +658,7 @@ testAsyncMulti('mongo-livedata - document with binary data, ' + idGeneration, [
testAsyncMulti('mongo-livedata - specified _id', [
function (test, expect) {
- var collectionName = Meteor.uuid();
+ var collectionName = Random.id();
if (Meteor.isClient) {
Meteor.call('createInsecureCollection', collectionName);
Meteor.subscribe('c-' + collectionName);
diff --git a/packages/mongo-livedata/observe_changes_tests.js b/packages/mongo-livedata/observe_changes_tests.js
index e1fa9eecf1..908da0f180 100644
--- a/packages/mongo-livedata/observe_changes_tests.js
+++ b/packages/mongo-livedata/observe_changes_tests.js
@@ -2,7 +2,7 @@
var makeCollection = function () {
if (Meteor.isServer)
- return new Meteor.Collection(Meteor.id());
+ return new Meteor.Collection(Random.id());
else
return new Meteor.Collection(null);
};
diff --git a/packages/mongo-livedata/package.js b/packages/mongo-livedata/package.js
index 47f7ad5114..49a36c5614 100644
--- a/packages/mongo-livedata/package.js
+++ b/packages/mongo-livedata/package.js
@@ -13,7 +13,7 @@ Package.describe({
});
Package.on_use(function (api) {
- api.use(['uuid', 'ejson', 'json', 'underscore', 'minimongo', 'logging', 'livedata'],
+ api.use(['random', 'ejson', 'json', 'underscore', 'minimongo', 'logging', 'livedata'],
['client', 'server']);
api.add_files('mongo_driver.js', 'server');
diff --git a/packages/past/past.js b/packages/past/past.js
index 033fbcce12..45b9b4fb66 100644
--- a/packages/past/past.js
+++ b/packages/past/past.js
@@ -11,3 +11,19 @@ Meteor.deps.Context.prototype.on_invalidate =
// We used to require a special "autosubscribe" call to reactively subscribe to
// things. Now, it works with autorun.
Meteor.autosubscribe = Meteor.autorun;
+
+// Instead of the "random" package with Random.id(), we used to have this
+// Meteor.uuid() implementing the RFC 4122 v4 UUID.
+Meteor.uuid = function () {
+ var HEX_DIGITS = "0123456789abcdef";
+ var s = [];
+ for (var i = 0; i < 36; i++) {
+ s[i] = Random.choice(HEX_DIGITS);
+ }
+ s[14] = "4";
+ s[19] = HEX_DIGITS.substr((parseInt(s[19],16) & 0x3) | 0x8, 1);
+ s[8] = s[13] = s[18] = s[23] = "-";
+
+ var uuid = s.join("");
+ return uuid;
+};
diff --git a/packages/uuid/package.js b/packages/random/package.js
similarity index 57%
rename from packages/uuid/package.js
rename to packages/random/package.js
index 0cfea8b7d4..18f30588a1 100644
--- a/packages/uuid/package.js
+++ b/packages/random/package.js
@@ -1,9 +1,9 @@
Package.describe({
- summary: "Better random number and UUIDv4 generators",
+ summary: "Random number generator and utilities",
internal: true
});
Package.on_use(function (api, where) {
where = where || ['client', 'server'];
- api.add_files('uuid.js', where);
+ api.add_files('random.js', where);
});
diff --git a/packages/uuid/uuid.js b/packages/random/random.js
similarity index 61%
rename from packages/uuid/uuid.js
rename to packages/random/random.js
index 90854020db..b5f1b43abc 100644
--- a/packages/uuid/uuid.js
+++ b/packages/random/random.js
@@ -1,38 +1,10 @@
-// XXX dups packages/minimongo/uuid.js
+(function() {
-// Meteor.random() -- known good PRNG, replaces Math.random()
-// Meteor.uuid() -- returns RFC 4122 v4 UUID.
+Random = {};
// see http://baagoe.org/en/wiki/Better_random_numbers_for_javascript
// for a full discussion and Alea implementation.
-
-// Copyright (C) 2010 by Johannes Baagøe
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use, copy,
-// modify, merge, publish, distribute, sublicense, and/or sell copies
-// of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-(function() {
-
-var HEX_DIGITS = "0123456789abcdef";
-var UNMISTAKABLE_CHARS = "23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz";
-
-var Alea = Meteor._Alea = function () {
+Random._Alea = function () {
function Mash() {
var n = 0xefc8249d;
@@ -103,7 +75,7 @@ var Alea = Meteor._Alea = function () {
return random;
} (Array.prototype.slice.call(arguments)));
-}
+};
// instantiate RNG. Heuristically collect entropy from various sources
@@ -131,32 +103,38 @@ var agent = (typeof navigator !== 'undefined' && navigator.userAgent) || "";
// server sources
var pid = (typeof process !== 'undefined' && process.pid) || 1;
-Meteor.random = new Alea([
+// XXX On the server, use the crypto module (OpenSSL) instead of this PRNG.
+// (Make Random.fraction be generated from Random.hexString instead of the
+// other way around, and generate Random.hexString from crypto.randomBytes.)
+Random.fraction = new Random._Alea([
new Date(), height, width, agent, pid, Math.random()]);
-// RFC 4122 v4 UUID.
-Meteor.uuid = function () {
- var s = [];
- for (var i = 0; i < 36; i++) {
- s[i] = HEX_DIGITS.substr(Math.floor(Meteor.random() * 0x10), 1);
- }
- s[14] = "4";
- s[19] = HEX_DIGITS.substr((parseInt(s[19],16) & 0x3) | 0x8, 1);
- s[8] = s[13] = s[18] = s[23] = "-";
-
- var uuid = s.join("");
- return uuid;
+Random.choice = function (arrayOrString) {
+ var index = Math.floor(Random.fraction() * arrayOrString.length);
+ if (typeof arrayOrString === "string")
+ return arrayOrString.substr(index, 1);
+ else
+ return arrayOrString[index];
};
-Meteor.id = function() {
+var UNMISTAKABLE_CHARS = "23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz";
+Random.id = function() {
var digits = [];
- var base = UNMISTAKABLE_CHARS.length;
// Length of 17 preserves around 96 bits of entropy, which is the
// amount of state in our PRNG
for (var i = 0; i < 17; i++) {
- digits[i] = UNMISTAKABLE_CHARS.substr(Math.floor(Meteor.random() * base), 1);
+ digits[i] = Random.choice(UNMISTAKABLE_CHARS);
}
return digits.join("");
};
+var HEX_DIGITS = "0123456789abcdef";
+Random.hexString = function (digits) {
+ var hexDigits = [];
+ for (var i = 0; i < digits; ++i) {
+ hexDigits.push(Random.choice("0123456789abcdef"));
+ }
+ return hexDigits.join('');
+};
+
})();
diff --git a/packages/spark/package.js b/packages/spark/package.js
index 189ae6e56e..1383dd5ebc 100644
--- a/packages/spark/package.js
+++ b/packages/spark/package.js
@@ -4,7 +4,7 @@ Package.describe({
});
Package.on_use(function (api) {
- api.use(['underscore', 'uuid', 'domutils', 'liverange', 'universal-events'],
+ api.use(['underscore', 'random', 'domutils', 'liverange', 'universal-events'],
'client');
api.add_files(['spark.js', 'patch.js', 'convenience.js',
diff --git a/packages/spark/spark.js b/packages/spark/spark.js
index 5a33b5146a..48533e30fc 100644
--- a/packages/spark/spark.js
+++ b/packages/spark/spark.js
@@ -44,7 +44,7 @@ Spark._currentRenderer = (function () {
};
})();
-Spark._TAG = "_spark_" + Meteor.uuid();
+Spark._TAG = "_spark_" + Random.id();
// XXX document contract for each type of annotation?
Spark._ANNOTATION_NOTIFY = "notify";
Spark._ANNOTATION_DATA = "data";
@@ -106,16 +106,6 @@ var withEventGuard = function (func) {
finally { eventGuardActive = previous; }
};
-Spark._createId = function () {
- // Chars can't include '-' to be safe inside HTML comments.
- var chars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_";
- var id = "";
- for (var i = 0; i < 8; i++)
- id += chars.substr(Math.floor(Meteor.random() * 64), 1);
- return id;
-};
-
Spark._Renderer = function () {
// Map from annotation ID to an annotation function, which is called
// at render time and receives (startNode, endNode).
@@ -164,7 +154,7 @@ _.extend(Spark._Renderer.prototype, {
// unescaped < and > in HTML attribute values, where they are normally
// safe. We can't assume that a string like '<1>' came from us
// and not arbitrary user-entered data.
- var id = (type || '') + ":" + Spark._createId();
+ var id = (type || '') + ":" + Random.id();
this.annotations[id] = function (start, end) {
if ((! start) || (! type)) {
// ! start: materialize called us with no args because this
@@ -1100,7 +1090,7 @@ Spark.labelBranch = function (label, htmlFunc) {
return htmlFunc();
if (label === Spark.UNIQUE_LABEL)
- label = Spark._createId();
+ label = Random.id();
renderer.currentBranch.pushLabel(label);
var html = htmlFunc();
diff --git a/packages/spark/spark_tests.js b/packages/spark/spark_tests.js
index bf78da9dd0..6e3acdeaa2 100644
--- a/packages/spark/spark_tests.js
+++ b/packages/spark/spark_tests.js
@@ -1639,8 +1639,8 @@ Tinytest.add("spark - landmark patching", function(test) {
for(var i=0; i<5; i++) {
// Use non-deterministic randomness so we can have a shorter fuzz
// test (fewer iterations). For deterministic (fully seeded)
- // randomness, remove the call to Math.random().
- rand = new SeededRandom("preserved nodes "+i+" "+Math.random());
+ // randomness, remove the call to Random.fraction().
+ rand = new SeededRandom("preserved nodes "+i+" "+Random.fraction());
var R = ReactiveVar(false);
var structure = randomNodeList(null, 6);
@@ -1878,7 +1878,7 @@ Tinytest.add("spark - leaderboard, " + idGeneration, function(test) {
}));
var idGen;
if (idGeneration === 'STRING')
- idGen = LocalCollection.id;
+ idGen = Random.id;
else
idGen = function () { return new LocalCollection._ObjectID(); };
@@ -2550,7 +2550,7 @@ testAsyncMulti(
// This is quite a tricky implementation.
var withIframe = function(onReady1, onReady2) {
- var frameName = "submitframe"+String(Math.random()).slice(2);
+ var frameName = "submitframe"+String(Random.fraction()).slice(2);
var iframeDiv = OnscreenDiv(
Meteor.render(function() {
return '