Add hasEnumPrototype to avoid including the fix if not needed.

Former-commit-id: f826b725180a95d41b66612919c8b3fddfe568a0
This commit is contained in:
John-David Dalton
2013-02-01 01:24:34 -08:00
parent c3b984fea7
commit 8adb060edb
3 changed files with 33 additions and 15 deletions

View File

@@ -177,6 +177,7 @@
'bottom', 'bottom',
'firstArg', 'firstArg',
'hasDontEnumBug', 'hasDontEnumBug',
'hasEnumPrototype',
'isKeysFast', 'isKeysFast',
'loop', 'loop',
'nonEnumArgs', 'nonEnumArgs',
@@ -1924,8 +1925,9 @@
// remove `prototype` [[Enumerable]] fix from `iteratorTemplate` // remove `prototype` [[Enumerable]] fix from `iteratorTemplate`
source = source.replace(getIteratorTemplate(source), function(match) { source = source.replace(getIteratorTemplate(source), function(match) {
return match return match
.replace(/(?: *\/\/.*\n)* *["'] *(?:<% *)?if *\(!hasDontEnumBug *(?:&&|\))[\s\S]+?<% *} *(?:%>|["']).+/g, '') .replace(/(?: *\/\/.*\n)* *["']( *)<% *if *\(hasDontEnumBug[\s\S]+?["']\1<% *} *%>.+/, '')
.replace(/!hasDontEnumBug *\|\|/g, ''); .replace(/(?: *\/\/.*\n)* *["'] *(?:<% *)?if *\(hasEnumPrototype *(?:&&|\))[\s\S]+?<% *} *(?:%>|["']).+/g, '')
.replace(/hasEnumPrototype *\|\|/g, '');
}); });
} }
vm.runInContext(source, context); vm.runInContext(source, context);
@@ -2095,10 +2097,10 @@
} }
}); });
// remove `hasDontEnumBug`, `iteratesOwnLast`, and `nonEnumArgs` declarations and assignments // remove `hasDontEnumBug`, `hasEnumPrototype`, `iteratesOwnLast`, and `nonEnumArgs` declarations and assignments
source = source source = source
.replace(/^ *\(function\(\) *{[\s\S]+?}\(1\)\);\n/m, '') .replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var (?:hasDontEnumBug|hasEnumPrototype|iteratesOwnLast|nonEnumArgs).+\n/g, '')
.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var (?:hasDontEnumBug|iteratesOwnLast|nonEnumArgs).+\n/g, ''); .replace(/^ *\(function\(\) *{[\s\S]+?}\(1\)\);\n/m, '');
// remove `iteratesOwnLast` from `shimIsPlainObject` // remove `iteratesOwnLast` from `shimIsPlainObject`
source = source.replace(matchFunction(source, 'shimIsPlainObject'), function(match) { source = source.replace(matchFunction(source, 'shimIsPlainObject'), function(match) {
@@ -2256,6 +2258,7 @@
if ((source.match(/\bcreateIterator\b/g) || []).length < 2) { if ((source.match(/\bcreateIterator\b/g) || []).length < 2) {
source = removeFunction(source, 'createIterator'); source = removeFunction(source, 'createIterator');
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug;|.+?hasDontEnumBug *=.+/g, ''); source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug;|.+?hasDontEnumBug *=.+/g, '');
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasEnumPrototype;|.+?hasEnumPrototype *=.+/g, '');
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var nonEnumArgs;|.+?nonEnumArgs *=.+/g, ''); source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var nonEnumArgs;|.+?nonEnumArgs *=.+/g, '');
} }
if (isRemoved(source, 'createIterator', 'bind', 'keys')) { if (isRemoved(source, 'createIterator', 'bind', 'keys')) {
@@ -2267,8 +2270,8 @@
source = removeVar(source, 'nativeKeys'); source = removeVar(source, 'nativeKeys');
source = removeKeysOptimization(source); source = removeKeysOptimization(source);
} }
if (!source.match(/var (?:hasDontEnumBug|iteratesOwnLast|nonEnumArgs)\b/g)) { if (!source.match(/var (?:hasDontEnumBug|hasEnumPrototype|iteratesOwnLast|nonEnumArgs)\b/g)) {
// remove `hasDontEnumBug`, `iteratesOwnLast`, and `nonEnumArgs` assignments // remove `hasDontEnumBug`, `hasEnumPrototype`, `iteratesOwnLast`, and `nonEnumArgs` assignments
source = source.replace(/ *\(function\(\) *{[\s\S]+?}\(1\)\);\n/, ''); source = source.replace(/ *\(function\(\) *{[\s\S]+?}\(1\)\);\n/, '');
} }
} }

View File

@@ -40,6 +40,7 @@
'bottom', 'bottom',
'firstArg', 'firstArg',
'hasDontEnumBug', 'hasDontEnumBug',
'hasEnumPrototype',
'isKeysFast', 'isKeysFast',
'loop', 'loop',
'nonEnumArgs', 'nonEnumArgs',

View File

