Ensure clone methods create maps and sets from other realms.

This commit is contained in:
John-David Dalton
2015-09-10 19:05:25 -07:00
parent e50734a6fb
commit 8e0011d07a
2 changed files with 86 additions and 47 deletions

View File

@@ -976,28 +976,6 @@
return object; return object;
} }
/**
* Creates a map from key-value `pairs`.
*
* @private
* @param {Array} pairs The key-value pairs to add.
* @returns {Object} Returns the new map.
*/
function createMap(pairs) {
return arrayReduce(pairs, addMapEntry, new Map);
}
/**
* Creates a set from `values`.
*
* @private
* @param {Array} values The values to add.
* @returns {Object} Returns the new set.
*/
function createSet(values) {
return arrayReduce(values, addSetEntry, new Set);
}
/** /**
* Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters. * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
* *
@@ -3113,20 +3091,75 @@
} }
/** /**
* Creates a clone of the given array buffer. * Creates a clone of `buffer`.
* *
* @private * @private
* @param {ArrayBuffer} buffer The array buffer to clone. * @param {ArrayBuffer} buffer The array buffer to clone.
* @returns {ArrayBuffer} Returns the cloned array buffer. * @returns {ArrayBuffer} Returns the cloned array buffer.
*/ */
function cloneBuffer(buffer) { function cloneBuffer(buffer) {
var result = new ArrayBuffer(buffer.byteLength), var Ctor = buffer.constructor,
result = new Ctor(buffer.byteLength),
view = new Uint8Array(result); view = new Uint8Array(result);
view.set(new Uint8Array(buffer)); view.set(new Uint8Array(buffer));
return result; return result;
} }
/**
* Creates a clone of `map`.
*
* @private
* @param {Object} map The map to clone.
* @returns {Object} Returns the cloned map.
*/
function cloneMap(map) {
var Ctor = map.constructor;
return arrayReduce(mapToArray(map), addMapEntry, new Ctor);
}
/**
* Creates a clone of `regexp`.
*
* @private
* @param {Object} regexp The regexp to clone.
* @returns {Object} Returns the cloned regexp.
*/
function cloneRegExp(regexp) {
var Ctor = regexp.constructor,
result = new Ctor(regexp.source, reFlags.exec(regexp));
result.lastIndex = regexp.lastIndex;
return result;
}
/**
* Creates a clone of `set`.
*
* @private
* @param {Object} set The set to clone.
* @returns {Object} Returns the cloned set.
*/
function cloneSet(set) {
var Ctor = set.constructor;
return arrayReduce(setToArray(set), addSetEntry, new Ctor);
}
/**
* Creates a clone of `typedArray`.
*
* @private
* @param {Object} typedArray The typed array to clone.
* @param {boolean} [isDeep] Specify a deep clone.
* @returns {Object} Returns the cloned typed array.
*/
function cloneTypedArray(typedArray, isDeep) {
var buffer = typedArray.buffer,
Ctor = typedArray.constructor;
return new Ctor(isDeep ? cloneBuffer(buffer) : buffer, typedArray.byteOffset, typedArray.length);
}
/** /**
* Creates an array that is the composition of partially applied arguments, * Creates an array that is the composition of partially applied arguments,
* placeholders, and provided arguments into a single array of arguments. * placeholders, and provided arguments into a single array of arguments.
@@ -4088,24 +4121,21 @@
case float32Tag: case float64Tag: case float32Tag: case float64Tag:
case int8Tag: case int16Tag: case int32Tag: case int8Tag: case int16Tag: case int32Tag:
case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
var buffer = object.buffer; return cloneTypedArray(object, isDeep);
return new Ctor(isDeep ? cloneBuffer(buffer) : buffer, object.byteOffset, object.length);
case mapTag: case mapTag:
return createMap(mapToArray(object)); return cloneMap(object);
case numberTag: case numberTag:
case stringTag: case stringTag:
return new Ctor(object); return new Ctor(object);
case setTag: case setTag:
return createSet(setToArray(object)); return cloneSet(object);
case regexpTag: case regexpTag:
var result = new Ctor(object.source, reFlags.exec(object)); return cloneRegExp(object);
result.lastIndex = object.lastIndex;
} }
return result;
} }
/** /**

View File

@@ -449,24 +449,29 @@
_.attempt(function() { _.attempt(function() {
_.extend(_, require('vm').runInNewContext([ _.extend(_, require('vm').runInNewContext([
'(function() {', '(function() {',
' var object = {', ' var root = this;',
" '_arguments': (function() { return arguments; }(1, 2, 3)),", '',
" '_array': [1, 2, 3],", ' var object = {',
" '_boolean': Object(false),", " '_arguments': (function() { return arguments; }(1, 2, 3)),",
" '_date': new Date,", " '_array': [1, 2, 3],",
" '_errors': [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError],", " '_arrayBuffer': new (this.ArrayByffer || Object),",
" '_function': function() {},", " '_boolean': Object(false),",
" '_nan': NaN,", " '_date': new Date,",
" '_null': null,", " '_errors': [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError],",
" '_number': Object(0),", " '_function': function() {},",
" '_object': { 'a': 1, 'b': 2, 'c': 3 },", " '_map': new (root.Map || Object),",
" '_regexp': /x/,", " '_nan': NaN,",
" '_string': Object('a'),", " '_null': null,",
" '_undefined': undefined", " '_number': Object(0),",
" '_object': { 'a': 1, 'b': 2, 'c': 3 },",
" '_regexp': /x/,",
" '_set': new (root.Set || Object),",
" '_string': Object('a'),",
" '_undefined': undefined",
' };', ' };',
'', '',
" ['" + typedArrays.join("', '") + "'].forEach(function(type) {", " ['" + typedArrays.join("', '") + "'].forEach(function(type) {",
" var Ctor = Function('return typeof ' + type + \" != 'undefined' && \" + type)()", " var Ctor = root[type]",
' if (Ctor) {', ' if (Ctor) {',
" object['_' + type.toLowerCase()] = new Ctor(new ArrayBuffer(24));", " object['_' + type.toLowerCase()] = new Ctor(new ArrayBuffer(24));",
' }', ' }',
@@ -486,22 +491,26 @@
var idoc = (idoc = iframe.contentDocument || iframe.contentWindow).document || idoc; var idoc = (idoc = iframe.contentDocument || iframe.contentWindow).document || idoc;
idoc.write([ idoc.write([
'<script>', '<script>',
'var root = this;',
'',
'parent._._arguments = (function() { return arguments; }(1, 2, 3));', 'parent._._arguments = (function() { return arguments; }(1, 2, 3));',
'parent._._array = [1, 2, 3];', 'parent._._array = [1, 2, 3];',
'parent._._arrayBuffer = new (this.ArrayByffer || Object);',
'parent._._boolean = Object(false);', 'parent._._boolean = Object(false);',
'parent._._date = new Date;', 'parent._._date = new Date;',
"parent._._element = document.createElement('div');", "parent._._element = document.createElement('div');",
'parent._._errors = [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError];', 'parent._._errors = [new Error, new EvalError, new RangeError, new ReferenceError, new SyntaxError, new TypeError, new URIError];',
'parent._._function = function() {};', 'parent._._function = function() {};',
'parent._._map = new (this.Map || Object);',
'parent._._nan = NaN;', 'parent._._nan = NaN;',
'parent._._null = null;', 'parent._._null = null;',
'parent._._number = Object(0);', 'parent._._number = Object(0);',
"parent._._object = { 'a': 1, 'b': 2, 'c': 3 };", "parent._._object = { 'a': 1, 'b': 2, 'c': 3 };",
'parent._._regexp = /x/;', 'parent._._regexp = /x/;',
'parent._._set = new (this.Set || Object);',
"parent._._string = Object('a');", "parent._._string = Object('a');",
'parent._._undefined = undefined;', 'parent._._undefined = undefined;',
'', '',
'var root = this;',
"parent._.each(['" + typedArrays.join("', '") + "'], function(type) {", "parent._.each(['" + typedArrays.join("', '") + "'], function(type) {",
' var Ctor = root[type];', ' var Ctor = root[type];',
' if (Ctor) {', ' if (Ctor) {',