JavaScriptBridge: интеграция со страницей
Global API, callbacks, диапазоны байтов, Eval и ограничения Web.
JavaScriptBridge: явная интеграция со страницей
JavaScriptBridge соединяет Web-сборку с JavaScript страницы. Он не превращает нативное приложение в браузер и не отменяет browser permissions. Установленный C# SDK 1.0.0 предоставляет API, но его C# exporter не реализует Web. Статья не подтверждает работающий браузерный экспорт C#.
Проверьте реальную цель и сборку
Настольный класс/singleton может существовать с заглушками методов. Вне Web методы Eval/GetInterface/CreateCallback дают пустые результаты; DownloadBuffer и ForceFsSync ничего не делают, PwaUpdate недоступен. Web template без javascript_eval также заглушает object/evaluation bridge. Feature tag web определяет платформу, а не включение всех функций моста.
Сохраняйте fallback при недоступности интеграции страницы. null не позволяет надёжно различить отключённую поддержку, отсутствующий global, JavaScript null, неподдерживаемый тип результата и исключение Eval: несколько путей дают пустой Variant.
Явный адаптер страницы
GetInterface ищет одно точное window[name], не разбирает пути вроде app.sdk. CreateObject вызывает new window[name](...args). До запроса из игры объявите явный page-global adapter; локальное имя модуля не становится этим global автоматически. Разделяйте загрузку/готовность библиотеки и старт игры.
Адаптер ниже передаёт движку только нужный диапазон байтов. Он выполнен проверкой моста:
// Include in the page before the game requests GetInterface("ReckfellPage").
window.ReckfellPage = Object.freeze({
copyViewBytes(view) {
if (!ArrayBuffer.isView(view)) throw new TypeError('Expected an ArrayBuffer view');
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength).slice();
}
});Получите его через GetInterface("ReckfellPage"), затем вызовите copyViewBytes с JavaScript view. Возвращённый Uint8Array — отдельная копия байтов. Если значение может не быть буфером, перед JsBufferToPackedByteArray проверьте IsJsBuffer. Не читайте через уже освобождённый wrapper.
Текущее ограничение диапазона: Eval и JsBufferToPackedByteArray нормализуют DataView и не-Uint8Array views через весь backing ArrayBuffer. View байтов [20,30] внутри [10,20,30,40] воспроизведённо вернул все четыре байта. Точный адаптер скопировал только [20,30]. Сначала нормализуйте view в JavaScript; это документированный обход, не исправление движка. Элементы typed array не становятся независимым от платформы числовым форматом сериализации: отдельно задайте byte order и схему.
Значения и Eval — разные пути
| Путь | Существенное поведение |
|---|---|
| Object/method bridge | Null/undefined становятся nil; целые numbers получают integer tag, дробные — floating tag; объекты/функции проксируются. |
| Eval | Numbers получают floating tag; строки и byte buffers имеют отдельные пути; обычные объекты/функции дают nil. |
| Большие целые | Не предполагайте сохранение произвольной точности через native Variant. Для идентификаторов вне поддерживаемого integer range задайте строковый формат. |
| Исключения | Текущий JS сообщает ошибки; пустой/error result не является успешным ответом приложения. |
Ветка JS Eval выдаёт boolean tag, но текущая C++-ветка возвращает uint32-поле в Variant. Сохранность native bool-типа здесь не выполнялась; проверяйте фактический тип результата вместо общего обещания bool из импортированной статьи.
Eval по умолчанию использует local execution; optional global flag меняет влияние на namespace. Это не замена object wrapper. Предпочитайте именованные методы адаптера и передачу значений аргументами вместо сборки исполняемой строки из внешнего текста. Удалённые примеры ссылались на отсутствующий код и не подтверждали работающий export.
Callbacks и время жизни
JavaScript callback wrapper создаёт CreateCallback, не GetInterface. Принимающий Callable должен иметь один engine Array со всеми JavaScript arguments, даже если JavaScript вызывает функцию с несколькими аргументами. До индексации проверяйте количество/типы. Держите возвращённый JavaScriptObject живым всё время работы listener/promise.
При очистке сначала остановите внешнюю подписку/listener или исключите дальнейшую доставку, затем освободите собственную ссылку callback. Освобождение wrapper само не вызывает removeEventListener. JS-проверка подтвердила прекращение dispatch сохранённой JavaScript-функцией после освобождения wrapper handle; это не доказывает безопасную native asynchronous cleanup во всех случаях.
Не стройте синхронный JavaScript-ответ на managed return value callback: текущий native _callback вызывает Callable, но отдельно создаёт пустой return Variant. Proxy-to-pthread сборка может отложить доставку callback в поток движка. Это native-поведение сверено с исходниками, не выполнено через WASM/C#.
Скачивание, storage и PWA
DownloadBuffer запрашивает browser Blob/link download с байтами, filename и MIME; он не подтверждает сохранение файла на диск. MIME по умолчанию application/octet-stream. Свяжите скачивание с понятным действием пользователя и проверьте реальный файл; browser permission/policy продолжает действовать.
ForceFsSync планирует filesystem synchronization при доступном persistence; квитанции завершения не возвращает. Это не скачивание файла. См. хранилище браузерного проекта и копии.
PwaUpdateAvailable/PwaNeedsUpdate относятся к ожидающему PWA update, не к версии продукта движка или общему reload signal. Сохраните состояние и обработайте результат PwaUpdate. Вне Web заглушка возвращает unavailable error; service-worker update workflow в этой редактуре не выполнялся.
Диагностика и границы проверки
При ошибке GetInterface проверяйте точное window name, готовность скрипта, Web build и javascript_eval. При молчащем callback — CreateCallback, единственный Array parameter, сохранённый wrapper и время жизни listener. При лишних байтах сначала нормализуйте byteOffset/byteLength view.
Реальные тела JS движка и точный адаптер прошли 21 проверку в Node с mock native memory/handles. Дефект диапазона байтов остаётся непройденным условием приёмки, хотя адаптер прошёл. Native C++/C# ABI, реальный browser/WASM export, callback cleanup, download, permissions, storage и PWA не приняты как проверенные. Source, Runtime и SDK движка не менялись.