
# Primii pași

## Instalare

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

Phasis necesită PHP 8.2 sau o versiune ulterioară, cu trei extensii, toate necesare pentru `composer.json`:

- `mbstring` — gestionarea șirurilor.
- `bcmath` — operații aritmetice BigInt și gestionarea numerelor cu precizie întreagă.
- `curl` — transportul implicit din spatele `fetch()`.

`mbstring` și `curl` sunt activate în majoritatea build-urilor. Adesea, `bcmath` nu este: imaginile oficiale `php` Docker (`php:8.x-cli`, `php:8.x-fpm`) nu îl includ, iar unele distribuții îl împachetează separat (`php-bcmath`). Fără acesta, Composer refuză să instaleze Phasis. Într-un Dockerfile bazat pe imaginea oficială, adăugați:

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

Rulați `php -m` pentru a vedea ce extensii are build-ul dvs.

`ext-intl` este opțional. Phasis funcționează fără el, dar întreaga familie `Intl.*` (`Collator`, `NumberFormat`, `DateTimeFormat`, `PluralRules`, `Locale`, `DisplayNames`, `ListFormat`, `RelativeTimeFormat`, `Segmenter`, `DurationFormat`) și calendarele Temporal non-ISO (`hebrew`, `islamic`, `japanese`, `persian` etc.) au nevoie de el. Instalați-l ori de câte ori aplicația gazdă expune JS care afectează formatarea în funcție de localizare. Și `ext-openssl` este opțional: criptarea AES-CBC, AES-CTR și AES-GCM din `crypto.subtle` necesită această extensie, în timp ce rezumatele criptografice și HMAC funcționează fără ea.

Fără `exec`, fără FFI, fără Node.js, fără extensii native personalizate.

## Rulați un script din 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 afișează ce scrie scriptul cu `console.log`; nu afișează valoarea ultimei expresii.

Consultați referința [CLI pentru ](https://phasis.inline0.dev/ro/docs/cli) cu setul complet de comenzi.

## Încorporați în 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
```

Instanța `Engine` își păstrează starea globală între apeluri, astfel că invocările ulterioare ale `eval()` văd tot ce ați definit anterior.

`console.log` și elementele înrudite adaugă date într-un buffer al motorului în loc să scrie la stdout. Citiți-l cu `getConsoleOutput()` (un șir, cu liniile unite prin `\n`) sau cu `getConsoleLines()` (o listă de linii) și goliți-l cu `clearConsole()`.

Pornirea la rece este rapidă: la început se instalează doar nucleul necesar pentru încărcarea specificațiilor (`Object`, `Function`, `Array`, `Promise`, `Symbol`, `BigInt`, `RegExp` și tipurile de erori). `Map`, `TypedArray`, `Temporal`, `Intl`, `URL`, `fetch`, pachetele Web Platform / Fetch complete și toate celelalte se materializează transparent la prima citire. Transmiteți `new Engine(eager: true)` pentru a instala toate elementele încorporate la creare — util pentru instrumentele de conformitate care inspectează descriptorii înainte de a-i citi; rar este necesar la încorporarea obișnuită.

## Apelați funcții JS din PHP

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

`call()` caută funcția după nume pe obiectul global și o invocă folosind argumentele PHP furnizate (convertite automat în valori JS).

## Expuneți o funcție apelabilă PHP ca funcție 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")');
```

Închiderile PHP sunt împachetate ca funcții JS. Argumentele lor sunt convertite din JS în PHP la apel, iar valorile returnate sunt convertite înapoi din PHP în JS.

## Obiecte PHP

Obiectele PHP nu pot fi partajate cu JavaScript încă. `setGlobal()` cu un obiect simplu PHP asociază `undefined` (urmărit în [problema #18](https://github.com/inline0/phasis/issues/18)). Transmiteți datele ca tablouri, care sunt copiate în JS, și expuneți comportamentul prin închideri:

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

Consultați [Obiecte partajate](https://phasis.inline0.dev/ro/docs/interop/shared-objects) pentru detalii și alte soluții alternative.

## Limite de resurse

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

`maxLoopIterations` (valoarea implicită 100,000) este singura limită care poate fi ajustată în timpul rulării, iar în prezent se aplică doar codului executat de interpretul care parcurge arborele. Buclele executate de VM-ul de bytecode (corpurile funcțiilor și majoritatea codului de nivel superior) nu sunt contorizate, astfel că limita singură nu oprește `while (true) {}` ([problema #19](https://github.com/inline0/phasis/issues/19)). Când se atinge limita, eroarea poate fi prinsă în JS; dacă nu este prinsă, ajunge la PHP drept `Phasis\Exceptions\InternalError`, o subclasă a lui `Phasis\Exceptions\RuntimeError`.

Motorul are și o limită fixă de 4,096 cadre pentru stiva de apeluri (și o protecție la 8,192 cadre pentru închiderile transpuse); depășirea acesteia generează „Maximum call stack size exceeded”, tot ca `InternalError`. Nu există o limită de timp de execuție, așa că rulați codul neîncredere sub PHP cu propriul `max_execution_time` sau într-un proces separat. Consultați [API: setLimit](https://phasis.inline0.dev/ro/docs/api#setlimit).

## Pașii următori

- [API — referință](https://phasis.inline0.dev/ro/docs/api) cu întreaga suprafață `Phasis\Engine`.
- [Interoperabilitate](https://phasis.inline0.dev/ro/docs/interop) — reguli de conversie a valorilor, funcții gazdă și obiecte PHP.
- [Compatibilitate](https://phasis.inline0.dev/ro/docs/compatibility) — ce este implementat și acoperirea test262.
- [Parser](https://phasis.inline0.dev/ro/docs/parser) și [Formator](https://phasis.inline0.dev/ro/docs/formatter) — parsați și formatați JavaScript fără a-l executa.
- [Avansat](https://phasis.inline0.dev/ro/docs/advanced) — arhitectură, VM de bytecode, teste de performanță și testare oracle.
