
# Kom godt i gang

## Installation

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

Phasis kræver PHP 8.2 eller nyere med tre udvidelser, som alle kræves af `composer.json`:

- `mbstring` — strenghåndtering.
- `bcmath` — BigInt-aritmetik og håndtering af tal med heltalspræcision.
- `curl` — standardtransporten bag `fetch()`.

`mbstring` og `curl` er aktiveret i de fleste builds. Det er `bcmath` ofte ikke: de officielle `php` Docker-images (`php:8.x-cli`, `php:8.x-fpm`) udelader det, og nogle distributioner pakker det separat (`php-bcmath`). Uden det afviser Composer installation af Phasis. Tilføj følgende i en Dockerfile baseret på det officielle image:

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

Kør `php -m` for at se, hvilke udvidelser dit build har.

`ext-intl` er valgfrit. Phasis virker uden det, men hele `Intl.*`-familien (`Collator`, `NumberFormat`, `DateTimeFormat`, `PluralRules`, `Locale`, `DisplayNames`, `ListFormat`, `RelativeTimeFormat`, `Segmenter`, `DurationFormat`) og ikke-ISO Temporal-kalendere (`hebrew`, `islamic`, `japanese`, `persian` osv.) kræver det. Installér det, når værtsprogrammet stiller JS til rådighed, som håndterer lokalitetsbevidst formatering. `ext-openssl` er også valgfrit: kryptering med `crypto.subtle` AES-CBC, AES-CTR og AES-GCM kræver det, mens digest og HMAC fungerer uden.

Ingen `exec`, ingen FFI, ingen Node.js, ingen brugerdefineret native-udvidelse.

## Kør et script fra 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 udskriver det, scriptet skriver med `console.log`; det udskriver ikke værdien af det sidste udtryk.

Se [CLI-referencen](https://phasis.inline0.dev/da/docs/cli) for den fulde kommandoliste.

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

`Engine`-instansen bevarer sin globale tilstand mellem kald, så efterfølgende `eval()`-kald kan se alt, du tidligere har defineret.

`console.log` og dens søskendefunktioner føjer indhold til en buffer på motoren i stedet for at skrive til stdout. Læs den med `getConsoleOutput()` (én streng, linjer adskilt med `\n`) eller `getConsoleLines()` (en liste over linjer), og tøm den med `clearConsole()`.

Koldstart er hurtig: Kun den kerne, der indlæser specifikationerne (`Object`, `Function`, `Array`, `Promise`, `Symbol`, `BigInt`, `RegExp` og fejltyperne) installeres på forhånd. `Map`, `TypedArray`, `Temporal`, `Intl`, `URL`, `fetch`, de fulde Web Platform- og Fetch-pakker samt alt andet materialiseres automatisk ved første læsning. Angiv `new Engine(eager: true)` for at installere alle indbyggede komponenter under oprettelsen — nyttigt til værktøjer til overensstemmelsestests, der undersøger deskriptorer, før de læser dem; sjældent nødvendigt ved normal indlejring.

## Kald JS-funktioner fra PHP

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

`call()` finder funktionen ved navn på det globale objekt og kalder den med de angivne PHP-argumenter (der automatisk konverteres til JS-værdier).

## Eksponér en PHP-funktion som 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-closures omsluttes som JS-funktioner. Deres argumenter konverteres fra JS til PHP ved kald, og returværdierne konverteres tilbage fra PHP til JS.

## PHP-objekter

PHP-objekter kan endnu ikke deles med JavaScript. `setGlobal()` med et almindeligt PHP-objekt binder `undefined` (registreret i [issue #18](https://github.com/inline0/phasis/issues/18)). Send data som arrays, der kopieres til JS, og eksponér adfærd som closures:

```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 [Delte objekter](https://phasis.inline0.dev/da/docs/interop/shared-objects) for detaljer og andre løsninger.

## Ressourcegrænser

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

`maxLoopIterations` (standardværdi 100,000) er den eneste grænse, der kan indstilles ved kørsel, og i dag gælder den kun for kode, som den trævandrende fortolker kører. Løkker, som bytecode-VM'en kører (funktionsindhold og det meste kode på øverste niveau), tælles ikke med, så en grænse alene stopper ikke `while (true) {}` ([issue #19](https://github.com/inline0/phasis/issues/19)). Når grænsen nås, kan fejlen indfanges i JS; hvis den ikke indfanges, når den PHP som `Phasis\Exceptions\InternalError`, en underklasse af `Phasis\Exceptions\RuntimeError`.

Motoren har også en fast grænse på 4,096 frames for kaldestakken (og en vagt på 8,192 frames for transpilerede closures); overskrides den, udløses "Maximum call stack size exceeded", igen som `InternalError`. Der er ingen grænse for vægurtid, så kør ikke-betroet kode under PHPs eget `max_execution_time` eller i en separat proces. Se [API: setLimit](https://phasis.inline0.dev/da/docs/api#setlimit).

## Næste trin

- [API-reference](https://phasis.inline0.dev/da/docs/api) — hele `Phasis\Engine`-overfladen.
- [Interop](https://phasis.inline0.dev/da/docs/interop) — regler for værdikonvertering, værtsfunktioner, PHP-objekter.
- [Kompatibilitet](https://phasis.inline0.dev/da/docs/compatibility) — hvad der er implementeret, test262-dækning.
- [Parser](https://phasis.inline0.dev/da/docs/parser) og [Formatter](https://phasis.inline0.dev/da/docs/formatter) — parse og formatér JavaScript uden at køre det.
- [Avanceret](https://phasis.inline0.dev/da/docs/advanced) — arkitektur, bytecode-VM, benchmarks, oracle-tests.
