
# Memulai

## Instalasi

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

Phasis memerlukan PHP 8.2 atau lebih baru dengan tiga ekstensi, semuanya diwajibkan oleh `composer.json`:

- `mbstring` — penanganan string.
- `bcmath` — aritmetika BigInt dan penanganan angka presisi bilangan bulat.
- `curl` — transportasi default di balik `fetch()`.

`mbstring` dan `curl` aktif di sebagian besar build. `bcmath` sering kali tidak: image resmi `php` Docker (`php:8.x-cli`, `php:8.x-fpm`) tidak menyertakannya, dan beberapa distribusi mengemasnya secara terpisah (`php-bcmath`). Tanpanya, Composer menolak menginstal Phasis. Dalam Dockerfile yang berbasis image resmi, tambahkan:

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

Jalankan `php -m` untuk melihat ekstensi yang tersedia di build Anda.

`ext-intl` bersifat opsional. Phasis berfungsi tanpanya, tetapi seluruh keluarga `Intl.*` (`Collator`, `NumberFormat`, `DateTimeFormat`, `PluralRules`, `Locale`, `DisplayNames`, `ListFormat`, `RelativeTimeFormat`, `Segmenter`, `DurationFormat`) dan kalender Temporal non-ISO (`hebrew`, `islamic`, `japanese`, `persian`, dll.) memerlukannya. Instal ekstensi ini jika aplikasi host menyediakan JS yang menggunakan pemformatan peka lokal. `ext-openssl` juga opsional: enkripsi AES-CBC, AES-CTR, dan AES-GCM `crypto.subtle` memerlukannya, sedangkan digest dan HMAC dapat berfungsi tanpanya.

Tanpa `exec`, tanpa FFI, tanpa Node.js, tanpa ekstensi native khusus.

## Jalankan skrip dari 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 mencetak apa yang ditulis skrip menggunakan `console.log`; ia tidak mencetak nilai ekspresi terakhir.

Lihat referensi [CLI](https://phasis.inline0.dev/id/docs/cli) untuk rangkaian perintah lengkap.

## Sematkan di 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
```

Instans `Engine` mempertahankan status globalnya di antara pemanggilan, sehingga pemanggilan `eval()` berikutnya dapat menggunakan apa pun yang Anda definisikan sebelumnya.

`console.log` dan saudaranya menambahkan keluaran ke buffer pada mesin alih-alih menulis ke stdout. Baca dengan `getConsoleOutput()` (satu string, baris digabung dengan `\n`) atau `getConsoleLines()` (daftar baris), lalu kosongkan dengan `clearConsole()`.

Mulai dingin tidak mahal: hanya inti yang diperlukan untuk memuat spesifikasi (`Object`, `Function`, `Array`, `Promise`, `Symbol`, `BigInt`, `RegExp`, tipe error) yang dipasang di awal. `Map`, `TypedArray`, `Temporal`, `Intl`, `URL`, `fetch`, seluruh Paket Web Platform / Fetch, dan semua lainnya tersedia secara transparan saat pertama kali dibaca. Berikan `new Engine(eager: true)` untuk memasang semua bawaan saat konstruksi — berguna untuk perkakas kesesuaian yang memeriksa deskriptor sebelum membacanya; jarang diperlukan untuk penyematan biasa.

## Panggil fungsi JS dari PHP

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

`call()` mencari fungsi berdasarkan nama pada objek global dan memanggilnya dengan argumen PHP yang diberikan (secara otomatis dikonversi menjadi nilai JS).

## Tampilkan callable PHP sebagai fungsi 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")');
```

Closure PHP dibungkus sebagai fungsi JS. Argumennya dikonversi dari JS ke PHP saat dipanggil, dan nilai kembalian dikonversi kembali dari PHP ke JS.

## Objek PHP

Objek PHP belum dapat dibagikan dengan JavaScript. `setGlobal()` dengan objek PHP biasa mengikat `undefined` (dilacak di [masalah #18](https://github.com/inline0/phasis/issues/18)). Teruskan data sebagai array, yang disalin ke JS, dan tampilkan perilaku sebagai closure:

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

Lihat [Objek bersama](https://phasis.inline0.dev/id/docs/interop/shared-objects) untuk detail dan solusi lainnya.

## Batas sumber daya

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

`maxLoopIterations` (default 100,000) adalah satu-satunya batas yang dapat diatur saat runtime, dan saat ini hanya berlaku untuk kode yang dijalankan interpreter penjelajah pohon. Loop yang dijalankan VM bytecode (badan fungsi dan sebagian besar kode tingkat teratas) tidak dihitung, jadi batas saja tidak menghentikan `while (true) {}` ([masalah #19](https://github.com/inline0/phasis/issues/19)). Saat batas tercapai, error dapat ditangkap di JS; jika tidak ditangkap, error mencapai PHP sebagai `Phasis\Exceptions\InternalError`, subkelas dari `Phasis\Exceptions\RuntimeError`.

Mesin juga memiliki batas tetap tumpukan pemanggilan 4,096 frame (serta pelindung 8,192 frame untuk closure yang ditranspilasi); jika terlampaui, akan melempar “Maximum call stack size exceeded”, sekali lagi sebagai `InternalError`. Tidak ada batas waktu nyata, jadi jalankan kode yang tidak tepercaya di bawah PHP `max_execution_time` sendiri atau dalam proses terpisah. Lihat [API: setLimit](https://phasis.inline0.dev/id/docs/api#setlimit).

## Langkah berikutnya

- Referensi [API](https://phasis.inline0.dev/id/docs/api) — seluruh permukaan `Phasis\Engine`.
- [Interoperabilitas](https://phasis.inline0.dev/id/docs/interop) — aturan konversi nilai, fungsi host, objek PHP.
- [Kompatibilitas](https://phasis.inline0.dev/id/docs/compatibility) — apa yang diimplementasikan, cakupan test262.
- [Parser](https://phasis.inline0.dev/id/docs/parser) dan [Pemformat](https://phasis.inline0.dev/id/docs/formatter) — mengurai dan memformat JavaScript tanpa menjalankannya.
- [Lanjutan](https://phasis.inline0.dev/id/docs/advanced) — arsitektur, VM bytecode, tolok ukur, pengujian oracle.
