channel = $channel; $this->timer = new Timer([ $this, "update" ]); } public function update() { while ($msg = $this->channel->receive()) { if (!array_key_exists('op', $msg)) { fprintf(STDERR, "Warning: Frame missing op -- %s\n", json_encode($msg)); continue; } switch ($msg['op']) { case 'retn': $id = $msg['id']; if (!array_key_exists($id, $this->promises)) { continue; } $promise = $this->promises[$id]; $promise->invoke($msg['ret']); unset($this->promises[$id]); continue; case 'call': $id = $msg['id']; $obj = $msg['obj']; if (!array_key_exists($obj, $this->exports)) { continue; } $ret = call_user_func($this->exports[$obj], ...$msg['arg']); $frame = [ 'op' => 'retn', 'id' => $id, 'ret' => $ret ]; $this->channel->send($frame); continue; case 'msg': default: foreach ($this->listeners as $listener) { call_user_func($listener, $msg); } } } } public function addListener(callable $handler) { $this->listeners[] = $handler; } public function export($path, callable $function) { $this->exports[$path] = $function; } public function send($data) { $frame = [ 'op' => 'msg', 'msg' => $data ]; $this->channel->send($frame); } public function call($path, ...$args) { $promise = new Promise(); $rid = uniqid(md5($path),true); $frame = [ 'op' => 'call', 'id' => $rid, 'obj' => $path, 'arg' => $args, ]; $this->promises[$rid] = $promise; $this->channel->send($frame); return $promise; } }