Приватное поле JavaScript с именем вида #x не является обычным свойством с необычным названием. Его нельзя получить через Reflect.get или перечисление собственных свойств. Инженеры SpiderMonkey реализовали это так, чтобы поведение соответствовало языковой семантике, хотя внутреннее устройство движка отличается от буквального описания в спецификации.
Модель и устройство движка
Для понимания полезна мысленная модель скрытой WeakMap, где объект служит ключом к приватному состоянию. При таком представлении каждое приватное поле ассоциируется с хранилищем, доступ к которому возможен только при наличии соответствующего ключа — объекта, объявляющего поле. Однако это не обязывает движок хранить отдельную WeakMap для каждого приватного поля.
В описанной реализации SpiderMonkey использует скрытые свойства со специальными идентификаторами и опирается на существующие механизмы оптимизации доступа к свойствам. Такой подход даёт тот же наблюдаемый результат: приватные поля не видны через стандартные механизмы отражения и перечисления, и доступ к ним возможен только в контексте, где поле объявлено.
Необходимые проверки и байткод
При обращении к приватному полю требуется выполнять строгие проверки. Если поле запрошено на объекте, где оно не было объявлено, это должно приводить к TypeError, а не возвращать undefined. Аналогично, повторное объявление того же приватного поля на одном классе должно вызывать ошибку. Для выполнения этих проверок в движке введён специальный байткод CheckPrivateField, который обеспечивает корректную валидацию на этапе выполнения.
Особенности при работе с Proxy
Особый случай — взаимодействие с Proxy. Приватное состояние прокси и приватное состояние его целевого объекта различаются: приватность определяется местом объявления поля, а не тем, через какие наблюдатели или ловушки происходит доступ. Из этого следует, что приватные поля нельзя корректно смоделировать только через обычные ловушки прокси без дополнительных механизмов в рантайме. В реализации движка сохранён инженерный принцип: важна воспроизводимость наблюдаемого поведения языка, даже если внутренние структуры и алгоритмы отличаются от формальных шагов спецификации.
В результате SpiderMonkey обеспечивает требуемую семантику приватных полей — невидимость через отражение и корректные ошибки при неправильном доступе — за счёт собственных внутренних структур и новых проверок в байткоде, а не через буквальную имитацию WeakMap для каждого поля.