blob: 8ef758f1ff1da243f2265e4448498e98e34921e3 [file] [edit]
// 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:_embedder' as embedder;
import 'dart:_wasm';
@patch
class Timer {
@patch
static Timer _createTimer(Duration duration, void callback()) {
return _OneShotTimer(duration, callback);
}
@patch
static Timer _createPeriodicTimer(
Duration duration,
void callback(Timer timer),
) {
return _PeriodicTimer(duration, callback);
}
}
abstract class _Timer implements Timer {
final int _microseconds;
int _tick;
WasmExternRef? _handle;
@override
int get tick => _tick;
@override
bool get isActive => !_handle.isNull;
_Timer(Duration duration)
: _microseconds = duration.inMicroseconds,
_tick = 0,
_handle = WasmExternRef.nullRef {
_schedule();
}
void _schedule();
void _processTick();
@override
void cancel() {
if (!_handle.isNull) {
embedder.clearSchedule(_handle);
_handle = WasmExternRef.nullRef;
}
}
static WasmVoid runtimeCallback(WasmAnyRef timer) {
final dartTimer = timer.toObject() as _Timer;
dartTimer._processTick();
return WasmVoid();
}
}
class _OneShotTimer extends _Timer {
final void Function() _callback;
_OneShotTimer(Duration duration, this._callback) : super(duration);
@override
void _schedule() {
_handle = embedder.scheduleOnce(
_microseconds.toWasmI64(),
WasmFunction.fromFunction(_Timer.runtimeCallback),
WasmAnyRef.fromObject(this),
);
}
_processTick() {
_tick++;
_handle = WasmExternRef.nullRef;
_callback();
}
}
class _PeriodicTimer extends _Timer {
final void Function(Timer) _callback;
int _start = 0;
_PeriodicTimer(Duration duration, this._callback) : super(duration);
@override
void _schedule() {
_start = embedder.currentTimeMicros().toInt();
_handle = embedder.scheduleRepeated(
_microseconds.toWasmI64(),
WasmFunction.fromFunction(_Timer.runtimeCallback),
WasmAnyRef.fromObject(this),
);
}
@override
void _processTick() {
_tick++;
if (_microseconds > 0) {
final int duration = embedder.currentTimeMicros().toInt() - _start;
if (duration > _tick * _microseconds) {
_tick = duration ~/ _microseconds;
}
}
_callback(this);
}
}
@patch
class _AsyncRun {
@patch
static void _scheduleImmediate(void callback()) {
embedder.queueMicrotask(
WasmFunction.fromFunction(_runtimeCallback),
WasmAnyRef.fromObject(callback),
);
}
static WasmVoid _runtimeCallback(WasmAnyRef callbackFunction) {
final function = callbackFunction.toObject() as void Function();
function();
return WasmVoid();
}
}