Skip to content

Commit a961f7d

Browse files
committed
Add "throw" method to an event loop
1 parent 8c98aa2 commit a961f7d

5 files changed

Lines changed: 54 additions & 35 deletions

File tree

src/Internal/Poller/SaucerPoller.php

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ final class SaucerPoller implements PollerInterface
2323
/**
2424
* @var array<array-key, \Closure(array-key):void>
2525
*/
26-
private array $queueTasks = [];
26+
private array $microTasks = [];
2727

2828
/**
2929
* @var array<array-key, \Closure(array-key):void>
3030
*/
31-
private array $periodicTasks = [];
31+
private array $periodicMicroTasks = [];
3232

3333
private TaskType $type = TaskType::DEFAULT;
3434

@@ -60,6 +60,11 @@ public function createSuspension(): Suspension
6060
return new Suspension($this);
6161
}
6262

63+
public function throw(\Throwable $e): int|string
64+
{
65+
return $this->defer(static fn(): never => throw $e);
66+
}
67+
6368
public function next(): void
6469
{
6570
switch ($this->type) {
@@ -89,7 +94,7 @@ private function executeInternalTask(): void
8994

9095
private function executePeriodicTask(): void
9196
{
92-
foreach ($this->periodicTasks as $id => $task) {
97+
foreach ($this->periodicMicroTasks as $id => $task) {
9398
$task($id);
9499

95100
return;
@@ -98,8 +103,8 @@ private function executePeriodicTask(): void
98103

99104
private function executeQueuedTask(): void
100105
{
101-
foreach ($this->queueTasks as $id => $task) {
102-
unset($this->queueTasks[$id]);
106+
foreach ($this->microTasks as $id => $task) {
107+
unset($this->microTasks[$id]);
103108

104109
$task($id);
105110

@@ -109,14 +114,14 @@ private function executeQueuedTask(): void
109114

110115
public function defer(callable $task): int|string
111116
{
112-
$this->queueTasks[$id = $this->ids->nextId()] = $task(...);
117+
$this->microTasks[$id = $this->ids->nextId()] = $task(...);
113118

114119
return $id;
115120
}
116121

117122
public function repeat(callable $task): int|string
118123
{
119-
$this->periodicTasks[$id = $this->ids->nextId()] = $task(...);
124+
$this->periodicMicroTasks[$id = $this->ids->nextId()] = $task(...);
120125

121126
return $id;
122127
}
@@ -134,8 +139,21 @@ public function delay(float $delay, callable $task): int|string
134139
});
135140
}
136141

142+
public function timer(float $interval, callable $task): int|string
143+
{
144+
$execAfter = \microtime(true) + $interval;
145+
146+
return $this->repeat(function (string|int $taskId) use (&$execAfter, $interval, $task): void {
147+
if (\microtime(true) > $execAfter) {
148+
$task($taskId);
149+
150+
$execAfter += $interval;
151+
}
152+
});
153+
}
154+
137155
public function cancel(int|string $taskId): void
138156
{
139-
unset($this->periodicTasks[$taskId], $this->queueTasks[$taskId]);
157+
unset($this->periodicMicroTasks[$taskId], $this->microTasks[$taskId]);
140158
}
141159
}

src/Poller/PollerInterface.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ public function next(): void;
2020
*/
2121
public function createSuspension(): SuspensionInterface;
2222

23+
/**
24+
* Sends an exception to the main execution thread.
25+
*
26+
* @return TaskIdType a unique identifier that can be used to cancel
27+
* an exception throwing
28+
*/
29+
public function throw(\Throwable $e): int|string;
30+
2331
/**
2432
* Defer the execution of a callback.
2533
*
@@ -51,6 +59,17 @@ public function repeat(callable $task): int|string;
5159
*/
5260
public function delay(float $delay, callable $task): int|string;
5361

62+
/**
63+
* Repeatedly execute a callback with delay.
64+
*
65+
* @param float $interval the amount of time, in seconds, to interval the execution for
66+
* @param callable(TaskIdType):void $task the callback to execute
67+
*
68+
* @return TaskIdType a unique identifier that can be used to cancel
69+
* the callback
70+
*/
71+
public function timer(float $interval, callable $task): int|string;
72+
5473
/**
5574
* Cancel a task.
5675
*

src/Poller/Suspension.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ public function resolve(mixed $result): void
3030

3131
public function reject(\Throwable $error): void
3232
{
33-
$this->parent->defer(function () use ($error): never {
34-
throw $error;
35-
});
33+
$this->parent->throw($error);
3634
}
3735

3836
public function suspend(): mixed

src/WebView/Api/LifecycleEvents/LifecycleEventsExtension.php

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,7 @@ private function onSafeMessageReceived(string $message): bool
116116
try {
117117
return $this->onMessageReceived($message);
118118
} catch (\Throwable $e) {
119-
$this->webview->window->app->poller->defer(static function () use ($e) {
120-
throw $e;
121-
});
119+
$this->webview->window->app->poller->throw($e);
122120
}
123121

124122
return true;
@@ -138,9 +136,7 @@ private function onSafeDomReady(CData $_): void
138136
try {
139137
$this->onDomReady($_);
140138
} catch (\Throwable $e) {
141-
$this->webview->window->app->poller->defer(static function () use ($e) {
142-
throw $e;
143-
});
139+
$this->webview->window->app->poller->throw($e);
144140
}
145141
}
146142

@@ -152,9 +148,7 @@ private function onNavigated(CData $_, string $url): void
152148
url: Request::castUrl($url),
153149
));
154150
} catch (\Throwable $e) {
155-
$this->webview->window->app->poller->defer(static function () use ($e) {
156-
throw $e;
157-
});
151+
$this->webview->window->app->poller->throw($e);
158152
}
159153
}
160154

@@ -163,9 +157,7 @@ private function onSafeNavigated(CData $_, string $url): void
163157
try {
164158
$this->onNavigated($_, $url);
165159
} catch (\Throwable $e) {
166-
$this->webview->window->app->poller->defer(static function () use ($e) {
167-
throw $e;
168-
});
160+
$this->webview->window->app->poller->throw($e);
169161
}
170162
}
171163

@@ -195,9 +187,7 @@ private function onSafeNavigating(CData $_, CData $navigation): int
195187
try {
196188
return $this->onNavigating($_, $navigation);
197189
} catch (\Throwable $e) {
198-
$this->webview->window->app->poller->defer(static function () use ($e) {
199-
throw $e;
200-
});
190+
$this->webview->window->app->poller->throw($e);
201191

202192
return Policy::SAUCER_POLICY_BLOCK;
203193
}
@@ -223,9 +213,7 @@ private function onSafeFaviconChanged(CData $ptr, CData $icon): void
223213
try {
224214
$this->onFaviconChanged($ptr, $icon);
225215
} catch (\Throwable $e) {
226-
$this->webview->window->app->poller->defer(static function () use ($e) {
227-
throw $e;
228-
});
216+
$this->webview->window->app->poller->throw($e);
229217
}
230218
}
231219

@@ -244,9 +232,7 @@ private function onSafeTitleChanged(CData $ptr, string $title): void
244232
try {
245233
$this->onTitleChanged($ptr, $title);
246234
} catch (\Throwable $e) {
247-
$this->webview->window->app->poller->defer(static function () use ($e) {
248-
throw $e;
249-
});
235+
$this->webview->window->app->poller->throw($e);
250236
}
251237
}
252238

src/WebView/Api/Schemes/SchemesExtension.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,7 @@ private function onSafeRequest(CData $_, CData $request, CData $executor): void
5757
$code = SchemeError::SAUCER_REQUEST_ERROR_FAILED;
5858
$this->app->saucer->saucer_scheme_executor_reject($executor, $code);
5959

60-
$this->app->poller->defer(static function () use ($e) {
61-
throw $e;
62-
});
60+
$this->app->poller->throw($e);
6361

6462
return;
6563
}

0 commit comments

Comments
 (0)