@@ -127,6 +127,18 @@
*/ */
var hasDontEnumBug; var hasDontEnumBug;
/**
* Detect if a `prototype` properties are enumerable by default:
*
* Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
* (if the prototype or a property on the prototype has been set)
* incorrectly sets a function's `prototype` property [[Enumerable]]
* value to `true`. Because of this Lo-Dash standardizes on skipping
* the the `prototype` property of functions regardless of its
* [[Enumerable]] value.
*/
var hasEnumPrototype;
/** Detect if own properties are iterated after inherited properties (IE < 9) */ /** Detect if own properties are iterated after inherited properties (IE < 9) */
var iteratesOwnLast; var iteratesOwnLast;
@@ -154,6 +166,7 @@
for (prop in arguments) { nonEnumArgs = !prop; } for (prop in arguments) { nonEnumArgs = !prop; }
hasDontEnumBug = !/valueOf/.test(props); hasDontEnumBug = !/valueOf/.test(props);
hasEnumPrototype = propertyIsEnumerable.call(ctor, 'prototype');
iteratesOwnLast = props[0] != 'x'; iteratesOwnLast = props[0] != 'x';
}(1)); }(1));
@@ -385,7 +398,7 @@
// value to `true`. Because of this Lo-Dash standardizes on skipping // value to `true`. Because of this Lo-Dash standardizes on skipping
// the the `prototype` property of functions regardless of its // the the `prototype` property of functions regardless of its
// [[Enumerable]] value. // [[Enumerable]] value.
' <% if (!hasDontEnumBug) { %>\n' + ' <% if (hasEnumPrototype) { %>\n' +
" var skipProto = typeof iterable == 'function' && \n" + " var skipProto = typeof iterable == 'function' && \n" +
" propertyIsEnumerable.call(iterable, 'prototype');\n" + " propertyIsEnumerable.call(iterable, 'prototype');\n" +
' <% } %>' + ' <% } %>' +
@@ -397,22 +410,22 @@
' length = ownProps.length;\n\n' + ' length = ownProps.length;\n\n' +
' while (++ownIndex < length) {\n' + ' while (++ownIndex < length) {\n' +
' index = ownProps[ownIndex];\n' + ' index = ownProps[ownIndex];\n' +
" <% if (!hasDontEnumBug) { %>if (!(skipProto && index == 'prototype')) {\n <% } %>" + " <% if (hasEnumPrototype) { %>if (!(skipProto && index == 'prototype')) {\n <% } %>" +
' <%= loop %>\n' + ' <%= loop %>\n' +
' <% if (!hasDontEnumBug) { %>}\n<% } %>' + ' <% if (hasEnumPrototype) { %>}\n<% } %>' +
' }' + ' }' +
// else using a for-in loop // else using a for-in loop
' <% } else { %>\n' + ' <% } else { %>\n' +
' for (index in iterable) {<%' + ' for (index in iterable) {<%' +
' if (!hasDontEnumBug || useHas) { %>\n if (<%' + ' if (hasEnumPrototype || useHas) { %>\n if (<%' +
" if (!hasDontEnumBug) { %>!(skipProto && index == 'prototype')<% }" + " if (hasEnumPrototype) { %>!(skipProto && index == 'prototype')<% }" +
' if (!hasDontEnumBug && useHas) { %> && <% }' + ' if (hasEnumPrototype && useHas) { %> && <% }' +
' if (useHas) { %>hasOwnProperty.call(iterable, index)<% }' + ' if (useHas) { %>hasOwnProperty.call(iterable, index)<% }' +
' %>) {' + ' %>) {' +
' <% } %>\n' + ' <% } %>\n' +
' <%= loop %>;' + ' <%= loop %>;' +
' <% if (!hasDontEnumBug || useHas) { %>\n }<% } %>\n' + ' <% if (hasEnumPrototype || useHas) { %>\n }<% } %>\n' +
' }' + ' }' +
' <% } %>' + ' <% } %>' +
@@ -678,6 +691,7 @@
var data = { var data = {
// support properties // support properties
'hasDontEnumBug': hasDontEnumBug, 'hasDontEnumBug': hasDontEnumBug,
'hasEnumPrototype': hasEnumPrototype,
'isKeysFast': isKeysFast, 'isKeysFast': isKeysFast,
'nonEnumArgs': nonEnumArgs, 'nonEnumArgs': nonEnumArgs,
'noCharByIndex': noCharByIndex, 'noCharByIndex': noCharByIndex,
@@ -931,7 +945,7 @@
*/ */
var keys = !nativeKeys ? shimKeys : function(object) { var keys = !nativeKeys ? shimKeys : function(object) {
// avoid iterating over the `prototype` property // avoid iterating over the `prototype` property
return typeof object == 'function' && propertyIsEnumerable.call(object, 'prototype') return hasEnumPrototype && typeof object == 'function' && propertyIsEnumerable.call(object, 'prototype')
? shimKeys(object) ? shimKeys(object)
: (isObject(object) ? nativeKeys(object) : []); : (isObject(object) ? nativeKeys(object) : []);
}; };