Skip to content

Bootstrap: extension_loaded('hash'/'json') false while in-tree handlers are active (ext/standard/info.c) #7190

Description

@PurHur

Category

bootstrap | stdlib

Problem

In-tree modules register builtins (hash(), json_encode(), json_decode(), …) but extension_loaded('hash') and extension_loaded('json') return false, and those names are missing from get_loaded_extensions().

Framework/feature probes and self-host scripts gate on extension_loaded() exactly like Zend — false negatives cause fallback paths or fatal misconfiguration even when functions work.

Verified 2026-06-07:

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php bin/vm.php -r "var_export(function_exists(\"hash\")); echo \"\\n\";
var_export(extension_loaded(\"hash\")); echo \"\\n\";
var_export(in_array(\"hash\", get_loaded_extensions(), true)); echo \"\\n\";
var_export(function_exists(\"json_encode\")); echo \"\\n\";
var_export(extension_loaded(\"json\")); echo \"\\n\";"'
# true / false / false / true / false

php-src reference

  • php/php-src ext/standard/info.c — PHP_FUNCTION(extension_loaded), get_loaded_extensions
  • Module registration: ext/hash/hash.c, ext/json/json.c — zend_module_entry names

Repro

<?php
declare(strict_types=1);

foreach (['hash', 'json', 'date', 'random'] as $ext) {
    echo $ext, ': fn=', (int) function_exists($ext === 'hash' ? 'hash' : ($ext === 'json' ? 'json_encode' : $ext)), 
         ' loaded=', (int) extension_loaded($ext), "\n";
}
print_r(get_loaded_extensions());

Zend: extension_loaded('hash') true when ext/hash enabled; list includes module names.

VM today: functions may work while extension_loaded is false (see probe above).

Scope (this repo)

Layer Path Notes
Module registry ext/*/Module.php, runtime loader in lib/Runtime.php Track logical extension names when modules register
Builtins ext/standard/extension_loaded.php, get_loaded_extensions.php Read registry, not host extension_loaded()
Bootstrap script/bootstrap-inventory.php probes align with M5 vendor/self-host gates
Tests test/compliance/cases/stdlib/extension_loaded_in_tree.phpt hash/json/date at minimum

PHP-in-PHP first: registry table in PHP (ext/standard/ModuleRegistry.php or similar), not new C module list.

Umbrella: #4839 full registry parity — implement this slice first (modules that already have handlers).

Done when

  • extension_loaded('hash') and extension_loaded('json') true when respective handlers registered
  • get_loaded_extensions() includes hash, json, standard, types, … matching active in-tree modules
  • extension_loaded('nonexistent') still false
  • ./script/ci-fast.sh --filter extension_loaded_in_tree green
  • Document registry in capability matrix / bootstrap inventory

Verification

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter extension_loaded_in_tree'
php script/bootstrap-inventory.php --check

Links

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:vmVirtual machineenhancementNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-0:FoundationPhase 0 – foundation & DevExphase-4:stdlibPhase 4 – stdlib for web apps

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions