Skip to content

Commit

Permalink
Merge pull request #2986 from colingm/native-data-view
Browse files Browse the repository at this point in the history
Add nativeDataView check to isDataView
  • Loading branch information
jgonggrijp committed Sep 27, 2023
2 parents d122213 + dbb5475 commit 0bd9b48
Show file tree
Hide file tree
Showing 15 changed files with 80 additions and 37 deletions.
1 change: 1 addition & 0 deletions karma.conf-sauce.js
Expand Up @@ -63,6 +63,7 @@ module.exports = function(config) {
files: [
'test/vendor/qunit-extras.js',
'test/qunit-setup.js',
'test/overrides.js',
'underscore-umd.js',
'test/*.js'
],
Expand Down
1 change: 1 addition & 0 deletions karma.conf.js
Expand Up @@ -15,6 +15,7 @@ module.exports = function(config) {
// list of files / patterns to load in the browser
files: [
'test/qunit-setup.js',
'test/overrides.js',
'underscore-umd.js',
'test/*.js'
],
Expand Down
7 changes: 5 additions & 2 deletions modules/_stringTagBug.js
Expand Up @@ -4,7 +4,10 @@ import hasObjectTag from './_hasObjectTag.js';
// In IE 10 - Edge 13, `DataView` has string tag `'[object Object]'`.
// In IE 11, the most common among them, this problem also applies to
// `Map`, `WeakMap` and `Set`.
export var hasStringTagBug = (
supportsDataView && hasObjectTag(new DataView(new ArrayBuffer(8)))
// Also, there are cases where an application can override the native
// `DataView` object, in cases like that we can't use the constructor
// safely and should just rely on alternate `DataView` checks
export var hasDataViewBug = (
supportsDataView && (!/\[native code\]/.test(String(DataView)) || hasObjectTag(new DataView(new ArrayBuffer(8))))
),
isIE11 = (typeof Map !== 'undefined' && hasObjectTag(new Map));
8 changes: 5 additions & 3 deletions modules/isDataView.js
@@ -1,14 +1,16 @@
import tagTester from './_tagTester.js';
import isFunction from './isFunction.js';
import isArrayBuffer from './isArrayBuffer.js';
import { hasStringTagBug } from './_stringTagBug.js';
import { hasDataViewBug } from './_stringTagBug.js';

var isDataView = tagTester('DataView');

// In IE 10 - Edge 13, we need a different heuristic
// to determine whether an object is a `DataView`.
function ie10IsDataView(obj) {
// Also, in cases where the native `DataView` is
// overriden we can't rely on the tag itself.
function alternateIsDataView(obj) {
return obj != null && isFunction(obj.getInt8) && isArrayBuffer(obj.buffer);
}

export default (hasStringTagBug ? ie10IsDataView : isDataView);
export default (hasDataViewBug ? alternateIsDataView : isDataView);
4 changes: 2 additions & 2 deletions modules/isEqual.js
Expand Up @@ -3,7 +3,7 @@ import { toString, SymbolProto } from './_setup.js';
import getByteLength from './_getByteLength.js';
import isTypedArray from './isTypedArray.js';
import isFunction from './isFunction.js';
import { hasStringTagBug } from './_stringTagBug.js';
import { hasDataViewBug } from './_stringTagBug.js';
import isDataView from './isDataView.js';
import keys from './keys.js';
import has from './_has.js';
Expand Down Expand Up @@ -36,7 +36,7 @@ function deepEq(a, b, aStack, bStack) {
var className = toString.call(a);
if (className !== toString.call(b)) return false;
// Work around a bug in IE 10 - Edge 13.
if (hasStringTagBug && className == '[object Object]' && isDataView(a)) {
if (hasDataViewBug && className == '[object Object]' && isDataView(a)) {
if (!isDataView(b)) return false;
className = tagDataView;
}
Expand Down
1 change: 1 addition & 0 deletions test/index.html
Expand Up @@ -9,6 +9,7 @@
<div id="qunit"></div>
<div id="exports" style="display: none"></div>
<script src="vendor/qunit.js"></script>
<script src="overrides.js"></script>
<script src="../underscore-umd.js"></script>
<script src="qunit-setup.js"></script>
<script src="collections.js"></script>
Expand Down
17 changes: 10 additions & 7 deletions test/objects.js
Expand Up @@ -5,6 +5,9 @@

var testElement = typeof document === 'object' ? document.createElement('div') : void 0;

// Some browsers support typed arrays but not DataView and some applications could override DataView
var DataViewImpl = typeof NativeDataView !== 'undefined' ? NativeDataView : typeof DataView !== 'undefined' ? DataView : undefined;

QUnit.test('keys', function(assert) {
assert.deepEqual(_.keys({one: 1, two: 2}), ['one', 'two'], 'can extract the keys from an object');
// the test above is not safe because it relies on for-in enumeration order
Expand Down Expand Up @@ -610,11 +613,11 @@
assert.notOk(_.isEqual(view1, view2), 'same buffer with different offset is not equal');

// Some older browsers support typed arrays but not DataView.
if (typeof DataView !== 'undefined') {
assert.ok(_.isEqual(new DataView(u8.buffer), new DataView(u8b.buffer)), 'Identical DataViews are equal');
assert.ok(_.isEqual(new DataView(u8.buffer), new DataView(i8.buffer)), 'Identical DataViews of different typed arrays are equal');
assert.notOk(_.isEqual(new DataView(u8.buffer), new DataView(u16.buffer)), 'Different DataViews with different length are not equal');
assert.notOk(_.isEqual(new DataView(u8.buffer), new DataView(u16one.buffer)), 'Different DataViews with different byte data are not equal');
if (DataViewImpl) {
assert.ok(_.isEqual(new DataViewImpl(u8.buffer), new DataViewImpl(u8b.buffer)), 'Identical DataViews are equal');
assert.ok(_.isEqual(new DataViewImpl(u8.buffer), new DataViewImpl(i8.buffer)), 'Identical DataViews of different typed arrays are equal');
assert.notOk(_.isEqual(new DataViewImpl(u8.buffer), new DataViewImpl(u16.buffer)), 'Different DataViews with different length are not equal');
assert.notOk(_.isEqual(new DataViewImpl(u8.buffer), new DataViewImpl(u16one.buffer)), 'Different DataViews with different byte data are not equal');
}
}
});
Expand Down Expand Up @@ -931,8 +934,8 @@
'a TypedArray': new Uint8Array(buffer)
};
// Some older browsers support typed arrays but not DataView.
if (typeof DataView !== 'undefined') {
checkValues['a DataView'] = new DataView(buffer);
if (DataViewImpl) {
checkValues['a DataView'] = new DataViewImpl(buffer);
}
var types = ['an ArrayBuffer', 'a DataView', 'a TypedArray'];
_.each(types, function(type) {
Expand Down
12 changes: 12 additions & 0 deletions test/overrides.js
@@ -0,0 +1,12 @@
(function() {
function overrideDataView() {
NativeDataView = DataView;
DataView = {};
}

// Only override browser functions roughly 1/3rd of the time
var runOverrides = Math.floor(Math.random() * 3) === 0;
if (runOverrides) {
overrideDataView();
}
})();
15 changes: 10 additions & 5 deletions underscore-esm.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion underscore-esm.js.map

Large diffs are not rendered by default.

15 changes: 10 additions & 5 deletions underscore-node-f.cjs
Expand Up @@ -143,20 +143,25 @@ var hasObjectTag = tagTester('Object');
// In IE 10 - Edge 13, `DataView` has string tag `'[object Object]'`.
// In IE 11, the most common among them, this problem also applies to
// `Map`, `WeakMap` and `Set`.
var hasStringTagBug = (
supportsDataView && hasObjectTag(new DataView(new ArrayBuffer(8)))
// Also, there are cases where an application can override the native
// `DataView` object, in cases like that we can't use the constructor
// safely and should just rely on alternate `DataView` checks
var hasDataViewBug = (
supportsDataView && (!/\[native code\]/.test(String(DataView)) || hasObjectTag(new DataView(new ArrayBuffer(8))))
),
isIE11 = (typeof Map !== 'undefined' && hasObjectTag(new Map));

var isDataView = tagTester('DataView');

// In IE 10 - Edge 13, we need a different heuristic
// to determine whether an object is a `DataView`.
function ie10IsDataView(obj) {
// Also, in cases where the native `DataView` is
// overriden we can't rely on the tag itself.
function alternateIsDataView(obj) {
return obj != null && isFunction$1(obj.getInt8) && isArrayBuffer(obj.buffer);
}

var isDataView$1 = (hasStringTagBug ? ie10IsDataView : isDataView);
var isDataView$1 = (hasDataViewBug ? alternateIsDataView : isDataView);

// Is a given value an array?
// Delegates to ECMA5's native `Array.isArray`.
Expand Down Expand Up @@ -369,7 +374,7 @@ function deepEq(a, b, aStack, bStack) {
var className = toString.call(a);
if (className !== toString.call(b)) return false;
// Work around a bug in IE 10 - Edge 13.
if (hasStringTagBug && className == '[object Object]' && isDataView$1(a)) {
if (hasDataViewBug && className == '[object Object]' && isDataView$1(a)) {
if (!isDataView$1(b)) return false;
className = tagDataView;
}
Expand Down
2 changes: 1 addition & 1 deletion underscore-node-f.cjs.map

Large diffs are not rendered by default.

15 changes: 10 additions & 5 deletions underscore-umd.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion underscore-umd.js.map

Large diffs are not rendered by default.

15 changes: 10 additions & 5 deletions underscore.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 0bd9b48

Please sign in to comment.