JerryScript 扩展 API 实战:属性批量注册与常用原生 Handler(jerryscript-ext/properties.h 与 handlers.h 完全指南)

发布时间:2026/9/28 3:30:27
JerryScript 扩展 API 实战:属性批量注册与常用原生 Handler(jerryscript-ext/properties.h 与 handlers.h 完全指南) 语言运行时嵌入式物联网编译器【免费下载链接】jerryscriptUltra-lightweight JavaScript engine for the Internet of Things.项目地址https://gitcode.com/gh_mirrors/je/jerryscript点击查看免费下载本文以 JerryScript 扩展库jerryscript-ext/properties.h与jerryscript-ext/handlers.h为线索系统讲解如何在嵌入式 C 应用中批量注册 JavaScript 全局属性/函数、通过assert/gc/print等预置原生 Handler 为脚本提供运行时能力并介绍jerryx_register_global注册辅助函数及其在官方命令行入口中的真实用法。读完本文你将能够用最少的样板代码把 C 函数与常量暴露给 JS 脚本并正确处理引用计数与错误清理。概览两个头文件一套通用属性处理方案JerryScript 的扩展层jerry-ext提供了两个与属性处理直接相关的头文件jerryscript-ext/properties.h定义批量属性注册所需的结构体、便利宏与核心函数jerryscript-ext/handlers.h声明一组通用外部函数处理器assert、gc、print 等以及全局注册辅助函数jerryx_register_global。对应的实现位于 jerry-ext/util/properties.c、jerry-ext/util/handlers.c 与 jerry-ext/util/print.c。这套工具让把原生能力暴露给脚本从逐条调用jerry_object_set的繁琐代码中解放出来。批量注册多个属性jerryx_property_entry 与 jerryx_set_properties在嵌入场景中我们经常需要一次性向某个对象通常是全局对象注册一批属性几个数值常量、几个布尔开关、几个原生函数。逐条调用jerry_object_set不仅冗长还容易在出错时漏掉引用释放。扩展库为此提供了三个配套构件。jerryx_property_entry属性条目结构Summary用于定义属性数组的结构体每个条目由name属性名与value属性值两个字段组成可以整体注册到目标对象上。Prototypetypedef struct { const char *name; jerry_value_t value; } jerryx_property_entry;重要前提必须在引擎初始化jerry_init之后再构造该结构体数组因为在初始化之前创建的jerry_value_t是无效的——这一点与下文jerryx_set_properties示例中的注释一致。See alsojerryx_set_propertiesjerryx_register_result注册结果结构Summaryjerryx_set_properties操作的结果结构体。result字段要么是 JavaScript 的 undefined 值要么是一个错误对象无论成败registered字段都表示成功注册的属性个数。该结构体必须在属性注册之后传给 jerryx_release_property_entry 完成清理。若注册过程中发生了错误result字段中的错误值需要在使用完毕后手动释放。Prototypetypedef struct { jerry_value_t result; uint32_t registered; } jerryx_register_result;See alsojerryx_set_properties、jerryx_release_property_entryjerryx_set_properties批量设置属性Summary在目标对象上批量设置属性。输入是一个(name, jerry_value_t)二元组数组且必须以(NULL, 0)条目结尾对应JERRYX_PROPERTY_LIST_END()宏。使用要点原文强调数组中的每个属性值在成功注册后会被自动释放只要有任一注册失败就必须调用 jerryx_release_property_entry 释放条目数组中尚未注册的值该清理函数在成功场景下调用也是安全的若result携带了错误值必须手动释放。Prototypejerryx_register_result jerryx_set_properties (const jerry_value_t target_object, const jerryx_property_entry entries[]);target_object—— 目标对象属性将被设置到其上entries——(name, jerry_value_t)二元组数组返回 jerryx_register_result全部成功时result字段为 JS undefined 值出错时result字段为错误对象无论成败registered字段都包含成功注册的属性个数。Example完整可运行示例#include stdio.h #include jerryscript.h #include jerryscript-ext/handlers.h #include jerryscript-ext/properties.h static jerry_value_t handler (const jerry_call_info_t *call_info_p, const jerry_value_t args_p[], const jerry_length_t args_cnt) { printf (native handler called!\n); return jerry_boolean (true); } int main (int argc, char **argv) { jerry_init (JERRY_INIT_EMPTY); jerryx_property_entry methods[] { { demo, jerry_function_external (handler) }, { NULL, 0 }, }; jerry_value_t global jerry_current_realm (); jerryx_register_result reg jerryx_set_properties (global, methods); /* if reg.result is undefined all methods are registered */ if (jerry_value_is_exception (reg.result)) { printf (Only registered %d properties\r\n, reg.registered); /* clean up not registered property values */ jerryx_release_property_entry (methods, reg); /* clean up the error */ jerry_value_free (reg.result); } jerry_value_free (global); jerry_cleanup(); return 0; }源码级原理jerryx_set_properties 的实现细节查看 jerry-ext/util/properties.c 的实现可以印证上述语义若entries为 NULL直接返回(undefined, 0)循环以entries[idx].name ! NULL为终止条件逐条通过jerry_object_set (target_object, prop_name, entry-value)注册属性根据 API 约定jerry_object_set成功返回 boolean失败返回错误对象因此实现中用!jerry_value_is_boolean (result)判断失败成功后立即jerry_value_free (entry-value)释放该条目值这正是文档所说成功注册后值被自动释放的代码依据失败时返回(错误对象, idx)idx即已成功注册的数量。因此reg.registered与jerryx_release_property_entry配合可以精确跳过已注册已被释放的条目仅释放剩余未注册的值。便利宏JERRYX_PROPERTY_*为了进一步减少样板代码properties.h提供了一组用于构造属性条目的宏定义见 jerry-ext/include/jerryscript-ext/properties.h宏作用JERRYX_PROPERTY_NUMBER(NAME, NUMBER)创建数值属性条目等价于jerry_numberJERRYX_PROPERTY_STRING(NAME, STR, SIZE)创建 UTF-8 字符串条目使用STR的前SIZE字节JERRYX_PROPERTY_STRING_SZ(NAME, STR)创建 ASCII 字符串条目STR必须是零结尾字符串JERRYX_PROPERTY_BOOLEAN(NAME, VALUE)创建布尔属性条目等价于jerry_booleanJERRYX_PROPERTY_FUNCTION(NAME, NATIVE)创建原生 C 函数条目等价于jerry_function_externalJERRYX_PROPERTY_UNDEFINED(NAME)创建 undefined 属性条目JERRYX_PROPERTY_LIST_END()标记属性列表结束即(NULL, 0)条目从宏定义可以看出它们本质上都是(jerryx_property_entry) { NAME, jerry_xxx (...)}的语法糖因此数组必须以JERRYX_PROPERTY_LIST_END()收尾。Convenience macros 使用示例#include stdio.h #include jerryscript.h #include jerryscript-ext/handlers.h #include jerryscript-ext/properties.h static jerry_value_t handler (const jerry_call_info_t *call_info_p, const jerry_value_t args_p[], const jerry_length_t args_cnt) { printf (native handler called!\n); return jerry_boolean (true); } int main (int argc, char **argv) { jerry_init (JERRY_INIT_EMPTY); /** * Create a array of properties to be registered. * This must be done after initializing the engine as creating jerry_value_t * elements are invalid before jerry_init. */ jerryx_property_entry methods[] { JERRYX_PROPERTY_FUNCTION (demo, handler), JERRYX_PROPERTY_NUMBER (test_num, 2.3), JERRYX_PROPERTY_UNDEFINED (this_is_undefined), JERRYX_PROPERTY_LIST_END(), }; jerry_value_t global jerry_current_realm (); jerryx_register_result reg jerryx_set_properties (global, methods); /* if reg.result is undefined all methods are registered */ if (jerry_value_is_exception (reg.result)) { printf (Only registered %d properties\r\n, reg.registered); /* clean up not registered property values */ jerryx_release_property_entry (methods, reg); /* clean up the error */ jerry_value_free (reg.result); } jerry_value_free (global); jerry_cleanup(); return 0; }错误路径与单元测试验证tests/unit-ext/test-ext-method-register.c 是这套 API 的直接测试用例覆盖了典型场景test_simple_registration一次性注册函数、数值、两种字符串、布尔true/false、undefined 共 7 个属性断言registered 7随后通过 JS 表达式验证每个属性的值与可调用性test_error_single_function向已被冻结非可配置的属性名注册函数断言registered 0且result为异常test_error_multiple_functions三个条目中第二个注册失败断言registered 1并验证第一个属性已注册、第二个仍保留原值、第三个不存在——精确印证了出错即返回、已注册数记录在registered的行为。jerryx_release_property_entry释放未注册的属性值Summary根据之前一次 jerryx_set_properties 调用的结果释放jerryx_property_entry数组中所有剩余的jerry_value_t并同时处理jerryx_register_result结构中的错误值如有。在注册完全成功的情况下调用本函数也是安全的。调用之后entries数组不应再被使用因为其中的值都已被释放。Prototypevoid jerryx_release_property_entry (const jerryx_property_entry entries[], const jerryx_register_result register_result);entries—— jerryx_property_entry 数组register_result—— 之前一次 jerryx_set_properties 调用的结果。Example使用示例见 jerryx_set_properties。实现上jerry-ext/util/properties.c该函数从register_result.registered下标开始遍历并逐个释放剩余条目的value这正是跳过已成功注册已释放条目的机制。注意错误值register_result.result的释放仍由调用方负责见上文示例中的jerry_value_free (reg.result)。常用外部函数处理器assert / gc / printjerryscript-ext/handlers.h声明了一组可直接暴露给脚本的通用处理器全部遵循标准的外部函数签名jerry_value_t handler (const jerry_call_info_t *call_info_p, const jerry_value_t args_p[], const jerry_length_t args_cnt)。官方命令行入口 jerry-main/main-desktop.c 正是通过它们向全局对象注册了assert、gc、print以及sourceName、createRealm。jerryx_handler_assert脚本硬断言Summary为脚本提供硬断言能力。断言失败时例程会调用jerry_port_fatal终止程序。若运行时特性JERRY_FEATURE_LINE_INFO已启用构建选项JERRY_LINE_INFO见 jerry-core/CMakeLists.txt还会额外打印调用栈回溯。Prototypejerry_value_t jerryx_handler_assert (const jerry_call_info_t *call_info_p, const jerry_value_t args_p[], const jerry_length_t args_cnt);call_info_p—— 指向 jerry_call_info_t 结构体的指针携带调用相关信息本函数未使用args_p—— 函数参数数组args_cnt—— 参数个数返回值 —— 当且仅当只传入一个参数且该参数为布尔 true 时返回布尔 true否则该函数不会返回直接触发致命错误。从实现jerry-ext/util/handlers.c可见其失败路径先用jerry_log输出Script Error: assertion failed再调用jerryx_print_backtrace (5)打印最多 5 帧回溯仅在JERRY_FEATURE_LINE_INFO开启时有效最后以JERRY_FATAL_FAILED_ASSERTION调用jerry_port_fatal。默认端口实现位于 jerry-port/common/jerry-port-process.c。See alsojerryx_register_globaljerryx_handler_gc向脚本暴露垃圾回收器Summary向脚本暴露垃圾回收能力。若第一个参数为逻辑真则执行高压力high pressureGC否则执行低压力low pressureGC不传参数时默认也是低压力 GC。Prototypejerry_value_t jerryx_handler_gc (const jerry_call_info_t *call_info_p, const jerry_value_t args_p[], const jerry_length_t args_cnt);call_info_p—— 调用相关信息未使用args_p—— 函数参数数组未使用args_cnt—— 参数个数未使用返回值 —— 表示undefined的jerry_value_t。实现jerry-ext/util/handlers.c按args_cnt 0 jerry_value_to_boolean (args_p[0])选择JERRY_GC_PRESSURE_HIGH或JERRY_GC_PRESSURE_LOW然后调用jerry_heap_gc。See alsojerryx_register_globaljerryx_handler_print脚本 print 实现Summary为脚本提供print实现。例程将所有参数转换为字符串并通过jerry_port_print_buffer输出。NUL 字符输出为\u0000其余字符按字节原样输出。注意该实现不使用标准 C 的printf输出这带来更大灵活性但同时也扩展了 JerryScript 核心引擎的端口 API。凡是使用jerryx_handler_print的应用其端口实现必须同时提供jerry_port_print_buffer默认端口实现见 jerry-port/common/jerry-port-io.c。Prototypejerry_value_t jerryx_handler_print (const jerry_call_info_t *call_info_p, const jerry_value_t args_p[], const jerry_length_t args_cnt);call_info_p—— 调用相关信息未使用args_p—— 函数参数数组args_cnt—— 参数个数返回值 —— 若所有参数都能转换为字符串返回undefined否则返回Error。实现细节jerry-ext/util/handlers.c值得展开多个参数之间以空格分隔末尾输出换行符每个参数经jerryx_print_value转换该函数对 Symbol 使用jerry_symbol_descriptive_string其余值用jerry_value_to_string转换出错立即把异常返回给调用方。底层输出经 jerry-ext/util/print.c 的jerryx_print_buffer分批写出并且若连接了调试器同一份输出还会通过jerry_debugger_send_output转发给调试端。See alsojerryx_register_global、docs/05.PORT-API.md处理器注册辅助jerryx_register_globalSummary将 JavaScript 函数注册到全局对象上。注意返回值在不再需要时必须用jerry_value_free释放。Prototype文档所载形式jerry_value_t jerryx_register_global (const char *name_p, jerry_external_handler_t handler_p);name_p—— 要注册的函数名handler_p—— 外部函数处理器的地址返回值 —— 操作成功时表示布尔 true否则为Error。需要说明的是在当前仓库的头文件 jerry-ext/include/jerryscript-ext/properties.h 中该函数实际声明为返回boolbool jerryx_register_global (...)实现jerry-ext/util/properties.c内部通过jerry_current_realm ()取得全局对象用jerry_function_external包装处理器后调用jerry_object_set并以jerry_value_is_true判定结果最后释放全部临时值。文档示例中按jerry_value_t语义编写实际使用时请以你所链接版本的公开头文件声明为准。Example批量注册常用函数的经典模式#include jerryscript.h #include jerryscript-ext/handlers.h #include jerryscript-ext/properties.h static const struct { const char *name_p; jerry_external_handler_t handler_p; } common_functions[] { { assert, jerryx_handler_assert }, { gc, jerryx_handler_gc }, { print, jerryx_handler_print }, { NULL, NULL } }; static void register_common_functions (void) { jerry_value_t ret jerry_undefined (); for (int i 0; common_functions[i].name_p ! NULL !jerry_value_is_exception (ret); i) { ret jerryx_register_global (common_functions[i].name_p, common_functions[i].handler_p); } jerry_value_free (ret); }这个模式在 JerryScript 官方命令行入口中得到了真实应用jerry-main/main-desktop.c 在main_init_engine中依次注册assert、gc、print、sourceName、createRealm这正是你在桌面版 JerryScript 里能直接使用这些全局函数的原因。更多内置 Handler面向调试与多 Realm 场景除了文档重点讲解的三个处理器jerry-ext/include/jerryscript-ext/handlers.h 还声明了其余几个处理器它们在main-desktop.c中与前述三个一起被注册jerryx_handler_source_name返回当前执行脚本或给定函数对象的资源名未提供参数时取当前执行函数否则返回anonymousjerryx_handler_create_realm创建一个新的 Realm 对象对应 JS 全局createRealmjerryx_handler_promise_reject未处理 Promise 拒绝事件回调对JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER事件打印Uncaught Promise rejection警告注册方式见 jerry-main/main-desktop.c 中的jerry_promise_on_eventjerryx_handler_source_received调试器场景下解析并执行jerry_debugger_wait_for_client_source收到的源码。这些处理器展示了外部函数处理器这一设计在调试、测试、多隔离环境等场景下的通用性也是阅读 jerry-ext/util/handlers.c 时值得对照学习的完整集合。实战要点小结先初始化再构造条目jerryx_property_entry数组必须在jerry_init之后创建因为其中的jerry_value_t在初始化前无效务必以JERRYX_PROPERTY_LIST_END()收尾jerryx_set_properties依赖name NULL判断数组结尾成功与失败都要清理注册成功后条目值已自动释放失败时调用jerryx_release_property_entry释放剩余条目值并手动jerry_value_free释放result中的错误对象端口依赖使用jerryx_handler_print前确认端口实现了jerry_port_print_bufferjerryx_handler_assert失败会经jerry_port_fatal终止进程属于硬断言语义参考测试tests/unit-ext/test-ext-method-register.c 覆盖了批量注册的成功与失败路径是理解引用计数语义的最佳范本。赞分享语言运行时嵌入式物联网编译器【免费下载链接】jerryscriptUltra-lightweight JavaScript engine for the Internet of Things.项目地址https://gitcode.com/gh_mirrors/je/jerryscript点击查看免费下载相关推荐JerryScript 扩展 API 实战用 jerryx_arg 实现 JS 参数校验与 C 类型转换JerryScript 扩展 API 实战用 jerryx_arg 实现 JS 参数校验与 C 类型转换 本指南围绕 JerryScript 扩展库jerr语言运行时嵌入式物联网编译器JerryScript Autorelease 扩展用 JERRYX_AR_VALUE_T 自动释放 jerry_value_tJerryScript Autorelease 扩展用 JERRYX_AR_VALUE_T 自动释放 jerry_value_t 导读 在基于 JerrySc语言运行时嵌入式物联网编译器thumbor 自定义 Handler Lists 完全指南注册扩展路由的官方机制与实战写法thumbor 自定义 Handler Lists 完全指南注册扩展路由的官方机制与实战写法 Handler Lists 是 thumbor 向服务中注入新后端图像处理计算机视觉上一篇GetQzonehistoryQQ空间说说本地备份一次扫码留档下一篇大麦自动抢票工具Web端与Appium双端配置指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询