Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 71 additions & 19 deletions docs/bootstrap-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ Regenerate: `php script/bootstrap-inventory.php`

| Metric | Count |
|--------|------:|
| PHP files on vm.php path | 5679 |
| Phase A inventory files (M2 ratio SSOT) | 5679 |
| PHP files on vm.php path | 5685 |
| Phase A inventory files (M2 ratio SSOT) | 5685 |
| Phase A ratio-deferred paths | 0 |
| Source constructs flagged (blockers) | 0 |
| Source constructs flagged (warnings) | 16269 |
| Source constructs flagged (warnings) | 16291 |

## Compiler CFG gaps (`lib/Compiler.php`)

Expand Down Expand Up @@ -1466,24 +1466,30 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
| `ext/spl/spl_classes.php` | 0 | 2 |
| `ext/sqlite3/BuiltinClasses.php` | 0 | 1 |
| `ext/sqlite3/Module.php` | 0 | 1 |
| `ext/sqlite3/SQLite3Backup.php` | 0 | 2 |
| `ext/sqlite3/SQLite3BusyTimeout.php` | 0 | 2 |
| `ext/sqlite3/SQLite3Changes.php` | 0 | 1 |
| `ext/sqlite3/SQLite3Close.php` | 0 | 1 |
| `ext/sqlite3/SQLite3Construct.php` | 0 | 2 |
| `ext/sqlite3/SQLite3CreateCollation.php` | 0 | 2 |
| `ext/sqlite3/SQLite3CreateFunction.php` | 0 | 2 |
| `ext/sqlite3/SQLite3EnableExceptions.php` | 0 | 1 |
| `ext/sqlite3/SQLite3EscapeString.php` | 0 | 2 |
| `ext/sqlite3/SQLite3Exec.php` | 0 | 2 |
| `ext/sqlite3/SQLite3LastErrorCode.php` | 0 | 1 |
| `ext/sqlite3/SQLite3LastErrorMsg.php` | 0 | 1 |
| `ext/sqlite3/SQLite3LastInsertRowID.php` | 0 | 1 |
| `ext/sqlite3/SQLite3Open.php` | 0 | 2 |
| `ext/sqlite3/SQLite3Prepare.php` | 0 | 2 |
| `ext/sqlite3/SQLite3Query.php` | 0 | 2 |
| `ext/sqlite3/SQLite3QuerySingle.php` | 0 | 2 |
| `ext/sqlite3/SQLite3Version.php` | 0 | 4 |
| `ext/sqlite3/Sqlite3ClassMethod.php` | 0 | 1 |
| `ext/sqlite3/Sqlite3ExtensionPolicy.php` | 0 | 1 |
| `ext/sqlite3/VmSQLite3.php` | 0 | 17 |
| `ext/sqlite3/VmSQLite3.php` | 0 | 24 |
| `ext/sqlite3/VmSQLite3Result.php` | 0 | 12 |
| `ext/sqlite3/VmSQLite3Stmt.php` | 0 | 15 |
| `ext/sqlite3/VmSqlite3Native.php` | 0 | 6 |
| `ext/sqlite3/VmSqlite3Native.php` | 0 | 9 |
| `ext/sqlite3/VmSqlite3Udf.php` | 0 | 3 |
| `ext/standard/AbsJitHelper.php` | 0 | 1 |
| `ext/standard/AcosJitHelper.php` | 0 | 1 |
Expand Down Expand Up @@ -16556,6 +16562,12 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
**Warnings** (review for bootstrap subset):
- 2 class method(s)

### `ext/sqlite3/SQLite3Backup.php`

**Warnings** (review for bootstrap subset):
- new ArgumentCountError (line 25)
- 1 class method(s)

### `ext/sqlite3/SQLite3BusyTimeout.php`

**Warnings** (review for bootstrap subset):
Expand All @@ -16578,6 +16590,12 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
- new ArgumentCountError (line 20)
- 1 class method(s)

### `ext/sqlite3/SQLite3CreateCollation.php`

**Warnings** (review for bootstrap subset):
- new ArgumentCountError (line 29)
- 1 class method(s)

### `ext/sqlite3/SQLite3CreateFunction.php`

**Warnings** (review for bootstrap subset):
Expand All @@ -16601,11 +16619,27 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
- new ArgumentCountError (line 21)
- 1 class method(s)

### `ext/sqlite3/SQLite3LastErrorCode.php`

**Warnings** (review for bootstrap subset):
- 1 class method(s)

### `ext/sqlite3/SQLite3LastErrorMsg.php`

**Warnings** (review for bootstrap subset):
- 1 class method(s)

### `ext/sqlite3/SQLite3LastInsertRowID.php`

**Warnings** (review for bootstrap subset):
- 1 class method(s)

### `ext/sqlite3/SQLite3Open.php`

**Warnings** (review for bootstrap subset):
- new ArgumentCountError (line 34)
- 1 class method(s)

### `ext/sqlite3/SQLite3Prepare.php`

**Warnings** (review for bootstrap subset):
Expand All @@ -16624,6 +16658,14 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
- new ArgumentCountError (line 21)
- 1 class method(s)

