
# Primeiros passos

## Instalação

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

Phasis requer PHP 8.2 ou posterior com três extensões, todas exigidas por `composer.json`:

- `mbstring` — tratamento de strings.
- `bcmath` — operações aritméticas com BigInt e tratamento de números com precisão inteira.
- `curl` — o transporte padrão por trás de `fetch()`.

`mbstring` e `curl` vêm habilitados na maioria das compilações. Muitas vezes, `bcmath` não vem: as imagens oficiais de `php` Docker (`php:8.x-cli`, `php:8.x-fpm`) não o incluem, e algumas distribuições o oferecem em um pacote separado (`php-bcmath`). Sem ele, Composer se recusa a instalar Phasis. Em um Dockerfile baseado na imagem oficial, adicione:

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

Execute `php -m` para ver quais extensões sua compilação tem.

`ext-intl` é opcional. Phasis funciona sem ela, mas toda a família `Intl.*` (`Collator`, `NumberFormat`, `DateTimeFormat`, `PluralRules`, `Locale`, `DisplayNames`, `ListFormat`, `RelativeTimeFormat`, `Segmenter`, `DurationFormat`) e os calendários não ISO Temporal (`hebrew`, `islamic`, `japanese`, `persian` etc.) precisam dela. Instale-a sempre que o aplicativo host oferecer JS que envolva formatação sensível à localidade. `ext-openssl` também é opcional: a criptografia AES-CBC, AES-CTR e AES-GCM de `crypto.subtle` precisa dela, mas digests e HMAC funcionam sem ela.

Sem `exec`, sem FFI, sem Node.js, sem extensão nativa personalizada.

## Executar um script a partir do 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
```

O CLI exibe o que o script escreve com `console.log`; não exibe o valor da última expressão.

Consulte a [Referência do CLI](https://phasis.inline0.dev/pt/docs/cli) para ver a lista completa de comandos.

## Incorporar em 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
```

A instância de `Engine` mantém seu estado global entre chamadas, então as chamadas subsequentes de `eval()` veem tudo o que você definiu anteriormente.

`console.log` e seus métodos irmãos acrescentam conteúdo a um buffer na engine, em vez de escreverem em stdout. Leia-o com `getConsoleOutput()` (uma string, com linhas unidas por `\n`) ou `getConsoleLines()` (uma lista de linhas), e esvazie-o com `clearConsole()`.

A inicialização a frio é rápida: somente o núcleo necessário para carregar a especificação (`Object`, `Function`, `Array`, `Promise`, `Symbol`, `BigInt`, `RegExp` e os tipos de erro) é instalado de imediato. `Map`, `TypedArray`, `Temporal`, `Intl`, `URL`, `fetch`, os pacotes Web Platform / Fetch completos e todo o restante são materializados de forma transparente na primeira leitura. Passe `new Engine(eager: true)` para instalar todos os recursos integrados durante a construção — útil para ferramentas de conformidade que inspecionam descritores antes de lê-los; raramente necessário na incorporação normal.

## Chamar funções de JS a partir de PHP

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

`call()` procura a função pelo nome no objeto global e a invoca com os argumentos PHP fornecidos (convertidos automaticamente em valores JS).

## Expor uma função chamável de PHP como função 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")');
```

As closures de PHP são encapsuladas como funções JS. Seus argumentos são convertidos de JS para PHP na chamada, e seus valores de retorno são convertidos de PHP de volta para JS.

## Objetos PHP

Objetos PHP ainda não podem ser compartilhados com JavaScript. `setGlobal()` com um objeto PHP simples vincula `undefined` (acompanhado em [problema #18](https://github.com/inline0/phasis/issues/18)). Passe os dados como arrays, que são copiados para JS, e exponha o comportamento como 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
```

Consulte [Objetos compartilhados](https://phasis.inline0.dev/pt/docs/interop/shared-objects) para ver os detalhes e outras soluções alternativas.

## Limites de recursos

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

`maxLoopIterations` (limite padrão 100,000) é o único limite ajustável durante a execução e, atualmente, só se aplica ao código executado pelo interpretador que percorre a árvore. Loops executados pela VM de bytecode (corpos de funções e a maior parte do código de nível superior) não são contabilizados, então o limite por si só não interrompe `while (true) {}` ([problema #19](https://github.com/inline0/phasis/issues/19)). Quando o limite é atingido, o erro pode ser capturado em JS; se não for capturado, chega a PHP como `Phasis\Exceptions\InternalError`, uma subclasse de `Phasis\Exceptions\RuntimeError`.

O engine também tem um limite fixo de pilha de chamadas de 4,096 quadros (e uma proteção de 8,192 quadros para closures transpiladas); ultrapassá-lo gera "Maximum call stack size exceeded", novamente como `InternalError`. Não há limite de tempo de parede, então execute código não confiável no próprio PHP `max_execution_time` ou em um processo separado. Consulte [Referência: APIsetLimit](https://phasis.inline0.dev/pt/docs/api#setlimit).

## Próximas etapas

- [Referência de API](https://phasis.inline0.dev/pt/docs/api) — superfície completa de `Phasis\Engine`.
- [Interoperabilidade](https://phasis.inline0.dev/pt/docs/interop) — regras de conversão de valores, funções host, objetos PHP.
- [Compatibilidade](https://phasis.inline0.dev/pt/docs/compatibility) — o que está implementado, cobertura de test262.
- [Parser](https://phasis.inline0.dev/pt/docs/parser) e [Formatador](https://phasis.inline0.dev/pt/docs/formatter) — analise e formate JavaScript sem executá-lo.
- [Avançado](https://phasis.inline0.dev/pt/docs/advanced) — arquitetura, VM de bytecode, benchmarks, testes com oráculo.
