
# Kom igång

## Installation

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

Phasis kräver PHP 8.2 eller senare med tre tillägg, som alla krävs av `composer.json`:

- `mbstring` — stränghantering.
- `bcmath` — BigInt-aritmetik och hantering av heltal med exakt precision.
- `curl` — standardtransporten bakom `fetch()`.

`mbstring` och `curl` är aktiverade i de flesta byggen. `bcmath` är det ofta inte: de officiella `php`-Docker-avbildningarna (`php:8.x-cli`, `php:8.x-fpm`) saknar det, och vissa distributioner paketerar det separat (`php-bcmath`). Utan det vägrar Composer att installera Phasis. Lägg till följande i en Dockerfile som bygger på den officiella avbildningen:

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

Kör `php -m` för att se vilka tillägg som finns i ditt bygge.

`ext-intl` är valfritt. Phasis fungerar utan det, men hela familjen `Intl.*` (`Collator`, `NumberFormat`, `DateTimeFormat`, `PluralRules`, `Locale`, `DisplayNames`, `ListFormat`, `RelativeTimeFormat`, `Segmenter`, `DurationFormat`) och Temporal-kalendrar som inte följer ISO (`hebrew`, `islamic`, `japanese`, `persian` osv.) kräver det. Installera det när värdapplikationen exponerar JS som använder lokalanpassad formatering. Även `ext-openssl` är valfritt: AES-CBC-, AES-CTR- och AES-GCM-kryptering med `crypto.subtle` kräver det, medan hashberäkningar och HMAC fungerar utan det.

Inget `exec`, ingen FFI, inget Node.js, inget anpassat inbyggt tillägg.

## Kör ett skript från 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 skriver ut det som skriptet skriver med `console.log`; det skriver inte ut värdet av det sista uttrycket.

Se referensen för [CLI CLI](https://phasis.inline0.dev/sv/docs/cli) för den fullständiga uppsättningen kommandon.

## Bädda in i 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
```

Instansen `Engine` behåller sitt globala tillstånd mellan anrop, så efterföljande anrop till `eval()` ser allt du har definierat tidigare.

`console.log` och dess motsvarigheter lägger till i en buffert i motorn i stället för att skriva till stdout. Läs den med `getConsoleOutput()` (en sträng, med rader sammanfogade med `\n`) eller `getConsoleLines()` (en lista med rader), och töm den med `clearConsole()`.

Kallstarten är snabb: endast kärnan som behövs för att läsa in specifikationen (`Object`, `Function`, `Array`, `Promise`, `Symbol`, `BigInt`, `RegExp` och feltyperna) installeras från början. `Map`, `TypedArray`, `Temporal`, `Intl`, `URL`, `fetch`, de fullständiga Web Platform- och Fetch-paketen samt allt annat materialiseras transparent vid första läsningen. Skicka med `new Engine(eager: true)` för att installera alla inbyggda delar vid konstruktion — användbart för konformitetsverktyg som granskar deskriptorer innan de läses; behövs sällan vid normal inbäddning.

## Anropa JS-funktioner från PHP

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

`call()` letar upp funktionen med namn på det globala objektet och anropar den med de angivna PHP-argumenten (som automatiskt konverteras till JS-värden).

## Gör en anropbar PHP till en JS-funktion

```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-slutningar omsluts som JS-funktioner. Deras argument konverteras från JS till PHP vid anrop, och returvärdena konverteras tillbaka från PHP till JS.

## PHP-objekt

PHP-objekt kan ännu inte delas med JavaScript. `setGlobal()` med ett vanligt PHP-objekt binder `undefined` (spåras i [issue #18](https://github.com/inline0/phasis/issues/18)). Skicka data som arrayer, vilka kopieras till JS, och exponera beteende som slutningar:

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

Se [Delade objekt](https://phasis.inline0.dev/sv/docs/interop/shared-objects) för information och andra lösningar.

## Resursgränser

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

`maxLoopIterations` (standardvärde 100,000) är den enda gräns som kan justeras under körning, och i dag gäller den bara kod som körs av den trädvandrande tolken. Loopar som körs av bytekod-VM:en (funktionskroppar och det mesta av koden på toppnivå) räknas inte, så enbart en gräns stoppar inte `while (true) {}` ([issue #19](https://github.com/inline0/phasis/issues/19)). När gränsen nås kan felet fångas i JS; om det inte fångas når det PHP som `Phasis\Exceptions\InternalError`, en underklass till `Phasis\Exceptions\RuntimeError`.

Motorn har också en fast gräns på 4,096 anropsstackramar (och en spärr vid 8,192 ramar för transpilerade slutningar); om den överskrids kastas "Maximum call stack size exceeded", återigen som `InternalError`. Det finns ingen tidsgräns, så kör otillförlitlig kod under PHPs egen `max_execution_time` eller i en separat process. Se [API: setLimit](https://phasis.inline0.dev/sv/docs/api#setlimit).

## Nästa steg

- [API-referens](https://phasis.inline0.dev/sv/docs/api) — hela `Phasis\Engine`-gränssnittet.
- [Samverkan](https://phasis.inline0.dev/sv/docs/interop) — regler för värdekonvertering, värdfunktioner och PHP-objekt.
- [Kompatibilitet](https://phasis.inline0.dev/sv/docs/compatibility) — vad som är implementerat och test262-täckning.
- [Parser](https://phasis.inline0.dev/sv/docs/parser) och [Formaterare](https://phasis.inline0.dev/sv/docs/formatter) — parsa och formatera JavaScript utan att köra koden.
- [Avancerat](https://phasis.inline0.dev/sv/docs/advanced) — arkitektur, bytekod-VM, riktmärken och orakletestning.
