github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/typedarrays_test.go (about)

     1  package goja
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  )
     7  
     8  func TestUint16ArrayObject(t *testing.T) {
     9  	vm := New()
    10  	buf := vm._newArrayBuffer(vm.global.ArrayBufferPrototype, nil)
    11  	buf.data = make([]byte, 16)
    12  	if nativeEndian == littleEndian {
    13  		buf.data[2] = 0xFE
    14  		buf.data[3] = 0xCA
    15  	} else {
    16  		buf.data[2] = 0xCA
    17  		buf.data[3] = 0xFE
    18  	}
    19  	a := vm.newUint16ArrayObject(buf, 1, 1, nil)
    20  	v := a.getIdx(valueInt(0), nil)
    21  	if v != valueInt(0xCAFE) {
    22  		t.Fatalf("v: %v", v)
    23  	}
    24  }
    25  
    26  func TestArrayBufferGoWrapper(t *testing.T) {
    27  	vm := New()
    28  	data := []byte{0xAA, 0xBB}
    29  	buf := vm.NewArrayBuffer(data)
    30  	vm.Set("buf", buf)
    31  	_, err := vm.RunString(`
    32  	var a = new Uint8Array(buf);
    33  	if (a.length !== 2 || a[0] !== 0xAA || a[1] !== 0xBB) {
    34  		throw new Error(a);
    35  	}
    36  	`)
    37  	if err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	ret, err := vm.RunString(`
    41  	var b = Uint8Array.of(0xCC, 0xDD);
    42  	b.buffer;
    43  	`)
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  	buf1 := ret.Export().(ArrayBuffer)
    48  	data1 := buf1.Bytes()
    49  	if len(data1) != 2 || data1[0] != 0xCC || data1[1] != 0xDD {
    50  		t.Fatal(data1)
    51  	}
    52  	if buf1.Detached() {
    53  		t.Fatal("buf1.Detached() returned true")
    54  	}
    55  	if !buf1.Detach() {
    56  		t.Fatal("buf1.Detach() returned false")
    57  	}
    58  	if !buf1.Detached() {
    59  		t.Fatal("buf1.Detached() returned false")
    60  	}
    61  	_, err = vm.RunString(`
    62  	if (b[0] !== undefined) {
    63  		throw new Error("b[0] !== undefined");
    64  	}
    65  	`)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  }
    70  
    71  func TestTypedArrayIdx(t *testing.T) {
    72  	const SCRIPT = `
    73  	var a = new Uint8Array(1);
    74  
    75  	// 32-bit integer overflow, should not panic on 32-bit architectures
    76  	if (a[4294967297] !== undefined) {
    77  		throw new Error("4294967297");
    78  	}
    79  
    80  	// Canonical non-integer
    81  	a["Infinity"] = 8;
    82  	if (a["Infinity"] !== undefined) {
    83  		throw new Error("Infinity");
    84  	}
    85  	a["NaN"] = 1;
    86  	if (a["NaN"] !== undefined) {
    87  		throw new Error("NaN");
    88  	}
    89  
    90  	// Non-canonical integer
    91  	a["00"] = "00";
    92  	if (a["00"] !== "00") {
    93  		throw new Error("00");
    94  	}
    95  
    96  	// Non-canonical non-integer
    97  	a["1e-3"] = "1e-3";
    98  	if (a["1e-3"] !== "1e-3") {
    99  		throw new Error("1e-3");
   100  	}
   101  	if (a["0.001"] !== undefined) {
   102  		throw new Error("0.001");
   103  	}
   104  
   105  	// Negative zero
   106  	a["-0"] = 88;
   107  	if (a["-0"] !== undefined) {
   108  		throw new Error("-0");
   109  	}
   110  
   111  	if (a[0] !== 0) {
   112  		throw new Error("0");
   113  	}
   114  
   115  	a["9007199254740992"] = 1;
   116  	if (a["9007199254740992"] !== undefined) {
   117  		throw new Error("9007199254740992");
   118  	}
   119  	a["-9007199254740992"] = 1;
   120  	if (a["-9007199254740992"] !== undefined) {
   121  		throw new Error("-9007199254740992");
   122  	}
   123  
   124  	// Safe integer overflow, not canonical (Number("9007199254740993") === 9007199254740992)
   125  	a["9007199254740993"] = 1;
   126  	if (a["9007199254740993"] !== 1) {
   127  		throw new Error("9007199254740993");
   128  	}
   129  	a["-9007199254740993"] = 1;
   130  	if (a["-9007199254740993"] !== 1) {
   131  		throw new Error("-9007199254740993");
   132  	}
   133  
   134  	// Safe integer overflow, canonical Number("9007199254740994") == 9007199254740994
   135  	a["9007199254740994"] = 1;
   136  	if (a["9007199254740994"] !== undefined) {
   137  		throw new Error("9007199254740994");
   138  	}
   139  	a["-9007199254740994"] = 1;
   140  	if (a["-9007199254740994"] !== undefined) {
   141  		throw new Error("-9007199254740994");
   142  	}
   143  	`
   144  
   145  	testScript(SCRIPT, _undefined, t)
   146  }
   147  
   148  func TestTypedArraySetDetachedBuffer(t *testing.T) {
   149  	const SCRIPT = `
   150  	let sample = new Uint8Array([42]);
   151  	$DETACHBUFFER(sample.buffer);
   152  	sample[0] = 1;
   153  
   154  	assert.sameValue(sample[0], undefined, 'sample[0] = 1 is undefined');
   155  	sample['1.1'] = 1;
   156  	assert.sameValue(sample['1.1'], undefined, 'sample[\'1.1\'] = 1 is undefined');
   157  	sample['-0'] = 1;
   158  	assert.sameValue(sample['-0'], undefined, 'sample[\'-0\'] = 1 is undefined');
   159  	sample['-1'] = 1;
   160  	assert.sameValue(sample['-1'], undefined, 'sample[\'-1\'] = 1 is undefined');
   161  	sample['1'] = 1;
   162  	assert.sameValue(sample['1'], undefined, 'sample[\'1\'] = 1 is undefined');
   163  	sample['2'] = 1;
   164  	assert.sameValue(sample['2'], undefined, 'sample[\'2\'] = 1 is undefined');	
   165  	`
   166  	vm := New()
   167  	vm.Set("$DETACHBUFFER", func(buf *ArrayBuffer) {
   168  		buf.Detach()
   169  	})
   170  	vm.testScriptWithTestLib(SCRIPT, _undefined, t)
   171  }
   172  
   173  func TestTypedArrayDefinePropDetachedBuffer(t *testing.T) {
   174  	const SCRIPT = `
   175  	var desc = {
   176  	  value: 0,
   177  	  configurable: false,
   178  	  enumerable: true,
   179  	  writable: true
   180  	};
   181  	
   182  	var obj = {
   183  	  valueOf: function() {
   184  		throw new Error("valueOf() was called");
   185  	  }
   186  	};
   187  	let sample = new Uint8Array(42);
   188  	$DETACHBUFFER(sample.buffer);
   189  	
   190  	assert.sameValue(
   191  	Reflect.defineProperty(sample, "0", desc),
   192  	false,
   193  	'Reflect.defineProperty(sample, "0", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
   194  	);
   195  	
   196  	assert.sameValue(
   197  	Reflect.defineProperty(sample, "-1", desc),
   198  	false,
   199  	'Reflect.defineProperty(sample, "-1", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
   200  	);
   201  	
   202  	assert.sameValue(
   203  	Reflect.defineProperty(sample, "1.1", desc),
   204  	false,
   205  	'Reflect.defineProperty(sample, "1.1", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
   206  	);
   207  	
   208  	assert.sameValue(
   209  	Reflect.defineProperty(sample, "-0", desc),
   210  	false,
   211  	'Reflect.defineProperty(sample, "-0", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
   212  	);
   213  	
   214  	assert.sameValue(
   215  	Reflect.defineProperty(sample, "2", {
   216  	  configurable: true,
   217  	  enumerable: true,
   218  	  writable: true,
   219  	  value: obj
   220  	}),
   221  	false,
   222  	'Reflect.defineProperty(sample, "2", {configurable: true, enumerable: true, writable: true, value: obj}) must return false'
   223  	);
   224  	
   225  	assert.sameValue(
   226  	Reflect.defineProperty(sample, "3", {
   227  	  configurable: false,
   228  	  enumerable: false,
   229  	  writable: true,
   230  	  value: obj
   231  	}),
   232  	false,
   233  	'Reflect.defineProperty(sample, "3", {configurable: false, enumerable: false, writable: true, value: obj}) must return false'
   234  	);
   235  	
   236  	assert.sameValue(
   237  	Reflect.defineProperty(sample, "4", {
   238  	  writable: false,
   239  	  configurable: false,
   240  	  enumerable: true,
   241  	  value: obj
   242  	}),
   243  	false,
   244  	'Reflect.defineProperty("new TA(42)", "4", {writable: false, configurable: false, enumerable: true, value: obj}) must return false'
   245  	);
   246  	
   247  	assert.sameValue(
   248  	Reflect.defineProperty(sample, "42", desc),
   249  	false,
   250  	'Reflect.defineProperty(sample, "42", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
   251  	);
   252  	
   253  	assert.sameValue(
   254  	Reflect.defineProperty(sample, "43", desc),
   255  	false,
   256  	'Reflect.defineProperty(sample, "43", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
   257  	);
   258  	
   259  	assert.sameValue(
   260  	Reflect.defineProperty(sample, "5", {
   261  	  get: function() {}
   262  	}),
   263  	false,
   264  	'Reflect.defineProperty(sample, "5", {get: function() {}}) must return false'
   265  	);
   266  	
   267  	assert.sameValue(
   268  	Reflect.defineProperty(sample, "6", {
   269  	  configurable: false,
   270  	  enumerable: true,
   271  	  writable: true
   272  	}),
   273  	false,
   274  	'Reflect.defineProperty(sample, "6", {configurable: false, enumerable: true, writable: true}) must return false'
   275  	);
   276  	`
   277  	vm := New()
   278  	vm.Set("$DETACHBUFFER", func(buf *ArrayBuffer) {
   279  		buf.Detach()
   280  	})
   281  	vm.testScriptWithTestLib(SCRIPT, _undefined, t)
   282  }
   283  
   284  func TestTypedArrayDefineProperty(t *testing.T) {
   285  	const SCRIPT = `
   286  	var a = new Uint8Array(1);
   287  
   288  	assert.throws(TypeError, function() {
   289  		Object.defineProperty(a, "1", {value: 1});
   290  	});
   291  	assert.sameValue(Reflect.defineProperty(a, "1", {value: 1}), false, "1");
   292  
   293  	assert.throws(TypeError, function() {
   294  		Object.defineProperty(a, "Infinity", {value: 8});
   295  	});
   296  	assert.sameValue(Reflect.defineProperty(a, "Infinity", {value: 8}), false, "Infinity");
   297  
   298  	Object.defineProperty(a, "test", {value: "passed"});
   299  	assert.sameValue(a.test, "passed", "string property");
   300  
   301  	assert.throws(TypeError, function() {
   302  		Object.defineProperty(a, "0", {value: 1, writable: false});
   303  	}, "define non-writable");
   304  
   305  	assert.throws(TypeError, function() {
   306  		Object.defineProperty(a, "0", {get() { return 1; }});
   307  	}, "define accessor");
   308  
   309  	var sample = new Uint8Array([42, 42]);
   310  
   311  	assert.sameValue(
   312  	Reflect.defineProperty(sample, "0", {
   313  	  value: 8,
   314  	  configurable: true,
   315  	  enumerable: true,
   316  	  writable: true
   317  	}),
   318  	true
   319  	);
   320  
   321  	assert.sameValue(sample[0], 8, "property value was set");
   322  	let descriptor0 = Object.getOwnPropertyDescriptor(sample, "0");
   323  	assert.sameValue(descriptor0.value, 8);
   324  	assert.sameValue(descriptor0.configurable, true, "configurable");
   325  	assert.sameValue(descriptor0.enumerable, true);
   326  	assert.sameValue(descriptor0.writable, true);
   327  	`
   328  	testScriptWithTestLib(SCRIPT, _undefined, t)
   329  }
   330  
   331  func TestTypedArrayGetInvalidIndex(t *testing.T) {
   332  	const SCRIPT = `
   333  	var TypedArray = Object.getPrototypeOf(Int8Array);
   334  	var proto = TypedArray.prototype;
   335  	Object.defineProperty(proto, "1", {
   336  		get: function() {
   337  			throw new Error("OrdinaryGet was called!");
   338  		}
   339  	});
   340  	var a = new Uint8Array(1);
   341  	assert.sameValue(a[1], undefined);
   342  	assert.sameValue(a["1"], undefined);
   343  	`
   344  	testScriptWithTestLib(SCRIPT, _undefined, t)
   345  }
   346  
   347  func TestExportArrayBufferToBytes(t *testing.T) {
   348  	vm := New()
   349  	bb := []byte("test")
   350  	ab := vm.NewArrayBuffer(bb)
   351  	var b []byte
   352  	err := vm.ExportTo(vm.ToValue(ab), &b)
   353  	if err != nil {
   354  		t.Fatal(err)
   355  	}
   356  	if !bytes.Equal(b, bb) {
   357  		t.Fatal("Not equal")
   358  	}
   359  
   360  	err = vm.ExportTo(vm.ToValue(123), &b)
   361  	if err == nil {
   362  		t.Fatal("expected error")
   363  	}
   364  }
   365  
   366  func TestTypedArrayExport(t *testing.T) {
   367  	vm := New()
   368  
   369  	t.Run("uint8", func(t *testing.T) {
   370  		v, err := vm.RunString("new Uint8Array([1, 2])")
   371  		if err != nil {
   372  			t.Fatal(err)
   373  		}
   374  		if a, ok := v.Export().([]uint8); ok {
   375  			if len(a) != 2 || a[0] != 1 || a[1] != 2 {
   376  				t.Fatal(a)
   377  			}
   378  		} else {
   379  			t.Fatal("Wrong export type")
   380  		}
   381  		_, err = vm.RunString(`{
   382  		let a = new Uint8Array([1, 2]);
   383  		if (a[0] !== 1 || a[1] !== 2) {
   384  			throw new Error(a);
   385  		}
   386  		}`)
   387  		if err != nil {
   388  			t.Fatal(err)
   389  		}
   390  	})
   391  
   392  	t.Run("uint8-slice", func(t *testing.T) {
   393  		v, err := vm.RunString(`{
   394  			const buf = new Uint8Array([1, 2]).buffer;
   395  			new Uint8Array(buf, 1, 1);
   396  		}`)
   397  		if err != nil {
   398  			t.Fatal(err)
   399  		}
   400  		if a, ok := v.Export().([]uint8); ok {
   401  			if len(a) != 1 || a[0] != 2 {
   402  				t.Fatal(a)
   403  			}
   404  		} else {
   405  			t.Fatal("Wrong export type")
   406  		}
   407  		_, err = vm.RunString(`{
   408  		let a = new Uint8Array([1, 2]);
   409  		if (a[0] !== 1 || a[1] !== 2) {
   410  			throw new Error(a);
   411  		}
   412  		}`)
   413  		if err != nil {
   414  			t.Fatal(err)
   415  		}
   416  	})
   417  
   418  	t.Run("int8", func(t *testing.T) {
   419  		v, err := vm.RunString("new Int8Array([1, -2])")
   420  		if err != nil {
   421  			t.Fatal(err)
   422  		}
   423  		if a, ok := v.Export().([]int8); ok {
   424  			if len(a) != 2 || a[0] != 1 || a[1] != -2 {
   425  				t.Fatal(a)
   426  			}
   427  		} else {
   428  			t.Fatal("Wrong export type")
   429  		}
   430  	})
   431  
   432  	t.Run("uint16", func(t *testing.T) {
   433  		v, err := vm.RunString("new Uint16Array([1, 63000])")
   434  		if err != nil {
   435  			t.Fatal(err)
   436  		}
   437  		if a, ok := v.Export().([]uint16); ok {
   438  			if len(a) != 2 || a[0] != 1 || a[1] != 63000 {
   439  				t.Fatal(a)
   440  			}
   441  		} else {
   442  			t.Fatal("Wrong export type")
   443  		}
   444  	})
   445  
   446  	t.Run("int16", func(t *testing.T) {
   447  		v, err := vm.RunString("new Int16Array([1, -31000])")
   448  		if err != nil {
   449  			t.Fatal(err)
   450  		}
   451  		if a, ok := v.Export().([]int16); ok {
   452  			if len(a) != 2 || a[0] != 1 || a[1] != -31000 {
   453  				t.Fatal(a)
   454  			}
   455  		} else {
   456  			t.Fatal("Wrong export type")
   457  		}
   458  	})
   459  
   460  	t.Run("uint32", func(t *testing.T) {
   461  		v, err := vm.RunString("new Uint32Array([1, 123456])")
   462  		if err != nil {
   463  			t.Fatal(err)
   464  		}
   465  		if a, ok := v.Export().([]uint32); ok {
   466  			if len(a) != 2 || a[0] != 1 || a[1] != 123456 {
   467  				t.Fatal(a)
   468  			}
   469  		} else {
   470  			t.Fatal("Wrong export type")
   471  		}
   472  	})
   473  
   474  	t.Run("int32", func(t *testing.T) {
   475  		v, err := vm.RunString("new Int32Array([1, -123456])")
   476  		if err != nil {
   477  			t.Fatal(err)
   478  		}
   479  		if a, ok := v.Export().([]int32); ok {
   480  			if len(a) != 2 || a[0] != 1 || a[1] != -123456 {
   481  				t.Fatal(a)
   482  			}
   483  		} else {
   484  			t.Fatal("Wrong export type")
   485  		}
   486  	})
   487  
   488  	t.Run("float32", func(t *testing.T) {
   489  		v, err := vm.RunString("new Float32Array([1, -1.23456])")
   490  		if err != nil {
   491  			t.Fatal(err)
   492  		}
   493  		if a, ok := v.Export().([]float32); ok {
   494  			if len(a) != 2 || a[0] != 1 || a[1] != -1.23456 {
   495  				t.Fatal(a)
   496  			}
   497  		} else {
   498  			t.Fatal("Wrong export type")
   499  		}
   500  	})
   501  
   502  	t.Run("float64", func(t *testing.T) {
   503  		v, err := vm.RunString("new Float64Array([1, -1.23456789])")
   504  		if err != nil {
   505  			t.Fatal(err)
   506  		}
   507  		if a, ok := v.Export().([]float64); ok {
   508  			if len(a) != 2 || a[0] != 1 || a[1] != -1.23456789 {
   509  				t.Fatal(a)
   510  			}
   511  		} else {
   512  			t.Fatal("Wrong export type")
   513  		}
   514  	})
   515  
   516  }