blob: 37c1eb9b63272f719a350f539072b7eac4e96ade [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart=2.9
@JS()
library native_version_javascript;
import 'package:js/js.dart';
import 'native_version.dart';
const NativeBigIntMethods nativeBigInt = _Methods();
@JS('eval')
external Object _eval(String s);
@JS('bigint_parse')
external Object _parse(String s);
@JS('bigint_toString')
external String _toStringMethod(Object o);
@JS('bigint_bitLength')
external int _bitLength(Object o);
@JS('bigint_isEven')
external bool _isEven(Object o);
@JS('bigint_add')
external Object _add(Object left, Object right);
@JS('bigint_shiftLeft')
external Object _shiftLeft(Object o, Object i);
@JS('bigint_shiftRight')
external Object _shiftRight(Object o, Object i);
@JS('bigint_subtract')
external Object _subtract(Object left, Object right);
@JS('bigint_fromInt')
external Object _fromInt(int i);
class _Methods implements NativeBigIntMethods {
static bool _initialized = false;
static bool _enabled = false;
const _Methods();
@override
bool get enabled {
if (!_initialized) {
_initialize();
}
return _enabled;
}
void _initialize() {
_initialized = true;
try {
_setup();
_enabled = true;
} catch (e) {
// We get here if the JavaScript implementation does not have BigInt (or
// run in a stand-alone JavaScript implementation without the right
// 'preamble').
//
// Print so we can see what failed.
print(e);
}
}
@override
Object parse(String string) => _parse(string);
@override
String toStringMethod(Object value) => _toStringMethod(value);
@override
Object fromInt(int i) => _fromInt(i);
@override
Object get one => _one;
@override
Object get eight => _eight;
@override
int bitLength(Object value) => _bitLength(value);
@override
bool isEven(Object value) => _isEven(value);
@override
Object add(Object left, Object right) => _add(left, right);
@override
Object shiftLeft(Object value, Object count) => _shiftLeft(value, count);
@override
Object shiftRight(Object value, Object count) => _shiftRight(value, count);
@override
Object subtract(Object left, Object right) => _subtract(left, right);
}
void _setup() {
_one = _eval('1n'); // Throws if JavaScript does not have BigInt.
_eight = _eval('8n');
_eval('self.bigint_parse = function parse(s) { return BigInt(s); }');
_eval('self.bigint_toString = function toString(b) { return b.toString(); }');
_eval('self.bigint_add = function add(a, b) { return a + b; }');
_eval('self.bigint_shiftLeft = function shl(v, i) { return v << i; }');
_eval('self.bigint_shiftRight = function shr(v, i) { return v >> i; }');
_eval('self.bigint_subtract = function subtract(a, b) { return a - b; }');
_eval('self.bigint_fromInt = function fromInt(i) { return BigInt(i); }');
_eval('self.bigint_bitLength = function bitLength(b) {'
'return b == 0 ? 0 : (b < 0 ? ~b : b).toString(2).length;'
'}');
_eval('self.bigint_isEven = function isEven(b) { return (b & 1n) == 0n; }');
}
// `dynamic` to allow null initialization pre- and post- NNBD.
dynamic _one;
dynamic _eight;