
# Alustamine

## Paigaldamine

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

Phasis vajab versiooni PHP 8.2 või uuemat ning kolme laiendust, mida kõiki nõuab `composer.json`:

- `mbstring` — stringide töötlemine.
- `bcmath` — BigInt-aritmeetika ja täisarvude täppisarvutus.
- `curl` — vaikeedastus, mida kasutab `fetch()`.

`mbstring` ja `curl` on enamikus järkudes lubatud. `bcmath` sageli pole: ametlikud `php` Docker-kujutised (`php:8.x-cli`, `php:8.x-fpm`) jätavad selle välja ning osa distributsioone pakendab selle eraldi (`php-bcmath`). Ilma selleta keeldub Composer paketti Phasis installimast. Ametlikul kujutisel põhinevas Dockerfile'is lisage:

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

Käivitage `php -m`, et näha, millised laiendused teie järgus olemas on.

`ext-intl` on valikuline. Phasis töötab selleta, kuid kogu `Intl.*`-perekond (`Collator`, `NumberFormat`, `DateTimeFormat`, `PluralRules`, `Locale`, `DisplayNames`, `ListFormat`, `RelativeTimeFormat`, `Segmenter`, `DurationFormat`) ja mitte-ISO Temporal-kalendrid (`hebrew`, `islamic`, `japanese`, `persian` jne) vajavad seda. Installige see siis, kui hostrakendus pakub JS, mis kasutab lokaaditeadlikku vormindamist. `ext-openssl` on samuti valikuline: `crypto.subtle` AES-CBC, AES-CTR ja AES-GCM-krüpteerimine vajab seda, räsid ja HMAC toimivad selleta.

Pole vaja `exec`, FFI-d, Node.js ega kohandatud natiivlaiendust.

## Skripti käivitamine CLI-ist

```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 väljastab selle, mida skript kirjutab käsuga `console.log`; viimase avaldise väärtust see ei väljasta.

Vaadake täielikku käskude loendit [CLI viite](https://phasis.inline0.dev/et/docs/cli) lehelt.

## Manustamine PHP-isse

```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
```

`Engine` eksemplar säilitab kutsete vahel globaalse oleku, seega näevad järgnevad `eval()` väljakutsed kõike varem defineeritut.

`console.log` ja selle sõsarmeetodid lisavad väljundi mootori puhvrisse, mitte stdout'i. Lugege seda käsuga `getConsoleOutput()` (üks string, read ühendatud märgiga `\n`) või `getConsoleLines()` (ridade loend) ning tühjendage käsuga `clearConsole()`.

Käivituse algkulu on väike: esmalt paigaldatakse ainult spetsifikatsiooni laadimist võimaldav tuum (`Object`, `Function`, `Array`, `Promise`, `Symbol`, `BigInt`, `RegExp` ja veatüübid). `Map`, `TypedArray`, `Temporal`, `Intl`, `URL`, `fetch`, täielikud Web Platformi ja Fetchi paketid ning kõik muu laaditakse esmakordsel lugemisel läbipaistvalt. Andke konstruktorile `new Engine(eager: true)`, et paigaldada loomisel kõik sisseehitatud komponendid — kasulik vastavustööriistadele, mis uurivad deskriptoreid enne lugemist; tavalisel manustamisel läheb seda harva vaja.

## Funktsioonide JS väljakutsumine PHP-ist

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

`call()` otsib funktsiooni nime järgi globaalobjektilt ja kutsub selle välja antud PHP argumentidega (teisendades need automaatselt JS väärtusteks).

## PHP-i kutsutava muutmine JS funktsiooniks

```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")');
```

PHP sulgurid mähitakse JS funktsioonideks. Väljakutse korral teisendatakse argumendid JS-ist PHP-ks ja tagastusväärtused PHP-st JS-ks.

## PHP objektid

PHP objekte ei saa veel jagada JavaScript-iga. Tavalisel PHP objektil põhinev `setGlobal()` seob `undefined`-i (jälgitud [teemas #18](https://github.com/inline0/phasis/issues/18)). Andke andmed edasi massiividena, mis kopeeritakse väärtuseks JS, ja tehke käitumine kättesaadavaks sulguritena:

```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
```

Üksikasju ja muid lahendusi leiate lehelt [Jagatud objektid](https://phasis.inline0.dev/et/docs/interop/shared-objects).

## Ressursipiirangud

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

`maxLoopIterations` (vaikimisi 100,000) on ainus käitusajal muudetav piirang ning praegu kehtib see ainult koodile, mida käivitab puud läbiv interpretaator. Baidikoodi VM-i käivitatavaid tsükleid (funktsioonide kehi ja enamikku tipptaseme koodi) ei loendata, seega piirang üksi ei peata `while (true) {}`-i ([teema #19](https://github.com/inline0/phasis/issues/19)). Piirangu saavutamisel saab vea JS-is kinni püüda; püüdmata vea korral jõuab see PHP-ni kui `Phasis\Exceptions\InternalError`, mis on `Phasis\Exceptions\RuntimeError` alamklass.

Mootoril on ka fikseeritud 4,096-raamiline väljakutsepinu ülempiir (ning transpileeritud sulgurite jaoks 8,192-raamiline kaitse); selle ületamine põhjustab taas `InternalError` kujul vea "Maximum call stack size exceeded". Seinalähedast ajalimiiti pole, seega käivitage usaldamata kood PHP enda `max_execution_time`-is või eraldi protsessis. Vt [API: setLimit](https://phasis.inline0.dev/et/docs/api#setlimit).

## Järgmised sammud

- [API viide](https://phasis.inline0.dev/et/docs/api) — täielik `Phasis\Engine`-i funktsioonistik.
- [Koostalitlus](https://phasis.inline0.dev/et/docs/interop) — väärtuste teisendamise reeglid, hostfunktsioonid, PHP objektid.
- [Ühilduvus](https://phasis.inline0.dev/et/docs/compatibility) — rakendatud funktsioonid, test262 katvus.
- [Parser](https://phasis.inline0.dev/et/docs/parser) ja [Vormindaja](https://phasis.inline0.dev/et/docs/formatter) — JavaScript parsimine ja vormindamine seda käivitamata.
- [Täpsem teave](https://phasis.inline0.dev/et/docs/advanced) — arhitektuur, baidikoodi VM, võrdlusalused, võrdlustestimine.
