@@ -10,6 +10,11 @@ function parseSyncLazy(filename, code, options = null) {
1010 return parseSync ( filename , code , { ...options , experimentalLazy : true } ) ;
1111}
1212
13+ // Get `NodeArray` constructor
14+ const NodeArray = Object . getPrototypeOf ( parseSyncLazy ( 'test.js' , '' ) . program . body ) . constructor ;
15+ expect ( NodeArray ) . not . toBe ( Array ) ;
16+ expect ( NodeArray . toString ( ) . startsWith ( 'class NodeArray extends Array {' ) ) . toBe ( true ) ;
17+
1318it ( 'parses' , ( ) => {
1419 const { program } = parseSyncLazy ( 'test.js' , 'let x = y + z;' ) ;
1520 expect ( program . type ) . toBe ( 'Program' ) ;
@@ -252,13 +257,128 @@ describe('NodeArray', () => {
252257 expect ( ( ) => body . shift ( ) ) . toThrow ( new TypeError ( 'Cannot redefine property: 0' ) ) ;
253258 } ) ;
254259
255- it ( 'slice' , ( ) => {
256- const { body } = parseSyncLazy ( 'test.js' , 'let x = 1; x = 2;' ) . program ;
257- const slice = body . slice ( 1 ) ;
258- expect ( Array . isArray ( slice ) ) . toBe ( true ) ;
259- expect ( Object . getPrototypeOf ( slice ) ) . toBe ( Array . prototype ) ;
260- expect ( slice ) . toHaveLength ( 1 ) ;
261- expect ( slice [ 0 ] ) . toBe ( body [ 1 ] ) ;
260+ describe ( 'slice' , ( ) => {
261+ class Case {
262+ constructor ( args , expected ) {
263+ this . args = args ;
264+ this . expected = expected ;
265+ }
266+
267+ toString ( ) {
268+ return `(${ this . args . map ( arg => JSON . stringify ( arg ) || 'undefined' ) . join ( ', ' ) } )` ;
269+ }
270+ }
271+
272+ it . each ( [
273+ // No args
274+ new Case ( [ ] , { start : 0 , length : 3 } ) ,
275+ // 1 arg integer
276+ new Case ( [ 1 ] , { start : 1 , length : 2 } ) ,
277+ new Case ( [ 2 ] , { start : 2 , length : 1 } ) ,
278+ new Case ( [ 3 ] , { start : 0 , length : 0 } ) ,
279+ new Case ( [ 4 ] , { start : 0 , length : 0 } ) ,
280+ // 1 arg negative integer
281+ new Case ( [ - 0 ] , { start : 0 , length : 3 } ) ,
282+ new Case ( [ - 1 ] , { start : 2 , length : 1 } ) ,
283+ new Case ( [ - 2 ] , { start : 1 , length : 2 } ) ,
284+ new Case ( [ - 3 ] , { start : 0 , length : 3 } ) ,
285+ new Case ( [ - 4 ] , { start : 0 , length : 3 } ) ,
286+ // 1 arg undefined/null
287+ new Case ( [ undefined ] , { start : 0 , length : 3 } ) ,
288+ new Case ( [ null ] , { start : 0 , length : 3 } ) ,
289+ // 1 arg non-integer
290+ new Case ( [ '0' ] , { start : 0 , length : 3 } ) ,
291+ new Case ( [ '2' ] , { start : 2 , length : 1 } ) ,
292+ new Case ( [ '-2' ] , { start : 1 , length : 2 } ) ,
293+ new Case ( [ '0x2' ] , { start : 2 , length : 1 } ) ,
294+ new Case ( [ 'oops' ] , { start : 0 , length : 3 } ) ,
295+ new Case ( [ false ] , { start : 0 , length : 3 } ) ,
296+ new Case ( [ true ] , { start : 1 , length : 2 } ) ,
297+ new Case ( [ { valueOf : ( ) => 1 } ] , { start : 1 , length : 2 } ) ,
298+ // 2 args integers
299+ new Case ( [ 0 , 0 ] , { start : 0 , length : 0 } ) ,
300+ new Case ( [ 0 , 1 ] , { start : 0 , length : 1 } ) ,
301+ new Case ( [ 0 , 2 ] , { start : 0 , length : 2 } ) ,
302+ new Case ( [ 0 , 3 ] , { start : 0 , length : 3 } ) ,
303+ new Case ( [ 0 , 4 ] , { start : 0 , length : 3 } ) ,
304+ new Case ( [ 1 , 2 ] , { start : 1 , length : 1 } ) ,
305+ new Case ( [ 1 , 3 ] , { start : 1 , length : 2 } ) ,
306+ new Case ( [ 1 , 4 ] , { start : 1 , length : 2 } ) ,
307+ new Case ( [ 3 , 3 ] , { start : 0 , length : 0 } ) ,
308+ new Case ( [ 3 , 5 ] , { start : 0 , length : 0 } ) ,
309+ new Case ( [ 3 , 0 ] , { start : 0 , length : 0 } ) ,
310+ // 2 args negative integers
311+ new Case ( [ - 1 , 3 ] , { start : 2 , length : 1 } ) ,
312+ new Case ( [ - 2 , 3 ] , { start : 1 , length : 2 } ) ,
313+ new Case ( [ - 3 , 3 ] , { start : 0 , length : 3 } ) ,
314+ new Case ( [ - 4 , 3 ] , { start : 0 , length : 3 } ) ,
315+ new Case ( [ - 2 , 5 ] , { start : 1 , length : 2 } ) ,
316+ new Case ( [ 0 , - 1 ] , { start : 0 , length : 2 } ) ,
317+ new Case ( [ 1 , - 1 ] , { start : 1 , length : 1 } ) ,
318+ new Case ( [ 2 , - 1 ] , { start : 0 , length : 0 } ) ,
319+ new Case ( [ 3 , - 1 ] , { start : 0 , length : 0 } ) ,
320+ new Case ( [ 0 , - 0 ] , { start : 0 , length : 0 } ) ,
321+ new Case ( [ - 2 , - 1 ] , { start : 1 , length : 1 } ) ,
322+ new Case ( [ - 3 , - 1 ] , { start : 0 , length : 2 } ) ,
323+ new Case ( [ - 3 , - 4 ] , { start : 0 , length : 0 } ) ,
324+ // 2 args undefined/null
325+ new Case ( [ undefined , undefined ] , { start : 0 , length : 3 } ) ,
326+ new Case ( [ null , null ] , { start : 0 , length : 0 } ) ,
327+ new Case ( [ null , undefined ] , { start : 0 , length : 3 } ) ,
328+ new Case ( [ undefined , null ] , { start : 0 , length : 0 } ) ,
329+ new Case ( [ undefined , 1 ] , { start : 0 , length : 1 } ) ,
330+ new Case ( [ undefined , 3 ] , { start : 0 , length : 3 } ) ,
331+ new Case ( [ undefined , 4 ] , { start : 0 , length : 3 } ) ,
332+ new Case ( [ undefined , - 1 ] , { start : 0 , length : 2 } ) ,
333+ new Case ( [ undefined , 0 ] , { start : 0 , length : 0 } ) ,
334+ new Case ( [ null , 1 ] , { start : 0 , length : 1 } ) ,
335+ new Case ( [ null , 3 ] , { start : 0 , length : 3 } ) ,
336+ new Case ( [ null , 4 ] , { start : 0 , length : 3 } ) ,
337+ new Case ( [ null , - 1 ] , { start : 0 , length : 2 } ) ,
338+ new Case ( [ null , 0 ] , { start : 0 , length : 0 } ) ,
339+ new Case ( [ 0 , undefined ] , { start : 0 , length : 3 } ) ,
340+ new Case ( [ 1 , undefined ] , { start : 1 , length : 2 } ) ,
341+ new Case ( [ 2 , undefined ] , { start : 2 , length : 1 } ) ,
342+ new Case ( [ 3 , undefined ] , { start : 0 , length : 0 } ) ,
343+ new Case ( [ 4 , undefined ] , { start : 0 , length : 0 } ) ,
344+ new Case ( [ - 2 , undefined ] , { start : 1 , length : 2 } ) ,
345+ new Case ( [ - 3 , undefined ] , { start : 0 , length : 3 } ) ,
346+ new Case ( [ - 5 , undefined ] , { start : 0 , length : 3 } ) ,
347+ new Case ( [ 0 , null ] , { start : 0 , length : 0 } ) ,
348+ new Case ( [ 1 , null ] , { start : 0 , length : 0 } ) ,
349+ new Case ( [ 3 , null ] , { start : 0 , length : 0 } ) ,
350+ new Case ( [ - 2 , null ] , { start : 0 , length : 0 } ) ,
351+ new Case ( [ - 3 , null ] , { start : 0 , length : 0 } ) ,
352+ new Case ( [ - 5 , null ] , { start : 0 , length : 0 } ) ,
353+ // 2 args non-integers
354+ new Case ( [ '0' , '2' ] , { start : 0 , length : 2 } ) ,
355+ new Case ( [ '0' , '-2' ] , { start : 0 , length : 1 } ) ,
356+ new Case ( [ '1' , '-1' ] , { start : 1 , length : 1 } ) ,
357+ new Case ( [ '0x1' , '0x2' ] , { start : 1 , length : 1 } ) ,
358+ new Case ( [ 0 , 'oops' ] , { start : 0 , length : 0 } ) ,
359+ new Case ( [ false , true ] , { start : 0 , length : 1 } ) ,
360+ new Case ( [ true , true ] , { start : 0 , length : 0 } ) ,
361+ new Case ( [ 1 , { valueOf : ( ) => 2 } ] , { start : 1 , length : 1 } ) ,
362+ ] ) ( '%s' , ( { args, expected } ) => {
363+ const { body } = parseSyncLazy ( 'test.js' , 'let x = 1; x = 2; x = 3;' ) . program ;
364+ const slice = body . slice ( ...args ) ;
365+ expect ( Array . isArray ( slice ) ) . toBe ( true ) ;
366+ expect ( Object . getPrototypeOf ( slice ) ) . toBe ( NodeArray . prototype ) ;
367+ expect ( slice . length ) . toBe ( expected . length ) ;
368+
369+ for ( let i = 0 ; i < expected . length ; i ++ ) {
370+ expect ( slice [ i ] ) . toBe ( body [ i + expected . start ] ) ;
371+ }
372+
373+ // Check `Array.prototype.slice` behaves the same
374+ const arr = [ 11 , 22 , 33 ] ;
375+ const arrSlice = arr . slice ( ...args ) ;
376+ expect ( arrSlice . length ) . toBe ( expected . length ) ;
377+
378+ for ( let i = 0 ; i < expected . length ; i ++ ) {
379+ expect ( arrSlice [ i ] ) . toBe ( arr [ i + expected . start ] ) ;
380+ }
381+ } ) ;
262382 } ) ;
263383
264384 it ( 'some' , ( ) => {
0 commit comments