Use `JSScheduler` from `OpenCombineJS` package (#304)

Now that OpenCombineJS had its first release, we can rely on its `JSScheduler` implementation.
This commit is contained in:
Max Desiatov 2020-11-26 09:01:54 +00:00 committed by GitHub
parent d5a50e7045
commit 05465be93d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 12 additions and 176 deletions

View File

@ -19,6 +19,15 @@
"version": "0.12.0-alpha2"
}
},
{
"package": "OpenCombineJS",
"repositoryURL": "https://github.com/swiftwasm/OpenCombineJS.git",
"state": {
"branch": null,
"revision": "b346f955ed21ab44576e204a7554210c77f69b9b",
"version": "0.0.1"
}
},
{
"package": "Runtime",
"repositoryURL": "https://github.com/MaxDesiatov/Runtime.git",

View File

@ -43,6 +43,7 @@ let package = Package(
),
.package(url: "https://github.com/MaxDesiatov/Runtime.git", from: "2.1.2"),
.package(url: "https://github.com/TokamakUI/OpenCombine.git", from: "0.12.0-alpha2"),
.package(url: "https://github.com/swiftwasm/OpenCombineJS.git", from: "0.0.1"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define
@ -71,6 +72,7 @@ let package = Package(
name: "TokamakDOM",
dependencies: [
"CombineShim",
"OpenCombineJS",
"TokamakCore",
"TokamakStaticHTML",
.product(

View File

@ -16,6 +16,7 @@
//
import JavaScriptKit
import OpenCombineJS
import TokamakCore
import TokamakStaticHTML

View File

@ -1,176 +0,0 @@
// Copyright 2020 Tokamak contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import CombineShim
import JavaScriptKit
final class JSScheduler: Scheduler {
private final class CancellableTimer: Cancellable {
let cancellation: () -> ()
init(_ cancellation: @escaping () -> ()) {
self.cancellation = cancellation
}
func cancel() {
cancellation()
}
}
struct SchedulerTimeType: Strideable {
let millisecondsValue: Double
func advanced(by n: Stride) -> Self {
.init(millisecondsValue: millisecondsValue + n.magnitude)
}
func distance(to other: Self) -> Stride {
.init(millisecondsValue: other.millisecondsValue - millisecondsValue)
}
struct Stride: SchedulerTimeIntervalConvertible, Comparable, SignedNumeric {
/// Time interval magnitude in milliseconds
var magnitude: Double
init?<T>(exactly source: T) where T: BinaryInteger {
guard let magnitude = Double(exactly: source) else { return nil }
self.magnitude = magnitude
}
init(millisecondsValue: Double) {
magnitude = millisecondsValue
}
init(floatLiteral value: Double) {
self = .seconds(value)
}
init(integerLiteral value: Int) {
self = .seconds(value)
}
static func microseconds(_ us: Int) -> Self {
.init(millisecondsValue: 1.0 / (Double(us) * 1000))
}
static func milliseconds(_ ms: Int) -> Self {
.init(millisecondsValue: Double(ms))
}
static func nanoseconds(_ ns: Int) -> Self {
.init(millisecondsValue: 1.0 / (Double(ns) * 1_000_000))
}
static func seconds(_ s: Double) -> Self {
.init(millisecondsValue: s * 1000)
}
static func seconds(_ s: Int) -> Self {
.init(millisecondsValue: Double(s) * 1000)
}
public static func < (lhs: Self, rhs: Self) -> Bool {
lhs.magnitude < rhs.magnitude
}
public static func * (lhs: Self, rhs: Self) -> Self {
.init(millisecondsValue: lhs.magnitude * rhs.magnitude)
}
public static func + (lhs: Self, rhs: Self) -> Self {
.init(millisecondsValue: lhs.magnitude + rhs.magnitude)
}
public static func - (lhs: Self, rhs: Self) -> Self {
.init(millisecondsValue: lhs.magnitude - rhs.magnitude)
}
public static func -= (lhs: inout Self, rhs: Self) {
lhs.magnitude -= rhs.magnitude
}
public static func *= (lhs: inout Self, rhs: Self) {
lhs.magnitude *= rhs.magnitude
}
public static func += (lhs: inout Self, rhs: Self) {
lhs.magnitude += rhs.magnitude
}
}
}
struct SchedulerOptions {}
var now: SchedulerTimeType { .init(millisecondsValue: JSDate.now()) }
var minimumTolerance: SchedulerTimeType.Stride {
.init(millisecondsValue: .leastNonzeroMagnitude)
}
private var scheduledTimers = [ObjectIdentifier: JSTimer]()
func schedule(options: SchedulerOptions?, _ action: @escaping () -> ()) {
var timer: JSTimer!
timer = .init(millisecondsDelay: 0) { [weak self, weak timer] in
action()
if let timer = timer {
self?.scheduledTimers[ObjectIdentifier(timer)] = nil
}
}
scheduledTimers[ObjectIdentifier(timer)] = timer
}
func schedule(
after date: SchedulerTimeType,
tolerance: SchedulerTimeType.Stride,
options: SchedulerOptions?,
_ action: @escaping () -> ()
) {
var timer: JSTimer!
timer = .init(
millisecondsDelay: date.millisecondsValue - JSDate.now()
) { [weak self, weak timer] in
action()
if let timer = timer {
self?.scheduledTimers[ObjectIdentifier(timer)] = nil
}
}
scheduledTimers[ObjectIdentifier(timer)] = timer
}
func schedule(
after date: SchedulerTimeType,
interval: SchedulerTimeType.Stride,
tolerance: SchedulerTimeType.Stride,
options: SchedulerOptions?,
_ action: @escaping () -> ()
) -> Cancellable {
var timeoutTimer, intervalTimer: JSTimer!
timeoutTimer = .init(
millisecondsDelay: date.millisecondsValue - JSDate.now()
) { [weak self, weak timeoutTimer] in
intervalTimer = .init(millisecondsDelay: interval.magnitude) { action() }
self?.scheduledTimers[ObjectIdentifier(intervalTimer)] = intervalTimer
if let timeoutTimer = timeoutTimer {
self?.scheduledTimers[ObjectIdentifier(timeoutTimer)] = nil
}
}
scheduledTimers[ObjectIdentifier(timeoutTimer)] = timeoutTimer
return CancellableTimer { self.scheduledTimers[ObjectIdentifier(intervalTimer)] = nil }
}
}