
# Darba sākšana

## Instalēšana

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

Phasis vajadzīgs PHP 8.2 vai jaunāks ar trim paplašinājumiem, kas visi nepieciešami `composer.json`:

- `mbstring` — virkņu apstrāde.
- `bcmath` — BigInt aritmētika un veselu skaitļu precizitātes skaitļu apstrāde.
- `curl` — noklusētais transports, ko izmanto `fetch()`.

`mbstring` un `curl` ir iespējoti lielākajā daļā būvējumu. `bcmath` bieži nav pieejams: oficiālajos `php` Docker attēlos (`php:8.x-cli`, `php:8.x-fpm`) tas nav iekļauts, un daži izplatījumi to piedāvā atsevišķā pakotnē (`php-bcmath`). Bez tā Composer atsakās instalēt Phasis. Dockerfile, kura pamatā ir oficiālais attēls, pievienojiet:

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

Palaidiet `php -m`, lai noskaidrotu, kādi paplašinājumi ir iekļauti jūsu būvējumā.

`ext-intl` nav obligāts. Phasis darbojas arī bez tā, taču visai `Intl.*` saimei (`Collator`, `NumberFormat`, `DateTimeFormat`, `PluralRules`, `Locale`, `DisplayNames`, `ListFormat`, `RelativeTimeFormat`, `Segmenter`, `DurationFormat`) un Temporal kalendāriem, kas nav ISO (`hebrew`, `islamic`, `japanese`, `persian` u.c.), tas ir nepieciešams. Instalējiet to, ja resursdatora lietotne nodrošina JS, kas izmanto lokalizācijai pielāgotu formatēšanu. `ext-openssl` arī nav obligāts: `crypto.subtle` AES-CBC, AES-CTR un AES-GCM šifrēšanai tas ir nepieciešams, bet jaucējvērtību aprēķināšana un HMAC darbojas arī bez tā.

Nav `exec`, FFI, Node.js vai pielāgotu vietējo paplašinājumu.

## Skripta palaišana no 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 izvada to, ko skripts raksta, izmantojot `console.log`; tas neizvada pēdējās izteiksmes vērtību.

Pilno komandu kopuma skatiet [CLI atsaucē](https://phasis.inline0.dev/lv/docs/cli).

## Iegulšana 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
```

`Engine` instance starp izsaukumiem saglabā savu globālo stāvokli, tāpēc turpmākajos `eval()` izsaukumos ir pieejams viss iepriekš definētais.

`console.log` un tā radniecīgās funkcijas pievieno datus dzinēja buferim, nevis raksta uz stdout. Nolasiet to ar `getConsoleOutput()` (viena virkne, rindas savienotas ar `\n`) vai `getConsoleLines()` (rindu saraksts) un iztukšojiet ar `clearConsole()`.

Aukstā startēšana ir lēta: sākumā tiek instalēts tikai specifikācijas ielādei nepieciešamais kodols (`Object`, `Function`, `Array`, `Promise`, `Symbol`, `BigInt`, `RegExp` un kļūdu tipi). `Map`, `TypedArray`, `Temporal`, `Intl`, `URL`, `fetch`, pilnās Web Platform / Fetch pakotnes un viss pārējais tiek nemanāmi ielādēts pirmajā nolasīšanas reizē. Nododiet `new Engine(eager: true)`, lai izveides laikā instalētu visas iebūvētās funkcijas — noder atbilstības pārbaudes rīkiem, kas pārbauda deskriptorus pirms to nolasīšanas; parasti iegulšanai tas nav vajadzīgs.

## JS funkciju izsaukšana no PHP

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

`call()` meklē funkciju pēc nosaukuma globālajā objektā un izsauc to ar norādītajiem PHP argumentiem (kas tiek automātiski pārveidoti par JS vērtībām).

## PHP izsaucamās funkcijas atklāšana kā JS funkcija

```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 slēgumi tiek ietīti kā JS funkcijas. Izsaukšanas brīdī argumenti no JS tiek pārveidoti par PHP, bet atgrieztās vērtības no PHP tiek pārveidotas atpakaļ par JS.

## PHP objekti

PHP objektus pagaidām nevar koplietot ar JavaScript. `setGlobal()` sasaista `undefined`, ja tam nodod parastu PHP objektu (tas tiek izsekots kā [issue #18](https://github.com/inline0/phasis/issues/18)). Nododiet datus kā masīvus, kas tiek kopēti uz JS, un atklājiet darbības kā slēgumus:

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

Plašāku informāciju un citus risinājumus skatiet sadaļā [Koplietoti objekti](https://phasis.inline0.dev/lv/docs/interop/shared-objects).

## Resursu ierobežojumi

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

`maxLoopIterations` (noklusējuma vērtība 100,000) ir vienīgais izpildlaikā pielāgojamais ierobežojums, un pašlaik tas attiecas tikai uz kodu, ko izpilda koka šķērsošanas interpretētājs. Baitu koda virtuālās mašīnas izpildītās cilpas (funkciju pamatdaļas un lielākā daļa augstākā līmeņa koda) netiek skaitītas, tāpēc ar šo ierobežojumu vien nepietiek, lai apturētu `while (true) {}` ([issue #19](https://github.com/inline0/phasis/issues/19)). Sasniedzot ierobežojumu, kļūdu var uztvert ar JS; ja tā netiek uztverta, tā nonāk līdz PHP kā `Phasis\Exceptions\InternalError`, kas ir `Phasis\Exceptions\RuntimeError` apakšklase.

Dzinējam ir arī fiksēts izsaukumu steka ierobežojums — 4,096 kadri (un transpiletiem slēgumiem paredzēta 8,192 kadru aizsardzība); tā pārsniegšana izraisa kļūdu "Maximum call stack size exceeded", atkal kā `InternalError`. Laika ierobežojuma nav, tāpēc neuzticamu kodu palaidiet ar PHP paša `max_execution_time` vai atsevišķā procesā. Skatiet [API: setLimit](https://phasis.inline0.dev/lv/docs/api#setlimit).

## Nākamās darbības

- [API atsauce](https://phasis.inline0.dev/lv/docs/api) — pilns `Phasis\Engine` iespēju klāsts.
- [Savietojamība](https://phasis.inline0.dev/lv/docs/interop) — vērtību pārveidošanas noteikumi, resursdatora funkcijas, PHP objekti.
- [Saderība](https://phasis.inline0.dev/lv/docs/compatibility) — ieviestās funkcijas un test262 pārklājums.
- [Parsētājs](https://phasis.inline0.dev/lv/docs/parser) un [Formatētājs](https://phasis.inline0.dev/lv/docs/formatter) — parsējiet un formatējiet JavaScript, to neizpildot.
- [Papildu informācija](https://phasis.inline0.dev/lv/docs/advanced) — arhitektūra, baitu koda virtuālā mašīna, etalonmērījumi un orākula testēšana.