### `ext/sqlite3/SQLite3Version.php`

**Warnings** (review for bootstrap subset):
- new HashTable (line 28)
- new Variable (line 29)
- new Variable (line 32)
- 1 class method(s)

### `ext/sqlite3/Sqlite3ClassMethod.php`

**Warnings** (review for bootstrap subset):
Expand All @@ -16641,19 +16683,26 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
- new Variable (line 38)
- new SQLite3Construct (line 45)
- new SQLite3Close (line 50)
- new SQLite3Exec (line 51)
- new SQLite3QuerySingle (line 52)
- new SQLite3Query (line 53)
- new SQLite3Prepare (line 54)
- new SQLite3Changes (line 55)
- new SQLite3LastInsertRowID (line 56)
- new SQLite3EscapeString (line 57)
- new SQLite3BusyTimeout (line 58)
- new SQLite3EnableExceptions (line 59)
- new SQLite3CreateFunction (line 60)
- new Sqlite3State (line 78)
- new Variable (line 210)
- 14 class method(s)
- new SQLite3Open (line 51)
- new SQLite3Exec (line 52)
- new SQLite3QuerySingle (line 53)
- new SQLite3Query (line 54)
- new SQLite3Prepare (line 55)
- new SQLite3Changes (line 56)
- new SQLite3LastInsertRowID (line 57)
- new SQLite3LastErrorCode (line 58)
- new SQLite3LastErrorMsg (line 59)
- new SQLite3EscapeString (line 60)
- new SQLite3BusyTimeout (line 61)
- new SQLite3EnableExceptions (line 62)
- new SQLite3CreateFunction (line 63)
- new SQLite3CreateCollation (line 64)
- new SQLite3Backup (line 65)
- new SQLite3Version (line 66)
- new Sqlite3State (line 85)
- new Exception (line 104)
- new Variable (line 268)
- 18 class method(s)

### `ext/sqlite3/VmSQLite3Result.php`

Expand Down Expand Up @@ -16698,7 +16747,10 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
- new SQLite3Exception (line 92)
- new SQLite3Exception (line 139)
- new SQLite3Exception (line 183)
- 33 class method(s)
- new SQLite3Exception (line 262)
- new SQLite3Exception (line 265)
- new SQLite3Exception (line 268)
- 36 class method(s)

### `ext/sqlite3/VmSqlite3Udf.php`

Expand Down
70 changes: 70 additions & 0 deletions ext/sqlite3/SQLite3Backup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\sqlite3;

use PHPCompiler\Frame;
use PHPCompiler\VM\Variable;

/**
* SQLite3::backup(SQLite3 $destination, string $sourceDB = "main", string $destinationDB = "main"): bool
* (php-src ext/sqlite3/sqlite3.c; #20565).
*/
final class SQLite3Backup extends Sqlite3ClassMethod
{
public function __construct()
{
parent::__construct('backup');
}

public function execute(Frame $frame): void
{
$receiver = $this->receiver($frame, 'SQLite3::backup()');
if (\count($frame->calledArgs) < 2) {
throw new \ArgumentCountError('SQLite3::backup() expects at least 1 argument, 0 given');
}
$destVar = $frame->calledArgs[1]->resolveIndirect();
if (Variable::TYPE_OBJECT !== $destVar->type) {
throw new \TypeError(\sprintf(
'SQLite3::backup(): Argument #1 ($destination) must be of type SQLite3, %s given',
VmSQLite3::publicTypeLabel($destVar)
));
}
$dest = $destVar->toObject();
if (VmSQLite3::CLASS_LC !== strtolower($dest->class->name)) {
throw new \TypeError(\sprintf(
'SQLite3::backup(): Argument #1 ($destination) must be of type SQLite3, %s given',
$dest->class->name
));
}
if (!$dest->constructed) {
throw new \TypeError('SQLite3::backup(): Argument #1 ($destination) must be of type SQLite3, uninitialized SQLite3 given');
}
$sourceDb = 'main';
$destDb = 'main';
if (\count($frame->calledArgs) >= 3) {
$sourceDb = $this->stringArg($frame->calledArgs[2], 'SQLite3::backup', 1, 'sourceDatabase');
}
if (\count($frame->calledArgs) >= 4) {
$destDb = $this->stringArg($frame->calledArgs[3], 'SQLite3::backup', 2, 'destinationDatabase');
}
$srcHandle = VmSQLite3::requireOpenDb($receiver, 'SQLite3::backup');
$dstHandle = VmSQLite3::requireOpenDb($dest, 'SQLite3::backup');
try {
$ok = VmSqlite3Native::backup($srcHandle, $sourceDb, $dstHandle, $destDb);
} catch (\SQLite3Exception $e) {
if (VmSQLite3::handleException($receiver, $e)) {
if (null !== $frame->returnVar) {
$frame->returnVar->bool(false);
}

return;
}
$ok = false;
}
if (null !== $frame->returnVar) {
$frame->returnVar->bool($ok);
}
}
}
60 changes: 60 additions & 0 deletions ext/sqlite3/SQLite3CreateCollation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\sqlite3;

use PHPCompiler\Frame;
use PHPCompiler\ext\standard\VmCallable;
use PHPCompiler\ext\spl\SplIteratorSupport;

/**
* SQLite3::createCollation(string $name, callable $callback): bool
* (php-src ext/sqlite3/sqlite3.c; #20565).
*
* Stores the callable for registration parity; full COLLATE FFI callback is follow-up.
*/
final class SQLite3CreateCollation extends Sqlite3ClassMethod
{
public function __construct()
{
parent::__construct('createCollation');
}

public function execute(Frame $frame): void
{
$receiver = $this->receiver($frame, 'SQLite3::createCollation()');
VmSQLite3::requireOpenDb($receiver, 'SQLite3::createCollation');
if (\count($frame->calledArgs) < 3) {
throw new \ArgumentCountError(
'SQLite3::createCollation() expects exactly 2 arguments, '.(\count($frame->calledArgs) - 1).' given'
);
}
$name = $this->stringArg($frame->calledArgs[1], 'SQLite3::createCollation', 0, 'name');
if ('' === $name) {
if (null !== $frame->returnVar) {
$frame->returnVar->bool(false);
}

return;
}
$ctx = $frame->vmContext;
if (null === $ctx) {
throw new \LogicException('SQLite3::createCollation() requires a VM context');
}
$callback = $frame->calledArgs[2]->resolveIndirect();
if (!VmCallable::isCallable($ctx, $callback)) {
throw new \TypeError(VmCallable::invalidCallbackTypeError('SQLite3::createCollation'));
}
[$pinned, $closureState] = SplIteratorSupport::pinCallback($callback);
$state = VmSQLite3::state($receiver);
$state->collations[strtolower($name)] = [
'callback' => $pinned,
'closure' => $closureState,
'ctx' => $ctx,
];
if (null !== $frame->returnVar) {
$frame->returnVar->bool(true);
}
}
}
24 changes: 24 additions & 0 deletions ext/sqlite3/SQLite3LastErrorCode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\sqlite3;

use PHPCompiler\Frame;

/** SQLite3::lastErrorCode(): int — php-src ext/sqlite3/sqlite3.c; #20565. */
final class SQLite3LastErrorCode extends Sqlite3ClassMethod
{
public function __construct()
{
parent::__construct('lastErrorCode');
}

public function execute(Frame $frame): void
{
$receiver = $this->receiver($frame, 'SQLite3::lastErrorCode()');
if (null !== $frame->returnVar) {
$frame->returnVar->int(VmSQLite3::lastErrorCode($receiver));
}
}
}
24 changes: 24 additions & 0 deletions ext/sqlite3/SQLite3LastErrorMsg.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\sqlite3;

use PHPCompiler\Frame;

/** SQLite3::lastErrorMsg(): string — php-src ext/sqlite3/sqlite3.c; #20565. */
final class SQLite3LastErrorMsg extends Sqlite3ClassMethod
{
public function __construct()
{
parent::__construct('lastErrorMsg');
}

public function execute(Frame $frame): void
{
$receiver = $this->receiver($frame, 'SQLite3::lastErrorMsg()');
if (null !== $frame->returnVar) {
$frame->returnVar->string(VmSQLite3::lastErrorMsg($receiver));
}
}
}
43 changes: 43 additions & 0 deletions ext/sqlite3/SQLite3Open.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\sqlite3;

use PHPCompiler\Frame;

/**
* SQLite3::open(string $filename, int $flags = …, string $encryptionKey = ""): void
* (php-src ext/sqlite3/sqlite3.c; #20565).
*/
final class SQLite3Open extends Sqlite3ClassMethod
{
public function __construct()
{
parent::__construct('open');
}

public function execute(Frame $frame): void
{
if (\count($frame->calledArgs) < 1) {
throw new \LogicException('SQLite3::open() called without $this');
}
$var = $frame->calledArgs[0]->resolveIndirect();
if (\PHPCompiler\VM\Variable::TYPE_OBJECT !== $var->type) {
throw new \TypeError('SQLite3::open() must be called on SQLite3');
}
$receiver = $var->toObject();
if (VmSQLite3::CLASS_LC !== strtolower($receiver->class->name)) {
throw new \TypeError('SQLite3::open() must be called on SQLite3');
}
if (\count($frame->calledArgs) < 2) {
throw new \ArgumentCountError('SQLite3::open() expects at least 1 argument, 0 given');
}
$filename = $this->stringArg($frame->calledArgs[1], 'SQLite3::open', 0, 'filename');
$defaultFlags = Sqlite3Constants::OPEN_READWRITE | Sqlite3Constants::OPEN_CREATE;
$flags = \count($frame->calledArgs) >= 3
? $this->intArg($frame->calledArgs[2], 'SQLite3::open', 1, 'flags', $defaultFlags)
: $defaultFlags;
VmSQLite3::openObject($receiver, $filename, $flags);
}
}
Loading
Loading