Commit e5dfdf46 authored by Neil Fraser's avatar Neil Fraser

Improve randomness of UUIDs.

parent a239c720
...@@ -552,24 +552,43 @@ Blockly.tokenizeInterpolation = function(message) { ...@@ -552,24 +552,43 @@ Blockly.tokenizeInterpolation = function(message) {
return tokens; return tokens;
}; };
/**
* Legal characters for the unique ID.
* Should be all on a US keyboard. No XML special characters or control codes.
* @private
*/
Blockly.CHARACTER_SOUP_ = '!#$%()*+,-./:;=?@[]^_`{|}~' +
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
/** /**
* Generate a unique ID. This should be globally unique. * Generate a unique ID. This should be globally unique.
* 88 characters ^ 20 length ≈ 129 bits (one bit better than a UUID). * 88 characters ^ 20 length ≈ 129 bits (one bit better than a UUID).
* @return {string} * @return {string}
*/ */
Blockly.genUid = function() { Blockly.genUid = function() {
var length = 20;
var soupLength = Blockly.genUid.soup_.length;
var id = []; var id = [];
for (var i = 0; i < 20; i++) { if (Blockly.genUid.crypto_) {
id[i] = Blockly.CHARACTER_SOUP_.charAt(Math.random() * // Cryptographically strong randomness is supported.
Blockly.CHARACTER_SOUP_.length); var array = new Uint32Array(length);
Blockly.genUid.crypto_.getRandomValues(array);
for (var i = 0; i < length; i++) {
id[i] = Blockly.genUid.soup_.charAt(array[i] % soupLength);
}
} else {
// Fall back to Math.random for IE 10.
for (var i = 0; i < length; i++) {
id[i] = Blockly.genUid.soup_.charAt(Math.random() * soupLength);
}
} }
return id.join(''); return id.join('');
}; };
/**
* Determine if window.crypto or global.crypto exists.
* @type {=RandomSource}
* @private
*/
Blockly.genUid.crypto_ = this.crypto;
/**
* Legal characters for the unique ID.
* Should be all on a US keyboard. No XML special characters or control codes.
* @private
*/
Blockly.genUid.soup_ = '!#$%()*+,-./:;=?@[]^_`{|}~' +
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
...@@ -20,9 +20,12 @@ ...@@ -20,9 +20,12 @@
'use strict'; 'use strict';
function test_genUid() { function test_genUid() {
var a = Blockly.genUid(); var uuids = {};
var b = Blockly.genUid(); for (var i = 0; i < 1000; i++) {
assertFalse('UUID different', a == b); var uuid = Blockly.genUid();
assertFalse('UUID different: ' + uuid, uuid in uuids);
uuids[uuid] = true;
}
} }
function test_addClass() { function test_addClass() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment