diff --git a/docs/capabilities.md b/docs/capabilities.md
index fca87d57..94864e0f 100644
--- a/docs/capabilities.md
+++ b/docs/capabilities.md
@@ -74,7 +74,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `is_object` | yes | yes | yes | types | |
| `is_scalar` | yes | yes | yes | standard | |
| `is_string` | yes | yes | yes | types | JIT PHPT |
-| `json_encode` | yes | yes | yes | standard | JIT PHPT |
+| `json_encode` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `lcfirst` | yes | yes | yes | standard | |
| `log` | yes | yes | yes | standard | |
| `ltrim` | yes | yes | yes | standard | AOT PHPT |
diff --git a/test/aot/ExampleWebAotTest.php b/test/aot/ExampleWebAotTest.php
index 74f87cc4..f47886e0 100644
--- a/test/aot/ExampleWebAotTest.php
+++ b/test/aot/ExampleWebAotTest.php
@@ -64,6 +64,17 @@ public function testStaticWebExampleFile(): void
$this->assertStringContainsString('
Hello World
', $result);
}
+ public function testApiJsonExampleFile(): void
+ {
+ $source = realpath(__DIR__ . '/../../examples/004-ApiJson/example.php');
+ $this->assertNotFalse($source);
+ $result = $this->compileAndRun($source, []);
+ $this->assertStringContainsString('Content-Type: application/json', $result);
+ $this->assertStringContainsString('Status: 200', $result);
+ $this->assertStringContainsString('"ok":true', $result);
+ $this->assertStringContainsString('php-compiler', $result);
+ }
+
/**
* @param list $compileExtraArgs
*/
diff --git a/test/fixtures/aot/cases/json_encode_api.phpt b/test/fixtures/aot/cases/json_encode_api.phpt
new file mode 100644
index 00000000..5b627b74
--- /dev/null
+++ b/test/fixtures/aot/cases/json_encode_api.phpt
@@ -0,0 +1,13 @@
+--TEST--
+AOT: json_encode API body with Content-Type and Status 200 (issues #61, #270)
+--FILE--
+ true, 'service' => 'php-compiler']);
+--EXPECT--
+Content-Type: application/json
+Status: 200
+{"ok":true,"service":"php-compiler"}
+--EXPECT_EXIT--
+0
diff --git a/test/unit/ExamplesCompileTest.php b/test/unit/ExamplesCompileTest.php
index 79e19596..523f6ba8 100644
--- a/test/unit/ExamplesCompileTest.php
+++ b/test/unit/ExamplesCompileTest.php
@@ -239,6 +239,37 @@ public function testAotExecuteSimpleWebPost(): void
@unlink($binary);
}
+ /**
+ * Shipped 004-ApiJson: compile.php -o temp binary — json_encode + http_response_code(200) AOT smoke.
+ *
+ * @group llvm
+ * @group aot
+ *
+ * @see https://github.com/PurHur/php-compiler/issues/270
+ */
+ public function testAotExecuteSmoke004ApiJson(): void
+ {
+ if (!self::isLlvmReady()) {
+ $this->markTestSkipped(
+ 'LLVM 9 toolchain not available. Run script/install-llvm9.sh from the repository root.'
+ );
+ }
+ $repoRoot = dirname(__DIR__, 2);
+ $source = realpath($repoRoot.'/examples/004-ApiJson/example.php');
+ $this->assertNotFalse($source);
+
+ $env = $this->llvmProcessEnv($repoRoot);
+ $binary = $this->compileAotBinaryNoQueryBaking($source, $repoRoot, $env);
+ $out = $this->runAotBinary($binary, $env);
+ $this->assertStringContainsString('Content-Type: application/json', $out);
+ $this->assertStringContainsString('Status: 200', $out);
+ foreach (self::smokeNeedles('004-ApiJson') as $needle) {
+ $this->assertStringContainsString($needle, $out);
+ }
+
+ @unlink($binary);
+ }
+
/**
* Shipped 002-StaticWeb: compile.php -o temp binary, run once — AOT link + runtime smoke (no superglobals).
*