[core/shared] Allow for BigInt to work in isolategroup-bound callbacks.
Introduce runtime checks for BigInt to allow it being used as deeply immutable class. TEST=run_isolate_group_run_test Bug: https://github.com/dart-lang/sdk/issues/61030 Bug: https://github.com/dart-lang/sdk/issues/62601 Change-Id: I343862bdf5603be571d3bf937261dd61aca9ca0e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/477040 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Alexander Aprelev <aam@google.com>
This commit is contained in:
committed by
Commit Queue
parent
652395537d
commit
f3bc347448
@@ -804,39 +804,39 @@ final class Arm64VMOffsets extends VMOffsets {
|
||||
@override
|
||||
int get Object_tags_offset => 0x0;
|
||||
@override
|
||||
int get ObjectStore_double_type_offset => 0x1b0;
|
||||
int get ObjectStore_double_type_offset => 0x1b8;
|
||||
@override
|
||||
int get ObjectStore_int_type_offset => 0x160;
|
||||
int get ObjectStore_int_type_offset => 0x168;
|
||||
@override
|
||||
int get ObjectStore_record_field_names_offset => 0x428;
|
||||
int get ObjectStore_record_field_names_offset => 0x430;
|
||||
@override
|
||||
int get ObjectStore_string_type_offset => 0x1d8;
|
||||
int get ObjectStore_string_type_offset => 0x1e0;
|
||||
@override
|
||||
int get ObjectStore_type_type_offset => 0x138;
|
||||
int get ObjectStore_type_type_offset => 0x140;
|
||||
@override
|
||||
int get ObjectStore_ffi_callback_code_offset => 0x520;
|
||||
int get ObjectStore_ffi_callback_code_offset => 0x528;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_await_offset => 0x478;
|
||||
int get ObjectStore_suspend_state_await_offset => 0x480;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_await_with_type_check_offset => 0x480;
|
||||
int get ObjectStore_suspend_state_await_with_type_check_offset => 0x488;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_handle_exception_offset => 0x4c0;
|
||||
int get ObjectStore_suspend_state_handle_exception_offset => 0x4c8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_async_offset => 0x470;
|
||||
int get ObjectStore_suspend_state_init_async_offset => 0x478;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_async_star_offset => 0x498;
|
||||
int get ObjectStore_suspend_state_init_async_star_offset => 0x4a0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_sync_star_offset => 0x4b0;
|
||||
int get ObjectStore_suspend_state_init_sync_star_offset => 0x4b8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_offset => 0x488;
|
||||
int get ObjectStore_suspend_state_return_async_offset => 0x490;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_not_future_offset => 0x490;
|
||||
int get ObjectStore_suspend_state_return_async_not_future_offset => 0x498;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_star_offset => 0x4a8;
|
||||
int get ObjectStore_suspend_state_return_async_star_offset => 0x4b0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_suspend_sync_star_at_start_offset => 0x4b8;
|
||||
int get ObjectStore_suspend_state_suspend_sync_star_at_start_offset => 0x4c0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_yield_async_star_offset => 0x4a0;
|
||||
int get ObjectStore_suspend_state_yield_async_star_offset => 0x4a8;
|
||||
@override
|
||||
int get OneByteString_data_offset => 0x10;
|
||||
@override
|
||||
@@ -1715,39 +1715,39 @@ final class Arm64ProductVMOffsets extends VMOffsets {
|
||||
@override
|
||||
int get Object_tags_offset => 0x0;
|
||||
@override
|
||||
int get ObjectStore_double_type_offset => 0x1b0;
|
||||
int get ObjectStore_double_type_offset => 0x1b8;
|
||||
@override
|
||||
int get ObjectStore_int_type_offset => 0x160;
|
||||
int get ObjectStore_int_type_offset => 0x168;
|
||||
@override
|
||||
int get ObjectStore_record_field_names_offset => 0x428;
|
||||
int get ObjectStore_record_field_names_offset => 0x430;
|
||||
@override
|
||||
int get ObjectStore_string_type_offset => 0x1d8;
|
||||
int get ObjectStore_string_type_offset => 0x1e0;
|
||||
@override
|
||||
int get ObjectStore_type_type_offset => 0x138;
|
||||
int get ObjectStore_type_type_offset => 0x140;
|
||||
@override
|
||||
int get ObjectStore_ffi_callback_code_offset => 0x520;
|
||||
int get ObjectStore_ffi_callback_code_offset => 0x528;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_await_offset => 0x478;
|
||||
int get ObjectStore_suspend_state_await_offset => 0x480;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_await_with_type_check_offset => 0x480;
|
||||
int get ObjectStore_suspend_state_await_with_type_check_offset => 0x488;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_handle_exception_offset => 0x4c0;
|
||||
int get ObjectStore_suspend_state_handle_exception_offset => 0x4c8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_async_offset => 0x470;
|
||||
int get ObjectStore_suspend_state_init_async_offset => 0x478;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_async_star_offset => 0x498;
|
||||
int get ObjectStore_suspend_state_init_async_star_offset => 0x4a0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_sync_star_offset => 0x4b0;
|
||||
int get ObjectStore_suspend_state_init_sync_star_offset => 0x4b8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_offset => 0x488;
|
||||
int get ObjectStore_suspend_state_return_async_offset => 0x490;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_not_future_offset => 0x490;
|
||||
int get ObjectStore_suspend_state_return_async_not_future_offset => 0x498;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_star_offset => 0x4a8;
|
||||
int get ObjectStore_suspend_state_return_async_star_offset => 0x4b0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_suspend_sync_star_at_start_offset => 0x4b8;
|
||||
int get ObjectStore_suspend_state_suspend_sync_star_at_start_offset => 0x4c0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_yield_async_star_offset => 0x4a0;
|
||||
int get ObjectStore_suspend_state_yield_async_star_offset => 0x4a8;
|
||||
@override
|
||||
int get OneByteString_data_offset => 0x10;
|
||||
@override
|
||||
|
||||
@@ -194,12 +194,17 @@ class DeeplyImmutableValidator {
|
||||
continue;
|
||||
}
|
||||
if (!checkResult.isImmutable) {
|
||||
diagnosticReporter.report(
|
||||
diag.ffiDeeplyImmutableFieldsMustBeDeeplyImmutable,
|
||||
field.fileOffset,
|
||||
field.name.text.length,
|
||||
field.location!.file,
|
||||
);
|
||||
// Allow BigIntImpl since it's only violating "final Uint32List _digits"
|
||||
// is actually never modified.
|
||||
if (node.name != '_BigIntImpl' &&
|
||||
node.enclosingLibrary.name != 'dart:core') {
|
||||
diagnosticReporter.report(
|
||||
diag.ffiDeeplyImmutableFieldsMustBeDeeplyImmutable,
|
||||
field.fileOffset,
|
||||
field.name.text.length,
|
||||
field.location!.file,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!field.isFinal || field.isLate) {
|
||||
diagnosticReporter.report(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1832,17 +1832,23 @@ class WorkSet : public StackResource {
|
||||
};
|
||||
|
||||
void Object::EnsureDeeplyImmutable(Zone* zone) const {
|
||||
WorkSet workset(Thread::Current(), zone);
|
||||
auto thread = Thread::Current();
|
||||
WorkSet workset(thread, zone);
|
||||
workset.Add(*this);
|
||||
|
||||
Object& current = Object::Handle(zone);
|
||||
Function& function = Function::Handle(zone);
|
||||
Object& obj = Object::Handle(zone);
|
||||
|
||||
ObjectStore* object_store = thread->isolate_group()->object_store();
|
||||
const intptr_t bigint_cid =
|
||||
Class::Handle(zone, object_store->bigint_impl_class()).id();
|
||||
|
||||
while (workset.TakeAndPush(¤t)) {
|
||||
if (current.IsSmi() || current.IsNull() || current.IsCanonical() ||
|
||||
current.IsDeeplyImmutable() ||
|
||||
IsTypedDataBaseClassId(current.GetClassId())) {
|
||||
IsTypedDataBaseClassId(current.GetClassId()) ||
|
||||
current.GetClassId() == bigint_cid) {
|
||||
workset.PopAndProcessCompletedClosuresAndContexts(&obj);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -446,6 +446,10 @@ void ObjectStore::LazyInitCoreMembers() {
|
||||
ASSERT(!field.IsNull());
|
||||
enum_name_field_.store(field.ptr());
|
||||
|
||||
cls = core_lib.LookupClassAllowPrivate(Symbols::_BigIntImpl());
|
||||
ASSERT(!cls.IsNull());
|
||||
bigint_impl_class_.store(cls.ptr());
|
||||
|
||||
auto& function = Function::Handle(zone);
|
||||
|
||||
function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectHashCode());
|
||||
|
||||
@@ -47,6 +47,7 @@ class ObjectPointerVisitor;
|
||||
LAZY_CORE(Class, list_class) \
|
||||
LAZY_CORE(Class, map_class) \
|
||||
LAZY_CORE(Class, set_class) \
|
||||
LAZY_CORE(Class, bigint_impl_class) \
|
||||
LAZY_CORE(Type, non_nullable_list_rare_type) \
|
||||
LAZY_CORE(Type, non_nullable_map_rare_type) \
|
||||
LAZY_CORE(Field, enum_index_field) \
|
||||
|
||||
@@ -29,6 +29,7 @@ class ObjectPointerVisitor;
|
||||
V(StateError, "StateError") \
|
||||
V(AssertionError, "_AssertionError") \
|
||||
V(AssignIndexToken, "[]=") \
|
||||
V(_BigIntImpl, "_BigIntImpl") \
|
||||
V(Bool, "bool") \
|
||||
V(BooleanExpression, "boolean expression") \
|
||||
V(BoundsCheckForPartialInstantiation, "_boundsCheckForPartialInstantiation") \
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2026, 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.
|
||||
|
||||
import "dart:_internal" show patch;
|
||||
|
||||
import 'dart:_vm' show FinalThreadLocal, ThreadLocal;
|
||||
|
||||
import "dart:typed_data" show Uint32List;
|
||||
|
||||
@patch
|
||||
class _BigIntImpl {
|
||||
@patch
|
||||
static _DivRemResult get _cachedDivRemResult =>
|
||||
_cachedDivRemResultValue.value;
|
||||
|
||||
@patch
|
||||
static RegExp get _parseRE => _parseREThreadLocal.value;
|
||||
|
||||
@pragma('vm:shared')
|
||||
static final _cachedDivRemResultValue = FinalThreadLocal<_DivRemResult>(
|
||||
() => _DivRemResult(),
|
||||
);
|
||||
|
||||
@pragma('vm:shared')
|
||||
static final _parseREThreadLocal = FinalThreadLocal<RegExp>(
|
||||
() => RegExp(
|
||||
r'^\s*([+-]?)((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$',
|
||||
caseSensitive: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -65,13 +65,55 @@ int _min(int a, int b) => a < b ? a : b;
|
||||
/// Allocate a new digits list of even length.
|
||||
Uint32List _newDigits(int length) => Uint32List(length + (length & 1));
|
||||
|
||||
class _DivRemResult {
|
||||
Uint32List? get dividendDigits => _dividendDigits;
|
||||
int? get dividendUsed => _dividendUsed;
|
||||
Uint32List? get divisorDigits => _divisorDigits;
|
||||
int? get divisorUsed => _divisorUsed;
|
||||
|
||||
Uint32List get quoRemDigits => _quoRemDigits;
|
||||
int get quoRemUsed => _quoRemUsed;
|
||||
int get remUsed => _remUsed;
|
||||
int get rem_nsh => _rem_nsh;
|
||||
|
||||
void update(
|
||||
Uint32List dividendDigits,
|
||||
int dividendUsed,
|
||||
Uint32List divisorDigits,
|
||||
int divisorUsed,
|
||||
Uint32List quoRemDigits,
|
||||
int quoRemUsed,
|
||||
int remUsed,
|
||||
int rem_nsh,
|
||||
) {
|
||||
_dividendUsed = dividendUsed;
|
||||
_divisorDigits = divisorDigits;
|
||||
_divisorUsed = divisorUsed;
|
||||
_quoRemDigits = quoRemDigits;
|
||||
_quoRemUsed = quoRemUsed;
|
||||
_remUsed = remUsed;
|
||||
_rem_nsh = rem_nsh;
|
||||
}
|
||||
|
||||
Uint32List? _dividendDigits;
|
||||
int? _dividendUsed;
|
||||
Uint32List? _divisorDigits;
|
||||
int? _divisorUsed;
|
||||
|
||||
late Uint32List _quoRemDigits;
|
||||
late int _quoRemUsed;
|
||||
late int _remUsed;
|
||||
late int _rem_nsh;
|
||||
}
|
||||
|
||||
/**
|
||||
* An implementation for the arbitrarily large integer.
|
||||
*
|
||||
* The integer number is represented by a sign, an array of 32-bit unsigned
|
||||
* integers in little endian format, and a number of used digits in that array.
|
||||
*/
|
||||
class _BigIntImpl implements BigInt {
|
||||
@pragma("vm:entry-point")
|
||||
final class _BigIntImpl implements BigInt {
|
||||
// Bits per digit.
|
||||
static const int _digitBits = 32;
|
||||
static const int _digitBase = 1 << _digitBits;
|
||||
@@ -81,14 +123,22 @@ class _BigIntImpl implements BigInt {
|
||||
static const int _halfDigitBits = _digitBits >> 1;
|
||||
static const int _halfDigitMask = (1 << _halfDigitBits) - 1;
|
||||
|
||||
@pragma('vm:shared')
|
||||
static final _BigIntImpl zero = _BigIntImpl._fromInt(0);
|
||||
@pragma('vm:shared')
|
||||
static final _BigIntImpl one = _BigIntImpl._fromInt(1);
|
||||
@pragma('vm:shared')
|
||||
static final _BigIntImpl two = _BigIntImpl._fromInt(2);
|
||||
|
||||
@pragma('vm:shared')
|
||||
static final _BigIntImpl _minusOne = -one;
|
||||
@pragma('vm:shared')
|
||||
static final _BigIntImpl _oneDigitMask = _BigIntImpl._fromInt(_digitMask);
|
||||
@pragma('vm:shared')
|
||||
static final _BigIntImpl _twoDigitMask = (one << (2 * _digitBits)) - one;
|
||||
@pragma('vm:shared')
|
||||
static final _BigIntImpl _oneBillion = _BigIntImpl._fromInt(1000000000);
|
||||
|
||||
static const int _minInt = -0x8000000000000000;
|
||||
static const int _maxInt = 0x7fffffffffffffff;
|
||||
|
||||
@@ -106,14 +156,7 @@ class _BigIntImpl implements BigInt {
|
||||
);
|
||||
|
||||
// Result cache for last _divRem call.
|
||||
static Uint32List? _lastDividendDigits;
|
||||
static int? _lastDividendUsed;
|
||||
static Uint32List? _lastDivisorDigits;
|
||||
static int? _lastDivisorUsed;
|
||||
static late Uint32List _lastQuoRemDigits;
|
||||
static late int _lastQuoRemUsed;
|
||||
static late int _lastRemUsed;
|
||||
static late int _lastRem_nsh;
|
||||
external static _DivRemResult get _cachedDivRemResult;
|
||||
|
||||
/// Whether this bigint is negative.
|
||||
final bool _isNegative;
|
||||
@@ -125,6 +168,9 @@ class _BigIntImpl implements BigInt {
|
||||
/// be strictly greater than `_used`.
|
||||
/// Also, `_digits.length` must always be even, because intrinsics on 64-bit
|
||||
/// platforms may process a digit pair as a 64-bit value.
|
||||
///
|
||||
/// Uint32List normally prevent pragma('vm:deeply-immutable')-check, but
|
||||
/// this class is explicitly allow-listed in deeply_immutable.dart.
|
||||
final Uint32List _digits;
|
||||
|
||||
/// The number of used entries in [_digits].
|
||||
@@ -322,10 +368,7 @@ class _BigIntImpl implements BigInt {
|
||||
return _parseRadix(nonNullMatch, radix, isNegative);
|
||||
}
|
||||
|
||||
static RegExp _parseRE = RegExp(
|
||||
r'^\s*([+-]?)((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$',
|
||||
caseSensitive: false,
|
||||
);
|
||||
external static RegExp get _parseRE;
|
||||
|
||||
/// Finds the amount significant digits in the provided [digits] array.
|
||||
static int _normalize(int used, Uint32List digits) {
|
||||
@@ -1389,11 +1432,12 @@ class _BigIntImpl implements BigInt {
|
||||
_divRem(other);
|
||||
// Return quotient, i.e.
|
||||
// _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign.
|
||||
var lastQuo_used = _lastQuoRemUsed - _lastRemUsed;
|
||||
var lastQuo_used =
|
||||
_cachedDivRemResult.quoRemUsed - _cachedDivRemResult.remUsed;
|
||||
var quo_digits = _cloneDigits(
|
||||
_lastQuoRemDigits,
|
||||
_lastRemUsed,
|
||||
_lastQuoRemUsed,
|
||||
_cachedDivRemResult.quoRemDigits,
|
||||
_cachedDivRemResult.remUsed,
|
||||
_cachedDivRemResult.quoRemUsed,
|
||||
lastQuo_used,
|
||||
);
|
||||
var quo = _BigIntImpl._(false, lastQuo_used, quo_digits);
|
||||
@@ -1414,14 +1458,14 @@ class _BigIntImpl implements BigInt {
|
||||
// Return remainder, i.e.
|
||||
// denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign.
|
||||
var remDigits = _cloneDigits(
|
||||
_lastQuoRemDigits,
|
||||
_cachedDivRemResult.quoRemDigits,
|
||||
0,
|
||||
_lastRemUsed,
|
||||
_lastRemUsed,
|
||||
_cachedDivRemResult.remUsed,
|
||||
_cachedDivRemResult.remUsed,
|
||||
);
|
||||
var rem = _BigIntImpl._(false, _lastRemUsed, remDigits);
|
||||
if (_lastRem_nsh > 0) {
|
||||
rem = rem >> _lastRem_nsh; // Denormalize remainder.
|
||||
var rem = _BigIntImpl._(false, _cachedDivRemResult.remUsed, remDigits);
|
||||
if (_cachedDivRemResult.rem_nsh > 0) {
|
||||
rem = rem >> _cachedDivRemResult.rem_nsh; // Denormalize remainder.
|
||||
}
|
||||
if (_isNegative && (rem._used > 0)) {
|
||||
rem = -rem;
|
||||
@@ -1431,18 +1475,18 @@ class _BigIntImpl implements BigInt {
|
||||
|
||||
/// Computes this ~/ other and this.remainder(other).
|
||||
///
|
||||
/// Stores the result in [_lastQuoRemDigits], [_lastQuoRemUsed] and
|
||||
/// [_lastRemUsed]. The [_lastQuoRemDigits] contains the digits of *both*, the
|
||||
/// Stores the result in [_cachedDivRemResult]'s [quoRemDigits], [quoRemUsed]
|
||||
/// and [remUsed]. The [quoRemDigits] contains the digits of *both*, the
|
||||
/// quotient and the remainder.
|
||||
///
|
||||
/// Caches the input to avoid doing the work again when users write
|
||||
/// `a ~/ b` followed by a `a % b`.
|
||||
void _divRem(_BigIntImpl other) {
|
||||
// Check if result is already cached.
|
||||
if ((this._used == _lastDividendUsed) &&
|
||||
(other._used == _lastDivisorUsed) &&
|
||||
identical(this._digits, _lastDividendDigits) &&
|
||||
identical(other._digits, _lastDivisorDigits)) {
|
||||
if ((this._used == _cachedDivRemResult.dividendUsed) &&
|
||||
(other._used == _cachedDivRemResult.divisorUsed) &&
|
||||
identical(this._digits, _cachedDivRemResult.dividendDigits) &&
|
||||
identical(other._digits, _cachedDivRemResult.divisorDigits)) {
|
||||
return;
|
||||
}
|
||||
assert(_used >= other._used);
|
||||
@@ -1561,14 +1605,16 @@ class _BigIntImpl implements BigInt {
|
||||
i -= d0;
|
||||
}
|
||||
// Cache result.
|
||||
_lastDividendDigits = _digits;
|
||||
_lastDividendUsed = _used;
|
||||
_lastDivisorDigits = other._digits;
|
||||
_lastDivisorUsed = other._used;
|
||||
_lastQuoRemDigits = resultDigits;
|
||||
_lastQuoRemUsed = resultUsed;
|
||||
_lastRemUsed = yUsed;
|
||||
_lastRem_nsh = nsh;
|
||||
_cachedDivRemResult.update(
|
||||
_digits,
|
||||
_used,
|
||||
other._digits,
|
||||
other._used,
|
||||
resultDigits,
|
||||
resultUsed,
|
||||
yUsed,
|
||||
nsh,
|
||||
);
|
||||
}
|
||||
|
||||
// Customized version of _rem() minimizing allocations for use in reduction.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2026, 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.
|
||||
|
||||
import "dart:_internal" show patch;
|
||||
|
||||
import "dart:typed_data" show Uint32List;
|
||||
|
||||
@patch
|
||||
class _BigIntImpl {
|
||||
@patch
|
||||
static _DivRemResult get _cachedDivRemResult => _cachedDivRemResultValue;
|
||||
|
||||
@patch
|
||||
static RegExp get _parseRE => _parseREValue;
|
||||
|
||||
static final _cachedDivRemResultValue = _DivRemResult();
|
||||
|
||||
static final RegExp _parseREValue = RegExp(
|
||||
r'^\s*([+-]?)((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$',
|
||||
caseSensitive: false,
|
||||
);
|
||||
}
|
||||
@@ -47,6 +47,7 @@
|
||||
"_internal/vm/lib/array_patch.dart",
|
||||
"_internal/vm/lib/core_patch.dart",
|
||||
"_internal/vm_shared/lib/bigint_patch.dart",
|
||||
"_internal/vm/lib/bigint_patch_patch.dart",
|
||||
"_internal/vm_shared/lib/bool_patch.dart",
|
||||
"_internal/vm_shared/lib/date_patch.dart",
|
||||
"_internal/vm_shared/lib/integers_patch.dart",
|
||||
@@ -146,6 +147,7 @@
|
||||
"_internal/vm_shared/lib/map_patch.dart",
|
||||
"_internal/vm_shared/lib/null_patch.dart",
|
||||
"_internal/wasm/lib/array_patch.dart",
|
||||
"_internal/wasm/lib/bigint_patch_patch.dart",
|
||||
"_internal/wasm/lib/core_patch.dart",
|
||||
"_internal/wasm/lib/date_patch_patch.dart",
|
||||
"_internal/wasm/lib/int_common_patch.dart",
|
||||
@@ -209,6 +211,7 @@
|
||||
"_internal/vm_shared/lib/map_patch.dart",
|
||||
"_internal/vm_shared/lib/null_patch.dart",
|
||||
"_internal/wasm/lib/array_patch.dart",
|
||||
"_internal/wasm/lib/bigint_patch_patch.dart",
|
||||
"_internal/wasm/lib/core_patch.dart",
|
||||
"_internal/wasm/lib/date_patch_patch.dart",
|
||||
"_internal/wasm/lib/int_common_patch.dart",
|
||||
|
||||
@@ -53,6 +53,7 @@ vm_common:
|
||||
- "_internal/vm/lib/array_patch.dart"
|
||||
- "_internal/vm/lib/core_patch.dart"
|
||||
- "_internal/vm_shared/lib/bigint_patch.dart"
|
||||
- "_internal/vm/lib/bigint_patch_patch.dart"
|
||||
- "_internal/vm_shared/lib/bool_patch.dart"
|
||||
- "_internal/vm_shared/lib/date_patch.dart"
|
||||
- "_internal/vm_shared/lib/integers_patch.dart"
|
||||
@@ -135,6 +136,7 @@ wasm:
|
||||
- _internal/vm_shared/lib/map_patch.dart
|
||||
- _internal/vm_shared/lib/null_patch.dart
|
||||
- _internal/wasm/lib/array_patch.dart
|
||||
- _internal/wasm/lib/bigint_patch_patch.dart
|
||||
- _internal/wasm/lib/core_patch.dart
|
||||
- _internal/wasm/lib/date_patch_patch.dart
|
||||
- _internal/wasm/lib/int_common_patch.dart
|
||||
@@ -182,6 +184,7 @@ wasm_js_compatibility:
|
||||
- _internal/vm_shared/lib/map_patch.dart
|
||||
- _internal/vm_shared/lib/null_patch.dart
|
||||
- _internal/wasm/lib/array_patch.dart
|
||||
- _internal/wasm/lib/bigint_patch_patch.dart
|
||||
- _internal/wasm/lib/core_patch.dart
|
||||
- _internal/wasm/lib/date_patch_patch.dart
|
||||
- _internal/wasm/lib/int_common_patch.dart
|
||||
|
||||
@@ -71,6 +71,7 @@ main(List<String> args) {
|
||||
testBytesBuilder();
|
||||
testRegExp();
|
||||
testContentType();
|
||||
testBigInt();
|
||||
|
||||
print("All tests completed :)");
|
||||
}
|
||||
@@ -562,3 +563,106 @@ void testContentType() {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
///
|
||||
expectSum(aString, bString, expectedString) {
|
||||
BigInt a = BigInt.parse(aString, radix: 16);
|
||||
BigInt b = BigInt.parse(bString, radix: 16);
|
||||
BigInt expected = BigInt.parse(expectedString, radix: 16);
|
||||
BigInt actual = a + b;
|
||||
Expect.equals(expected, actual);
|
||||
}
|
||||
|
||||
expectDifference(aString, bString, expectedString) {
|
||||
BigInt a = BigInt.parse(aString, radix: 16);
|
||||
BigInt b = BigInt.parse(bString, radix: 16);
|
||||
BigInt expected = BigInt.parse(expectedString, radix: 16);
|
||||
BigInt actual = a - b;
|
||||
Expect.equals(expected, actual);
|
||||
}
|
||||
|
||||
expectQuotient(aString, bString, expectedString) {
|
||||
BigInt a = BigInt.parse(aString, radix: 16);
|
||||
BigInt b = BigInt.parse(bString, radix: 16);
|
||||
BigInt expected = BigInt.parse(expectedString, radix: 16);
|
||||
BigInt actual = a ~/ b;
|
||||
Expect.equals(expected, actual);
|
||||
}
|
||||
|
||||
expectRemainder(aString, bString, expectedString) {
|
||||
BigInt a = BigInt.parse(aString, radix: 16);
|
||||
BigInt b = BigInt.parse(bString, radix: 16);
|
||||
BigInt expected = BigInt.parse(expectedString, radix: 16);
|
||||
BigInt actual = a % b;
|
||||
Expect.equals(expected, actual);
|
||||
}
|
||||
|
||||
expectShifted(aString, n, expectedString) {
|
||||
BigInt a = BigInt.parse(aString, radix: 16);
|
||||
BigInt expected = BigInt.parse(expectedString, radix: 16);
|
||||
BigInt actual = a << n;
|
||||
Expect.equals(expected, actual);
|
||||
}
|
||||
|
||||
void testBigInt() {
|
||||
IsolateGroup.runSync(() {
|
||||
Expect.equals("${BigInt.zero}", "0");
|
||||
Expect.equals("${BigInt.one}", "1");
|
||||
Expect.equals("${BigInt.two}", "2");
|
||||
|
||||
expectSum(
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
"d4cba13fac3ee22b996ff6856c27c1f6d88aef0e",
|
||||
"1ad478de9e340aba6cb25ae8dbb531d2bc0105fa0",
|
||||
);
|
||||
expectSum(
|
||||
"d4cba13fac3ee22b996ff6856c27c1f6d88aef0e",
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
"1ad478de9e340aba6cb25ae8dbb531d2bc0105fa0",
|
||||
);
|
||||
|
||||
expectDifference(
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
"d4cba13fac3ee22b996ff6856c27c1f6d88aef0e",
|
||||
"3b04b6a8ac2e74f9845c182e303993e0efa8184",
|
||||
);
|
||||
expectDifference(
|
||||
"d4cba13fac3ee22b996ff6856c27c1f6d88aef0e",
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
"-3b04b6a8ac2e74f9845c182e303993e0efa8184",
|
||||
);
|
||||
|
||||
expectRemainder(
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
"d4cba13fac3ee22b996ff6856c27c1f6d88aef0e",
|
||||
"3b04b6a8ac2e74f9845c182e303993e0efa8184",
|
||||
);
|
||||
expectRemainder(
|
||||
"d4cba13fac3ee22b996ff6856c27c1f6d88aef0e",
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
"d4cba13fac3ee22b996ff6856c27c1f6d88aef0e",
|
||||
);
|
||||
|
||||
expectQuotient(
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
"d4cba13fac3ee22b996ff6856c27c1f6d88aef0e",
|
||||
"1",
|
||||
);
|
||||
expectQuotient(
|
||||
"d4cba13fac3ee22b996ff6856c27c1f6d88aef0e",
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
"0",
|
||||
);
|
||||
|
||||
expectShifted(
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
0,
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
);
|
||||
expectShifted(
|
||||
"d87becaa3701c97b31b5b8084f2b5b34e7857092",
|
||||
1,
|
||||
"1b0f7d9546e0392f6636b70109e56b669cf0ae124",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user