66
77package org .mozilla .javascript .typedarrays ;
88
9+ import java .math .BigInteger ;
910import org .mozilla .javascript .Context ;
1011import org .mozilla .javascript .LambdaConstructor ;
1112import org .mozilla .javascript .ScriptRuntime ;
@@ -81,6 +82,9 @@ public static Object init(Context cx, Scriptable scope, boolean sealed) {
8182 constructor .definePrototypeMethod (scope , "getUint8" , 1 , NativeDataView ::js_getUint8 );
8283 constructor .definePrototypeMethod (scope , "getUint16" , 1 , NativeDataView ::js_getUint16 );
8384 constructor .definePrototypeMethod (scope , "getUint32" , 1 , NativeDataView ::js_getUint32 );
85+ constructor .definePrototypeMethod (scope , "getBigInt64" , 1 , NativeDataView ::js_getBigInt64 );
86+ constructor .definePrototypeMethod (
87+ scope , "getBigUint64" , 1 , NativeDataView ::js_getBigUint64 );
8488 constructor .definePrototypeMethod (scope , "setFloat32" , 2 , NativeDataView ::js_setFloat32 );
8589 constructor .definePrototypeMethod (scope , "setFloat64" , 2 , NativeDataView ::js_setFloat64 );
8690 constructor .definePrototypeMethod (scope , "setInt8" , 2 , NativeDataView ::js_setInt8 );
@@ -89,6 +93,9 @@ public static Object init(Context cx, Scriptable scope, boolean sealed) {
8993 constructor .definePrototypeMethod (scope , "setUint8" , 2 , NativeDataView ::js_setUint8 );
9094 constructor .definePrototypeMethod (scope , "setUint16" , 2 , NativeDataView ::js_setUint16 );
9195 constructor .definePrototypeMethod (scope , "setUint32" , 2 , NativeDataView ::js_setUint32 );
96+ constructor .definePrototypeMethod (scope , "setBigInt64" , 2 , NativeDataView ::js_setBigInt64 );
97+ constructor .definePrototypeMethod (
98+ scope , "setBigUint64" , 2 , NativeDataView ::js_setBigUint64 );
9299
93100 if (sealed ) {
94101 constructor .sealObject ();
@@ -407,6 +414,87 @@ private void js_setFloat(Context cx, Scriptable scope, int bytes, Object[] args)
407414 }
408415 }
409416
417+ private static Object js_getBigInt64 (
418+ Context cx , Scriptable scope , Scriptable thisObj , Object [] args ) {
419+ NativeDataView realThis = realThis (thisObj );
420+ return realThis .js_getBigInt (true , args );
421+ }
422+
423+ private static Object js_getBigUint64 (
424+ Context cx , Scriptable scope , Scriptable thisObj , Object [] args ) {
425+ NativeDataView realThis = realThis (thisObj );
426+ return realThis .js_getBigInt (false , args );
427+ }
428+
429+ private Object js_getBigInt (boolean signed , Object [] args ) {
430+ int pos = ScriptRuntime .toIndex (isArg (args , 0 ) ? args [0 ] : Undefined .instance );
431+
432+ boolean littleEndian = isArg (args , 1 ) && ScriptRuntime .toBoolean (args [1 ]);
433+
434+ if (isDataViewOutOfBounds ()) {
435+ throw ScriptRuntime .typeErrorById ("msg.dataview.bounds" );
436+ }
437+
438+ int viewSize = byteLength ;
439+ if ((long ) pos + 8 > viewSize ) {
440+ throw ScriptRuntime .rangeErrorById ("msg.dataview.offset.range" );
441+ }
442+
443+ long base = ByteIo .readUint64Primitive (arrayBuffer .buffer , offset + pos , littleEndian );
444+
445+ if (signed ) {
446+ // Interpret as signed 64-bit integer
447+ return BigInteger .valueOf (base );
448+ } else {
449+ // Interpret as unsigned 64-bit integer
450+ if (base >= 0L ) {
451+ return BigInteger .valueOf (base );
452+ } else {
453+ // Split into two 32-bit parts for proper unsigned conversion
454+ var lsw = BigInteger .valueOf (base & 0xffffffffL );
455+ var msw = BigInteger .valueOf ((base >>> 32 )).shiftLeft (32 );
456+ return msw .add (lsw );
457+ }
458+ }
459+ }
460+
461+ // These two functions are specified separately, and sound like they should behave differently,
462+ // but end up having precisely the same effect, with only the interpretation of the 64 bits in
463+ // an intermediate state differing.
464+ private static Object js_setBigInt64 (
465+ Context cx , Scriptable scope , Scriptable thisObj , Object [] args ) {
466+ NativeDataView realThis = realThis (thisObj );
467+ realThis .js_setBigInt (args );
468+ return Undefined .instance ;
469+ }
470+
471+ private static Object js_setBigUint64 (
472+ Context cx , Scriptable scope , Scriptable thisObj , Object [] args ) {
473+ NativeDataView realThis = realThis (thisObj );
474+ realThis .js_setBigInt (args );
475+ return Undefined .instance ;
476+ }
477+
478+ private void js_setBigInt (Object [] args ) {
479+ int pos = ScriptRuntime .toIndex (isArg (args , 0 ) ? args [0 ] : Undefined .instance );
480+
481+ BigInteger val = ScriptRuntime .toBigInt (isArg (args , 1 ) ? args [1 ] : Undefined .instance );
482+
483+ boolean littleEndian = isArg (args , 2 ) && ScriptRuntime .toBoolean (args [2 ]);
484+
485+ if (isDataViewOutOfBounds ()) {
486+ throw ScriptRuntime .typeErrorById ("msg.dataview.bounds" );
487+ }
488+
489+ int viewSize = byteLength ;
490+ if ((long ) pos + 8 > viewSize ) {
491+ throw ScriptRuntime .rangeErrorById ("msg.dataview.offset.range" );
492+ }
493+
494+ long base = val .longValue ();
495+ ByteIo .writeUint64 (arrayBuffer .buffer , offset + pos , base , littleEndian );
496+ }
497+
410498 public boolean isDataViewOutOfBounds () {
411499 if (arrayBuffer .isDetached ()) {
412500 return true ;
0 commit comments