Skip to content

Commit df5f7f3

Browse files
committed
Add polyfill tests
1 parent 22b56f1 commit df5f7f3

File tree

2 files changed

+152
-12
lines changed

2 files changed

+152
-12
lines changed

lib/node_modules/@stdlib/utils/keys/lib/polyfill.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,39 +50,38 @@ var NON_ENUMERABLE = require( './non_enumerable.json' );
5050
function keys( value ) {
5151
var skipConstructor;
5252
var skipPrototype;
53-
var isArgs;
5453
var isFcn;
5554
var out;
5655
var k;
5756
var p;
5857
var i;
5958

6059
out = [];
60+
if ( isArguments( value ) ) {
61+
// Account for environments which treat `arguments` differently...
62+
for ( i = 0; i < value.length; i++ ) {
63+
out.push( i.toString() );
64+
}
65+
// Note: yes, we are precluding the `arguments` array-like object from having other enumerable properties; however, this should (1) be very rare and (2) not be encouraged (e.g., doing something like `arguments.a = 'b'`; in certain engines directly manipulating the `arguments` value results in automatic de-optimization).
66+
return out;
67+
}
6168
if ( typeof value === 'string' ) {
6269
// Account for environments which do not treat string character indices as "own" properties...
6370
if ( value.length > 0 && !hasOwnProp( value, '0' ) ) {
6471
for ( i = 0; i < value.length; i++ ) {
6572
out.push( i.toString() );
6673
}
6774
}
68-
} else if ( isArguments( value ) ) {
69-
// Account for environments which treat `arguments` differently...
70-
isArgs = true;
71-
for ( i = 0; i < value.length; i++ ) {
72-
out.push( i.toString() );
73-
}
7475
} else {
7576
isFcn = ( typeof value === 'function' );
7677
if ( isFcn === false && !isObjectLike( value ) ) {
7778
return out;
7879
}
7980
skipPrototype = ( HAS_ENUM_PROTO_BUG && isFcn );
8081
}
81-
if ( isArgs === void 0 ) {
82-
for ( k in value ) {
83-
if ( !( skipPrototype && k === 'prototype' ) && hasOwnProp( value, k ) ) {
84-
out.push( String( k ) );
85-
}
82+
for ( k in value ) {
83+
if ( !( skipPrototype && k === 'prototype' ) && hasOwnProp( value, k ) ) {
84+
out.push( String( k ) );
8685
}
8786
}
8887
if ( HAS_NON_ENUM_PROPS_BUG ) {

lib/node_modules/@stdlib/utils/keys/test/test.polyfill.js

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
// MODULES //
2222

2323
var tape = require( 'tape' );
24+
var proxyquire = require( 'proxyquire' );
2425
var indexOf = require( '@stdlib/utils/index-of' );
2526
var hasSymbolSupport = require( '@stdlib/assert/has-symbol-support' );
27+
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
2628
var objectKeys = require( './../lib/polyfill.js' );
2729

2830

@@ -95,6 +97,145 @@ tape( 'the function returns an array of an object\'s own enumerable property nam
9597
t.end();
9698
});
9799

100+
tape( 'the function returns an array of an object\'s own enumerable property names (string; non-enumerable character indices)', function test( t ) {
101+
var objectKeys;
102+
var expected;
103+
var actual;
104+
var idx;
105+
var i;
106+
107+
objectKeys = proxyquire( './../lib/polyfill.js', {
108+
'@stdlib/assert/has-own-property': mock
109+
});
110+
111+
expected = [ '0', '1', '2' ];
112+
actual = objectKeys( 'foo' );
113+
114+
for ( i = 0; i < expected.length; i++ ) {
115+
idx = indexOf( actual, expected[ i ] );
116+
t.strictEqual( idx !== -1, true, 'contains property name: '+expected[i] );
117+
}
118+
t.end();
119+
120+
function mock( obj, prop ) {
121+
if ( obj === 'foo' ) {
122+
return false;
123+
}
124+
return hasOwnProp( obj, prop );
125+
}
126+
});
127+
128+
tape( 'the function returns an array of an object\'s own enumerable property names (function; environments having enumerable prototype bug)', function test( t ) {
129+
var objectKeys;
130+
var expected;
131+
var actual;
132+
133+
function noop() {
134+
// No-op...
135+
}
136+
137+
noop.a = 'b';
138+
139+
objectKeys = proxyquire( './../lib/polyfill.js', {
140+
'./has_enumerable_prototype_bug.js': true
141+
});
142+
143+
expected = [ 'a' ];
144+
actual = objectKeys( noop );
145+
146+
t.deepEqual( actual, expected, 'returns expected value' );
147+
t.end();
148+
});
149+
150+
tape( 'the function returns an array of an object\'s own enumerable property names (environments having non-enumerable properties bug)', function test( t ) {
151+
var objectKeys;
152+
var expected;
153+
var actual;
154+
var FLG;
155+
var obj;
156+
var idx;
157+
var i;
158+
159+
FLG = true;
160+
161+
objectKeys = proxyquire( './../lib/polyfill.js', {
162+
'./has_non_enumerable_properties_bug.js': true,
163+
'@stdlib/assert/has-own-property': mock
164+
});
165+
166+
obj = {
167+
'a': 'b',
168+
'toString': toString
169+
};
170+
expected = [ 'a', 'toString' ];
171+
actual = objectKeys( obj );
172+
173+
for ( i = 0; i < expected.length; i++ ) {
174+
idx = indexOf( actual, expected[ i ] );
175+
t.strictEqual( idx !== -1, true, 'contains property name: '+expected[i] );
176+
}
177+
t.end();
178+
179+
function toString() {
180+
return 'beep';
181+
}
182+
183+
function mock( obj, prop ) {
184+
if ( prop === 'toString' && hasOwnProp( obj, prop ) ) {
185+
FLG = !FLG;
186+
return FLG;
187+
}
188+
return hasOwnProp( obj, prop );
189+
}
190+
});
191+
192+
tape( 'the function returns an array of an object\'s own enumerable property names (environments having non-enumerable properties and constructor equality bugs)', function test( t ) {
193+
var objectKeys;
194+
var expected;
195+
var actual;
196+
var FLG;
197+
var obj;
198+
var idx;
199+
var i;
200+
201+
FLG = true;
202+
203+
objectKeys = proxyquire( './../lib/polyfill.js', {
204+
'./has_non_enumerable_properties_bug.js': true,
205+
'@stdlib/assert/has-own-property': mock
206+
});
207+
208+
obj = {
209+
'a': 'b',
210+
'toString': toString,
211+
'constructor': {
212+
'prototype': null
213+
}
214+
};
215+
obj.constructor.prototype = obj; // circular
216+
217+
expected = [ 'a', 'toString' ];
218+
actual = objectKeys( obj );
219+
220+
for ( i = 0; i < expected.length; i++ ) {
221+
idx = indexOf( actual, expected[ i ] );
222+
t.strictEqual( idx !== -1, true, 'contains property name: '+expected[i] );
223+
}
224+
t.end();
225+
226+
function toString() {
227+
return 'beep';
228+
}
229+
230+
function mock( obj, prop ) {
231+
if ( prop === 'toString' && hasOwnProp( obj, prop ) ) {
232+
FLG = !FLG;
233+
return FLG;
234+
}
235+
return hasOwnProp( obj, prop );
236+
}
237+
});
238+
98239
tape( 'the function ignores non-enumerable properties', function test( t ) {
99240
var expected;
100241
var actual;

0 commit comments

Comments
 (0)