
# Začínáme

## Instalace

```bash
composer require phasis/phasis
```

Phasis vyžaduje PHP 8.2 nebo novější a tři rozšíření, která všechna potřebuje `composer.json`:

- `mbstring` — práce s řetězci.
- `bcmath` — aritmetika BigInt a práce s čísly s celočíselnou přesností.
- `curl` — výchozí přenosová vrstva `fetch()`.

`mbstring` a `curl` jsou povolená ve většině sestavení. `bcmath` často chybí: oficiální obrazy `php` Docker (`php:8.x-cli`, `php:8.x-fpm`) ho neobsahují a některé distribuce ho balí samostatně (`php-bcmath`). Bez něj Composer odmítne nainstalovat Phasis. Do Dockerfile založeného na oficiálním obrazu přidejte:

```dockerfile
RUN docker-php-ext-install bcmath
```

Spusťte `php -m` a zjistěte, která rozšíření vaše sestavení obsahuje.

`ext-intl` je volitelné. Phasis funguje i bez něj, ale celá rodina `Intl.*` (`Collator`, `NumberFormat`, `DateTimeFormat`, `PluralRules`, `Locale`, `DisplayNames`, `ListFormat`, `RelativeTimeFormat`, `Segmenter`, `DurationFormat`) a kalendáře Temporal jiné než ISO (`hebrew`, `islamic`, `japanese`, `persian` atd.) ho vyžadují. Nainstalujte ho, kdykoli hostitelská aplikace zpřístupňuje JS pro formátování závislé na národním prostředí. Volitelné je také `ext-openssl`: šifrování `crypto.subtle` AES-CBC, AES-CTR a AES-GCM ho vyžaduje, zatímco digesty a HMAC fungují bez něj.

Bez `exec`, FFI, Node.js i vlastního nativního rozšíření.

## Spuštění skriptu z CLI

```bash
./vendor/bin/phasis -e 'console.log(1 + 2 * 3)'
# 7

./vendor/bin/phasis -e 'console.log([1, 2, 3].map(x => x * x).join(","))'
# 1,4,9

./vendor/bin/phasis path/to/script.js
```

CLI vypisuje to, co skript zapíše pomocí `console.log`; hodnotu posledního výrazu nevypisuje.

Úplný seznam příkazů najdete v [referenční příručce CLI](https://phasis.inline0.dev/cs/docs/cli).

## Vložení do PHP

```php
<?php

require __DIR__ . '/vendor/autoload.php';

use Phasis\Engine;

$engine = new Engine();

// Evaluate an expression
$result = $engine->eval('1 + 2 * 3');
echo $result;
// 7

// Execute a script file
$engine->execFile('path/to/script.js');

// Bridge a PHP value into the JS global scope
$engine->setGlobal('config', ['debug' => true, 'version' => '1.0']);
$engine->eval('console.log(config.version)');

// console output is buffered on the engine, not printed
echo $engine->getConsoleOutput();
// 1.0
```

Instance `Engine` uchovává svůj globální stav mezi voláními, takže následující volání `eval()` uvidí vše, co jste definovali dříve.

`console.log` a související funkce přidávají výstup do vyrovnávací paměti enginu namísto zápisu na stdout. Přečtěte si ho pomocí `getConsoleOutput()` (jeden řetězec, řádky spojené pomocí `\n`) nebo `getConsoleLines()` (seznam řádků) a vyprázdněte ho pomocí `clearConsole()`.

Studený start je rychlý: předem se instaluje jen jádro potřebné pro načtení specifikace (`Object`, `Function`, `Array`, `Promise`, `Symbol`, `BigInt`, `RegExp` a typy chyb). `Map`, `TypedArray`, `Temporal`, `Intl`, `URL`, `fetch`, celé balíčky Web Platform / Fetch a vše ostatní se transparentně načítá při prvním čtení. Předáním `new Engine(eager: true)` nainstalujete při vytváření všechny vestavěné prvky — hodí se pro nástroje ověřující shodu se specifikací, které kontrolují deskriptory ještě před jejich čtením; při běžném vkládání se používá zřídka.

## Volání funkcí JS z PHP

```php
$engine->eval('function add(a, b) { return a + b; }');
echo $engine->call('add', 2, 3);
// 5
```

`call()` vyhledá funkci podle názvu na globálním objektu a zavolá ji s dodanými argumenty PHP (automaticky převedenými na hodnoty JS).

## Zpřístupnění volatelné funkce PHP jako funkce JS

```php
$engine->setGlobal('fetchData', function (string $url): array {
    return json_decode(file_get_contents($url), true);
});

$engine->eval('const users = fetchData("https://api.example.com/users")');
```

Uzávěry PHP se obalí jako funkce JS. Při volání se jejich argumenty převedou z JS na PHP a návratové hodnoty zpět z PHP na JS.

## Objekty PHP

Objekty PHP zatím nelze sdílet s JavaScript. `setGlobal()` s běžným objektem PHP sváže `undefined` (sledováno v [problému #18](https://github.com/inline0/phasis/issues/18)). Data předávejte jako pole, která se zkopírují do JS, a chování zpřístupněte jako uzávěry:

```php
class Counter {
    public int $value = 0;
    public function increment(): void { $this->value++; }
}

$counter = new Counter();
$engine->setGlobal('increment', fn () => $counter->increment());

$engine->eval('increment(); increment();');

echo $counter->value;
// 2
```

Podrobnosti a další možnosti náhradního řešení najdete v části [Sdílené objekty](https://phasis.inline0.dev/cs/docs/interop/shared-objects).

## Limity prostředků

```php
$engine = new Engine();
$engine->setLimit('maxLoopIterations', 100_000);
```

`maxLoopIterations` (výchozí 100,000) je jediný limit, který lze měnit za běhu, a v současnosti se vztahuje pouze na kód spouštěný interpretem procházejícím strom. Smyčky spouštěné bajtkódovým VM (těla funkcí a většina kódu nejvyšší úrovně) se nepočítají, takže samotný limit nezastaví `while (true) {}` ([problém #19](https://github.com/inline0/phasis/issues/19)). Po dosažení limitu lze chybu zachytit v JS; pokud ji nikdo nezachytí, dostane se do PHP jako `Phasis\Exceptions\InternalError`, podtřída `Phasis\Exceptions\RuntimeError`.

Engine má také pevný limit zásobníku volání 4,096 rámců (a kontrolní limit 8,192 rámců pro transpiled uzávěry); jeho překročení vyvolá chybu „Maximum call stack size exceeded“, opět jako `InternalError`. Časový limit není stanoven, proto nespouštějte nedůvěryhodný kód bez vlastního limitu `max_execution_time` PHP nebo v samostatném procesu. Viz [API: setLimit](https://phasis.inline0.dev/cs/docs/api#setlimit).

## Další kroky

- [Referenční příručka API](https://phasis.inline0.dev/cs/docs/api) — úplné rozhraní `Phasis\Engine`.
- [Propojení](https://phasis.inline0.dev/cs/docs/interop) — pravidla převodu hodnot, hostitelské funkce, objekty PHP.
- [Kompatibilita](https://phasis.inline0.dev/cs/docs/compatibility) — implementované funkce a pokrytí test262.
- [Parser](https://phasis.inline0.dev/cs/docs/parser) a [Formátovač](https://phasis.inline0.dev/cs/docs/formatter) — parsování a formátování JavaScript bez jeho spouštění.
- [Pokročilé informace](https://phasis.inline0.dev/cs/docs/advanced) — architektura, bajtkódový VM, benchmarky a testování proti referenční implementaci.
