├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── SConscript ├── examples ├── ImportCplusplus │ ├── README.md │ └── example_cplusplus.cpp └── ImportModule │ ├── README.md │ └── example_module.c └── rtthread-port ├── SConscript ├── config.h ├── jerry_buffer.c ├── jerry_buffer.h ├── jerry_callbacks.c ├── jerry_callbacks.h ├── jerry_console.c ├── jerry_event.c ├── jerry_event.h ├── jerry_main.c ├── jerry_message.c ├── jerry_message.h ├── jerry_module.c ├── jerry_module.h ├── jerry_mqtt.c ├── jerry_mqtt.h ├── jerry_net.c ├── jerry_net.h ├── jerry_os.c ├── jerry_request_init.c ├── jerry_request_init.h ├── jerry_utf8.c ├── jerry_utf8.h ├── jerry_util.c ├── jerry_util.h ├── jerry_wlan.c ├── jerry_wlan.h └── port.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | *.su 34 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "jerryscript"] 2 | path = jerryscript 3 | url = https://github.com/jerryscript-project/jerryscript.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jerryscript on RT-Thread 2 | 3 | ## 1、介绍 4 | 5 | JerryScript是一个轻量级的JavaScript引擎,用于资源受限的设备,如微控制器。它可以运行在小于64 kb RAM和小于200 kb的闪存的设备上。由于这个特性,它被移植到了RT-Thread中。 6 | 7 | API Reference :http://jerryscript.net/api-reference/ 8 | 9 | ### 1.1 目录结构 10 | 11 | Jerryscript on RT-Thread软件包目录如下所示: 12 | 13 | | 名称 | 说明 | 14 | | - | - | 15 | | examples | 示例代码,示范如何导入C++的API与添加builtin module | 16 | | jerryscript | jerryscript 官方库 | 17 | | rtthread-port | RT-Thread 移植代码目录 | 18 | 19 | ### 1.2 许可证 20 | 21 | Jerryscript on RT-Thread软件包遵循Apache-2.0 许可,详见 LICENSE 文件。 22 | 23 | ### 1.3 依赖 24 | 25 | - RT-Thread 3.0+ 26 | - finsh 软件包 27 | 28 | ## 2、 获取软件包 29 | 30 | 使用 Jerryscript on RT-Thread 软件包需要在 RT-Thread 的包管理中选中它,具体路径如下: 31 | 32 | RT-Thread online packages 33 | language packages ---> 34 | [ ] Lua: A lightweight, embeddable scripting language. ---> 35 | [*] JerryScript: Ultra-lightweight JavaScript engine for the Internet of Things. ---> 36 | [ ] MicroPython: A lean and efficient Python implementation for microcontrollers and constrained systems. ---> 37 | 38 | 然后让 RT-Thread 的包管理器自动更新,或者使用 `pkgs --update` 命令更新包到 BSP 中。 39 | 40 | ## 3、使用Jerryscript on RT-Thread软件包 41 | 42 | - 如何导入C++API,请参考[ImportCplusplus](examples/ImportCplusplus/README.md) 43 | - 如何添加builtin module,请参考[ImportModule](examples/ImportModule/README.md) 44 | 45 | ## 4、 注意事项 46 | 47 | - Jerryscript on RT-Thread软件包版本为`latest`,请勿选择版本`V1.0.0`。 48 | - Jerryscript on RT-Thread软件包依赖finsh软件包,请确认在 RT-Thread 的包管理中选中了`finsh`,具体路径如下: 49 | ``` 50 | RT-Thread Components 51 | Command shell ---> 52 | [*] finsh shell 53 | ``` 54 | ## 5、 联系方式 & 感谢 55 | 56 | - 维护: RT-Thread 开发团队 57 | - 主页: https://github.com/RT-Thread-packages/jerryscript 58 | -------------------------------------------------------------------------------- /SConscript: -------------------------------------------------------------------------------- 1 | # RT-Thread building script for JerryScript 2 | 3 | import os 4 | from building import * 5 | 6 | # get current directory 7 | cwd = GetCurrentDir() 8 | 9 | jerry_core_dir = 'jerryscript/jerry-core' 10 | 11 | jerry_core = Glob(jerry_core_dir + '/*.c') 12 | jerry_core += Glob(jerry_core_dir + '/api/*.c') 13 | jerry_core += Glob(jerry_core_dir + '/debugger/*.c') 14 | jerry_core += Glob(jerry_core_dir + '/ecma/base/*.c') 15 | jerry_core += Glob(jerry_core_dir + '/ecma/builtin-objects/*.c') 16 | jerry_core += Glob(jerry_core_dir + '/ecma/builtin-objects/typedarray/*.c') 17 | jerry_core += Glob(jerry_core_dir + '/ecma/operations/*.c') 18 | jerry_core += Glob(jerry_core_dir + '/jcontext/*.c') 19 | jerry_core += Glob(jerry_core_dir + '/jmem/*.c') 20 | jerry_core += Glob(jerry_core_dir + '/jrt/*.c') 21 | jerry_core += Glob(jerry_core_dir + '/lit/*.c') 22 | jerry_core += Glob(jerry_core_dir + '/parser/js/*.c') 23 | jerry_core += Glob(jerry_core_dir + '/parser/regexp/*.c') 24 | jerry_core += Glob(jerry_core_dir + '/vm/*.c') 25 | 26 | jerry_ext_dir = 'jerryscript/jerry-ext' 27 | 28 | jerry_ext = Glob(jerry_ext_dir + '/arg/*.c') 29 | jerry_ext += Glob(jerry_ext_dir + '/handler/*.c') 30 | jerry_ext += Glob(jerry_ext_dir + '/include/*.c') 31 | jerry_ext += Glob(jerry_ext_dir + '/module/*.c') 32 | 33 | src = jerry_core + jerry_ext 34 | 35 | CPPPATH = [cwd] 36 | 37 | jerry_core_dir = cwd + '/jerryscript/jerry-core' 38 | 39 | CPPPATH += [jerry_core_dir + '/api'] 40 | CPPPATH += [jerry_core_dir + '/debugger'] 41 | CPPPATH += [jerry_core_dir + '/ecma/base'] 42 | CPPPATH += [jerry_core_dir + '/ecma/builtin-objects'] 43 | CPPPATH += [jerry_core_dir + '/ecma/builtin-objects/typedarray'] 44 | CPPPATH += [jerry_core_dir + '/ecma/operations'] 45 | CPPPATH += [jerry_core_dir + '/include'] 46 | CPPPATH += [jerry_core_dir + '/jcontext'] 47 | CPPPATH += [jerry_core_dir + '/jmem'] 48 | CPPPATH += [jerry_core_dir + '/jrt'] 49 | CPPPATH += [jerry_core_dir + '/lit'] 50 | CPPPATH += [jerry_core_dir + '/parser/js'] 51 | CPPPATH += [jerry_core_dir + '/parser/regexp'] 52 | CPPPATH += [jerry_core_dir + '/vm'] 53 | 54 | jerry_ext_dir = cwd + '/jerryscript/jerry-ext' 55 | 56 | CPPPATH += [jerry_ext_dir + '/arg'] 57 | CPPPATH += [jerry_ext_dir + '/handler'] 58 | CPPPATH += [jerry_ext_dir + '/include'] 59 | CPPPATH += [jerry_ext_dir + '/module'] 60 | 61 | LOCAL_CCFLAGS = '' 62 | import rtconfig 63 | if rtconfig.CROSS_TOOL == 'keil': 64 | LOCAL_CCFLAGS += ' --gnu' 65 | elif rtconfig.CROSS_TOOL == 'gcc': 66 | LOCAL_CCFLAGS += ' -std=c11' 67 | 68 | CPPDEFINES = ['JERRY_JS_PARSER', 'JERRY_ENABLE_EXTERNAL_CONTEXT'] 69 | 70 | if GetDepend('PKG_JERRY_ENABLE_ERROR_MESSAGES'): 71 | CPPDEFINES += ['JERRY_ENABLE_ERROR_MESSAGES'] 72 | 73 | if GetDepend('PKG_JERRY_ENABLE_LOGGING'): 74 | CPPDEFINES += ['JERRY_ENABLE_LOGGING'] 75 | 76 | if GetDepend('PKG_JMEM_STATS'): 77 | CPPDEFINES += ['JMEM_STATS'] 78 | 79 | if GetDepend('PKG_CONFIG_DISABLE_ES2015'): 80 | CPPDEFINES += ['CONFIG_DISABLE_ES2015'] 81 | 82 | group = DefineGroup('JerryScript', src, depend = ['PKG_USING_JERRYSCRIPT'], CPPPATH = CPPPATH, 83 | CPPDEFINES = CPPDEFINES, LOCAL_CCFLAGS = LOCAL_CCFLAGS) 84 | 85 | group = group + SConscript(os.path.join('rtthread-port', 'SConscript')) 86 | 87 | Return('group') 88 | -------------------------------------------------------------------------------- /examples/ImportCplusplus/README.md: -------------------------------------------------------------------------------- 1 | # 如何导入C++API 2 | 3 | ## JerryScript基础类型 4 | 5 | 首先,不得不说明下JerryScript的基础类型:`jerry_value_t`。一个对象可以设定任意个属性,属性可以是`number`,`string`,`function`等,也可以是对象。但每个对象中,都有一个指针:`native_pointer`,这个指针就可用来存放或传递数据。 6 | 7 | jerry_value_t obj 8 | ├── 属性1 9 | ├── 属性2 10 | │ ... 11 | │ ... 12 | └── native_pointer 13 | 14 | 15 | JerryScript中则提供了获取、设定native_pointer的API。 16 | ```C 17 | bool 18 | jerry_get_object_native_pointer (const jerry_value_t obj_val, 19 | void **out_native_pointer_p, 20 | const jerry_object_native_info_t **out_native_info_p) 21 | 22 | bool 23 | jerry_set_object_native_pointer (const jerry_value_t obj_val, 24 | void *native_p, 25 | const jerry_object_native_info_t *info_p) 26 | ``` 27 | 28 | ## 如何导入C++的API 29 | 30 | 此Package中,我们一般使用以下的宏在JerryScript中创建一些接口,来使用C++的API: 31 | 32 | ```C 33 | #define REGISTER_HANDLER(NAME) \ 34 | jerryx_handler_register_global ( (jerry_char_t *)# NAME, NAME ## _handler) 35 | #define REGISTER_HANDLER_ALIAS(NAME, HANDLER) \ 36 | jerryx_handler_register_global ( (jerry_char_t *)# NAME, HANDLER) 37 | #define REGISTER_METHOD(OBJ, NAME) \ 38 | js_add_function (OBJ, # NAME, NAME ## _handler) 39 | #define REGISTER_METHOD_ALIAS(OBJ, NAME, HANDLER) \ 40 | js_add_function (OBJ, # NAME, HANDLER) 41 | #define REGISTER_METHOD_NAME(OBJ, NAME, HANDLER) \ 42 | js_add_function (OBJ, NAME, HANDLER ## _handler) 43 | 44 | ``` 45 | 46 | 可以看到,前两个宏指向函数`jerryx_handler_register_global`,具体内容如下: 47 | 48 | ```C 49 | jerry_value_t 50 | jerryx_handler_register_global (const jerry_char_t *name_p, /**< name of the function */ 51 | jerry_external_handler_t handler_p) /**< function callback */ 52 | { 53 | jerry_value_t global_obj_val = jerry_get_global_object (); 54 | jerry_value_t function_name_val = jerry_create_string (name_p); 55 | jerry_value_t function_val = jerry_create_external_function (handler_p); 56 | 57 | jerry_value_t result_val = jerry_set_property (global_obj_val, function_name_val, function_val); 58 | 59 | jerry_release_value (function_val); 60 | jerry_release_value (function_name_val); 61 | jerry_release_value (global_obj_val); 62 | 63 | return result_val; 64 | } 65 | ``` 66 | 后三个宏定义都指向了函数`js_add_function`,具体内容如下: 67 | ```C 68 | void js_add_function(const jerry_value_t obj, const char *name, 69 | jerry_external_handler_t func) 70 | { 71 | jerry_value_t str = jerry_create_string((const jerry_char_t *)name); 72 | jerry_value_t jfunc = jerry_create_external_function(func); 73 | 74 | jerry_set_property(obj, str, jfunc); 75 | 76 | jerry_release_value(str); 77 | jerry_release_value(jfunc); 78 | } 79 | ``` 80 | 81 | 从上述代码中可以看到`jerryx_handler_register_global`和`js_add_function`的实质操作就是在指定对象中加入一个名为`name`的`func`,这个`obj`可以指定为全局obj。而我们就只需要在这个func中添加C++的代码并使用API,并且可以把所需要的数据作为属性加入到指定JerryScript对象中或返回出来。如果想要在JS中传递C++对象,我们就可以利用文章开头所说的native_pointer 82 | 83 | 此func类型为`jerry_external_handler_t`,具体定义如下。 84 | ```C 85 | typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_obj, 86 | const jerry_value_t this_val, 87 | const jerry_value_t args_p[], 88 | const jerry_length_t args_count); 89 | ``` 90 | 为了方便书写代码,Package中添加了对应的宏定义。 91 | ```C 92 | #define DECLARE_HANDLER(NAME) \ 93 | static jerry_value_t \ 94 | NAME ## _handler (const jerry_value_t func_value, \ 95 | const jerry_value_t this_value, \ 96 | const jerry_value_t args[], \ 97 | const jerry_length_t args_cnt ) 98 | ``` 99 | 100 | ### 示例代码 101 | 102 | 以添加`request`接口为例 103 | 1. 创建一个初始化API:`js_request_init`,并设定入参变量`obj`。创建好初始化API后,我们就只要在API中执行`REGISTER_METHOD(obj, request)`,但此时函数`request`还未创建,那我们只需要创建它即可。而函数`request`内部,我们就可以添加C++的API,执行我们需要操作或把相关数据转换成JerryScript的数据类型返回出来。 104 | 105 | ```C 106 | DECLARE_HANDLER(request) 107 | { 108 | //此处就能添加对应的C++的API,并执行具体内容。 109 | } 110 | 111 | extern "C" 112 | { 113 | int js_request_init(jerry_value_t obj) 114 | { 115 | REGISTER_METHOD(obj, request); 116 | return 0; 117 | } 118 | } 119 | ``` 120 | 121 | 2. 譬如在此Package中,JerryScript的执行函数为`jerry_main`,那我们就还需要在`jerry_main`中执行下`js_request_init`。 122 | 123 | ```C 124 | extern int js_request_init(jerry_value_t obj); 125 | int jerry_main(int argc, char** argv) 126 | { 127 | //... 128 | jerry_value_t global_object = jerry_get_global_object(); 129 | js_request_init(global_object); 130 | //... 131 | } 132 | ``` 133 | 134 | 135 | ## 示例说明 136 | 137 | 本示例示仅范了如何导入C++的API,并在创建出一个与C++对象对应的JS对象,还需要在执行函数中执行`js_example_rect_init` 138 | 139 | ```C++ 140 | #include 141 | #include 142 | 143 | /*自定义C++类*/ 144 | class Rectangle 145 | { 146 | private: 147 | int length; 148 | int width; 149 | 150 | public: 151 | Rectangle(int length,int width); 152 | int getSize(); 153 | int getLength(); 154 | int getWidth(); 155 | }; 156 | 157 | Rectangle::Rectangle(int length,int width) 158 | { 159 | this->length = length; 160 | this->width = width; 161 | } 162 | 163 | int Rectangle::getSize() 164 | { 165 | return (this->length * this->width); 166 | } 167 | 168 | int Rectangle::getLength() 169 | { 170 | return this->length; 171 | } 172 | 173 | int Rectangle::getWidth() 174 | { 175 | return this->width; 176 | } 177 | /**********/ 178 | 179 | void rectangle_free_callback(void *native_p) 180 | { 181 | Rectangle* rect = (Rectangle*)native_p; 182 | delete(rect); 183 | } 184 | 185 | const static jerry_object_native_info_t rectangle_info = 186 | { 187 | rectangle_free_callback //当js_rect对象释放后,调用该回调函数 188 | }; 189 | 190 | DECLARE_HANDLER(getSize) 191 | { 192 | void *native_pointer = RT_NULL; 193 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); //获取当前对象中的native_pointer 194 | 195 | if(native_pointer) 196 | { 197 | /*调用C++对象的API,并将其返回值转换成JS对象*/ 198 | Rectangle* rectangle = (Rectangle*)native_pointer; 199 | jerry_value_t js_size = jerry_create_number(rectangle->getSize()); 200 | return js_size; 201 | } 202 | return jerry_create_undefined(); 203 | } 204 | 205 | DECLARE_HANDLER(getLength) 206 | { 207 | void *native_pointer = RT_NULL; 208 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); //获取当前对象中的native_pointer 209 | 210 | if(native_pointer) 211 | { 212 | /*调用C++对象的API,并将其返回值转换成JS对象*/ 213 | Rectangle* rectangle = (Rectangle*)native_pointer; 214 | jerry_value_t js_length = jerry_create_number(rectangle->getLength()); 215 | return js_length; 216 | } 217 | return jerry_create_undefined(); 218 | } 219 | 220 | DECLARE_HANDLER(getWidth) 221 | { 222 | void *native_pointer = RT_NULL; 223 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); //获取当前对象中的native_pointer 224 | 225 | if(native_pointer) 226 | { 227 | /*调用C++对象的API,并将其返回值转换成JS对象*/ 228 | Rectangle* rectangle = (Rectangle*)native_pointer; 229 | jerry_value_t js_width = jerry_create_number(rectangle->getWidth()); 230 | return js_width; 231 | } 232 | return jerry_create_undefined(); 233 | } 234 | 235 | DECLARE_HANDLER(rectangle) 236 | { 237 | /*入参判断*/ 238 | if(args_cnt !=2 || !jerry_value_is_number(args[0]) || !jerry_value_is_number(args[1])) 239 | return jerry_create_undefined(); 240 | 241 | jerry_value_t js_rect = jerry_create_object(); //创建JS对象 js_rect 242 | 243 | Rectangle* rectangle = new Rectangle(jerry_get_number_value(args[0]),jerry_get_number_value(args[1])); //创建C++对象 rectangle 244 | 245 | jerry_set_object_native_pointer(js_rect, rectangle,&rectangle_info); //把js_rect的native_pointer指向rectangle 246 | 247 | /*调用rectangle的API,并把其返回值转换成JS对象*/ 248 | jerry_value_t js_length = jerry_create_number(rectangle->getLength()); 249 | jerry_value_t js_width = jerry_create_number(rectangle->getWidth()); 250 | 251 | /*把js_length 和 js_width设置成js_rect的属性,类Rectangle中lenght与width为私有变量,如要JS对象与C++对象保持对应,此处代码可注释掉*/ 252 | js_set_property(js_rect,"length",js_length); 253 | js_set_property(js_rect,"width",js_width); 254 | 255 | jerry_release_value(js_length); 256 | jerry_release_value(js_width); 257 | 258 | REGISTER_METHOD(js_rect,getSize); //为js_retc注册一个方法getSize 259 | REGISTER_METHOD(js_rect,getLength); //为js_retc注册一个方法getLength 260 | REGISTER_METHOD(js_rect,getWidth); //为js_retc注册一个方法getWidth 261 | return js_rect; 262 | } 263 | 264 | extern "C" 265 | { 266 | int js_example_rect_init(jerry_value_t obj) 267 | { 268 | REGISTER_METHOD(obj, rectangle); //为指定对象obj注册一个方法rectangle_init,这个对象可以是global_obj 269 | return 0; 270 | } 271 | } 272 | 273 | ``` -------------------------------------------------------------------------------- /examples/ImportCplusplus/example_cplusplus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Rectangle 5 | { 6 | private: 7 | int length; 8 | int width; 9 | 10 | public: 11 | Rectangle(int length,int width); 12 | int getSize(); 13 | int getLength(); 14 | int getWidth(); 15 | }; 16 | 17 | Rectangle::Rectangle(int length,int width) 18 | { 19 | this->length = length; 20 | this->width = width; 21 | } 22 | 23 | int Rectangle::getSize() 24 | { 25 | return (this->length * this->width); 26 | } 27 | 28 | int Rectangle::getLength() 29 | { 30 | return this->length; 31 | } 32 | 33 | int Rectangle::getWidth() 34 | { 35 | return this->width; 36 | } 37 | 38 | void rectangle_free_callback(void *native_p) 39 | { 40 | Rectangle* rect = (Rectangle*)native_p; 41 | delete(rect); 42 | } 43 | 44 | const static jerry_object_native_info_t rectangle_info = 45 | { 46 | rectangle_free_callback 47 | }; 48 | 49 | DECLARE_HANDLER(getSize) 50 | { 51 | void *native_pointer = RT_NULL; 52 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); 53 | 54 | if(native_pointer) 55 | { 56 | Rectangle* rectangle = (Rectangle*)native_pointer; 57 | jerry_value_t js_size = jerry_create_number(rectangle->getSize()); 58 | return js_size; 59 | } 60 | return jerry_create_undefined(); 61 | } 62 | 63 | DECLARE_HANDLER(getLength) 64 | { 65 | void *native_pointer = RT_NULL; 66 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); 67 | 68 | if(native_pointer) 69 | { 70 | Rectangle* rectangle = (Rectangle*)native_pointer; 71 | jerry_value_t js_length = jerry_create_number(rectangle->getLength()); 72 | return js_length; 73 | } 74 | return jerry_create_undefined(); 75 | } 76 | 77 | DECLARE_HANDLER(getWidth) 78 | { 79 | void *native_pointer = RT_NULL; 80 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); 81 | 82 | if(native_pointer) 83 | { 84 | Rectangle* rectangle = (Rectangle*)native_pointer; 85 | jerry_value_t js_width = jerry_create_number(rectangle->getWidth()); 86 | return js_width; 87 | } 88 | return jerry_create_undefined(); 89 | 90 | } 91 | 92 | DECLARE_HANDLER(rectangle) 93 | { 94 | if(args_cnt !=2 || !jerry_value_is_number(args[0]) || !jerry_value_is_number(args[1])) 95 | return jerry_create_undefined(); 96 | 97 | jerry_value_t js_rect = jerry_create_object(); 98 | 99 | Rectangle* rectangle = new Rectangle(jerry_get_number_value(args[0]),jerry_get_number_value(args[1])); 100 | jerry_set_object_native_pointer(js_rect, rectangle,&rectangle_info); 101 | 102 | jerry_value_t js_length = jerry_create_number(rectangle->getLength()); 103 | jerry_value_t js_width = jerry_create_number(rectangle->getWidth()); 104 | 105 | js_set_property(js_rect,"length",js_length); 106 | js_set_property(js_rect,"width",js_width); 107 | 108 | jerry_release_value(js_length); 109 | jerry_release_value(js_width); 110 | 111 | REGISTER_METHOD(js_rect,getSize); 112 | REGISTER_METHOD(js_rect,getLength); 113 | REGISTER_METHOD(js_rect,getWidth); 114 | 115 | return js_rect; 116 | } 117 | 118 | extern "C" 119 | { 120 | int js_example_rect_init(jerry_value_t obj) 121 | { 122 | REGISTER_METHOD(obj, rectangle); 123 | return 0; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /examples/ImportModule/README.md: -------------------------------------------------------------------------------- 1 | # 如何添加builtin module 2 | 3 | 由于JerryScript是一款轻量级的JavaScript的引擎,因此它没有直接提供常见的builtin module。但是开发者可以根据自身需求,去添加相应module。 4 | 5 | 阅读本文档前,请先阅读[ImportCplusplus](../ImportCplusplus/README.md)。 6 | 7 | ## 添加builtin module 8 | 9 | 当相应module的入口建立好后,只需要使用以下宏导出命令即可: 10 | 11 | ```c 12 | JS_MODULE(NAME, MODULE_INIT); 13 | /* 14 | * 其中 15 | * NAME : module的名称 16 | * MODULE_INIT : module的入口函数,它会返回一个JsObject对象,也即require('module')时返回的JsObject对象 17 | */ 18 | ``` 19 | 20 | 示例代码: 21 | ```c 22 | jerry_value_t myModule_init(void) 23 | { 24 | 25 | jerry_value_t obj = jerry_create_object(); 26 | // ... 27 | // do something 28 | // ... 29 | return obj; 30 | } 31 | JS_MODULE(myModule, myModule_init); 32 | ``` 33 | 34 | 以上代码就在JerryScript中创建里一个名为`myModule`的module,其返回值为`obj`。 35 | 36 | 在JS脚本中,我们都是通过以下方式调用module的。 37 | 38 | ```JavaScript 39 | var mqtt = require('myModule'); 40 | ``` 41 | 42 | ## 示例说明 43 | 44 | 本示例示范了如何添加builtin module。 45 | 46 | ```c 47 | #include 48 | #include 49 | 50 | struct circle_t 51 | { 52 | double radius; 53 | }; 54 | 55 | void circle_free_callback(void *native_p) 56 | { 57 | struct circle_t* circle = (struct circle_t*)native_p; 58 | free(circle); 59 | } 60 | 61 | const static jerry_object_native_info_t circle_info = 62 | { 63 | circle_free_callback //当js_circle对象释放后,调用该回调函数 64 | }; 65 | 66 | DECLARE_HANDLER(setRadius) 67 | { 68 | /*入参判断*/ 69 | if(args_cnt!=1 || !jerry_value_is_number(args[0])) 70 | return jerry_create_undefined(); 71 | 72 | void* native_pointer = RT_NULL; 73 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); //获取当前对象中的native_pointer 74 | 75 | if(native_pointer) 76 | { 77 | circle_t* circle = (circle_t*)native_pointer; 78 | 79 | double r = jerry_get_number_value(args[0]); 80 | circle->radius = r; 81 | } 82 | 83 | return jerry_create_undefined(); 84 | }; 85 | 86 | DECLARE_HANDLER(getRadius) 87 | { 88 | if(args_cnt != 0) 89 | return jerry_create_undefined(); 90 | 91 | void* native_pointer = RT_NULL; 92 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); 93 | 94 | if(native_pointer) 95 | { 96 | circle_t* circle = (circle_t*)native_pointer; 97 | 98 | jerry_value_t js_radius = jerry_create_number(circle->radius); //获取circle->radius,并将其返回值转换成JS对象 99 | return js_radius; 100 | } 101 | 102 | return jerry_create_undefined(); 103 | }; 104 | 105 | jerry_value_t Circle_init() 106 | { 107 | jerry_value_t js_circle = jerry_create_object(); 108 | 109 | circle_t* circle = (circle_t*)malloc(sizeof(circle_t)); 110 | memset(circle,0,sizeof(circle_t)); 111 | 112 | jerry_set_object_native_pointer(js_circle,circle,&circle_info); //把js_circle的native_pointer指向circle 113 | 114 | REGISTER_METHOD(js_circle,setRadius); //为js_circle注册一个方法 setRadius 115 | REGISTER_METHOD(js_circle,getRadius); //为js_circle注册一个方法 getRadius 116 | return js_circle; 117 | } 118 | 119 | JS_MODULE(Circle,Circle_init); //注册builtin module,名称:Circle,入口函数:Circle_init 120 | ``` 121 | -------------------------------------------------------------------------------- /examples/ImportModule/example_module.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct circle_t 5 | { 6 | double radius; 7 | }; 8 | 9 | void circle_free_callback(void *native_p) 10 | { 11 | struct circle_t* circle = (struct circle_t*)native_p; 12 | free(circle); 13 | } 14 | 15 | const static jerry_object_native_info_t circle_info = 16 | { 17 | circle_free_callback 18 | }; 19 | 20 | DECLARE_HANDLER(setRadius) 21 | { 22 | if(args_cnt!=1 || !jerry_value_is_number(args[0])) 23 | return jerry_create_undefined(); 24 | 25 | void* native_pointer = RT_NULL; 26 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); 27 | 28 | if(native_pointer) 29 | { 30 | struct circle_t* circle = (struct circle_t*)native_pointer; 31 | 32 | double r = jerry_get_number_value(args[0]); 33 | circle->radius = r; 34 | } 35 | 36 | return jerry_create_undefined(); 37 | }; 38 | 39 | DECLARE_HANDLER(getRadius) 40 | { 41 | if(args_cnt != 0) 42 | return jerry_create_undefined(); 43 | 44 | void* native_pointer = RT_NULL; 45 | jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); 46 | 47 | if(native_pointer) 48 | { 49 | struct circle_t* circle = (struct circle_t*)native_pointer; 50 | 51 | jerry_value_t js_radius = jerry_create_number(circle->radius); 52 | return js_radius; 53 | } 54 | 55 | return jerry_create_undefined(); 56 | }; 57 | 58 | jerry_value_t Circle_init() 59 | { 60 | jerry_value_t js_circle = jerry_create_object(); 61 | 62 | struct circle_t* circle = (struct circle_t*)malloc(sizeof(struct circle_t)); 63 | memset(circle,0,sizeof(struct circle_t)); 64 | 65 | jerry_set_object_native_pointer(js_circle,circle,&circle_info); 66 | 67 | REGISTER_METHOD(js_circle,setRadius); 68 | REGISTER_METHOD(js_circle,getRadius); 69 | return js_circle; 70 | } 71 | 72 | JS_MODULE(Circle,Circle_init); 73 | -------------------------------------------------------------------------------- /rtthread-port/SConscript: -------------------------------------------------------------------------------- 1 | # RT-Thread building script for JerryScript RT port 2 | 3 | from building import * 4 | 5 | cwd = GetCurrentDir() 6 | src = Glob('*.c') 7 | CPPPATH = [cwd] 8 | 9 | group = DefineGroup('JerryScriptPort', src, depend = ['PKG_USING_JERRYSCRIPT'], CPPPATH = CPPPATH) 10 | 11 | Return('group') 12 | -------------------------------------------------------------------------------- /rtthread-port/config.h: -------------------------------------------------------------------------------- 1 | /* Copyright JS Foundation and other contributors, http://js.foundation 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #ifndef CONFIG_H 17 | #define CONFIG_H 18 | 19 | #include "rtconfig.h" 20 | 21 | /** 22 | * Group of builtin-related features that can be disabled together. 23 | */ 24 | #ifdef CONFIG_DISABLE_BUILTINS 25 | # define CONFIG_DISABLE_ANNEXB_BUILTIN 26 | # define CONFIG_DISABLE_ARRAY_BUILTIN 27 | # define CONFIG_DISABLE_BOOLEAN_BUILTIN 28 | # define CONFIG_DISABLE_DATE_BUILTIN 29 | # define CONFIG_DISABLE_ERROR_BUILTINS 30 | # define CONFIG_DISABLE_JSON_BUILTIN 31 | # define CONFIG_DISABLE_MATH_BUILTIN 32 | # define CONFIG_DISABLE_NUMBER_BUILTIN 33 | # define CONFIG_DISABLE_REGEXP_BUILTIN 34 | # define CONFIG_DISABLE_STRING_BUILTIN 35 | #endif /* CONFIG_DISABLE_BUILTINS */ 36 | 37 | /** 38 | * Group of ES2015-related features that can be disabled together. 39 | */ 40 | #ifdef CONFIG_DISABLE_ES2015 41 | # define CONFIG_DISABLE_ES2015_ARROW_FUNCTION 42 | # define CONFIG_DISABLE_ES2015_BUILTIN 43 | # define CONFIG_DISABLE_ES2015_CLASS 44 | # define CONFIG_DISABLE_ES2015_MAP_BUILTIN 45 | # define CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER 46 | # define CONFIG_DISABLE_ES2015_PROMISE_BUILTIN 47 | # define CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS 48 | # define CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN 49 | #endif /* CONFIG_DISABLE_ES2015 */ 50 | 51 | /** 52 | * Size of heap 53 | */ 54 | #ifndef CONFIG_MEM_HEAP_AREA_SIZE 55 | # define CONFIG_MEM_HEAP_AREA_SIZE PKG_JMEM_HEAP_SIZE 56 | //# define CONFIG_MEM_HEAP_AREA_SIZE (512 * 1024) 57 | #endif /* !CONFIG_MEM_HEAP_AREA_SIZE */ 58 | 59 | /** 60 | * Max heap usage limit 61 | */ 62 | #define CONFIG_MEM_HEAP_MAX_LIMIT 8192 63 | 64 | /** 65 | * Desired limit of heap usage 66 | */ 67 | #define CONFIG_MEM_HEAP_DESIRED_LIMIT (JERRY_MIN (CONFIG_MEM_HEAP_AREA_SIZE / 32, CONFIG_MEM_HEAP_MAX_LIMIT)) 68 | 69 | /** 70 | * Use 32-bit/64-bit float for ecma-numbers 71 | */ 72 | #define CONFIG_ECMA_NUMBER_FLOAT32 (1u) /* 32-bit float */ 73 | #define CONFIG_ECMA_NUMBER_FLOAT64 (2u) /* 64-bit float */ 74 | 75 | #ifndef CONFIG_ECMA_NUMBER_TYPE 76 | # define CONFIG_ECMA_NUMBER_TYPE CONFIG_ECMA_NUMBER_FLOAT64 77 | #else /* CONFIG_ECMA_NUMBER_TYPE */ 78 | # if (CONFIG_ECMA_NUMBER_TYPE != CONFIG_ECMA_NUMBER_FLOAT32 \ 79 | && CONFIG_ECMA_NUMBER_TYPE != CONFIG_ECMA_NUMBER_FLOAT64) 80 | # error "ECMA-number storage is configured incorrectly" 81 | # endif /* CONFIG_ECMA_NUMBER_TYPE != CONFIG_ECMA_NUMBER_FLOAT32 82 | && CONFIG_ECMA_NUMBER_TYPE != CONFIG_ECMA_NUMBER_FLOAT64 */ 83 | #endif /* !CONFIG_ECMA_NUMBER_TYPE */ 84 | 85 | #if (!defined (CONFIG_DISABLE_DATE_BUILTIN) && (CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32)) 86 | # error "Date does not support float32" 87 | #endif 88 | 89 | /** 90 | * Disable ECMA lookup cache 91 | */ 92 | // #define CONFIG_ECMA_LCACHE_DISABLE 93 | 94 | /** 95 | * Disable ECMA property hashmap 96 | */ 97 | // #define CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE 98 | 99 | /** 100 | * Share of newly allocated since last GC objects among all currently allocated objects, 101 | * after achieving which, GC is started upon low severity try-give-memory-back requests. 102 | * 103 | * Share is calculated as the following: 104 | * 1.0 / CONFIG_ECMA_GC_NEW_OBJECTS_SHARE_TO_START_GC 105 | */ 106 | #define CONFIG_ECMA_GC_NEW_OBJECTS_SHARE_TO_START_GC (16) 107 | 108 | #endif /* !CONFIG_H */ 109 | -------------------------------------------------------------------------------- /rtthread-port/jerry_buffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License") 3 | * Copyright (c) 2016-2018, Intel Corporation. 4 | * 5 | * ported from zephyr.js 6 | * COPYRIGHT (C) 2018, RT-Thread Development Team 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "jerry_buffer.h" 16 | #include "jerry_utf8.h" 17 | 18 | #define strequal(a, b) !strcmp(a, b) 19 | 20 | #define DECL_FUNC_ARGS(name, ...) \ 21 | jerry_value_t name(const jerry_value_t function_obj, \ 22 | const jerry_value_t this, const jerry_value_t argv[], \ 23 | const jerry_length_t args_cnt, __VA_ARGS__) 24 | 25 | static jerry_value_t jerry_buffer_prototype; 26 | js_buffer_t *jerry_buffer_find(const jerry_value_t obj); 27 | 28 | static void jerry_buffer_callback_free(void *handle) 29 | { 30 | js_buffer_t *item = (js_buffer_t *)handle; 31 | 32 | free(item->buffer); 33 | free(item); 34 | } 35 | 36 | static const jerry_object_native_info_t buffer_type_info = 37 | { 38 | .free_cb = jerry_buffer_callback_free 39 | }; 40 | 41 | bool jerry_value_is_buffer(const jerry_value_t value) 42 | { 43 | if (jerry_value_is_object(value) && jerry_buffer_find(value)) 44 | { 45 | return true; 46 | } 47 | return false; 48 | } 49 | 50 | js_buffer_t *jerry_buffer_find(const jerry_value_t obj) 51 | { 52 | // requires: obj should be the JS object associated with a buffer, created 53 | // in jerry_buffer 54 | // effects: looks up obj in our list of known buffer objects and returns 55 | // the associated list item struct, or NULL if not found 56 | js_buffer_t *handle; 57 | const jerry_object_native_info_t *tmp; 58 | if (jerry_get_object_native_pointer(obj, (void **)&handle, &tmp)) 59 | { 60 | if (tmp == &buffer_type_info) 61 | { 62 | return handle; 63 | } 64 | } 65 | 66 | return NULL; 67 | } 68 | 69 | static DECL_FUNC_ARGS(jerry_buffer_read_bytes, int bytes, bool big_endian, bool sign) 70 | { 71 | // requires: this is a JS buffer object created with jerry_buffer_create, 72 | // argv[0] should be an offset into the buffer, but will treat 73 | // offset as 0 if not given, as node.js seems to 74 | // bytes is the number of bytes to read (expects 1, 2, or 4) 75 | // big_endian true reads the bytes in big endian order, false in 76 | // little endian order 77 | // effects: reads bytes from the buffer associated with this JS object, if 78 | // found, at the given offset, if within the bounds of the 79 | // buffer; otherwise returns an error 80 | 81 | // args: offset 82 | // ZJS_VALIDATE_ARGS(Z_OPTIONAL Z_NUMBER); 83 | 84 | uint32_t offset = 0; 85 | if (args_cnt >= 1) 86 | offset = (uint32_t)jerry_get_number_value(argv[0]); 87 | 88 | js_buffer_t *buf = jerry_buffer_find(this); 89 | if (!buf) 90 | return jerry_create_undefined(); 91 | 92 | if (offset + bytes > buf->bufsize) 93 | return jerry_create_undefined(); 94 | 95 | int dir = big_endian ? 1 : -1; 96 | if (!big_endian) 97 | offset += bytes - 1; // start on the big end 98 | 99 | uint32_t value = 0, i; 100 | for (i = 0; i < bytes; i++) 101 | { 102 | value <<= 8; 103 | value |= buf->buffer[offset]; 104 | offset += dir; 105 | } 106 | 107 | if (sign) 108 | { 109 | if (bytes == 1) 110 | return jerry_create_number((int8_t)value); 111 | else if (bytes == 2) 112 | return jerry_create_number((int16_t)value); 113 | else if (bytes == 4) 114 | return jerry_create_number((int32_t)value); 115 | } 116 | 117 | return jerry_create_number(value); 118 | } 119 | 120 | static DECL_FUNC_ARGS(jerry_buffer_write_bytes, int bytes, bool big_endian) 121 | { 122 | // requires: this is a JS buffer object created with jerry_buffer_create, 123 | // argv[0] must be the value to be written, argv[1] should be 124 | // an offset into the buffer, but will treat offset as 0 if not 125 | // given, as node.js seems to 126 | // bytes is the number of bytes to write (expects 1, 2, or 4) 127 | // big_endian true writes the bytes in big endian order, false in 128 | // little endian order 129 | // effects: writes bytes into the buffer associated with this JS object, if 130 | // found, at the given offset, if within the bounds of the 131 | // buffer and returns the offset just beyond what was written; 132 | // otherwise returns an error 133 | 134 | // args: value[, offset] 135 | // ZJS_VALIDATE_ARGS(Z_NUMBER, Z_OPTIONAL Z_NUMBER); 136 | 137 | // technically negatives aren't supported but this makes them behave better 138 | double dval = jerry_get_number_value(argv[0]); 139 | uint32_t value = (uint32_t)(dval < 0 ? (int32_t)dval : dval); 140 | 141 | uint32_t offset = 0; 142 | if (args_cnt > 1) 143 | { 144 | offset = (uint32_t)jerry_get_number_value(argv[1]); 145 | } 146 | 147 | js_buffer_t *buf = jerry_buffer_find(this); 148 | if (!buf) 149 | { 150 | return jerry_create_undefined(); 151 | } 152 | 153 | uint32_t beyond = offset + bytes; 154 | if (beyond > buf->bufsize) 155 | { 156 | printf("bufsize %d, write attempted from %d to %d\n", (int)buf->bufsize, (int)offset, (int)beyond); 157 | return jerry_create_undefined(); 158 | } 159 | 160 | int dir = big_endian ? -1 : 1; 161 | if (big_endian) 162 | offset += bytes - 1; // start on the little end 163 | 164 | int i; 165 | for (i = 0; i < bytes; i++) 166 | { 167 | buf->buffer[offset] = value & 0xff; 168 | value >>= 8; 169 | offset += dir; 170 | } 171 | 172 | return jerry_create_number(beyond); 173 | } 174 | 175 | DECLARE_HANDLER(readUInt8) 176 | { 177 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 1, true, false); 178 | } 179 | 180 | DECLARE_HANDLER(readInt8) 181 | { 182 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 1, true, true); 183 | } 184 | 185 | DECLARE_HANDLER(readUInt16BE) 186 | { 187 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 2, true, false); 188 | } 189 | 190 | DECLARE_HANDLER(readInt16BE) 191 | { 192 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 2, true, true); 193 | } 194 | 195 | DECLARE_HANDLER(readUInt16LE) 196 | { 197 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 2, false, false); 198 | } 199 | 200 | DECLARE_HANDLER(readInt16LE) 201 | { 202 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 2, false, true); 203 | } 204 | 205 | DECLARE_HANDLER(readUInt32BE) 206 | { 207 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 4, true, false); 208 | } 209 | 210 | DECLARE_HANDLER(readInt32BE) 211 | { 212 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 4, true, true); 213 | } 214 | 215 | DECLARE_HANDLER(readUInt32LE) 216 | { 217 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 4, false, false); 218 | } 219 | 220 | DECLARE_HANDLER(readInt32LE) 221 | { 222 | return jerry_buffer_read_bytes(func_value, this_value, args, args_cnt, 4, false, true); 223 | } 224 | 225 | DECLARE_HANDLER(writeUInt8) 226 | { 227 | return jerry_buffer_write_bytes(func_value, this_value, args, args_cnt, 1, true); 228 | } 229 | 230 | DECLARE_HANDLER(writeUInt16BE) 231 | { 232 | return jerry_buffer_write_bytes(func_value, this_value, args, args_cnt, 2, true); 233 | } 234 | 235 | DECLARE_HANDLER(writeUInt16LE) 236 | { 237 | return jerry_buffer_write_bytes(func_value, this_value, args, args_cnt, 2, false); 238 | } 239 | 240 | DECLARE_HANDLER(writeUInt32BE) 241 | { 242 | return jerry_buffer_write_bytes(func_value, this_value, args, args_cnt, 4, true); 243 | } 244 | 245 | DECLARE_HANDLER(writeUInt32LE) 246 | { 247 | return jerry_buffer_write_bytes(func_value, this_value, args, args_cnt, 4, false); 248 | } 249 | 250 | DECLARE_HANDLER(readFloatBE) 251 | { 252 | return jerry_create_undefined(); 253 | } 254 | 255 | DECLARE_HANDLER(readDoubleBE) 256 | { 257 | return jerry_create_undefined(); 258 | } 259 | 260 | char jerry_int_to_hex(int value) 261 | { 262 | if (value < 10) 263 | return '0' + value; 264 | 265 | return 'A' + value - 10; 266 | } 267 | 268 | static int hex2int(const char *str) 269 | { 270 | int i = 0; 271 | int r = 0; 272 | 273 | for (i = 0; i < 2; i++) 274 | { 275 | if (str[i] >= '0' && str[i] <= '9') r += str[i] - '0'; 276 | else if (str[i] >= 'a' && str[i] <= 'f') r += str[i] - 'a' + 10; 277 | else if (str[i] >= 'A' && str[i] <= 'F') r += str[i] - 'A' + 10; 278 | 279 | if (!i) r *= 16; 280 | } 281 | 282 | return r; 283 | } 284 | 285 | /* 286 | * toString(encoding[opt], start[opt], end[opt]) 287 | */ 288 | DECLARE_HANDLER(toString) 289 | { 290 | int start, end; 291 | int optcount = args_cnt; 292 | 293 | if (args_cnt > 1 && !jerry_value_is_string(args[0])) return jerry_create_undefined(); 294 | 295 | js_buffer_t *buf = jerry_buffer_find(this_value); 296 | if (!buf) return jerry_create_undefined(); 297 | 298 | if (args_cnt > 1) start = jerry_get_number_value(args[1]); 299 | else start = 0; 300 | if (args_cnt > 2) end = jerry_get_number_value(args[2]); 301 | else end = buf->bufsize; 302 | 303 | int size; 304 | char *enc = NULL; 305 | const char *encoding = "utf8"; 306 | if (optcount) 307 | { 308 | enc = js_value_to_string(args[0]); 309 | size = strlen(enc); 310 | if (!size) 311 | { 312 | free(enc); 313 | return jerry_create_undefined(); 314 | } 315 | 316 | encoding = enc; 317 | } 318 | 319 | if (strequal(encoding, "utf8")) 320 | { 321 | jerry_char_t *str = (jerry_char_t *)buf->buffer; 322 | 323 | str += start; 324 | rt_free(enc); 325 | if (jerry_str_is_utf8(str, end - start)) 326 | return jerry_create_string_sz_from_utf8(str, end - start); 327 | else 328 | return jerry_create_undefined(); 329 | } 330 | else if (strequal(encoding, "ascii")) 331 | { 332 | char *str = malloc(buf->bufsize); 333 | if (!str) 334 | { 335 | free(enc); 336 | return jerry_create_undefined(); 337 | } 338 | 339 | int index; 340 | for (index = start; index < end; ++index) 341 | { 342 | // strip off high bit if present 343 | str[index - start] = buf->buffer[index] & 0x7f; 344 | if (!str[index - start]) 345 | break; 346 | } 347 | 348 | jerry_value_t jstr; 349 | if (jerry_str_is_utf8(str, index - start)) 350 | jstr = jerry_create_string_sz_from_utf8((jerry_char_t *)str, index - start); 351 | else 352 | jstr = jerry_create_undefined(); 353 | free(str); 354 | free(enc); 355 | return jstr; 356 | } 357 | else if (strequal(encoding, "hex")) 358 | { 359 | if (buf && end - start > 0) 360 | { 361 | int size = (end - start); 362 | char *hexbuf = malloc(size * 2 + 1); 363 | if (hexbuf) 364 | { 365 | int i; 366 | jerry_value_t ret; 367 | 368 | for (i = 0; i < size; i++) 369 | { 370 | int high = (0xf0 & buf->buffer[i + start]) >> 4; 371 | int low = 0xf & buf->buffer[i + start]; 372 | hexbuf[2 * i] = jerry_int_to_hex(high); 373 | hexbuf[2 * i + 1] = jerry_int_to_hex(low); 374 | } 375 | hexbuf[size * 2] = '\0'; 376 | 377 | free(enc); 378 | 379 | ret = jerry_create_string((jerry_char_t *)hexbuf); 380 | 381 | free(hexbuf); 382 | 383 | return ret; 384 | } 385 | else 386 | { 387 | free(enc); 388 | return jerry_create_undefined(); 389 | } 390 | } 391 | } 392 | else 393 | { 394 | free(enc); 395 | return jerry_create_undefined(); 396 | } 397 | 398 | free(enc); 399 | return jerry_create_undefined(); 400 | } 401 | 402 | DECLARE_HANDLER(jsonParse) 403 | { 404 | int start, end; 405 | 406 | js_buffer_t *buf = jerry_buffer_find(this_value); 407 | if (!buf) return jerry_create_undefined(); 408 | 409 | if (args_cnt > 0) 410 | start = jerry_get_number_value(args[0]); 411 | else 412 | start = 0; 413 | 414 | if (args_cnt > 1) 415 | end = jerry_get_number_value(args[1]); 416 | else 417 | end = buf->bufsize; 418 | 419 | if (end - start > 0) 420 | { 421 | jerry_value_t parsed_json; 422 | jerry_char_t *str = (jerry_char_t *)buf->buffer; 423 | 424 | str += start; 425 | 426 | parsed_json = jerry_json_parse(str, end - start); 427 | if (jerry_value_is_error(parsed_json)) 428 | { 429 | jerry_release_value(parsed_json); 430 | return jerry_create_undefined(); 431 | } 432 | else 433 | return parsed_json; 434 | } 435 | 436 | return jerry_create_undefined(); 437 | } 438 | 439 | DECLARE_HANDLER(concat) 440 | { 441 | if (args_cnt == 1) 442 | { 443 | uint8_t *ptr; 444 | 445 | js_buffer_t *source = jerry_buffer_find(this_value); 446 | js_buffer_t *target = jerry_buffer_find(args[0]); 447 | if (!source || !target) 448 | { 449 | return jerry_create_undefined(); 450 | } 451 | 452 | if (target->bufsize == 0 || source->bufsize == 0) return this_value; 453 | 454 | ptr = realloc(source->buffer, source->bufsize + target->bufsize); 455 | if (ptr) 456 | { 457 | source->buffer = ptr; 458 | 459 | memcpy(&source->buffer[source->bufsize], target->buffer, target->bufsize); 460 | source->bufsize += target->bufsize; 461 | js_set_property(this_value, "length", jerry_create_number(source->bufsize)); 462 | } 463 | } 464 | 465 | return jerry_create_undefined(); 466 | } 467 | 468 | DECLARE_HANDLER(copy) 469 | { 470 | // requires: this must be a JS buffer object and args[0] a target buffer 471 | // object 472 | // effects: copies buffer contents w/ optional offsets considered to the 473 | // target buffer (following Node v8.9.4 API) 474 | 475 | // args: target, [targetStart], [sourceStart], [sourceEnd] 476 | // ZJS_VALIDATE_ARGS_OPTCOUNT(optcount, Z_BUFFER, 477 | // Z_OPTIONAL Z_NUMBER Z_UNDEFINED, 478 | // Z_OPTIONAL Z_NUMBER Z_UNDEFINED, 479 | // Z_OPTIONAL Z_NUMBER Z_UNDEFINED); 480 | 481 | int optcount = args_cnt; 482 | 483 | if (optcount <= 0) 484 | return jerry_create_undefined(); 485 | 486 | js_buffer_t *source = jerry_buffer_find(this_value); 487 | js_buffer_t *target = jerry_buffer_find(args[0]); 488 | if (!source || !target) 489 | { 490 | return jerry_create_undefined(); 491 | } 492 | 493 | int targetStart = 0; 494 | int sourceStart = 0; 495 | int sourceEnd = -1; 496 | if (optcount > 1 && !jerry_value_is_undefined(args[1])) 497 | { 498 | targetStart = (int)jerry_get_number_value(args[1]); 499 | } 500 | if (optcount > 2 && !jerry_value_is_undefined(args[2])) 501 | { 502 | sourceStart = (int)jerry_get_number_value(args[2]); 503 | } 504 | if (optcount > 3 && !jerry_value_is_undefined(args[3])) 505 | { 506 | sourceEnd = (int)jerry_get_number_value(args[3]); 507 | } 508 | 509 | if (sourceEnd == -1) 510 | { 511 | sourceEnd = source->bufsize; 512 | } 513 | 514 | if (targetStart < 0 || targetStart >= target->bufsize || 515 | sourceStart < 0 || sourceStart >= source->bufsize || 516 | sourceEnd < 0 || sourceEnd <= sourceStart || 517 | sourceEnd > source->bufsize) 518 | { 519 | return jerry_create_undefined(); 520 | } 521 | 522 | if (sourceEnd - sourceStart > target->bufsize - targetStart) 523 | { 524 | return jerry_create_undefined(); 525 | } 526 | 527 | int len = sourceEnd - sourceStart; 528 | memcpy(target->buffer + targetStart, source->buffer + sourceStart, len); 529 | return jerry_create_number(len); 530 | } 531 | 532 | DECLARE_HANDLER(write) 533 | { 534 | // requires: string - what will be written to buf 535 | // offset - where to start writing (Default: 0) 536 | // length - how many bytes to write (Default: buf.length -offset) 537 | // encoding - the character encoding of string. Currently only 538 | // supports the default of utf8 539 | // effects: writes string to buf at offset according to the character 540 | // encoding in encoding. 541 | 542 | // args: data[, offset[, length[, encoding]]] 543 | // ZJS_VALIDATE_ARGS(Z_STRING, Z_OPTIONAL Z_NUMBER, Z_OPTIONAL Z_NUMBER, 544 | // Z_OPTIONAL Z_STRING); 545 | 546 | js_buffer_t *buf = jerry_buffer_find(this_value); 547 | if (!buf) 548 | { 549 | return jerry_create_undefined(); 550 | } 551 | 552 | // Check if the encoding string is anything other than utf8 553 | if (args_cnt > 3) 554 | { 555 | char *encoding = js_value_to_string(args[3]); 556 | if (!encoding) 557 | { 558 | return jerry_create_undefined(); 559 | } 560 | 561 | // ask for one more char than needed to make sure not just prefix match 562 | const char *utf8_encoding = "utf8"; 563 | int utf8_len = strlen(utf8_encoding); 564 | int rval = strncmp(encoding, utf8_encoding, utf8_len + 1); 565 | free(encoding); 566 | if (rval != 0) 567 | { 568 | return jerry_create_undefined(); 569 | } 570 | } 571 | 572 | char *str = js_value_to_string(args[0]); 573 | if (!str) 574 | { 575 | return jerry_create_undefined(); 576 | } 577 | jerry_size_t size = strlen(str); 578 | 579 | uint32_t offset = 0; 580 | if (args_cnt > 1) 581 | offset = (uint32_t)jerry_get_number_value(args[1]); 582 | 583 | uint32_t length = buf->bufsize - offset; 584 | if (args_cnt > 2) 585 | length = (uint32_t)jerry_get_number_value(args[2]); 586 | 587 | if (length > size) 588 | { 589 | free(str); 590 | return jerry_create_undefined(); 591 | } 592 | 593 | if (offset + length > buf->bufsize) 594 | { 595 | free(str); 596 | return jerry_create_undefined(); 597 | } 598 | 599 | memcpy(buf->buffer + offset, str, length); 600 | free(str); 601 | 602 | return jerry_create_number(length); 603 | } 604 | 605 | DECLARE_HANDLER(fill) 606 | { 607 | // requires: value - what will be written to buf 608 | // offset - where to start writing (Default: 0) 609 | // end - offset at which to stop writing (Default: buf.length) 610 | // encoding - the character encoding of value. Currently only 611 | // supports the default of utf8 612 | // effects: writes string to buf at offset according to the character 613 | // encoding in encoding. 614 | 615 | // args: data[, offset[, length[, encoding]]] 616 | // ZJS_VALIDATE_ARGS(Z_STRING Z_NUMBER Z_BUFFER, Z_OPTIONAL Z_NUMBER, 617 | // Z_OPTIONAL Z_NUMBER, Z_OPTIONAL Z_STRING); 618 | 619 | // TODO: support encodings other than 'utf8' 620 | 621 | uint32_t num; 622 | char *source = NULL; 623 | char *str = NULL; 624 | uint32_t srclen = 0; 625 | 626 | if (jerry_value_is_number(args[0])) 627 | { 628 | uint32_t srcnum = (uint32_t)jerry_get_number_value(args[0]); 629 | 630 | // convert in case of endian difference 631 | source = (char *)# 632 | source[0] = (0xff000000 & srcnum) >> 24; 633 | source[1] = (0x00ff0000 & srcnum) >> 16; 634 | source[2] = (0x0000ff00 & srcnum) >> 8; 635 | source[3] = 0x000000ff & srcnum; 636 | srclen = sizeof(uint32_t); 637 | } 638 | else if (jerry_value_is_buffer(args[0])) 639 | { 640 | js_buffer_t *srcbuf = jerry_buffer_find(args[0]); 641 | source = (char *)srcbuf->buffer; 642 | srclen = srcbuf->bufsize; 643 | } 644 | 645 | js_buffer_t *buf = jerry_buffer_find(this_value); 646 | if (!buf) 647 | { 648 | return jerry_create_undefined(); 649 | } 650 | 651 | // Check if the encoding string is anything other than utf8 652 | if (args_cnt > 3) 653 | { 654 | char *encoding = js_value_to_string(args[3]); 655 | if (!encoding) 656 | { 657 | return jerry_create_undefined(); 658 | } 659 | 660 | // ask for one more char than needed to make sure not just prefix match 661 | const char *utf8_encoding = "utf8"; 662 | int utf8_len = strlen(utf8_encoding); 663 | int rval = strncmp(encoding, utf8_encoding, utf8_len + 1); 664 | free(encoding); 665 | if (rval != 0) 666 | { 667 | return jerry_create_undefined(); 668 | } 669 | } 670 | 671 | uint32_t offset = 0; 672 | if (args_cnt > 1) 673 | offset = (uint32_t)jerry_get_number_value(args[1]); 674 | 675 | uint32_t end = buf->bufsize; 676 | if (args_cnt > 2) 677 | { 678 | end = (uint32_t)jerry_get_number_value(args[2]); 679 | if (end > buf->bufsize) 680 | { 681 | end = buf->bufsize; 682 | } 683 | } 684 | 685 | if (offset >= end) 686 | { 687 | // nothing to do 688 | return jerry_acquire_value(this_value); 689 | } 690 | 691 | if (jerry_value_is_string(args[0])) 692 | { 693 | char *str = js_value_to_string(args[0]); 694 | if (!str) 695 | { 696 | return jerry_create_undefined(); 697 | } 698 | source = str; 699 | srclen = strlen(str); 700 | } 701 | 702 | uint32_t bytes_left = end - offset; 703 | while (bytes_left > 0) 704 | { 705 | uint32_t bytes = srclen; 706 | if (bytes > bytes_left) 707 | { 708 | bytes = bytes_left; 709 | } 710 | memcpy(buf->buffer + offset, source, bytes); 711 | offset += bytes; 712 | bytes_left -= bytes; 713 | } 714 | 715 | free(str); 716 | return jerry_acquire_value(this_value); 717 | } 718 | 719 | jerry_value_t jerry_buffer_create(uint32_t size, js_buffer_t **ret_buf) 720 | { 721 | // follow Node's Buffer.kMaxLength limits though we don't expose that 722 | uint32_t maxLength = (1UL << 31) - 1; 723 | if (sizeof(size_t) == 4) 724 | { 725 | // detected 32-bit architecture 726 | maxLength = (1 << 30) - 1; 727 | } 728 | 729 | if (size > maxLength) 730 | { 731 | printf("size: %d\n", (int)size); 732 | return jerry_create_undefined(); 733 | } 734 | 735 | void *buf = malloc(size); 736 | js_buffer_t *buf_item = (js_buffer_t *)malloc(sizeof(js_buffer_t)); 737 | 738 | if (!buf || !buf_item) 739 | { 740 | free(buf); 741 | free(buf_item); 742 | if (ret_buf) 743 | { 744 | *ret_buf = NULL; 745 | } 746 | return jerry_create_undefined(); 747 | } 748 | 749 | jerry_value_t buf_obj = jerry_create_object(); 750 | buf_item->buffer = buf; 751 | buf_item->bufsize = size; 752 | 753 | jerry_set_prototype(buf_obj, jerry_buffer_prototype); 754 | jerry_value_t length = jerry_create_number(size); 755 | js_set_property(buf_obj, "length", length); 756 | jerry_release_value(length); 757 | 758 | // watch for the object getting garbage collected, and clean up 759 | jerry_set_object_native_pointer(buf_obj, buf_item, &buffer_type_info); 760 | if (ret_buf) 761 | { 762 | *ret_buf = buf_item; 763 | } 764 | 765 | return buf_obj; 766 | } 767 | 768 | #define ENCODING_UTF8 0 769 | #define ENCODING_ASCII 1 770 | #define ENCODING_HEX 2 771 | #define ENCODING_BASE64 3 772 | 773 | int buffer_encoding_type(const char* encoding) 774 | { 775 | int ret = ENCODING_UTF8; 776 | 777 | if (strequal(encoding, "hex")) ret = ENCODING_HEX; 778 | else if (strequal(encoding, "ascii")) ret = ENCODING_ASCII; 779 | else if (strequal(encoding, "utf8")) ret = ENCODING_UTF8; 780 | else if (strequal(encoding, "base64")) ret = ENCODING_BASE64; 781 | 782 | return ret; 783 | } 784 | 785 | /* 786 | * Buffer(number); 787 | * Buffer(string, encoding[opt]); 788 | * Buffer(array); 789 | * Buffer(object); 790 | */ 791 | DECLARE_HANDLER(Buffer) 792 | { 793 | int encoding_type = ENCODING_UTF8; 794 | 795 | if (args_cnt > 1) 796 | { 797 | char *encoding = js_value_to_string(args[1]); 798 | if (encoding) 799 | { 800 | encoding_type = buffer_encoding_type(encoding); 801 | 802 | free(encoding); 803 | } 804 | } 805 | 806 | if (jerry_value_is_number(args[0])) 807 | { 808 | double dnum = jerry_get_number_value(args[0]); 809 | uint32_t unum; 810 | 811 | if (dnum < 0) 812 | { 813 | unum = 0; 814 | } 815 | else if (dnum > 0xffffffff) 816 | { 817 | unum = 0xffffffff; 818 | } 819 | else 820 | { 821 | // round to the nearest integer 822 | unum = (uint32_t)(dnum + 0.5); 823 | } 824 | 825 | // treat a number argument as a length 826 | return jerry_buffer_create(unum, NULL); 827 | } 828 | else if (jerry_value_is_string(args[0])) 829 | { 830 | uint8_t *data = NULL; 831 | char *str = js_value_to_string(args[0]); 832 | if (!str) 833 | { 834 | return jerry_create_undefined(); 835 | } 836 | 837 | js_buffer_t *buf; 838 | jerry_size_t size = strlen(str); 839 | 840 | if (encoding_type == ENCODING_HEX) 841 | { 842 | data = malloc(size / 2); 843 | if (data) 844 | { 845 | int index; 846 | for (index = 0; index < size / 2; index++) 847 | { 848 | data[index] = hex2int(&str[index * 2]); 849 | } 850 | } 851 | 852 | size = size / 2; 853 | } 854 | else 855 | { 856 | data = (uint8_t *)str; 857 | } 858 | 859 | jerry_value_t new_buf = jerry_buffer_create(size, &buf); 860 | if (buf) 861 | { 862 | memcpy(buf->buffer, data, size); 863 | } 864 | 865 | if ((char*)data != str) free(data); 866 | free(str); 867 | 868 | return new_buf; 869 | } 870 | else if (jerry_value_is_array(args[0])) 871 | { 872 | // treat array argument as byte initializers 873 | jerry_value_t array = args[0]; 874 | uint32_t len = jerry_get_array_length(array); 875 | 876 | js_buffer_t *buf; 877 | jerry_value_t new_buf = jerry_buffer_create(len, &buf); 878 | if (buf) 879 | { 880 | int i; 881 | for (i = 0; i < len; i++) 882 | { 883 | jerry_value_t item = jerry_get_property_by_index(array, i); 884 | if (jerry_value_is_number(item)) 885 | { 886 | buf->buffer[i] = (uint8_t)jerry_get_number_value(item); 887 | } 888 | else 889 | { 890 | printf("non-numeric value in array, treating as 0\n"); 891 | buf->buffer[i] = 0; 892 | } 893 | } 894 | } 895 | return new_buf; 896 | } 897 | else if (jerry_value_is_object(args[0])) 898 | { 899 | jerry_value_t stringified = jerry_json_stringfy(args[0]); 900 | if (!jerry_value_is_error(stringified)) 901 | { 902 | char *json_string = js_value_to_string(stringified); 903 | if (json_string) 904 | { 905 | js_buffer_t *buf; 906 | jerry_value_t new_buf = jerry_buffer_create(strlen(json_string), &buf); 907 | if (buf) 908 | { 909 | memcpy(buf->buffer, json_string, strlen(json_string)); 910 | } 911 | free(json_string); 912 | jerry_release_value(stringified); 913 | return new_buf; 914 | } 915 | } 916 | jerry_release_value(stringified); 917 | } 918 | 919 | return jerry_create_undefined(); 920 | } 921 | 922 | int js_buffer_cleanup(void) 923 | { 924 | jerry_release_value(jerry_buffer_prototype); 925 | return 0; 926 | } 927 | 928 | int js_buffer_init(void) 929 | { 930 | REGISTER_HANDLER(Buffer); 931 | 932 | jerry_buffer_prototype = jerry_create_object(); 933 | REGISTER_METHOD(jerry_buffer_prototype, readUInt8); 934 | REGISTER_METHOD(jerry_buffer_prototype, readInt8); 935 | REGISTER_METHOD(jerry_buffer_prototype, writeUInt8); 936 | REGISTER_METHOD(jerry_buffer_prototype, readUInt16BE); 937 | REGISTER_METHOD(jerry_buffer_prototype, readInt16BE); 938 | REGISTER_METHOD(jerry_buffer_prototype, writeUInt16BE); 939 | REGISTER_METHOD(jerry_buffer_prototype, readUInt16LE); 940 | REGISTER_METHOD(jerry_buffer_prototype, readInt16LE); 941 | REGISTER_METHOD(jerry_buffer_prototype, writeUInt16LE); 942 | REGISTER_METHOD(jerry_buffer_prototype, readUInt32BE); 943 | REGISTER_METHOD(jerry_buffer_prototype, readInt32BE); 944 | REGISTER_METHOD(jerry_buffer_prototype, writeUInt32BE); 945 | REGISTER_METHOD(jerry_buffer_prototype, readUInt32LE); 946 | REGISTER_METHOD(jerry_buffer_prototype, readInt32LE); 947 | REGISTER_METHOD(jerry_buffer_prototype, writeUInt32LE); 948 | REGISTER_METHOD(jerry_buffer_prototype, readFloatBE); 949 | REGISTER_METHOD(jerry_buffer_prototype, readDoubleBE); 950 | REGISTER_METHOD(jerry_buffer_prototype, copy); 951 | REGISTER_METHOD(jerry_buffer_prototype, fill); 952 | REGISTER_METHOD(jerry_buffer_prototype, toString); 953 | REGISTER_METHOD(jerry_buffer_prototype, jsonParse); 954 | REGISTER_METHOD(jerry_buffer_prototype, write); 955 | REGISTER_METHOD(jerry_buffer_prototype, concat); 956 | 957 | return 0; 958 | } 959 | -------------------------------------------------------------------------------- /rtthread-port/jerry_buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License") 3 | * Copyright (c) 2016-2018, Intel Corporation. 4 | * 5 | * ported from zephyr.js 6 | * COPYRIGHT (C) 2018, RT-Thread Development Team 7 | */ 8 | 9 | #ifndef JERRY_BUFFER_H__ 10 | #define JERRY_BUFFER_H__ 11 | 12 | #include 13 | #include 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | typedef struct js_buffer 20 | { 21 | uint8_t *buffer; 22 | uint32_t bufsize; 23 | } js_buffer_t; 24 | 25 | int js_buffer_init(void); 26 | int js_buffer_cleanup(void); 27 | 28 | js_buffer_t *jerry_buffer_find(const jerry_value_t obj); 29 | bool jerry_value_is_buffer(const jerry_value_t value); 30 | jerry_value_t jerry_buffer_create(uint32_t size, js_buffer_t **ret_buf); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /rtthread-port/jerry_callbacks.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | 5 | struct js_callback *_js_callback = NULL; 6 | static js_mq_func _js_mq_func = NULL; 7 | 8 | static void append_callback(struct js_callback *callback) 9 | { 10 | struct js_callback *_callback = _js_callback; 11 | 12 | if (_js_callback == NULL) 13 | { 14 | _js_callback = callback; 15 | return; 16 | } 17 | 18 | while (_callback->next != NULL) 19 | { 20 | _callback = _callback->next; 21 | } 22 | 23 | _callback->next = callback; 24 | } 25 | 26 | static void remove_callback(struct js_callback *callback) 27 | { 28 | struct js_callback *_callback = _js_callback; 29 | 30 | if (_js_callback == NULL) 31 | return; 32 | 33 | if (_js_callback == callback) 34 | { 35 | _js_callback = _js_callback->next; 36 | rt_free(callback); 37 | return; 38 | } 39 | 40 | while (_callback->next != NULL) 41 | { 42 | if (_callback->next == callback) 43 | { 44 | _callback->next = callback->next; 45 | rt_free(callback); 46 | break; 47 | } 48 | 49 | _callback = _callback->next; 50 | } 51 | } 52 | 53 | static rt_bool_t has_callback(struct js_callback *callback) 54 | { 55 | struct js_callback *_callback = _js_callback; 56 | 57 | if (callback == NULL || _js_callback == NULL) 58 | { 59 | return RT_FALSE; 60 | } 61 | 62 | do 63 | { 64 | if (_callback == callback) 65 | { 66 | return RT_TRUE; 67 | } 68 | 69 | _callback = _callback->next; 70 | } 71 | while (_callback != NULL); 72 | 73 | return RT_FALSE; 74 | } 75 | 76 | struct js_callback *js_add_callback(js_callback_func callback) 77 | { 78 | struct js_callback *cb = (struct js_callback *)rt_calloc(1, sizeof(struct js_callback)); 79 | if (!cb) 80 | { 81 | return NULL; 82 | } 83 | 84 | cb->function = callback; 85 | cb->next = NULL; 86 | 87 | append_callback(cb); 88 | 89 | return cb; 90 | } 91 | 92 | void js_remove_callback(struct js_callback *callback) 93 | { 94 | remove_callback(callback); 95 | } 96 | 97 | void js_remove_all_callbacks(void) 98 | { 99 | struct js_callback *_callback_free; 100 | 101 | while (_js_callback != NULL) 102 | { 103 | _callback_free = _js_callback; 104 | _js_callback = _js_callback->next; 105 | rt_free(_callback_free); 106 | } 107 | 108 | _js_callback = NULL; 109 | } 110 | 111 | void js_call_callback(struct js_callback *callback, const void *data, uint32_t size) 112 | { 113 | if (has_callback(callback)) 114 | { 115 | if (callback->function) 116 | { 117 | callback->function(data, size); 118 | } 119 | } 120 | } 121 | 122 | rt_bool_t js_send_callback(struct js_callback *callback, const void *args, uint32_t size) 123 | { 124 | rt_bool_t ret = RT_FALSE; 125 | struct js_mq_callback *jmc = NULL; 126 | 127 | jmc = (struct js_mq_callback *)rt_calloc(1, sizeof(struct js_mq_callback)); 128 | if (jmc) 129 | { 130 | jmc->callback = callback; 131 | jmc->args = rt_malloc(size); 132 | if (jmc->args && args) 133 | { 134 | memcpy(jmc->args, args, size); 135 | } 136 | jmc->size = size; 137 | 138 | if (_js_mq_func) 139 | { 140 | ret = _js_mq_func(jmc); 141 | } 142 | 143 | if (ret == RT_FALSE) 144 | { 145 | rt_free(jmc->args); 146 | rt_free(jmc); 147 | } 148 | } 149 | 150 | return ret; 151 | } 152 | 153 | void js_mq_func_init(js_mq_func signal) 154 | { 155 | _js_mq_func = signal; 156 | } 157 | 158 | void js_mq_func_deinit(void) 159 | { 160 | _js_mq_func = NULL; 161 | js_remove_all_callbacks(); 162 | } 163 | -------------------------------------------------------------------------------- /rtthread-port/jerry_callbacks.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef JERRY_CALLBACKS_H__ 4 | #define JERRY_CALLBACKS_H__ 5 | 6 | #include 7 | #include 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | typedef void(*js_callback_func)(const void *args, uint32_t size); 14 | typedef rt_bool_t(*js_mq_func)(void *args); 15 | 16 | struct js_callback 17 | { 18 | js_callback_func function; 19 | struct js_callback *next; 20 | }; 21 | 22 | struct js_mq_callback 23 | { 24 | struct js_callback *callback; 25 | void *args; 26 | uint32_t size; 27 | }; 28 | 29 | struct js_callback *js_add_callback(js_callback_func callback); 30 | void js_remove_callback(struct js_callback *callback); 31 | void js_remove_all_callbacks(void); 32 | void js_call_callback(struct js_callback *callback, const void *data, uint32_t size); 33 | rt_bool_t js_send_callback(struct js_callback *callback, const void *args, uint32_t size); 34 | void js_mq_func_init(js_mq_func signal); 35 | void js_mq_func_deinit(void); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /rtthread-port/jerry_console.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "jerry_util.h" 8 | 9 | DECLARE_HANDLER(dir) 10 | { 11 | int index; 12 | for (index = 0; index < args_cnt; index ++) 13 | { 14 | js_value_dump(args[index]); 15 | printf("\n"); 16 | } 17 | 18 | return jerry_create_undefined(); 19 | } 20 | 21 | int js_console_init(void) 22 | { 23 | jerry_value_t console = jerry_create_object(); 24 | jerry_value_t global_obj = jerry_get_global_object(); 25 | 26 | REGISTER_METHOD_ALIAS(console, log, jerryx_handler_print); 27 | REGISTER_METHOD_ALIAS(console, dir, dir_handler); 28 | 29 | js_set_property(global_obj, "console", console); 30 | 31 | jerry_release_value(global_obj); 32 | jerry_release_value(console); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /rtthread-port/jerry_event.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | 5 | static jerry_value_t emitter = 0; 6 | static jerry_value_t _js_emitter_prototype = 0; 7 | 8 | struct js_listener 9 | { 10 | jerry_value_t func; 11 | struct js_listener *next; 12 | }; 13 | 14 | struct js_event 15 | { 16 | char *name; 17 | struct js_listener *listeners; 18 | struct js_event *next; 19 | }; 20 | 21 | struct js_emitter 22 | { 23 | struct js_event *events; 24 | }; 25 | 26 | static void remove_event(struct js_emitter *emitter, struct js_event *event); 27 | 28 | static void free_listener(void *ptr) 29 | { 30 | if (ptr) 31 | { 32 | struct js_listener *listener = (struct js_listener *)ptr; 33 | jerry_release_value(listener->func); 34 | rt_free(listener); 35 | } 36 | } 37 | 38 | static void js_emitter_free_cb(void *native) 39 | { 40 | struct js_emitter *emitter = (struct js_emitter *)native; 41 | struct js_event *_event, *event = emitter->events; 42 | 43 | while (event) 44 | { 45 | _event = event; 46 | event = event->next; 47 | 48 | remove_event(emitter, _event); 49 | } 50 | 51 | rt_free(emitter); 52 | } 53 | 54 | static const jerry_object_native_info_t emitter_type_info = 55 | { 56 | .free_cb = js_emitter_free_cb 57 | }; 58 | 59 | static void js_event_proto_free_cb(void *native) 60 | { 61 | _js_emitter_prototype = 0; 62 | } 63 | 64 | static const jerry_object_native_info_t event_proto_type_info = 65 | { 66 | .free_cb = js_event_proto_free_cb 67 | }; 68 | 69 | static struct js_listener *find_listener(struct js_event *event, jerry_value_t func) 70 | { 71 | struct js_listener *_listener = event->listeners; 72 | 73 | while (_listener != NULL) 74 | { 75 | if (_listener->func == func) 76 | { 77 | break; 78 | } 79 | 80 | _listener = _listener->next; 81 | } 82 | 83 | return _listener; 84 | } 85 | 86 | static void append_listener(struct js_event *event, struct js_listener *listener) 87 | { 88 | struct js_listener *_listener = event->listeners; 89 | 90 | if (event->listeners == NULL) 91 | { 92 | event->listeners = listener; 93 | return; 94 | } 95 | 96 | while (_listener->next != NULL) 97 | { 98 | _listener = _listener->next; 99 | } 100 | 101 | _listener->next = listener; 102 | } 103 | 104 | static void remove_listener(struct js_event *event, struct js_listener *listener) 105 | { 106 | struct js_listener *_listener = event->listeners; 107 | 108 | if (event->listeners == listener || event->listeners == NULL) 109 | { 110 | event->listeners = NULL; 111 | return; 112 | } 113 | 114 | while (_listener->next != listener) 115 | { 116 | _listener = _listener->next; 117 | } 118 | 119 | _listener->next = listener->next; 120 | } 121 | 122 | static struct js_event *find_event(struct js_emitter *emitter, const char *event_name) 123 | { 124 | struct js_event *event = emitter->events; 125 | 126 | while (event != NULL) 127 | { 128 | if (strcmp(event->name, event_name) == 0) 129 | { 130 | break; 131 | } 132 | 133 | event = event->next; 134 | } 135 | 136 | return event; 137 | } 138 | 139 | static void append_event(struct js_emitter *emitter, struct js_event *event) 140 | { 141 | struct js_event *_event = emitter->events; 142 | 143 | if (emitter->events == NULL) 144 | { 145 | emitter->events = event; 146 | return; 147 | } 148 | 149 | while (_event->next != NULL) 150 | { 151 | _event = _event->next; 152 | } 153 | 154 | _event->next = event; 155 | } 156 | 157 | static void remove_event(struct js_emitter *emitter, struct js_event *event) 158 | { 159 | struct js_event *_event = emitter->events; 160 | struct js_listener *_listener, *listener = event->listeners; 161 | 162 | if (emitter->events == event) 163 | { 164 | emitter->events = event->next; 165 | } 166 | else 167 | { 168 | while (_event->next != event) 169 | { 170 | _event = _event->next; 171 | } 172 | 173 | _event->next = event->next; 174 | } 175 | 176 | while (listener != NULL) 177 | { 178 | _listener = listener; 179 | listener = listener->next; 180 | free_listener(_listener); 181 | } 182 | 183 | rt_free(event->name); 184 | rt_free(event); 185 | } 186 | 187 | void js_add_event_listener(jerry_value_t obj, const char *event_name, jerry_value_t func) 188 | { 189 | void *native_handle = NULL; 190 | 191 | jerry_get_object_native_pointer(obj, &native_handle, NULL); 192 | if (native_handle) 193 | { 194 | struct js_emitter *emitter = (struct js_emitter *)native_handle; 195 | struct js_event *event = NULL; 196 | struct js_listener *listener = NULL; 197 | 198 | event = find_event(emitter, event_name); 199 | if (!event) 200 | { 201 | event = (struct js_event *)rt_malloc(sizeof(struct js_event)); 202 | if (!event) 203 | { 204 | return; 205 | } 206 | 207 | event->next = NULL; 208 | event->listeners = NULL; 209 | event->name = rt_strdup(event_name); 210 | append_event((struct js_emitter *)native_handle, event); 211 | } 212 | 213 | listener = (struct js_listener *)rt_malloc(sizeof(struct js_listener)); 214 | if (!listener) 215 | { 216 | return; 217 | } 218 | 219 | listener->func = jerry_acquire_value(func); 220 | listener->next = NULL; 221 | 222 | append_listener(event, listener); 223 | } 224 | } 225 | 226 | void js_remove_event_listener(jerry_value_t obj, const char *event_name) 227 | { 228 | void *native_handle = NULL; 229 | 230 | jerry_get_object_native_pointer(obj, &native_handle, NULL); 231 | if (native_handle) 232 | { 233 | struct js_emitter *emitter = (struct js_emitter *)native_handle; 234 | struct js_event *event = find_event(emitter, event_name); 235 | if (event) 236 | { 237 | struct js_listener *_listener, *listener = event->listeners; 238 | 239 | while (listener != NULL) 240 | { 241 | _listener = listener; 242 | listener = listener->next; 243 | free_listener(_listener); 244 | } 245 | 246 | event->listeners = NULL; 247 | } 248 | } 249 | } 250 | 251 | rt_bool_t js_emit_event(jerry_value_t obj, const char *event_name, const jerry_value_t argv[], const jerry_length_t argc) 252 | { 253 | void *native_handle = NULL; 254 | 255 | jerry_get_object_native_pointer(obj, &native_handle, NULL); 256 | if (native_handle) 257 | { 258 | struct js_emitter *emitter = (struct js_emitter *)native_handle; 259 | struct js_event *event = find_event(emitter, event_name); 260 | if (event) 261 | { 262 | struct js_listener *listener = event->listeners; 263 | 264 | while (listener) 265 | { 266 | jerry_value_t ret = jerry_call_function(listener->func, obj, argv, argc); 267 | if (jerry_value_is_error(ret)) 268 | { 269 | js_value_dump(obj); 270 | rt_kprintf("event [%s] calling listener error!\n", event_name); 271 | } 272 | jerry_release_value(ret); 273 | listener = listener->next; 274 | } 275 | 276 | return RT_TRUE; 277 | } 278 | } 279 | 280 | return RT_FALSE; 281 | } 282 | 283 | DECLARE_HANDLER(add_listener) 284 | { 285 | if (args_cnt == 2) 286 | { 287 | char *name = js_value_to_string(args[0]); 288 | if (name) 289 | { 290 | js_add_event_listener(this_value, name, args[1]); 291 | } 292 | 293 | rt_free(name); 294 | } 295 | 296 | return jerry_acquire_value(this_value); 297 | } 298 | 299 | DECLARE_HANDLER(remove_listener) 300 | { 301 | if (args_cnt == 2) 302 | { 303 | char *name = js_value_to_string(args[0]); 304 | if (name) 305 | { 306 | void *native_handle = NULL; 307 | 308 | jerry_get_object_native_pointer(this_value, &native_handle, NULL); 309 | if (native_handle) 310 | { 311 | struct js_emitter *emitter = (struct js_emitter *)native_handle; 312 | struct js_event *event = find_event(emitter, name); 313 | if (event) 314 | { 315 | struct js_listener *listener = find_listener(event, args[1]); 316 | if (listener) 317 | { 318 | remove_listener(event, listener); 319 | free_listener(listener); 320 | } 321 | } 322 | } 323 | } 324 | rt_free(name); 325 | } 326 | 327 | return jerry_acquire_value(this_value); 328 | } 329 | 330 | DECLARE_HANDLER(remove_all_listeners) 331 | { 332 | if (args_cnt == 1) 333 | { 334 | char *name = js_value_to_string(args[0]); 335 | if (name) 336 | { 337 | js_remove_event_listener(this_value, name); 338 | } 339 | rt_free(name); 340 | } 341 | 342 | return jerry_acquire_value(this_value); 343 | } 344 | 345 | DECLARE_HANDLER(remove_event) 346 | { 347 | if (args_cnt == 1) 348 | { 349 | char *name = js_value_to_string(args[0]); 350 | if (name) 351 | { 352 | void *native_handle = NULL; 353 | 354 | jerry_get_object_native_pointer(this_value, &native_handle, NULL); 355 | if (native_handle) 356 | { 357 | struct js_emitter *emitter = (struct js_emitter *)native_handle; 358 | struct js_event *event = find_event(emitter, name); 359 | if (event) 360 | { 361 | remove_event(emitter, event); 362 | } 363 | } 364 | } 365 | 366 | rt_free(name); 367 | } 368 | 369 | return jerry_acquire_value(this_value); 370 | } 371 | 372 | DECLARE_HANDLER(emit_event) 373 | { 374 | rt_bool_t ret = RT_FALSE; 375 | 376 | if (args_cnt >= 1) 377 | { 378 | char *name = js_value_to_string(args[0]); 379 | if (name) 380 | { 381 | ret = js_emit_event(this_value, name, args + 1, args_cnt - 1); 382 | } 383 | 384 | rt_free(name); 385 | } 386 | 387 | return jerry_create_boolean(ret); 388 | } 389 | 390 | DECLARE_HANDLER(get_event_names) 391 | { 392 | void *native_handle = NULL; 393 | 394 | jerry_get_object_native_pointer(this_value, &native_handle, NULL); 395 | if (native_handle) 396 | { 397 | struct js_emitter *emitter = (struct js_emitter *)native_handle; 398 | struct js_event *event = emitter->events; 399 | uint32_t index = 0; 400 | jerry_value_t ret = 0; 401 | 402 | while (event) 403 | { 404 | index ++; 405 | event = event->next; 406 | } 407 | 408 | ret = jerry_create_array(index); 409 | if (ret) 410 | { 411 | event = emitter->events; 412 | index = 0; 413 | while (event) 414 | { 415 | jerry_set_property_by_index(ret, index++, jerry_create_string((jerry_char_t *)event->name)); 416 | event = event->next; 417 | } 418 | 419 | return ret; 420 | } 421 | } 422 | 423 | return jerry_create_undefined(); 424 | } 425 | 426 | void js_destroy_emitter(jerry_value_t obj) 427 | { 428 | void *native_handle = NULL; 429 | 430 | jerry_get_object_native_pointer(obj, &native_handle, NULL); 431 | if (native_handle) 432 | { 433 | struct js_emitter *emitter = (struct js_emitter *)native_handle; 434 | struct js_event *_event, *event = emitter->events; 435 | 436 | while (event) 437 | { 438 | _event = event; 439 | event = event->next; 440 | 441 | remove_event(emitter, _event); 442 | } 443 | 444 | emitter->events = NULL; 445 | } 446 | } 447 | 448 | DECLARE_HANDLER(destroy) 449 | { 450 | js_destroy_emitter(this_value); 451 | 452 | return jerry_create_undefined(); 453 | } 454 | 455 | static void js_event_init_prototype(void) 456 | { 457 | if (_js_emitter_prototype == 0) 458 | { 459 | _js_emitter_prototype = jerry_create_object(); 460 | 461 | REGISTER_METHOD_NAME(_js_emitter_prototype, "on", add_listener); 462 | REGISTER_METHOD_NAME(_js_emitter_prototype, "addListener", add_listener); 463 | REGISTER_METHOD_NAME(_js_emitter_prototype, "emit", emit_event); 464 | REGISTER_METHOD_NAME(_js_emitter_prototype, "removeListener", remove_listener); 465 | REGISTER_METHOD_NAME(_js_emitter_prototype, "removeEvent", remove_event); 466 | REGISTER_METHOD_NAME(_js_emitter_prototype, "removeAllListeners", remove_all_listeners); 467 | REGISTER_METHOD_NAME(_js_emitter_prototype, "eventNames", get_event_names); 468 | REGISTER_METHOD(_js_emitter_prototype, destroy); 469 | 470 | jerry_set_object_native_pointer(_js_emitter_prototype, NULL, &event_proto_type_info); 471 | } 472 | } 473 | 474 | void js_make_emitter(jerry_value_t obj, jerry_value_t prototype) 475 | { 476 | jerry_value_t proto; 477 | struct js_emitter *emitter = NULL; 478 | 479 | js_event_init_prototype(); 480 | proto = _js_emitter_prototype; 481 | if (jerry_value_is_object(prototype)) 482 | { 483 | jerry_set_prototype(prototype, proto); 484 | proto = prototype; 485 | } 486 | jerry_set_prototype(obj, proto); 487 | 488 | emitter = rt_malloc(sizeof(struct js_emitter)); 489 | if (emitter) 490 | { 491 | emitter->events = NULL; 492 | jerry_set_object_native_pointer(obj, emitter, &emitter_type_info); 493 | } 494 | } 495 | 496 | DECLARE_HANDLER(Event) 497 | { 498 | if (emitter != 0) 499 | return jerry_acquire_value(emitter); 500 | 501 | emitter = jerry_create_object(); 502 | js_make_emitter(emitter, jerry_create_undefined()); 503 | return jerry_acquire_value(emitter); 504 | } 505 | 506 | int js_event_init(void) 507 | { 508 | REGISTER_HANDLER(Event); 509 | return 0; 510 | } 511 | 512 | int js_event_deinit(void) 513 | { 514 | if (emitter != 0) 515 | { 516 | js_destroy_emitter(emitter); 517 | jerry_release_value(emitter); 518 | emitter = 0; 519 | } 520 | 521 | if (_js_emitter_prototype != 0) 522 | jerry_release_value(_js_emitter_prototype); 523 | 524 | return 0; 525 | } 526 | -------------------------------------------------------------------------------- /rtthread-port/jerry_event.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JERRY_EVENT_H__ 3 | #define JERRY_EVENT_H__ 4 | 5 | #include 6 | #include 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | void js_add_event_listener(jerry_value_t obj, const char *event_name, jerry_value_t func); 13 | void js_remove_event_listener(jerry_value_t obj, const char *event_name); 14 | rt_bool_t js_emit_event(jerry_value_t obj, const char *event_name, const jerry_value_t argv[], const jerry_length_t argc); 15 | void js_destroy_emitter(jerry_value_t obj); 16 | void js_make_emitter(jerry_value_t obj, jerry_value_t prototype); 17 | int js_event_init(void); 18 | int js_event_deinit(void); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /rtthread-port/jerry_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define malloc rt_malloc 13 | #define free rt_free 14 | 15 | extern void jerry_port_set_default_context(jerry_context_t *context); 16 | 17 | static rt_mq_t _js_mq = NULL; 18 | 19 | #define JERRY_EXIT 1 20 | 21 | static void *context_alloc(size_t size, void *cb_data_p) 22 | { 23 | return rt_malloc_align(size, 32); 24 | } 25 | 26 | rt_bool_t js_mq_send(void *parameter) 27 | { 28 | rt_err_t ret = -RT_ERROR; 29 | 30 | if (_js_mq) 31 | { 32 | ret = rt_mq_send(_js_mq, (void *)¶meter, sizeof(void *)); 33 | } 34 | 35 | if (ret == RT_EOK) 36 | { 37 | return RT_TRUE; 38 | } 39 | else 40 | { 41 | return RT_FALSE; 42 | } 43 | } 44 | 45 | static void _jerry_exit(void) 46 | { 47 | void *exit = (void *)JERRY_EXIT; 48 | 49 | js_mq_send(exit); 50 | } 51 | MSH_CMD_EXPORT_ALIAS(_jerry_exit, jerry_exit, jerryScript Demo exit); 52 | 53 | jerry_value_t 54 | jerry_exit(const jerry_value_t func_obj_val, /**< function object */ 55 | const jerry_value_t this_p, /**< this arg */ 56 | const jerry_value_t args_p[], /**< function arguments */ 57 | const jerry_length_t args_cnt) /**< number of function arguments */ 58 | { 59 | _jerry_exit(); 60 | 61 | return jerry_create_undefined(); 62 | } 63 | 64 | static void jerry_thread_entry(void* parameter) 65 | { 66 | char *script; 67 | size_t length; 68 | 69 | if (parameter == NULL) 70 | { 71 | printf("jerry_thread_entry (parameter == NULL)\n"); 72 | return; 73 | } 74 | 75 | length = js_read_file((const char*)parameter, &script); 76 | printf("jerry read file : %s\n", (const char*)parameter); 77 | if (length > 0) 78 | { 79 | /* JERRY_ENABLE_EXTERNAL_CONTEXT */ 80 | jerry_port_set_default_context(jerry_create_context(PKG_JMEM_HEAP_SIZE * 1024, context_alloc, NULL)); 81 | 82 | /* Initialize engine */ 83 | jerry_init(JERRY_INIT_EMPTY); 84 | 85 | /* Register 'print' function from the extensions */ 86 | jerryx_handler_register_global((const jerry_char_t *)"print", jerryx_handler_print); 87 | jerryx_handler_register_global((const jerry_char_t *)"exit", jerry_exit); 88 | 89 | js_util_init(); 90 | 91 | /* add __filename, __dirname */ 92 | jerry_value_t global_obj = jerry_get_global_object(); 93 | char *full_path = NULL; 94 | char *full_dir = NULL; 95 | 96 | full_path = js_module_normalize_path(NULL, (const char*)parameter); 97 | full_dir = js_module_dirname(full_path); 98 | 99 | js_set_string_property(global_obj, "__dirname", full_dir); 100 | js_set_string_property(global_obj, "__filename", full_path); 101 | jerry_release_value(global_obj); 102 | 103 | /* Setup Global scope code */ 104 | jerry_value_t parsed_code = jerry_parse(NULL, 0, (jerry_char_t*)script, length, JERRY_PARSE_NO_OPTS); 105 | if (jerry_value_is_error(parsed_code)) 106 | { 107 | printf("jerry parse failed!\n"); 108 | } 109 | else 110 | { 111 | _js_mq = rt_mq_create("js_mq", sizeof(void *), 128, RT_IPC_FLAG_FIFO); 112 | if (_js_mq) 113 | { 114 | js_mq_func_init(js_mq_send); 115 | 116 | /* Execute the parsed source code in the Global scope */ 117 | jerry_value_t ret = jerry_run(parsed_code); 118 | if (jerry_value_is_error(ret)) 119 | { 120 | printf("jerry run err!!!\n"); 121 | } 122 | else 123 | { 124 | while (1) 125 | { 126 | void *buffer = 0; 127 | 128 | if (rt_mq_recv(_js_mq, &buffer, sizeof(void *), RT_WAITING_FOREVER) == RT_EOK) 129 | { 130 | if ((int)(buffer) == JERRY_EXIT) 131 | { 132 | printf("jerry exit!!!\n"); 133 | break; 134 | } 135 | else if (buffer) 136 | { 137 | struct js_mq_callback *jmc = (struct js_mq_callback *)buffer; 138 | js_call_callback(jmc->callback, jmc->args, jmc->size); 139 | } 140 | } 141 | rt_thread_delay(rt_tick_from_millisecond(10)); 142 | } 143 | } 144 | 145 | rt_mq_delete(_js_mq); 146 | js_mq_func_deinit(); 147 | /* Returned value must be freed */ 148 | jerry_release_value(ret); 149 | } 150 | } 151 | 152 | /* Parsed source code must be freed */ 153 | jerry_release_value(parsed_code); 154 | 155 | rt_free(script); 156 | 157 | js_util_cleanup(); 158 | /* Cleanup engine */ 159 | jerry_cleanup(); 160 | 161 | rt_free_align((void *)jerry_port_get_current_context()); 162 | } 163 | } 164 | 165 | int jerry_main(int argc, char** argv) 166 | { 167 | rt_thread_t tid; 168 | 169 | if (argc != 2) return -1; 170 | 171 | tid = rt_thread_create("jerry", jerry_thread_entry, (void*)rt_strdup((const char*)argv[1]), 1024 * 32, 20, 10); 172 | if (tid) 173 | { 174 | rt_thread_startup(tid); 175 | } 176 | 177 | return 0; 178 | } 179 | MSH_CMD_EXPORT(jerry_main, jerryScript Demo); 180 | -------------------------------------------------------------------------------- /rtthread-port/jerry_message.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | 6 | static jerry_value_t js_message_obj = 0; 7 | static struct js_callback *js_message_cb = NULL; 8 | static js_message_send_func js_msg_send_func = NULL; 9 | 10 | struct js_message 11 | { 12 | char *name; 13 | rt_uint8_t *data; 14 | rt_uint32_t size; 15 | }; 16 | 17 | void js_message_send_func_init(js_message_send_func func) 18 | { 19 | js_msg_send_func = func; 20 | } 21 | 22 | rt_bool_t js_message_send(const char *name, rt_uint8_t *data, rt_uint32_t size) 23 | { 24 | rt_bool_t ret = RT_FALSE; 25 | 26 | if (js_message_cb) 27 | { 28 | struct js_message msg; 29 | 30 | msg.name = rt_strdup(name); 31 | msg.size = size; 32 | msg.data = rt_malloc(msg.size); 33 | if (msg.data) 34 | { 35 | rt_memcpy(msg.data, data, size); 36 | ret = js_send_callback(js_message_cb, &msg, sizeof(struct js_message)); 37 | } 38 | 39 | if (!ret) 40 | { 41 | rt_free(msg.data); 42 | rt_free(msg.name); 43 | } 44 | } 45 | 46 | return ret; 47 | } 48 | 49 | static void js_callback_message(const void *args, uint32_t size) 50 | { 51 | struct js_message *msg = (struct js_message *)args; 52 | if (msg) 53 | { 54 | js_buffer_t *buffer; 55 | jerry_value_t buf_obj = jerry_buffer_create(msg->size, &buffer); 56 | if (buffer) 57 | { 58 | rt_memcpy(buffer->buffer, msg->data, msg->size); 59 | js_emit_event(js_message_obj, msg->name, &buf_obj, 1); 60 | } 61 | /* release value */ 62 | jerry_release_value(buf_obj); 63 | rt_free(msg->name); 64 | rt_free(msg->data); 65 | rt_free(msg); 66 | } 67 | } 68 | 69 | static void js_message_info_free(void *native) 70 | { 71 | js_message_obj = 0; 72 | js_remove_callback(js_message_cb); 73 | js_message_cb = NULL; 74 | } 75 | 76 | static const jerry_object_native_info_t js_message_info = 77 | { 78 | .free_cb = js_message_info_free 79 | }; 80 | 81 | DECLARE_HANDLER(send) 82 | { 83 | bool result = false; 84 | 85 | if (js_msg_send_func && args_cnt == 2 && jerry_value_is_string(args[0])) 86 | { 87 | if (jerry_value_is_string(args[1])) 88 | { 89 | char *name = js_value_to_string(args[0]); 90 | if (name) 91 | { 92 | char *str = js_value_to_string(args[1]); 93 | js_msg_send_func(name, (rt_uint8_t *)str, rt_strlen(str)); 94 | result = true; 95 | rt_free(str); 96 | rt_free(name); 97 | } 98 | } 99 | else 100 | { 101 | js_buffer_t *buffer = jerry_buffer_find(args[1]); 102 | if (buffer) 103 | { 104 | char *name = js_value_to_string(args[0]); 105 | if (name) 106 | { 107 | js_msg_send_func(name, buffer->buffer, buffer->bufsize); 108 | result = true; 109 | rt_free(name); 110 | } 111 | } 112 | } 113 | } 114 | 115 | return jerry_create_boolean(result); 116 | } 117 | 118 | DECLARE_HANDLER(Message) 119 | { 120 | jerry_value_t info = 0; 121 | 122 | if (js_message_obj != 0) 123 | return jerry_create_undefined(); 124 | 125 | js_message_obj = jerry_create_object(); 126 | if (jerry_value_is_error(js_message_obj)) 127 | { 128 | jerry_release_value(js_message_obj); 129 | return jerry_create_undefined(); 130 | } 131 | 132 | info = jerry_create_object(); 133 | if (jerry_value_is_error(js_message_obj)) 134 | { 135 | jerry_release_value(js_message_obj); 136 | jerry_release_value(info); 137 | return jerry_create_undefined(); 138 | } 139 | 140 | js_make_emitter(js_message_obj, jerry_create_undefined()); 141 | 142 | REGISTER_METHOD(js_message_obj, send); 143 | 144 | jerry_set_object_native_pointer(info, NULL, &js_message_info); 145 | js_set_property(js_message_obj, "info", info); 146 | jerry_release_value(info); 147 | 148 | js_message_cb = js_add_callback(js_callback_message); 149 | if (js_message_cb) 150 | { 151 | return js_message_obj; 152 | } 153 | else 154 | { 155 | jerry_release_value(js_message_obj); 156 | return jerry_create_undefined(); 157 | } 158 | } 159 | 160 | int js_message_init(void) 161 | { 162 | REGISTER_HANDLER(Message); 163 | 164 | return 0; 165 | } 166 | 167 | #ifdef RT_USING_FINSH 168 | #include 169 | int js_msg_test(int argc, char** argv) 170 | { 171 | if (argc > 2) 172 | { 173 | js_message_send(argv[1], (rt_uint8_t *)argv[2], rt_strlen(argv[2])); 174 | } 175 | 176 | return 0; 177 | } 178 | MSH_CMD_EXPORT(js_msg_test, send msg to JS by test); 179 | #endif 180 | -------------------------------------------------------------------------------- /rtthread-port/jerry_message.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JERRY_MESSAGE_H__ 3 | #define JERRY_MESSAGE_H__ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | typedef void(*js_message_send_func)(const char *name, rt_uint8_t *data, rt_uint32_t size); 15 | 16 | void js_message_send_func_init(js_message_send_func func); 17 | rt_bool_t js_message_send(const char *name, rt_uint8_t *data, rt_uint32_t size); 18 | int js_message_init(void); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /rtthread-port/jerry_module.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "jerry_util.h" 9 | #include "jerry_module.h" 10 | 11 | #include 12 | #include 13 | 14 | #ifdef RT_USING_MODULE 15 | #include 16 | #endif 17 | 18 | #ifndef PATH_MAX 19 | #define PATH_MAX 256 20 | #endif 21 | 22 | char *getcwd(char *buf, size_t size); 23 | 24 | typedef jerry_value_t (*module_init_func_t)(void); 25 | 26 | #ifdef RT_USING_DFS 27 | char *js_module_dirname(char *path) 28 | { 29 | size_t i; 30 | char *s = NULL; 31 | 32 | if (!path || !*path) return NULL; 33 | 34 | s = rt_strdup(path); 35 | if (!s) return NULL; 36 | 37 | i = strlen(s)-1; 38 | for (; s[i]=='/'; i--) if (!i) 39 | { 40 | s[0] = '/'; 41 | goto __exit; 42 | } 43 | for (; s[i]!='/'; i--) if (!i) 44 | { 45 | s[0] = '.'; 46 | goto __exit; 47 | } 48 | for (; s[i]=='/'; i--) if (!i) 49 | { 50 | s[0] = '/'; 51 | goto __exit; 52 | } 53 | 54 | __exit: 55 | s[i+1] = 0; 56 | return s; 57 | } 58 | 59 | char *js_module_normalize_path(const char *directory, const char *filename) 60 | { 61 | char *fullpath; 62 | char *dst0, *dst, *src; 63 | char *cwd = NULL; 64 | 65 | /* check parameters */ 66 | if (filename == NULL) return NULL; 67 | 68 | if (directory == NULL && filename[0] != '/') 69 | { 70 | cwd = (char*) malloc (PATH_MAX); 71 | if (cwd == NULL) return NULL; 72 | 73 | /* get current working directory */ 74 | getcwd(cwd, PATH_MAX); 75 | directory = cwd; 76 | } 77 | 78 | if (filename[0] != '/') /* it's a absolute path, use it directly */ 79 | { 80 | fullpath = malloc(strlen(directory) + strlen(filename) + 2); 81 | 82 | if (fullpath == NULL) 83 | { 84 | free(cwd); 85 | return NULL; 86 | } 87 | 88 | /* join path and file name */ 89 | snprintf(fullpath, strlen(directory) + strlen(filename) + 2, 90 | "%s/%s", directory, filename); 91 | } 92 | else 93 | { 94 | fullpath = rt_strdup(filename); /* copy string */ 95 | 96 | if (fullpath == NULL) 97 | return NULL; 98 | } 99 | 100 | src = fullpath; 101 | dst = fullpath; 102 | 103 | dst0 = dst; 104 | while (1) 105 | { 106 | char c = *src; 107 | 108 | if (c == '.') 109 | { 110 | if (!src[1]) src ++; /* '.' and ends */ 111 | else if (src[1] == '/') 112 | { 113 | /* './' case */ 114 | src += 2; 115 | 116 | while ((*src == '/') && (*src != '\0')) 117 | src ++; 118 | continue; 119 | } 120 | else if (src[1] == '.') 121 | { 122 | if (!src[2]) 123 | { 124 | /* '..' and ends case */ 125 | src += 2; 126 | goto up_one; 127 | } 128 | else if (src[2] == '/') 129 | { 130 | /* '../' case */ 131 | src += 3; 132 | 133 | while ((*src == '/') && (*src != '\0')) 134 | src ++; 135 | goto up_one; 136 | } 137 | } 138 | } 139 | 140 | /* copy up the next '/' and erase all '/' */ 141 | while ((c = *src++) != '\0' && c != '/') 142 | *dst ++ = c; 143 | 144 | if (c == '/') 145 | { 146 | *dst ++ = '/'; 147 | while (c == '/') 148 | c = *src++; 149 | 150 | src --; 151 | } 152 | else if (!c) 153 | break; 154 | 155 | continue; 156 | 157 | up_one: 158 | dst --; 159 | if (dst < dst0) 160 | { 161 | free(cwd); 162 | free(fullpath); 163 | return NULL; 164 | } 165 | while (dst0 < dst && dst[-1] != '/') 166 | dst --; 167 | } 168 | 169 | *dst = '\0'; 170 | 171 | /* remove '/' in the end of path if exist */ 172 | dst --; 173 | if ((dst != fullpath) && (*dst == '/')) 174 | *dst = '\0'; 175 | 176 | /* final check fullpath is not empty, for the special path of lwext "/.." */ 177 | if ('\0' == fullpath[0]) 178 | { 179 | fullpath[0] = '/'; 180 | fullpath[1] = '\0'; 181 | } 182 | 183 | free(cwd); 184 | 185 | return fullpath; 186 | } 187 | 188 | /* load module from file system */ 189 | static bool load_module_from_filesystem(const jerry_value_t module_name, jerry_value_t *result) 190 | { 191 | bool ret = false; 192 | char *str = NULL; 193 | char *module = js_value_to_string(module_name); 194 | 195 | char *dirname = NULL; 196 | 197 | jerry_value_t dirname_value = ECMA_VALUE_UNDEFINED; 198 | jerry_value_t filename_value = ECMA_VALUE_UNDEFINED; 199 | jerry_value_t global_obj = ECMA_VALUE_UNDEFINED; 200 | 201 | char *full_path = NULL; 202 | char *full_dir = NULL; 203 | 204 | global_obj = jerry_get_global_object(); 205 | dirname_value = js_get_property(global_obj, "__dirname"); 206 | if (jerry_value_is_string(dirname_value)) 207 | { 208 | dirname = js_value_to_string(dirname_value); 209 | } 210 | else 211 | { 212 | dirname = NULL; 213 | } 214 | 215 | if (module[0] != '/') /* is a relative path */ 216 | { 217 | full_path = js_module_normalize_path(dirname, module); 218 | } 219 | else 220 | { 221 | full_path = js_module_normalize_path(NULL, module); 222 | } 223 | free(dirname); 224 | 225 | uint32_t len = js_read_file(full_path, &str); 226 | if (len == 0) goto __exit; 227 | 228 | filename_value = js_get_property(global_obj, "__filename"); 229 | 230 | /* set new __filename and __dirname */ 231 | full_dir = js_module_dirname(full_path); 232 | 233 | js_set_string_property(global_obj, "__dirname", full_dir); 234 | js_set_string_property(global_obj, "__filename", full_path); 235 | 236 | (*result) = jerry_eval((jerry_char_t *)str, len, false); 237 | if (jerry_value_is_error(*result)) 238 | printf("failed to evaluate JS\n"); 239 | else 240 | ret = true; 241 | 242 | /* restore __filename and __dirname */ 243 | js_set_property(global_obj, "__dirname", dirname_value); 244 | js_set_property(global_obj, "__filename", filename_value); 245 | 246 | __exit: 247 | if (full_dir) free(full_dir); 248 | if (full_path) free(full_path); 249 | 250 | jerry_release_value(global_obj); 251 | jerry_release_value(dirname_value); 252 | jerry_release_value(filename_value); 253 | 254 | free(module); 255 | free(str); 256 | 257 | return ret; 258 | } 259 | #endif 260 | 261 | /* load builtin module */ 262 | static bool load_module_from_builtin(const jerry_value_t module_name, 263 | jerry_value_t *result) 264 | { 265 | bool ret = false; 266 | module_init_func_t module_init; 267 | 268 | char *module = js_value_to_string(module_name); 269 | #ifdef HOST_BUILD 270 | { 271 | extern jerry_value_t js_module_rtthread_init(void); 272 | 273 | if (strcmp(module, "os") == 0) 274 | { 275 | module_init = js_module_rtthread_init; 276 | *result = module_init(); 277 | ret = true; 278 | } 279 | } 280 | #elif defined(RT_USING_FINSH) 281 | int len = strlen(module) + 7; 282 | char module_fullname[len]; 283 | 284 | snprintf(module_fullname, len, "__jsm_%s", module); 285 | module_fullname[len - 1] = '\0'; 286 | 287 | /* find syscall in shell symbol section */ 288 | struct finsh_syscall* syscall; 289 | 290 | for (syscall = _syscall_table_begin; syscall < _syscall_table_end; FINSH_NEXT_SYSCALL(syscall)) 291 | { 292 | if (strcmp(syscall->name, module_fullname) == 0) 293 | break; 294 | } 295 | if (syscall < _syscall_table_end) 296 | { 297 | module_init = (module_init_func_t)syscall->func; 298 | *result = module_init(); 299 | ret = true; 300 | } 301 | #endif 302 | 303 | free(module); 304 | 305 | return ret; 306 | } 307 | 308 | #ifdef RT_USING_DFS 309 | static jerryx_module_resolver_t load_filesystem_resolver = 310 | { 311 | NULL, 312 | load_module_from_filesystem 313 | }; 314 | #endif 315 | 316 | static jerryx_module_resolver_t load_builtin_resolver = 317 | { 318 | NULL, 319 | load_module_from_builtin 320 | }; 321 | 322 | static const jerryx_module_resolver_t *resolvers[] = 323 | { 324 | &load_builtin_resolver, 325 | #ifdef RT_USING_DFS 326 | &load_filesystem_resolver 327 | #endif 328 | }; 329 | 330 | #ifdef RT_USING_MODULE 331 | 332 | typedef jerry_value_t (*FFI_INIT)(void); 333 | 334 | static void js_module_info_free(void *native) 335 | { 336 | dlclose(native); 337 | } 338 | 339 | static const jerry_object_native_info_t js_module_info = 340 | { 341 | .free_cb = js_module_info_free 342 | }; 343 | 344 | #endif 345 | 346 | DECLARE_HANDLER(require) 347 | { 348 | jerry_value_t result; 349 | char *module = NULL; 350 | 351 | if (args_cnt == 0) 352 | { 353 | printf("No module name supplied\n"); 354 | return jerry_create_undefined(); 355 | } 356 | 357 | if (jerry_value_is_string(args[0]) == 0) 358 | { 359 | printf("No module name supplied as string\n"); 360 | return jerry_create_undefined(); 361 | } 362 | 363 | module = js_value_to_string(args[0]); 364 | /* Try each of the resolvers to see if we can find the requested module */ 365 | #ifdef RT_USING_MODULE 366 | if (strstr(module, ".so")) 367 | { 368 | void* handle; 369 | FFI_INIT ffi_init; 370 | jerry_value_t info; 371 | 372 | do 373 | { 374 | handle = dlopen(module, RTLD_LAZY); 375 | if(!handle) 376 | { 377 | printf("dlopen %s failed!\n", module); 378 | result = jerry_create_undefined(); 379 | break; 380 | } 381 | 382 | ffi_init = (FFI_INIT)dlsym(handle,"ffi_init"); 383 | if(!ffi_init) 384 | { 385 | printf("ffi_init not found!\n"); 386 | result = jerry_create_undefined(); 387 | dlclose(handle); 388 | break; 389 | } 390 | 391 | result = ffi_init(); 392 | info = jerry_create_object(); 393 | jerry_set_object_native_pointer(info, handle, &js_module_info); 394 | js_set_property(result, "info", info); 395 | jerry_release_value(info); 396 | } 397 | while(0); 398 | } 399 | else 400 | #endif 401 | { 402 | /* make new module.exports */ 403 | jerry_value_t global_obj = jerry_get_global_object(); 404 | jerry_value_t modules_obj = ECMA_VALUE_UNDEFINED; 405 | jerry_value_t exports_obj = ECMA_VALUE_UNDEFINED; 406 | 407 | modules_obj = js_get_property(global_obj, "module"); 408 | exports_obj = js_get_property(modules_obj, "exports"); 409 | 410 | jerry_value_t module_exports_obj = jerry_create_object(); 411 | js_set_property(modules_obj, "exports", module_exports_obj); 412 | jerry_release_value(module_exports_obj); 413 | 414 | result = jerryx_module_resolve(args[0], resolvers, sizeof(resolvers)/sizeof(resolvers[0])); 415 | if (jerry_value_is_error(result)) 416 | { 417 | printf("Couldn't load module %s\n", module); 418 | 419 | jerry_release_value(result); 420 | 421 | /* create result with error */ 422 | result = jerry_create_error(JERRY_ERROR_TYPE, 423 | (const jerry_char_t *) "Module not found"); 424 | } 425 | 426 | /* restore the parent module.exports */ 427 | js_set_property(modules_obj, "exports", exports_obj); 428 | 429 | jerry_release_value(global_obj); 430 | jerry_release_value(modules_obj); 431 | jerry_release_value(exports_obj); 432 | } 433 | 434 | free(module); 435 | 436 | return result; 437 | } 438 | 439 | int js_module_init(void) 440 | { 441 | jerry_value_t global_obj = jerry_get_global_object(); 442 | jerry_value_t modules_obj = jerry_create_object(); 443 | jerry_value_t exports_obj = jerry_create_object(); 444 | 445 | js_set_property(modules_obj, "exports", exports_obj); 446 | js_set_property(global_obj, "module", modules_obj); 447 | 448 | REGISTER_HANDLER(require); 449 | 450 | jerry_release_value(global_obj); 451 | jerry_release_value(modules_obj); 452 | jerry_release_value(exports_obj); 453 | 454 | return 0; 455 | } 456 | -------------------------------------------------------------------------------- /rtthread-port/jerry_module.h: -------------------------------------------------------------------------------- 1 | #ifndef JERRY_MODULE_H__ 2 | #define JERRY_MODULE_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | char *js_module_dirname(char *path); 10 | char *js_module_normalize_path(const char *directory, const char *filename); 11 | 12 | int js_module_init(void); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /rtthread-port/jerry_mqtt.c: -------------------------------------------------------------------------------- 1 | #include "jerry_mqtt.h" 2 | 3 | #ifdef PKG_USING_PAHOMQTT 4 | 5 | #include 6 | #define PIPE_BUFSZ 512 7 | static bool hasClient = false; 8 | 9 | extern int MQTT_CMD(MQTTClient *c, const char *cmd); 10 | 11 | void mqtt_event_callback(const void *args, uint32_t size) 12 | { 13 | mqtt_cbinfo_t *cb_info = (mqtt_cbinfo_t*)args; 14 | if (cb_info->return_value != RT_NULL) 15 | { 16 | js_emit_event(cb_info->this_value, cb_info->event_name, cb_info->return_value, cb_info->return_count); 17 | } 18 | else 19 | { 20 | js_emit_event(cb_info->this_value, cb_info->event_name, RT_NULL, 0); 21 | } 22 | 23 | if (cb_info->return_value != RT_NULL) 24 | { 25 | for(int i = 0 ; i < cb_info->return_count ; i++) 26 | { 27 | jerry_release_value(cb_info->return_value[i]); 28 | } 29 | free(cb_info->return_value); 30 | } 31 | free(cb_info->event_name); 32 | free(cb_info); 33 | } 34 | 35 | void mqtt_free_callback(const void *args, uint32_t size) 36 | { 37 | 38 | } 39 | 40 | void mqtt_func_callback(const void *args, uint32_t size) 41 | { 42 | mqtt_cbinfo_t *cb_info = (mqtt_cbinfo_t *)args; 43 | jerry_value_t ret = jerry_call_function(cb_info->js_func, cb_info->this_value, RT_NULL, 0); 44 | jerry_release_value(ret); 45 | free(cb_info); 46 | } 47 | 48 | void mqtt_sub_callback(MQTTClient *c, MessageData *msg_data) 49 | { 50 | mqtt_info_t* mqtt_info = (mqtt_info_t *)(c->user_data); 51 | struct js_callback* event_callback = mqtt_info->event_callback; 52 | 53 | char* topicName = (char*)malloc((msg_data->topicName->lenstring.len+1)*sizeof(char)); 54 | memset(topicName, 0, msg_data->topicName->lenstring.len+1); 55 | memcpy(topicName,msg_data->topicName->lenstring.data,msg_data->topicName->lenstring.len); 56 | 57 | js_buffer_t *js_buffer; 58 | jerry_value_t js_payload = jerry_buffer_create(msg_data->message->payloadlen, &js_buffer); 59 | if (js_buffer) 60 | { 61 | rt_memcpy(js_buffer->buffer, msg_data->message->payload, msg_data->message->payloadlen); 62 | } 63 | 64 | /*emit message event*/ 65 | mqtt_cbinfo_t* cb_info = (mqtt_cbinfo_t*)malloc(sizeof(mqtt_cbinfo_t)); 66 | memset(cb_info, 0, sizeof(mqtt_cbinfo_t)); 67 | 68 | cb_info->this_value = mqtt_info->this_value; 69 | cb_info->return_value = (jerry_value_t *)malloc(sizeof(jerry_value_t)*2); 70 | cb_info->return_value[0] = jerry_create_string((const jerry_char_t*)(topicName)); 71 | cb_info->return_value[1] = js_payload; 72 | cb_info->return_count = 2; 73 | cb_info->js_func = RT_NULL; 74 | cb_info->event_name = rt_strdup("message"); 75 | 76 | js_send_callback(event_callback,cb_info,sizeof(mqtt_cbinfo_t)); 77 | free(cb_info); 78 | 79 | /*emit topic's publish callback*/ 80 | for(int i =0 ; i < MAX_MESSAGE_HANDLERS ; i++) 81 | { 82 | if(strcmp(mqtt_info->callbackHandler[i].topic,topicName) == 0) 83 | { 84 | mqtt_cbinfo_t* cb_info = (mqtt_cbinfo_t*)malloc(sizeof(mqtt_cbinfo_t)); 85 | memset(cb_info, 0, sizeof(mqtt_cbinfo_t)); 86 | 87 | cb_info->this_value = mqtt_info->this_value; 88 | cb_info->return_value = RT_NULL; 89 | cb_info->return_count = 0; 90 | cb_info->js_func = mqtt_info->callbackHandler[i].js_func; 91 | 92 | js_send_callback(mqtt_info->fun_callback, cb_info, sizeof(mqtt_cbinfo_t)); 93 | free(cb_info); 94 | break; 95 | } 96 | } 97 | free(topicName); 98 | 99 | return; 100 | } 101 | 102 | void mqtt_connect_callback(MQTTClient *c) 103 | { 104 | LOG_D("inter mqtt_connect_callback!"); 105 | //to do 106 | } 107 | 108 | void mqtt_online_callback(MQTTClient *c) 109 | { 110 | LOG_D("inter mqtt_online_callback!"); 111 | 112 | mqtt_info_t* mqtt_info = (mqtt_info_t *)(c->user_data); 113 | struct js_callback* event_callback = mqtt_info->event_callback; 114 | 115 | mqtt_cbinfo_t* cb_info = (mqtt_cbinfo_t*)malloc(sizeof(mqtt_cbinfo_t)); 116 | memset(cb_info, 0, sizeof(mqtt_cbinfo_t)); 117 | cb_info->this_value = mqtt_info->this_value; 118 | cb_info->return_value = RT_NULL; 119 | cb_info->js_func = RT_NULL; 120 | cb_info->event_name = rt_strdup("connect"); 121 | 122 | js_send_callback(event_callback,cb_info,sizeof(mqtt_cbinfo_t)); 123 | free(cb_info); 124 | } 125 | 126 | void mqtt_offline_callback(MQTTClient *c) 127 | { 128 | LOG_D("inter mqtt_offline_callback!"); 129 | 130 | mqtt_info_t* mqtt_info = (mqtt_info_t *)(c->user_data); 131 | struct js_callback* event_callback = mqtt_info->event_callback; 132 | 133 | mqtt_cbinfo_t* cb_info = (mqtt_cbinfo_t*)malloc(sizeof(mqtt_cbinfo_t)); 134 | memset(cb_info, 0, sizeof(mqtt_cbinfo_t)); 135 | cb_info->this_value = mqtt_info->this_value; 136 | cb_info->return_value = RT_NULL; 137 | cb_info->event_name = rt_strdup("offline"); 138 | 139 | js_send_callback(event_callback, cb_info, sizeof(mqtt_cbinfo_t)); 140 | free(cb_info); 141 | } 142 | 143 | void mqtt_client_free_callback(void *native_p) 144 | { 145 | mqtt_info_t* mqtt_info = (mqtt_info_t*)native_p; 146 | 147 | if(!mqtt_info) 148 | { 149 | return; 150 | } 151 | 152 | if(mqtt_info->client->isconnected == 1) 153 | { 154 | MQTT_CMD(mqtt_info->client, "DISCONNECT"); 155 | } 156 | 157 | if(mqtt_info->sem) 158 | { 159 | rt_sem_delete(mqtt_info->sem); 160 | mqtt_info->sem = RT_NULL; 161 | js_destroy_emitter(mqtt_info->this_value); 162 | } 163 | 164 | 165 | if(mqtt_info->close_callback) 166 | { 167 | js_remove_callback(mqtt_info->close_callback); 168 | } 169 | 170 | if(mqtt_info->event_callback) 171 | { 172 | js_remove_callback(mqtt_info->event_callback); 173 | } 174 | 175 | if(mqtt_info->fun_callback) 176 | { 177 | js_remove_callback(mqtt_info->fun_callback); 178 | } 179 | 180 | if(mqtt_info->client) 181 | { 182 | if(mqtt_info->client->uri) 183 | { 184 | free((void*)mqtt_info->client->uri); 185 | } 186 | if(mqtt_info->client->buf) 187 | { 188 | free(mqtt_info->client->buf); 189 | } 190 | if(mqtt_info->client->readbuf) 191 | { 192 | free(mqtt_info->client->readbuf); 193 | } 194 | for(int i =0 ; i < MAX_MESSAGE_HANDLERS ; i++) 195 | { 196 | if(mqtt_info->client->messageHandlers[i].topicFilter) 197 | { 198 | free(mqtt_info->client->messageHandlers[i].topicFilter); 199 | } 200 | } 201 | free(mqtt_info->client); 202 | } 203 | 204 | for(int i =0 ; i < MAX_MESSAGE_HANDLERS ; i++) 205 | { 206 | if(mqtt_info->callbackHandler[i].topic) 207 | { 208 | free(mqtt_info->callbackHandler[i].topic); 209 | mqtt_info->callbackHandler[i].topic = RT_NULL; 210 | mqtt_info->callbackHandler[i].js_func = RT_NULL; 211 | } 212 | } 213 | 214 | free(mqtt_info); 215 | 216 | hasClient = false; 217 | } 218 | 219 | const static jerry_object_native_info_t mqtt_client_info = 220 | { 221 | mqtt_client_free_callback 222 | }; 223 | 224 | void get_mqtt_info(void **info, jerry_value_t js_target) 225 | { 226 | jerry_value_t js_info = js_get_property(js_target, "info"); 227 | jerry_get_object_native_pointer(js_info, info, NULL); 228 | jerry_release_value(js_info); 229 | } 230 | 231 | DECLARE_HANDLER(connect) 232 | { 233 | mqtt_info_t *mqtt_info = RT_NULL; 234 | get_mqtt_info((void **)&mqtt_info, this_value); 235 | 236 | paho_mqtt_start(mqtt_info->client); 237 | 238 | return jerry_create_undefined(); 239 | } 240 | 241 | DECLARE_HANDLER(publish) 242 | { 243 | mqtt_info_t *mqtt_info = RT_NULL; 244 | get_mqtt_info((void **)&mqtt_info, this_value); 245 | 246 | char *topic; 247 | unsigned char* send_str = NULL; 248 | int length = 0; 249 | int qos = 1; 250 | bool dup = false; 251 | bool retain = false; 252 | jerry_value_t js_pub_callback = RT_NULL; 253 | 254 | switch(args_cnt) 255 | { 256 | case 4: 257 | if(jerry_value_is_function(args[3])) 258 | { 259 | js_pub_callback = args[3]; 260 | } 261 | else 262 | { 263 | LOG_E("the 4rd parameter is not function"); 264 | goto _exit; 265 | } 266 | case 3: 267 | if(jerry_value_is_function(args[2])) 268 | { 269 | js_pub_callback = args[2]; 270 | } 271 | else if(jerry_value_is_object(args[2])) 272 | { 273 | if(jerry_value_is_object(js_get_property(args[2],"qos"))) 274 | { 275 | qos = jerry_get_number_value(js_get_property(args[2],"qos")); 276 | 277 | if(qos < 0) 278 | { 279 | qos = 0; 280 | } 281 | else if(qos > 2) 282 | { 283 | qos = 2; 284 | } 285 | } 286 | 287 | if(jerry_value_is_boolean(js_get_property(args[2],"dup"))) 288 | { 289 | dup = jerry_value_to_boolean(js_get_property(args[2],"dup")); 290 | } 291 | 292 | if(jerry_value_is_boolean(js_get_property(args[2],"retain"))) 293 | { 294 | retain = jerry_value_to_boolean(js_get_property(args[2],"retain")); 295 | } 296 | } 297 | else 298 | { 299 | LOG_E("the 3nd parameter is not object or func"); 300 | goto _exit; 301 | } 302 | case 2: 303 | if(jerry_value_is_string(args[1])) 304 | { 305 | send_str = (unsigned char *)js_value_to_string(args[1]); 306 | length = strlen((const char *)send_str); 307 | } 308 | else if(jerry_value_is_object(args[1])) 309 | { 310 | js_buffer_t *js_buffer = jerry_buffer_find(args[1]); 311 | if(js_buffer) 312 | { 313 | send_str = js_buffer->buffer; 314 | length = js_buffer->bufsize; 315 | } 316 | } 317 | else 318 | { 319 | LOG_E("the 1st parameter is not string or buffer"); 320 | goto _exit; 321 | } 322 | case 1 : 323 | if(jerry_value_is_string(args[0])) 324 | { 325 | topic = js_value_to_string(args[0]); 326 | } 327 | else 328 | { 329 | LOG_E("the 1st parameter is not string"); 330 | goto _exit; 331 | } 332 | break; 333 | default: 334 | LOG_E("the count of parameters is wrong"); 335 | goto _exit; 336 | break; 337 | } 338 | rt_sem_take(mqtt_info->sem,RT_WAITING_FOREVER); 339 | MQTTMessage message; 340 | 341 | message.qos = qos; 342 | message.retained = retain; 343 | message.payload = (void *)send_str; 344 | message.payloadlen = length; 345 | 346 | MQTTPublish(mqtt_info->client, topic, &message); 347 | 348 | if(js_pub_callback != RT_NULL) 349 | { 350 | for(int i =0 ; i < MAX_MESSAGE_HANDLERS ; i++) 351 | { 352 | if(mqtt_info->callbackHandler[i].topic == RT_NULL) 353 | { 354 | mqtt_info->callbackHandler[i].topic = topic; 355 | mqtt_info->callbackHandler[i].js_func = js_pub_callback; 356 | break; 357 | } 358 | } 359 | } 360 | rt_sem_release(mqtt_info->sem); 361 | free(send_str); 362 | free(topic); 363 | _exit: 364 | return jerry_create_undefined(); 365 | } 366 | 367 | DECLARE_HANDLER(subscribe) 368 | { 369 | mqtt_info_t *mqtt_info = RT_NULL; 370 | get_mqtt_info((void **)&mqtt_info, this_value); 371 | 372 | if(mqtt_info->subCount == MAX_MESSAGE_HANDLERS) 373 | { 374 | LOG_E("the count of topics is max"); 375 | goto _exit; 376 | } 377 | 378 | int qos = 0; 379 | char* topic = RT_NULL; 380 | jerry_value_t js_sub_callback = 0; 381 | switch(args_cnt) 382 | { 383 | case 3: 384 | if(jerry_value_is_function(args[2])) 385 | { 386 | js_sub_callback = args[2]; 387 | } 388 | else 389 | { 390 | LOG_E("the 3rd parameter is not function"); 391 | goto _exit; 392 | } 393 | case 2: 394 | if(jerry_value_is_object(args[1]) && jerry_value_is_number(js_get_property(args[1],"qos"))) 395 | { 396 | qos = jerry_get_number_value(js_get_property(args[1],"qos")); 397 | 398 | if(qos < 0) 399 | { 400 | qos = 0; 401 | } 402 | else if(qos > 2) 403 | { 404 | qos = 2; 405 | } 406 | } 407 | else if(jerry_value_is_function(args[1])) 408 | { 409 | js_sub_callback = args[1]; 410 | } 411 | else 412 | { 413 | LOG_E("the 2nd parameter is not number or func"); 414 | goto _exit; 415 | } 416 | case 1 : 417 | if(jerry_value_is_string(args[0])) 418 | { 419 | topic = js_value_to_string(args[0]); 420 | } 421 | else 422 | { 423 | LOG_E("the 1st parameter is not string"); 424 | goto _exit; 425 | } 426 | break; 427 | default: 428 | LOG_E("the count of parameters is wrong"); 429 | goto _exit; 430 | break; 431 | } 432 | rt_sem_take(mqtt_info->sem, RT_WAITING_FOREVER); 433 | for(int i = 0 ; i < MAX_MESSAGE_HANDLERS ; i++) 434 | { 435 | if(rt_strcmp(topic,mqtt_info->client->messageHandlers[i].topicFilter) == 0) 436 | { 437 | free(topic); 438 | rt_sem_release(mqtt_info->sem); 439 | goto _exit; 440 | break; 441 | } 442 | } 443 | 444 | int index; 445 | for(index = 0; index < MAX_MESSAGE_HANDLERS ; index++) 446 | { 447 | if(mqtt_info->client->messageHandlers[index].topicFilter == RT_NULL) 448 | { 449 | mqtt_info->client->messageHandlers[index].topicFilter =topic; 450 | mqtt_info->client->messageHandlers[index].callback = mqtt_sub_callback; 451 | mqtt_info->client->messageHandlers[index].qos = qos; 452 | 453 | 454 | mqtt_info->subCount++; 455 | 456 | if(mqtt_info->client->isconnected == 1) 457 | { 458 | MQTT_CMD(mqtt_info->client,"RECONNECT"); 459 | } 460 | 461 | /*emit the callback*/ 462 | if(js_sub_callback) 463 | { 464 | mqtt_cbinfo_t* cb_info = (mqtt_cbinfo_t*)malloc(sizeof(mqtt_cbinfo_t)); 465 | memset(cb_info, 0, sizeof(mqtt_cbinfo_t)); 466 | cb_info->this_value = this_value; 467 | cb_info->return_value = RT_NULL; 468 | cb_info->js_func = js_sub_callback; 469 | cb_info->event_name = RT_NULL; 470 | 471 | js_send_callback(mqtt_info->fun_callback,cb_info,sizeof(mqtt_cbinfo_t)); 472 | free(cb_info); 473 | } 474 | break; 475 | } 476 | } 477 | rt_sem_release(mqtt_info->sem); 478 | 479 | 480 | _exit: 481 | return jerry_create_undefined(); 482 | } 483 | 484 | DECLARE_HANDLER(unsubscribe) 485 | { 486 | mqtt_info_t *mqtt_info = RT_NULL; 487 | get_mqtt_info((void **)&mqtt_info, this_value); 488 | 489 | jerry_value_t js_unsub_callback = RT_NULL; 490 | char* topic; 491 | switch(args_cnt) 492 | { 493 | case 2: 494 | if(jerry_value_is_function(args[1])) 495 | { 496 | js_unsub_callback = args[1]; 497 | } 498 | else 499 | { 500 | goto _exit; 501 | } 502 | case 1 : 503 | if(jerry_value_is_string(args[0])) 504 | { 505 | topic = js_value_to_string(args[0]); 506 | } 507 | else 508 | { 509 | goto _exit; 510 | } 511 | break; 512 | default: 513 | goto _exit; 514 | break; 515 | } 516 | rt_sem_take(mqtt_info->sem, RT_WAITING_FOREVER); 517 | for(int i = 0 ; i < MAX_MESSAGE_HANDLERS ; i++) 518 | { 519 | if(strcmp(topic,mqtt_info->client->messageHandlers[i].topicFilter) == 0) 520 | { 521 | /*free data*/ 522 | free(mqtt_info->client->messageHandlers[i].topicFilter); 523 | mqtt_info->client->messageHandlers[i].topicFilter = RT_NULL; 524 | 525 | /*restart mqtt*/ 526 | mqtt_info->subCount--; 527 | if(mqtt_info->client->isconnected == 1) 528 | { 529 | MQTT_CMD(mqtt_info->client,"RECONNECT"); 530 | } 531 | 532 | /*emit the callback*/ 533 | if(js_unsub_callback) 534 | { 535 | mqtt_cbinfo_t* cb_info = (mqtt_cbinfo_t*)malloc(sizeof(mqtt_cbinfo_t)); 536 | memset(cb_info, 0, sizeof(mqtt_cbinfo_t)); 537 | cb_info->this_value = this_value; 538 | cb_info->return_value = RT_NULL; 539 | cb_info->js_func = js_unsub_callback; 540 | cb_info->event_name = RT_NULL; 541 | 542 | js_send_callback(mqtt_info->fun_callback,cb_info,sizeof(mqtt_cbinfo_t)); 543 | free(cb_info); 544 | } 545 | 546 | for(int i =0 ; i < MAX_MESSAGE_HANDLERS ; i++) 547 | { 548 | if(strcmp(mqtt_info->callbackHandler[i].topic,topic) == 0) 549 | { 550 | free(mqtt_info->callbackHandler[i].topic); 551 | mqtt_info->callbackHandler[i].topic = RT_NULL; 552 | mqtt_info->callbackHandler[i].js_func = RT_NULL; 553 | } 554 | } 555 | break; 556 | } 557 | } 558 | free(topic); 559 | rt_sem_release(mqtt_info->sem); 560 | _exit: 561 | return jerry_create_undefined(); 562 | } 563 | 564 | DECLARE_HANDLER(end) 565 | { 566 | mqtt_info_t *mqtt_info = RT_NULL; 567 | get_mqtt_info((void **)&mqtt_info, this_value); 568 | 569 | jerry_value_t js_end_callback = RT_NULL; 570 | bool force; 571 | switch(args_cnt) 572 | { 573 | case 2: 574 | if(jerry_value_is_function(args[1])) 575 | { 576 | js_end_callback = args[1]; 577 | } 578 | else 579 | { 580 | goto _exit; 581 | } 582 | case 1 : 583 | if(jerry_value_is_boolean(args[0])) 584 | { 585 | force = jerry_value_to_boolean(args[0]); 586 | } 587 | else if(jerry_value_is_function(args[0])) 588 | { 589 | js_end_callback = args[0]; 590 | } 591 | else 592 | { 593 | goto _exit; 594 | } 595 | break; 596 | default: 597 | goto _exit; 598 | break; 599 | } 600 | 601 | // if(mqtt_info->client->isconnected == 1) 602 | { 603 | MQTT_CMD(mqtt_info->client,"DISCONNECT"); 604 | 605 | /*emit the callback*/ 606 | if(js_end_callback) 607 | { 608 | mqtt_cbinfo_t* cb_info = (mqtt_cbinfo_t*)malloc(sizeof(mqtt_cbinfo_t)); 609 | memset(cb_info, 0, sizeof(mqtt_cbinfo_t)); 610 | cb_info->this_value = this_value; 611 | cb_info->return_value = RT_NULL; 612 | cb_info->js_func = js_end_callback; 613 | cb_info->event_name = RT_NULL; 614 | 615 | js_send_callback(mqtt_info->fun_callback,cb_info,sizeof(mqtt_cbinfo_t)); 616 | free(cb_info); 617 | } 618 | } 619 | _exit: 620 | return jerry_create_undefined(); 621 | } 622 | 623 | DECLARE_HANDLER(reconnect) 624 | { 625 | mqtt_info_t *mqtt_info = RT_NULL; 626 | get_mqtt_info((void **)&mqtt_info, this_value); 627 | 628 | if(mqtt_info->client->isconnected == 1) 629 | { 630 | MQTT_CMD(mqtt_info->client,"RECONNECT"); 631 | } 632 | else 633 | { 634 | paho_mqtt_start(mqtt_info->client); 635 | } 636 | 637 | return jerry_create_undefined(); 638 | } 639 | 640 | static jerry_value_t mqtt_create_client(int arg_cnt,const jerry_value_t* args) 641 | { 642 | jerry_value_t js_client = jerry_create_object(); 643 | mqtt_info_t* client_info = RT_NULL; 644 | 645 | if(hasClient == true) 646 | { 647 | goto _exit; 648 | } 649 | 650 | client_info = (mqtt_info_t*)malloc(sizeof(mqtt_info_t)); 651 | memset(client_info, 0, sizeof(mqtt_info_t)); 652 | 653 | if(!client_info) 654 | { 655 | goto _exit; 656 | } 657 | 658 | client_info->client = (MQTTClient*)malloc(sizeof(MQTTClient)); 659 | if(!client_info->client) 660 | { 661 | goto _exit; 662 | } 663 | 664 | /*initialize MQTTClient* client */ 665 | client_info->client->isconnected = 0; 666 | client_info->client->uri = js_value_to_string(args[0]); 667 | client_info->client->toClose = 0; 668 | client_info->client->user_data = (void*)client_info; 669 | MQTTPacket_connectData condata = MQTTPacket_connectData_initializer; 670 | memcpy(&(client_info->client->condata), &condata, sizeof(condata)); 671 | 672 | static char cid[20] = { 0 }; 673 | rt_snprintf(cid, sizeof(cid), "rtthread%d", rt_tick_get()); 674 | client_info->client->condata.clientID.cstring = cid; 675 | client_info->client->condata.keepAliveInterval = 60; 676 | client_info->client->condata.cleansession = 1; 677 | client_info->client->reconnectPeriod = 1000; //1s 678 | client_info->client->connectTimeout = 30*1000; //30s 679 | client_info->client->condata.username.cstring = RT_NULL; 680 | client_info->client->condata.password.cstring = RT_NULL; 681 | 682 | for(int i = 0 ; i < MAX_MESSAGE_HANDLERS ; i++) 683 | { 684 | client_info->client->messageHandlers[i].callback = RT_NULL; 685 | client_info->client->messageHandlers[i].qos = QOS0; 686 | client_info->client->messageHandlers[i].topicFilter = RT_NULL; 687 | } 688 | /* config MQTT will param. */ 689 | client_info->client->condata.willFlag = 0; 690 | 691 | /*set the options of client*/ 692 | if(arg_cnt == 2) 693 | { 694 | jerry_value_t js_keepalive = js_get_property(args[1],"keepalive"); 695 | if(jerry_value_is_number(js_keepalive)) 696 | { 697 | client_info->client->condata.keepAliveInterval = jerry_get_number_value(js_keepalive); 698 | } 699 | jerry_release_value(js_keepalive); 700 | 701 | jerry_value_t js_clientId = js_get_property(args[1], "clientId"); 702 | if(jerry_value_is_string(js_clientId)) 703 | { 704 | char* cid = js_value_to_string(js_clientId); 705 | client_info->client->condata.clientID.cstring = cid; 706 | free(cid); 707 | } 708 | jerry_release_value(js_clientId); 709 | 710 | jerry_value_t js_clean = js_get_property(args[1],"clean"); 711 | if(jerry_value_is_boolean(js_clean)) 712 | { 713 | client_info->client->condata.cleansession = jerry_value_to_boolean(js_clean); 714 | } 715 | jerry_release_value(js_clean); 716 | 717 | jerry_value_t js_reconnectPeriod = js_get_property(args[1],"reconnectPeriod"); 718 | if(jerry_value_is_number(js_reconnectPeriod)) 719 | { 720 | client_info->client->reconnectPeriod = jerry_get_number_value(js_reconnectPeriod); 721 | } 722 | jerry_release_value(js_reconnectPeriod); 723 | 724 | jerry_value_t js_connectTimeout = js_get_property(args[1],"connectTimeout"); 725 | if(jerry_value_is_number(js_connectTimeout)) 726 | { 727 | client_info->client->connectTimeout = jerry_get_number_value(js_connectTimeout); 728 | } 729 | jerry_release_value(js_connectTimeout); 730 | 731 | jerry_value_t js_username = js_get_property(args[1], "username"); 732 | if(jerry_value_is_string(js_username)) 733 | { 734 | char* username = js_value_to_string(js_username); 735 | client_info->client->condata.username.cstring = username; 736 | free(username); 737 | } 738 | jerry_release_value(js_username); 739 | 740 | jerry_value_t js_password = js_get_property(args[1], "password"); 741 | if(jerry_value_is_string(js_password)) 742 | { 743 | char* password = js_value_to_string(js_password); 744 | client_info->client->condata.password.cstring = password; 745 | free(password); 746 | } 747 | jerry_release_value(js_password); 748 | 749 | jerry_value_t js_will = js_get_property(args[1],"will"); 750 | if(jerry_value_is_object(js_will)) 751 | { 752 | client_info->client->condata.willFlag = 1; 753 | client_info->client->condata.will.qos = 0; 754 | client_info->client->condata.will.retained = 0; 755 | 756 | jerry_value_t js_will_topic = js_get_property(js_will,"topic"); 757 | if(jerry_value_is_string(js_will_topic)) 758 | { 759 | char* will_topic = js_value_to_string(js_will_topic); 760 | client_info->client->condata.will.topicName.cstring = will_topic; 761 | free(will_topic); 762 | jerry_release_value(js_will_topic); 763 | } 764 | else 765 | { 766 | jerry_release_value(js_will_topic); 767 | goto _exit; 768 | } 769 | 770 | jerry_value_t js_will_message = js_get_property(js_will,"payload"); 771 | if(jerry_value_is_string(js_will_message)) 772 | { 773 | char* will_message = js_value_to_string(js_will_message); 774 | client_info->client->condata.will.topicName.cstring = will_message; 775 | free(will_message); 776 | jerry_release_value(js_will_topic); 777 | } 778 | else 779 | { 780 | jerry_release_value(js_will_topic); 781 | goto _exit; 782 | } 783 | 784 | jerry_value_t js_will_qos = js_get_property(js_will,"qos"); 785 | if(jerry_value_is_number(js_will_message)) 786 | { 787 | int qos = jerry_get_number_value(js_will_qos); 788 | if(qos < 0) 789 | { 790 | qos =0; 791 | } 792 | else if(qos > 2) 793 | { 794 | qos = 2; 795 | } 796 | client_info->client->condata.will.qos = qos; 797 | } 798 | jerry_release_value(js_will_qos); 799 | 800 | jerry_value_t js_will_retain = js_get_property(js_will,"retain"); 801 | if(jerry_value_is_number(js_will_retain)) 802 | { 803 | client_info->client->condata.will.retained = jerry_value_to_boolean(js_will_retain); 804 | } 805 | jerry_release_value(js_will_retain); 806 | } 807 | } 808 | 809 | /* malloc buffer. */ 810 | client_info->client->buf_size = client_info->client->readbuf_size = 1024; 811 | client_info->client->buf = malloc(client_info->client->buf_size); 812 | client_info->client->readbuf = malloc(client_info->client->readbuf_size); 813 | if (!(client_info->client->buf && client_info->client->readbuf)) 814 | { 815 | goto _exit; 816 | } 817 | 818 | /*create sem*/ 819 | client_info->sem = rt_sem_create("mqtt_msghandler_semt", 1, RT_IPC_FLAG_FIFO); 820 | 821 | js_make_emitter(js_client, jerry_create_undefined()); 822 | 823 | /*add js event callback*/ 824 | client_info->fun_callback = js_add_callback(mqtt_func_callback); 825 | client_info->event_callback = js_add_callback(mqtt_event_callback); 826 | client_info->close_callback = js_add_callback(mqtt_free_callback); 827 | 828 | /* set client's event callback function */ 829 | client_info->client->connect_callback = mqtt_connect_callback; 830 | client_info->client->online_callback = mqtt_online_callback; 831 | client_info->client->offline_callback = mqtt_offline_callback; 832 | 833 | /*create js object*/ 834 | jerry_value_t js_info = jerry_create_object(); 835 | client_info->this_value = js_client; 836 | js_set_property(js_client, "info", js_info); 837 | jerry_set_object_native_pointer(js_info, client_info, &mqtt_client_info); // set native_pointer 838 | jerry_release_value(js_info); 839 | /*set method*/ 840 | REGISTER_METHOD_NAME(js_client, "connect", connect); 841 | REGISTER_METHOD_NAME(js_client, "publish", publish); 842 | REGISTER_METHOD_NAME(js_client, "subscribe", subscribe); 843 | REGISTER_METHOD_NAME(js_client, "unsubscribe", unsubscribe); 844 | REGISTER_METHOD_NAME(js_client, "end", end); 845 | REGISTER_METHOD_NAME(js_client, "reconnect", reconnect); 846 | 847 | hasClient = true; 848 | 849 | return (js_client); 850 | _exit: 851 | jerry_release_value(js_client); 852 | if(client_info) 853 | { 854 | if(client_info->client) 855 | { 856 | free(client_info->client); 857 | } 858 | 859 | free(client_info); 860 | } 861 | return jerry_create_undefined(); 862 | } 863 | 864 | DECLARE_HANDLER(Client) 865 | { 866 | if(args_cnt >2 ||args_cnt ==0) 867 | { 868 | return jerry_create_undefined(); 869 | } 870 | 871 | switch(args_cnt) 872 | { 873 | case 2: 874 | if(!jerry_value_is_object(args[1])) 875 | { 876 | return jerry_create_undefined(); 877 | } 878 | case 1: 879 | if(!jerry_value_is_string(args[0])) 880 | { 881 | return jerry_create_undefined(); 882 | } 883 | default: 884 | break; 885 | } 886 | 887 | jerry_value_t js_client = mqtt_create_client(args_cnt,args); 888 | return js_client; 889 | } 890 | 891 | DECLARE_HANDLER(client_connect) 892 | { 893 | if(args_cnt >2 ||args_cnt ==0) 894 | { 895 | return jerry_create_undefined(); 896 | } 897 | 898 | switch(args_cnt) 899 | { 900 | case 2: 901 | if(!jerry_value_is_object(args[1])) 902 | { 903 | return jerry_create_undefined(); 904 | } 905 | case 1: 906 | if(!jerry_value_is_string(args[0])) 907 | { 908 | return jerry_create_undefined(); 909 | } 910 | default: 911 | break; 912 | } 913 | 914 | jerry_value_t js_client = mqtt_create_client(args_cnt,args); 915 | 916 | mqtt_info_t *mqtt_info = RT_NULL; 917 | get_mqtt_info((void **)&mqtt_info, this_value); 918 | 919 | paho_mqtt_start(mqtt_info->client); 920 | 921 | return js_client; 922 | } 923 | 924 | static jerry_value_t jerry_mqtt_init() 925 | { 926 | jerry_value_t js_mqtt = jerry_create_object(); 927 | 928 | REGISTER_METHOD_NAME(js_mqtt, "Client", Client); 929 | REGISTER_METHOD_NAME(js_mqtt, "connect", client_connect); 930 | 931 | return js_mqtt; 932 | } 933 | 934 | JS_MODULE(mqtt, jerry_mqtt_init) 935 | 936 | #endif 937 | -------------------------------------------------------------------------------- /rtthread-port/jerry_mqtt.h: -------------------------------------------------------------------------------- 1 | #ifndef JERRY_MQTT_H__ 2 | #define JERRY_MQTT_H__ 3 | 4 | #include 5 | 6 | #ifdef PKG_USING_PAHOMQTT 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "paho_mqtt.h" 13 | 14 | #define MQTT_BUFFER_SIZE 1024 15 | 16 | struct mqtt_callback_info 17 | { 18 | jerry_value_t this_value; 19 | jerry_value_t js_func; 20 | int return_count; 21 | jerry_value_t* return_value; 22 | char* event_name; 23 | } typedef mqtt_cbinfo_t; 24 | 25 | struct mqtt_client_info 26 | { 27 | jerry_value_t this_value; 28 | int subCount; //the count of topics subscribed 29 | MQTTClient* client; 30 | 31 | struct js_callback* event_callback; 32 | struct js_callback* fun_callback; 33 | struct js_callback* close_callback; 34 | 35 | struct topic_callback_list 36 | { 37 | char* topic; 38 | jerry_value_t js_func; 39 | } callbackHandler[MAX_MESSAGE_HANDLERS]; 40 | 41 | rt_sem_t sem; 42 | } typedef mqtt_info_t; 43 | 44 | 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /rtthread-port/jerry_net.h: -------------------------------------------------------------------------------- 1 | #ifndef JERRY_NET_H__ 2 | #define JERRY_NET_H__ 3 | 4 | #ifdef RT_USING_LWIP 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define BUFFER_SIZE 1024 22 | #define SERVER_MAX_CONNECTIONS (RT_LWIP_TCP_PCB_NUM - 3) 23 | 24 | struct socket_node 25 | { 26 | struct socket_node *next; 27 | struct socket_node *prev; 28 | jerry_value_t js_socket; 29 | } typedef socket_list_t; 30 | 31 | struct socket_info 32 | { 33 | int socket_id ; 34 | 35 | int pipe_write_fd; 36 | int pipe_read_fd; 37 | struct rt_pipe_device *pipe; 38 | 39 | bool allowHalfOpen ; 40 | bool writable ; 41 | bool readable ; 42 | 43 | bool isClosing; 44 | 45 | struct js_callback *event_callback; 46 | struct js_callback *fun_callback; 47 | struct js_callback *close_callback; 48 | 49 | rt_thread_t readData_thread; 50 | rt_thread_t connect_thread; 51 | 52 | jerry_value_t js_server; 53 | jerry_value_t this_value; 54 | rt_sem_t socket_sem; 55 | struct timeval timeout; 56 | } typedef net_socoketInfo_t; 57 | 58 | 59 | struct server_info 60 | { 61 | int server_id; 62 | 63 | bool allowHalfOpen; 64 | 65 | struct js_callback *event_callback; 66 | struct js_callback *close_callback; 67 | 68 | rt_thread_t listen_thread; 69 | 70 | socket_list_t *socket_list; 71 | jerry_value_t this_value; 72 | 73 | rt_sem_t server_sem; 74 | } typedef net_serverInfo_t; 75 | 76 | struct read_thread_info 77 | { 78 | jerry_value_t js_socket; 79 | 80 | } typedef net_readInfo_t; 81 | 82 | struct connect_info 83 | { 84 | struct sockaddr_in *socket_fd; 85 | int socket_id; 86 | jerry_value_t js_socket; 87 | } typedef net_connectInfo_t; 88 | 89 | struct listen_thread_info 90 | { 91 | jerry_value_t js_server; 92 | int backlog; 93 | } typedef net_listenInfo_t; 94 | 95 | struct write_data_info 96 | { 97 | jerry_value_t js_data; 98 | jerry_value_t js_callback; 99 | bool stop_read; 100 | rt_sem_t stop_sem; 101 | } typedef net_writeInfo_t; 102 | 103 | struct event_callback_info 104 | { 105 | char *event_name; 106 | jerry_value_t js_return; 107 | jerry_value_t js_target; 108 | } typedef net_event_info; 109 | 110 | struct fun_callback_info 111 | { 112 | void *args; 113 | int args_cnt; 114 | jerry_value_t js_run; 115 | jerry_value_t js_this; 116 | } typedef net_funcInfo_t; 117 | 118 | struct close_callback_info 119 | { 120 | jerry_value_t js_server; 121 | jerry_value_t js_socket; 122 | } typedef net_closeInfo_t; 123 | 124 | #endif 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /rtthread-port/jerry_os.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "jerry_util.h" 4 | 5 | DECLARE_HANDLER(ps) 6 | { 7 | /* list thread information */ 8 | #ifdef HOST_BUILD 9 | printf("list thread\n"); 10 | #else 11 | extern long list_thread(void); 12 | list_thread(); 13 | #endif 14 | 15 | return jerry_create_undefined(); 16 | } 17 | 18 | jerry_value_t js_module_rtthread_init(void) 19 | { 20 | jerry_value_t rtthread_obj = jerry_create_object(); 21 | REGISTER_METHOD(rtthread_obj, ps); 22 | 23 | return rtthread_obj; 24 | } 25 | JS_MODULE(os, js_module_rtthread_init); 26 | -------------------------------------------------------------------------------- /rtthread-port/jerry_request_init.c: -------------------------------------------------------------------------------- 1 | #include "jerry_request_init.h" 2 | 3 | #ifdef PKG_USING_WEBCLIENT 4 | void request_callback_func(const void *args, uint32_t size) 5 | { 6 | request_cbinfo_t *cb_info = (request_cbinfo_t *)args; 7 | if (cb_info->return_value != RT_NULL) 8 | { 9 | js_emit_event(cb_info->target_value, cb_info->callback_name, &cb_info->return_value, 1); 10 | } 11 | else 12 | { 13 | js_emit_event(cb_info->target_value, cb_info->callback_name, RT_NULL, 0); 14 | } 15 | if (cb_info->return_value != RT_NULL) 16 | { 17 | jerry_release_value(cb_info->return_value); 18 | } 19 | if (cb_info->data_value != RT_NULL) 20 | { 21 | jerry_release_value(cb_info->data_value); 22 | } 23 | if (cb_info->callback_name != RT_NULL) 24 | { 25 | free(cb_info->callback_name); 26 | } 27 | free(cb_info); 28 | } 29 | 30 | void request_callback_free(const void *args, uint32_t size) 31 | { 32 | request_tdinfo_t *rp = (request_tdinfo_t *)args; 33 | if (rp->config) 34 | { 35 | if (rp->config->session) 36 | { 37 | webclient_close(rp->config->session); 38 | } 39 | if (rp->config->url) 40 | { 41 | free(rp->config->url); 42 | } 43 | if (rp->config->data) 44 | { 45 | free(rp->config->data); 46 | } 47 | free(rp->config); 48 | } 49 | js_remove_callback(rp->request_callback); 50 | js_remove_callback(rp->close_callback); 51 | js_destroy_emitter(rp->target_value); 52 | jerry_release_value(rp->target_value); 53 | free(rp); 54 | } 55 | 56 | bool request_combine_header(struct webclient_session *session, char *host, char *user_agent, char *content_type) 57 | { 58 | bool ret = false; 59 | if (host != RT_NULL) 60 | { 61 | webclient_header_fields_add(session, "Host: %s\r\n", host); 62 | free(host); 63 | ret = true; 64 | } 65 | if (user_agent != RT_NULL) 66 | { 67 | webclient_header_fields_add(session, "User-Agent: %s\r\n", user_agent); 68 | free(user_agent); 69 | ret = true; 70 | } 71 | if (content_type != RT_NULL) 72 | { 73 | webclient_header_fields_add(session, "Content-Type: %s\r\n", content_type); 74 | free(content_type); 75 | ret = true; 76 | } 77 | return ret; 78 | } 79 | 80 | void request_create_header(struct webclient_session *session, jerry_value_t header_value) 81 | { 82 | int enter_index = 0; 83 | int colon_index = 0; 84 | int per_enter_index = -1; 85 | char header_type[256]; 86 | char header_info[256]; 87 | 88 | for (int i = 0 ; i < session->header->length ; i++) 89 | { 90 | if (session->header->buffer[i] == ':' && per_enter_index != enter_index) 91 | { 92 | colon_index = i; 93 | per_enter_index = enter_index; 94 | memset(header_type, 0, 64); 95 | memset(header_info, 0, 128); 96 | strncpy(header_type, session->header->buffer + enter_index + 1, colon_index - enter_index - 1); 97 | strcpy(header_info, session->header->buffer + colon_index + 2); 98 | jerry_value_t header_info_value = jerry_create_string((jerry_char_t *)header_info); 99 | js_set_property(header_value, header_type, header_info_value); 100 | jerry_release_value(header_info_value); 101 | } 102 | if (session->header->buffer[i] == '\0') 103 | { 104 | enter_index = i; 105 | } 106 | } 107 | } 108 | 109 | bool request_get_header(struct webclient_session *session, jerry_value_t header_value) 110 | { 111 | if (jerry_value_is_object(header_value)) 112 | { 113 | char *host = RT_NULL, *user_agent = RT_NULL, *content_type = RT_NULL; 114 | 115 | jerry_value_t Host_value = js_get_property(header_value, "Host"); 116 | if (!jerry_value_is_undefined(Host_value)) 117 | { 118 | host = js_value_to_string(Host_value); 119 | } 120 | jerry_release_value(Host_value); 121 | 122 | jerry_value_t User_Agent_value = js_get_property(header_value, "User-Agent"); 123 | if (!jerry_value_is_undefined(User_Agent_value)) 124 | { 125 | user_agent = js_value_to_string(User_Agent_value); 126 | } 127 | jerry_release_value(User_Agent_value); 128 | 129 | jerry_value_t Content_Type_value = js_get_property(header_value, "Content-Type"); 130 | if (!jerry_value_is_undefined(Content_Type_value)) 131 | { 132 | content_type = js_value_to_string(Content_Type_value); 133 | } 134 | jerry_release_value(Content_Type_value); 135 | 136 | return request_combine_header(session, host, user_agent, content_type); 137 | } 138 | else 139 | { 140 | return false; 141 | } 142 | } 143 | 144 | void request_read_entry(void *p) 145 | { 146 | request_tdinfo_t *rp = (request_tdinfo_t *)p; 147 | 148 | if (rp->config->session != RT_NULL && rp->config->method == WEBCLIENT_GET) 149 | { 150 | rp->config->response = webclient_get(rp->config->session, rp->config->url); 151 | } 152 | else if (rp->config->session != RT_NULL && rp->config->method == WEBCLIENT_POST) 153 | { 154 | webclient_header_fields_add(rp->config->session, "Content-Length: %d\r\n", strlen(rp->config->data)); 155 | webclient_header_fields_add(rp->config->session, "Content-Type: application/octet-stream\r\n"); 156 | rp->config->response = webclient_post(rp->config->session, rp->config->url, rp->config->data); 157 | } 158 | 159 | free(rp->config->data); 160 | rp->config->data = RT_NULL; 161 | free(rp->config->url); 162 | rp->config->url = RT_NULL; 163 | 164 | if (rp->config->session == RT_NULL || rp->config->response != 200) 165 | { 166 | //do fail callback 167 | request_cbinfo_t *fail_info = (request_cbinfo_t *)malloc(sizeof(request_cbinfo_t)); 168 | fail_info->target_value = rp->target_value; 169 | fail_info->callback_name = rt_strdup("fail"); 170 | fail_info->return_value = RT_NULL; 171 | fail_info->data_value = RT_NULL; 172 | js_send_callback(rp->request_callback, fail_info, sizeof(request_cbinfo_t)); 173 | free(fail_info); 174 | 175 | //do complete callback 176 | request_cbinfo_t *complete_info = (request_cbinfo_t *)malloc(sizeof(request_cbinfo_t));; 177 | complete_info->target_value = rp->target_value; 178 | complete_info->callback_name = rt_strdup("complete"); 179 | complete_info->return_value = RT_NULL; 180 | complete_info->data_value = RT_NULL; 181 | js_send_callback(rp->request_callback, complete_info, sizeof(request_cbinfo_t)); 182 | free(complete_info); 183 | 184 | goto __exit; 185 | } 186 | 187 | unsigned char *buffer = RT_NULL; 188 | int ret_read = 0; 189 | int content_length = webclient_content_length_get(rp->config->session); 190 | int per_read_length = 0; 191 | buffer = (unsigned char *)malloc(READ_MAX_SIZE + 1); 192 | if (!buffer) 193 | { 194 | rt_kprintf("no more memory to create read buffer\n"); 195 | return; 196 | } 197 | memset(buffer, 0, READ_MAX_SIZE + 1); 198 | 199 | if (content_length != -1) 200 | { 201 | while (ret_read < content_length) 202 | { 203 | per_read_length += webclient_read(rp->config->session, buffer + ret_read, READ_MAX_SIZE + 1 - ret_read); 204 | if (per_read_length < 0) 205 | { 206 | ret_read = -1; 207 | break; 208 | } 209 | ret_read += per_read_length; 210 | } 211 | } 212 | else //Transfer-Encoding: chunked 213 | { 214 | while (ret_read < READ_MAX_SIZE) 215 | { 216 | per_read_length = webclient_read(rp->config->session, buffer + ret_read, READ_MAX_SIZE + 1 - ret_read); 217 | if (per_read_length <= 0) 218 | { 219 | break; 220 | } 221 | ret_read += per_read_length; 222 | } 223 | } 224 | 225 | //If file's size is bigger than buffer's, 226 | //give up reading and send a fail callback 227 | if (ret_read > READ_MAX_SIZE || ret_read < 0) 228 | { 229 | request_cbinfo_t *fail_info = (request_cbinfo_t *)malloc(sizeof(request_cbinfo_t)); 230 | fail_info->target_value = rp->target_value; 231 | fail_info->callback_name = rt_strdup("fail"); 232 | fail_info->return_value = RT_NULL; 233 | fail_info->data_value = RT_NULL; 234 | js_send_callback(rp->request_callback, fail_info, sizeof(request_cbinfo_t)); 235 | free(fail_info); 236 | } 237 | else 238 | { 239 | jerry_value_t return_value = jerry_create_object(); 240 | 241 | /* create the jerry_value_t of res */ 242 | js_buffer_t *js_buffer; 243 | jerry_value_t data_value = jerry_buffer_create(ret_read, &js_buffer); 244 | if (js_buffer) 245 | { 246 | rt_memcpy(js_buffer->buffer, buffer, ret_read); 247 | } 248 | js_set_property(return_value, "data", data_value); 249 | 250 | jerry_value_t statusCode_value = jerry_create_number(webclient_resp_status_get(rp->config->session)); 251 | js_set_property(return_value, "statusCode", statusCode_value); 252 | jerry_release_value(statusCode_value); 253 | 254 | /*** header's data saved as Object ***/ 255 | jerry_value_t header_value = jerry_create_object(); 256 | request_create_header(rp->config->session, header_value); 257 | js_set_property(return_value, "header", header_value); 258 | jerry_release_value(header_value); 259 | 260 | //do success callback 261 | request_cbinfo_t *success_info = (request_cbinfo_t *)malloc(sizeof(request_cbinfo_t)); 262 | memset(success_info, 0, sizeof(request_cbinfo_t)); 263 | success_info->target_value = rp->target_value; 264 | success_info->callback_name = rt_strdup("success"); 265 | success_info->return_value = return_value; 266 | success_info->data_value = data_value; 267 | js_send_callback(rp->request_callback, success_info, sizeof(request_cbinfo_t)); 268 | free(success_info); 269 | } 270 | free(buffer); 271 | //do complete callback 272 | request_cbinfo_t *complete_info = (request_cbinfo_t *)malloc(sizeof(request_cbinfo_t));; 273 | complete_info->target_value = rp->target_value; 274 | complete_info->callback_name = rt_strdup("complete"); 275 | complete_info->return_value = RT_NULL; 276 | complete_info->data_value = RT_NULL; 277 | js_send_callback(rp->request_callback, complete_info, sizeof(request_cbinfo_t)); 278 | free(complete_info); 279 | 280 | __exit: 281 | //create a callback function to free manager and close webClient session 282 | js_send_callback(rp->close_callback, rp, sizeof(request_cbinfo_t)); 283 | free(rp); 284 | } 285 | 286 | void requeset_add_event_listener(jerry_value_t js_target, jerry_value_t requestObj) 287 | { 288 | jerry_value_t success_func = js_get_property(requestObj, "success"); 289 | if (jerry_value_is_function(success_func)) 290 | { 291 | js_add_event_listener(js_target, "success", success_func); 292 | } 293 | jerry_release_value(success_func); 294 | 295 | jerry_value_t fail_func = js_get_property(requestObj, "fail"); 296 | if (jerry_value_is_function(fail_func)) 297 | { 298 | js_add_event_listener(js_target, "fail", fail_func); 299 | } 300 | jerry_release_value(fail_func); 301 | 302 | jerry_value_t complete_func = js_get_property(requestObj, "complete"); 303 | if (jerry_value_is_function(complete_func)) 304 | { 305 | js_add_event_listener(js_target, "complete", complete_func); 306 | } 307 | jerry_release_value(complete_func); 308 | } 309 | 310 | void reqeuset_get_config(request_config_t *config, jerry_value_t requestObj) 311 | { 312 | /*get url*/ 313 | jerry_value_t js_url = js_get_property(requestObj, "url"); 314 | if (jerry_value_is_string(js_url)) 315 | { 316 | config->url = js_value_to_string(js_url); 317 | } 318 | jerry_release_value(js_url); 319 | 320 | /*get data*/ 321 | jerry_value_t js_data = js_get_property(requestObj, "data"); 322 | if (jerry_value_is_object(js_data)) 323 | { 324 | jerry_value_t stringified = jerry_json_stringfy(js_data); 325 | config->data = js_value_to_string(stringified); 326 | jerry_release_value(stringified); 327 | } 328 | else if (jerry_value_is_string(js_data)) 329 | { 330 | config->data = js_value_to_string(js_data); 331 | } 332 | jerry_release_value(js_data); 333 | 334 | /*get header*/ 335 | config->session = webclient_session_create(HEADER_BUFSZ);; 336 | jerry_value_t js_header = js_get_property(requestObj, "header"); 337 | request_get_header(config->session, js_header); 338 | jerry_release_value(js_header); 339 | 340 | /*get method*/ 341 | jerry_value_t method_value = js_get_property(requestObj, "method"); 342 | if (jerry_value_is_string(method_value)) 343 | { 344 | char *method_str = js_value_to_string(method_value); 345 | if (method_str) 346 | { 347 | if (strcmp(method_str, "POST") == 0) 348 | { 349 | config->method = WEBCLIENT_POST; 350 | } 351 | free(method_str); 352 | } 353 | } 354 | jerry_release_value(method_value); 355 | } 356 | 357 | DECLARE_HANDLER(request) 358 | { 359 | if (args_cnt != 1 || !jerry_value_is_object(args[0])) 360 | { 361 | return jerry_create_undefined(); 362 | } 363 | 364 | jerry_value_t requestObj = args[0]; 365 | jerry_value_t rqObj = jerry_create_object(); 366 | js_make_emitter(rqObj, jerry_create_undefined()); 367 | struct js_callback *request_callback = js_add_callback(request_callback_func); 368 | struct js_callback *close_callback = js_add_callback(request_callback_free); 369 | 370 | requeset_add_event_listener(rqObj, requestObj); 371 | 372 | request_config_t *config = (request_config_t *)malloc(sizeof(request_config_t)); 373 | config->method = WEBCLIENT_GET; 374 | config->url = RT_NULL; 375 | config->data = RT_NULL; 376 | config->response = 0; 377 | config->session = RT_NULL; 378 | 379 | reqeuset_get_config(config, requestObj); 380 | 381 | request_tdinfo_t *rp = (request_tdinfo_t *)malloc(sizeof(request_tdinfo_t)); 382 | memset(rp, 0, sizeof(request_tdinfo_t)); 383 | rp->request_callback = request_callback; 384 | rp->close_callback = close_callback; 385 | rp->target_value = rqObj; 386 | rp->config = config; 387 | rt_thread_t read_request = rt_thread_create("requestRead", request_read_entry, rp, 4096, 20, 5); 388 | rt_thread_startup(read_request); 389 | return jerry_acquire_value(rqObj); 390 | } 391 | 392 | int jerry_request_init(jerry_value_t obj) 393 | { 394 | REGISTER_METHOD(obj, request); 395 | return 0; 396 | } 397 | 398 | static jerry_value_t _jerry_request_init() 399 | { 400 | jerry_value_t js_requset = jerry_create_object(); 401 | REGISTER_METHOD_NAME(js_requset, "request", request); 402 | return (js_requset); 403 | } 404 | 405 | JS_MODULE(http, _jerry_request_init) 406 | #endif 407 | -------------------------------------------------------------------------------- /rtthread-port/jerry_request_init.h: -------------------------------------------------------------------------------- 1 | #ifndef JERRY_REQUEST_INIT_H__ 2 | #define JERRY_REQUEST_INIT_H__ 3 | 4 | #include 5 | 6 | #ifdef PKG_USING_WEBCLIENT 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define READ_MAX_SIZE 50*1024 15 | #define HEADER_BUFSZ 1024 16 | 17 | struct request_callback_info 18 | { 19 | jerry_value_t target_value; 20 | jerry_value_t return_value; 21 | jerry_value_t data_value; 22 | char *callback_name; 23 | } typedef request_cbinfo_t; 24 | 25 | struct request_config_info 26 | { 27 | char *url; 28 | char *data; 29 | struct webclient_session *session; 30 | int method; 31 | int response; 32 | } typedef request_config_t; 33 | 34 | struct request_thread_info 35 | { 36 | jerry_value_t target_value; 37 | request_config_t *config; 38 | struct js_callback *request_callback; 39 | struct js_callback *close_callback; 40 | } typedef request_tdinfo_t; 41 | 42 | int jerry_request_init(jerry_value_t obj); 43 | 44 | #endif 45 | 46 | #endif -------------------------------------------------------------------------------- /rtthread-port/jerry_utf8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2018, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-19 bernard the first version 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include "jerry_utf8.h" 17 | 18 | #ifdef PKG_USING_GUIENGINE 19 | #include 20 | #endif 21 | 22 | bool jerry_str_is_utf8(const void* str, int size) 23 | { 24 | bool ret = true; 25 | unsigned char* start = (unsigned char*)str; 26 | unsigned char* end = (unsigned char*)str + size; 27 | 28 | while (start < end) 29 | { 30 | if (*start < 0x80) // (10000000): ASCII < 0x80 31 | { 32 | start++; 33 | } 34 | else if (*start < (0xC0)) // (11000000): 0x80 <= invalid ASCII < 0xC0 35 | { 36 | ret = false; 37 | break; 38 | } 39 | else if (*start < (0xE0)) // (11100000): two bytes UTF8 40 | { 41 | if (start >= end - 1) 42 | { 43 | break; 44 | } 45 | 46 | if ((start[1] & (0xC0)) != 0x80) 47 | { 48 | ret = false; 49 | break; 50 | } 51 | 52 | start += 2; 53 | } 54 | else if (*start < (0xF0)) // (11110000): three bytes UTF-8 55 | { 56 | if (start >= end - 2) 57 | { 58 | break; 59 | } 60 | 61 | if ((start[1] & (0xC0)) != 0x80 || (start[2] & (0xC0)) != 0x80) 62 | { 63 | ret = false; 64 | break; 65 | } 66 | 67 | start += 3; 68 | } 69 | else 70 | { 71 | ret = false; 72 | break; 73 | } 74 | } 75 | 76 | return ret; 77 | } 78 | 79 | int jerry_str2utf8(char *str, int len, char **utf8) 80 | { 81 | #ifdef PKG_USING_GUIENGINE 82 | Gb2312ToUtf8(str, len, utf8); 83 | #endif 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /rtthread-port/jerry_utf8.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2018, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-19 bernard the first version 9 | */ 10 | 11 | #ifndef JERRY_UTF8_H__ 12 | #define JERRY_UTF8_H__ 13 | 14 | #include 15 | 16 | #ifdef __cplusplus 17 | extern "C" 18 | { 19 | #endif 20 | 21 | bool jerry_str_is_utf8(const void* str, int size); 22 | int jerry_str2utf8(char *str, int len, char **utf8); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /rtthread-port/jerry_util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include "jerry_util.h" 8 | #include 9 | #include 10 | 11 | #include "jerry_utf8.h" 12 | 13 | extern int js_console_init(void); 14 | extern int js_module_init(void); 15 | extern int js_buffer_init(void); 16 | extern int js_buffer_cleanup(void); 17 | 18 | static void _js_value_dump(jerry_value_t value); 19 | 20 | static rt_mutex_t _util_lock = NULL; 21 | static js_util_user _user_init = NULL, _user_cleanup = NULL; 22 | 23 | void js_set_property(const jerry_value_t obj, const char *name, 24 | const jerry_value_t prop) 25 | { 26 | jerry_value_t str = jerry_create_string((const jerry_char_t *)name); 27 | jerry_set_property(obj, str, prop); 28 | jerry_release_value (str); 29 | } 30 | 31 | jerry_value_t js_get_property(const jerry_value_t obj, const char *name) 32 | { 33 | jerry_value_t ret; 34 | 35 | const jerry_value_t str = jerry_create_string ((const jerry_char_t*)name); 36 | ret = jerry_get_property(obj, str); 37 | jerry_release_value (str); 38 | 39 | return ret; 40 | } 41 | 42 | void js_set_string_property(const jerry_value_t obj, const char *name, 43 | char* value) 44 | { 45 | jerry_value_t str = jerry_create_string((const jerry_char_t *)name); 46 | jerry_value_t value_str = jerry_create_string((const jerry_char_t *)value); 47 | jerry_set_property(obj, str, value_str); 48 | jerry_release_value (str); 49 | jerry_release_value (value_str); 50 | } 51 | 52 | void js_set_boolean_property(const jerry_value_t obj, const char *name, 53 | bool value) 54 | { 55 | jerry_value_t str = jerry_create_string((const jerry_char_t *)name); 56 | jerry_value_t value_bool = jerry_create_boolean(value); 57 | jerry_set_property(obj, str, value_bool); 58 | jerry_release_value(str); 59 | jerry_release_value(value_bool); 60 | } 61 | 62 | void js_add_function(const jerry_value_t obj, const char *name, 63 | jerry_external_handler_t func) 64 | { 65 | jerry_value_t str = jerry_create_string((const jerry_char_t *)name); 66 | jerry_value_t jfunc = jerry_create_external_function(func); 67 | 68 | jerry_set_property(obj, str, jfunc); 69 | 70 | jerry_release_value(str); 71 | jerry_release_value(jfunc); 72 | } 73 | 74 | jerry_value_t js_string_to_value(const char *value) 75 | { 76 | jerry_value_t str = 0; 77 | 78 | if (jerry_str_is_utf8(value, strlen(value))) 79 | { 80 | str = jerry_create_string((const jerry_char_t *)value); 81 | } 82 | else 83 | { 84 | char *utf8 = NULL; 85 | 86 | jerry_str2utf8((char *)value, strlen(value), &utf8); 87 | str = jerry_create_string((const jerry_char_t *)utf8); 88 | 89 | rt_free(utf8); 90 | } 91 | 92 | return str; 93 | } 94 | 95 | char *js_value_to_string(const jerry_value_t value) 96 | { 97 | int len; 98 | char *str; 99 | 100 | len = jerry_get_utf8_string_size(value); 101 | 102 | str = (char*)malloc(len + 1); 103 | if (str) 104 | { 105 | jerry_string_to_char_buffer(value, (jerry_char_t*)str, len); 106 | str[len] = '\0'; 107 | } 108 | 109 | return str; 110 | } 111 | 112 | jerry_value_t js_call_func_obj(const jerry_value_t func_obj_val, /**< function object to call */ 113 | const jerry_value_t this_val, /**< object for 'this' binding */ 114 | const jerry_value_t args_p[], /**< function's call arguments */ 115 | jerry_size_t args_count) /**< number of the arguments */ 116 | { 117 | jerry_value_t ret; 118 | 119 | js_util_lock(); 120 | ret = jerry_call_function(func_obj_val, this_val, args_p, args_count); 121 | js_util_unlock(); 122 | 123 | return ret; 124 | } 125 | 126 | jerry_value_t js_call_function(const jerry_value_t obj, const char *name, 127 | const jerry_value_t args[], jerry_size_t args_cnt) 128 | { 129 | jerry_value_t ret; 130 | jerry_value_t function = js_get_property(obj, name); 131 | 132 | if (jerry_value_is_function(function)) 133 | { 134 | ret = js_call_func_obj(function, obj, args, args_cnt); 135 | } 136 | else 137 | { 138 | ret = jerry_create_null(); 139 | } 140 | 141 | jerry_release_value(function); 142 | return ret; 143 | } 144 | 145 | bool object_dump_foreach(const jerry_value_t property_name, 146 | const jerry_value_t property_value, void *user_data_p) 147 | { 148 | char *str; 149 | int str_size; 150 | int *first_property; 151 | 152 | first_property = (int *)user_data_p; 153 | 154 | if (*first_property) *first_property = 0; 155 | else 156 | { 157 | printf(", "); 158 | } 159 | 160 | if (jerry_value_is_string(property_name)) 161 | { 162 | str_size = jerry_get_string_size(property_name); 163 | str = (char*) malloc (str_size + 1); 164 | RT_ASSERT(str != NULL); 165 | 166 | jerry_string_to_char_buffer(property_name, (jerry_char_t*)str, str_size); 167 | str[str_size] = '\0'; 168 | printf("%s : ", str); 169 | free(str); 170 | } 171 | _js_value_dump(property_value); 172 | 173 | return true; 174 | } 175 | 176 | static void _js_value_dump(jerry_value_t value) 177 | { 178 | if (jerry_value_is_undefined(value)) 179 | { 180 | printf("undefined"); 181 | } 182 | else if (jerry_value_is_boolean(value)) 183 | { 184 | printf("%s", jerry_get_boolean_value(value)? "true" : "false"); 185 | } 186 | else if (jerry_value_is_number(value)) 187 | { 188 | printf("%f", jerry_get_number_value(value)); 189 | } 190 | else if (jerry_value_is_null(value)) 191 | { 192 | printf("null"); 193 | } 194 | else if (jerry_value_is_string(value)) 195 | { 196 | char *str; 197 | int str_size; 198 | 199 | str_size = jerry_get_string_size(value); 200 | str = (char*) malloc (str_size + 1); 201 | RT_ASSERT(str != NULL); 202 | 203 | jerry_string_to_char_buffer(value, (jerry_char_t*)str, str_size); 204 | str[str_size] = '\0'; 205 | printf("\"%s\"", str); 206 | free(str); 207 | } 208 | else if (jerry_value_is_promise(value)) 209 | { 210 | printf("promise??"); 211 | } 212 | else if (jerry_value_is_function(value)) 213 | { 214 | printf("[function]"); 215 | } 216 | else if (jerry_value_is_constructor(value)) 217 | { 218 | printf("constructor"); 219 | } 220 | else if (jerry_value_is_array(value)) 221 | { 222 | int index; 223 | printf("["); 224 | for (index = 0; index < jerry_get_array_length(value); index ++) 225 | { 226 | jerry_value_t item = jerry_get_property_by_index(value, index); 227 | _js_value_dump(item); 228 | printf(", "); 229 | jerry_release_value(item); 230 | } 231 | printf("]"); 232 | } 233 | else if (jerry_value_is_object(value)) 234 | { 235 | int first_property = 1; 236 | printf("{"); 237 | jerry_foreach_object_property(value, object_dump_foreach, &first_property); 238 | printf("}"); 239 | } 240 | else 241 | { 242 | printf("what?"); 243 | } 244 | } 245 | 246 | void js_value_dump(jerry_value_t value) 247 | { 248 | _js_value_dump(value); 249 | printf("\n"); 250 | } 251 | 252 | int js_read_file(const char* filename, char **script) 253 | { 254 | FILE *fp; 255 | int length = 0; 256 | struct stat statbuf; 257 | 258 | if (!filename || !script) return 0; 259 | 260 | stat(filename, &statbuf); 261 | length = statbuf.st_size; 262 | 263 | if(!length) return 0; 264 | 265 | *script = (char *)rt_malloc(length + 1); 266 | if(!(*script)) return 0; 267 | (*script)[length] = '\0'; 268 | 269 | fp = fopen(filename, "rb"); 270 | if(!fp) 271 | { 272 | rt_free(*script); 273 | *script = RT_NULL; 274 | printf("open %s failed!\n", filename); 275 | return 0; 276 | } 277 | 278 | if(fread(*script, length, 1, fp) != 1) 279 | { 280 | length = 0; 281 | rt_free(*script); 282 | *script = RT_NULL; 283 | printf("read %s failed!\n", filename); 284 | } 285 | fclose(fp); 286 | 287 | return length; 288 | } 289 | 290 | int js_util_init(void) 291 | { 292 | if (_util_lock == RT_NULL) 293 | _util_lock = rt_mutex_create("call_func", RT_IPC_FLAG_FIFO); 294 | 295 | js_console_init(); 296 | js_module_init(); 297 | js_buffer_init(); 298 | js_event_init(); 299 | js_message_init(); 300 | if (_user_init != NULL) 301 | { 302 | _user_init(); 303 | } 304 | 305 | return 0; 306 | } 307 | 308 | int js_util_cleanup(void) 309 | { 310 | js_event_deinit(); 311 | js_buffer_cleanup(); 312 | if (_user_cleanup != NULL) 313 | { 314 | _user_cleanup(); 315 | } 316 | 317 | return 0; 318 | } 319 | 320 | void js_util_user_init(js_util_user func) 321 | { 322 | _user_init = func; 323 | } 324 | 325 | void js_util_user_cleanup(js_util_user func) 326 | { 327 | _user_cleanup = func; 328 | } 329 | 330 | int js_util_lock(void) 331 | { 332 | return rt_mutex_take(_util_lock, RT_WAITING_FOREVER); 333 | } 334 | 335 | int js_util_unlock(void) 336 | { 337 | return rt_mutex_release(_util_lock); 338 | } 339 | -------------------------------------------------------------------------------- /rtthread-port/jerry_util.h: -------------------------------------------------------------------------------- 1 | #ifndef JERRY_UTIL_H__ 2 | #define JERRY_UTIL_H__ 3 | 4 | #include 5 | 6 | #define DECLARE_HANDLER(NAME) \ 7 | static jerry_value_t \ 8 | NAME ## _handler (const jerry_value_t func_value, \ 9 | const jerry_value_t this_value, \ 10 | const jerry_value_t args[], \ 11 | const jerry_length_t args_cnt ) 12 | 13 | #define REGISTER_HANDLER(NAME) \ 14 | jerryx_handler_register_global ( (jerry_char_t *)# NAME, NAME ## _handler) 15 | #define REGISTER_HANDLER_ALIAS(NAME, HANDLER) \ 16 | jerryx_handler_register_global ( (jerry_char_t *)# NAME, HANDLER) 17 | #define REGISTER_METHOD(OBJ, NAME) \ 18 | js_add_function (OBJ, # NAME, NAME ## _handler) 19 | #define REGISTER_METHOD_ALIAS(OBJ, NAME, HANDLER) \ 20 | js_add_function (OBJ, # NAME, HANDLER) 21 | #define REGISTER_METHOD_NAME(OBJ, NAME, HANDLER) \ 22 | js_add_function (OBJ, NAME, HANDLER ## _handler) 23 | 24 | #ifdef RT_USING_FINSH 25 | #include 26 | #define JS_MODULE(NAME, MODULE_INIT) \ 27 | MSH_FUNCTION_EXPORT_CMD(MODULE_INIT, __jsm_ ##NAME, RT_NULL) 28 | #else 29 | #define JS_MODULE(NAME, MODULE_INIT) 30 | #endif 31 | 32 | #ifdef __cplusplus 33 | extern "C" 34 | { 35 | #endif 36 | 37 | typedef void(*js_util_user)(void); 38 | 39 | bool is_utf8_string(const void* str, int size); 40 | 41 | void js_set_property(const jerry_value_t obj, const char *name, 42 | const jerry_value_t prop); 43 | void js_set_string_property(const jerry_value_t obj, const char *name, 44 | char* value); 45 | void js_set_boolean_property(const jerry_value_t obj, const char *name, 46 | bool value); 47 | 48 | jerry_value_t js_get_property(const jerry_value_t obj, const char *name); 49 | 50 | void js_add_function(const jerry_value_t obj, const char *name, 51 | jerry_external_handler_t func); 52 | jerry_value_t js_call_func_obj(const jerry_value_t func_obj_val, const jerry_value_t this_val, 53 | const jerry_value_t args_p[], jerry_size_t args_count); 54 | jerry_value_t js_call_function(const jerry_value_t obj, const char *name, 55 | const jerry_value_t args[], jerry_size_t args_cnt); 56 | 57 | jerry_value_t js_string_to_value(const char *value); 58 | char *js_value_to_string(const jerry_value_t value); 59 | 60 | void js_value_dump(const jerry_value_t value); 61 | int js_read_file(const char* filename, char **script); 62 | 63 | int js_util_init(void); 64 | int js_util_cleanup(void); 65 | int js_util_lock(void); 66 | int js_util_unlock(void); 67 | void js_util_user_init(js_util_user func); 68 | void js_util_user_cleanup(js_util_user func); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /rtthread-port/jerry_wlan.c: -------------------------------------------------------------------------------- 1 | #include "jerry_wlan.h" 2 | 3 | 4 | #ifdef RT_USING_WIFI 5 | 6 | #include 7 | 8 | #define DBG_ENABLE 9 | #define DBG_SECTION_NAME "JS WLAN" 10 | #define DBG_LEVEL DBG_LOG 11 | #include 12 | 13 | static void get_wifi_info(void **info, jerry_value_t js_target) 14 | { 15 | jerry_value_t js_info = js_get_property(js_target, "info"); 16 | if (js_info) 17 | { 18 | jerry_get_object_native_pointer(js_info, info, NULL); 19 | } 20 | jerry_release_value(js_info); 21 | } 22 | 23 | static void js_event_callback_func_wifi(const void *args, uint32_t size) 24 | { 25 | struct event_callback_info *cb_info = (struct event_callback_info*)args; 26 | 27 | if (cb_info->js_return != RT_NULL) 28 | { 29 | js_emit_event(cb_info->js_target, cb_info->event_name, &cb_info->js_return, 1); 30 | jerry_release_value(cb_info->js_return); 31 | } 32 | else 33 | { 34 | js_emit_event(cb_info->js_target, cb_info->event_name, NULL, 0); 35 | } 36 | 37 | free(cb_info->event_name); 38 | free(cb_info); 39 | } 40 | 41 | static int connect_wifi(struct wifi_info *info, char *ssid, char *password, char *bssid) 42 | { 43 | int ret = -2; 44 | 45 | if (info && ssid) 46 | { 47 | if (info->wifi_list.num) 48 | { 49 | int i = 0; 50 | char buffer[32]; 51 | 52 | for (; i < info->wifi_list.num; i ++) 53 | { 54 | rt_sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", 55 | info->wifi_list.info[i].bssid[0], 56 | info->wifi_list.info[i].bssid[1], 57 | info->wifi_list.info[i].bssid[2], 58 | info->wifi_list.info[i].bssid[3], 59 | info->wifi_list.info[i].bssid[4], 60 | info->wifi_list.info[i].bssid[5] 61 | ); 62 | 63 | if (bssid) 64 | { 65 | if (rt_strcmp((const char *)bssid, (const char *)buffer) != 0) 66 | { 67 | continue; 68 | } 69 | } 70 | 71 | if (rt_strcmp((const char *)ssid, (const char *)info->wifi_list.info[i].ssid.val) == 0) 72 | { 73 | ret = rt_wlan_connect_adv(&(info->wifi_list.info[i]), password); 74 | break; 75 | } 76 | else if (info->gb_ssid[i].ssid && rt_strcmp((const char *)ssid, (const char *)info->gb_ssid[i].ssid) == 0) 77 | { 78 | ret = rt_wlan_connect_adv(&(info->wifi_list.info[info->gb_ssid[i].index]), password); 79 | break; 80 | } 81 | } 82 | 83 | if (ret != RT_EOK) 84 | { 85 | ret = -1; 86 | } 87 | 88 | if (i >= info->wifi_list.num) 89 | { 90 | LOG_W("The scanned wifi is not included %s", ssid); 91 | ret = -2; 92 | } 93 | } 94 | } 95 | 96 | return ret; 97 | } 98 | 99 | static void scanEvent_handler(int event, struct rt_wlan_buff *buff, void *parameter) 100 | { 101 | jerry_value_t js_wifi = (jerry_value_t)(parameter); 102 | struct wifi_info *info = RT_NULL; 103 | 104 | get_wifi_info((void**)&info, js_wifi); 105 | if (info) 106 | { 107 | int i; 108 | jerry_value_t js_return = 0; 109 | struct rt_wlan_scan_result *temp_result = (struct rt_wlan_scan_result*)buff->data; 110 | 111 | if (temp_result->num > 0) 112 | { 113 | if (info->wifi_list.info) 114 | { 115 | free(info->wifi_list.info); 116 | } 117 | 118 | if (info->gb_ssid) 119 | { 120 | for (i = 0; i < info->wifi_list.num; i++) 121 | { 122 | if (info->gb_ssid[i].ssid) 123 | { 124 | rt_free(info->gb_ssid[i].ssid); 125 | } 126 | } 127 | free(info->gb_ssid); 128 | } 129 | 130 | info->wifi_list.num = temp_result->num; 131 | info->wifi_list.info = (struct rt_wlan_info*)malloc(sizeof(struct rt_wlan_info) * info->wifi_list.num); 132 | info->gb_ssid = (struct wifi_ssid*)malloc(sizeof(struct wifi_ssid) * info->wifi_list.num); 133 | if (info->wifi_list.info) 134 | { 135 | memcpy(info->wifi_list.info, temp_result->info, sizeof(struct rt_wlan_info) * info->wifi_list.num); 136 | 137 | if (info->gb_ssid) 138 | { 139 | int j = 0; 140 | memset(info->gb_ssid, 0x00, sizeof(struct wifi_ssid) * info->wifi_list.num); 141 | 142 | for (i = 0; i < info->wifi_list.num; i++) 143 | { 144 | if (!is_utf8_string((void *)info->wifi_list.info[i].ssid.val, strlen((const char *)info->wifi_list.info[i].ssid.val))) 145 | { 146 | info->gb_ssid[j].index = i; 147 | Gb2312ToUtf8((char *)info->wifi_list.info[i].ssid.val, strlen((const char *)info->wifi_list.info[i].ssid.val), &info->gb_ssid[j].ssid); 148 | j ++; 149 | } 150 | } 151 | } 152 | 153 | if (info->ssid) 154 | { 155 | if (connect_wifi(info, info->ssid, info->password, info->bssid) == -2) 156 | { 157 | struct event_callback_info cb_info; 158 | 159 | cb_info.event_name = strdup("ConnectEvent"); 160 | cb_info.js_target = js_wifi; 161 | cb_info.js_return = jerry_create_null(); 162 | 163 | if (!js_send_callback(info->event_callback, &cb_info, sizeof(struct event_callback_info))) 164 | { 165 | jerry_release_value(js_return); 166 | } 167 | } 168 | 169 | free(info->ssid); 170 | free(info->password); 171 | free(info->bssid); 172 | info->ssid = NULL; 173 | info->password = NULL; 174 | info->bssid = NULL; 175 | 176 | return; 177 | } 178 | else 179 | { 180 | char buffer[32]; 181 | jerry_value_t js_ssid, js_strength, js_bssid, js_secure, js_ret; 182 | 183 | js_return = jerry_create_array(info->wifi_list.num); 184 | 185 | for (i = 0; i < info->wifi_list.num; i++) 186 | { 187 | struct rt_wlan_info *wifi_info = &(info->wifi_list.info[i]); 188 | jerry_value_t js_wifi_info = jerry_create_object(); 189 | 190 | js_ssid = js_string_to_value((const char*)wifi_info->ssid.val); 191 | js_set_property(js_wifi_info, "ssid", js_ssid); 192 | jerry_release_value(js_ssid); 193 | 194 | js_strength = jerry_create_number(wifi_info->rssi); 195 | js_set_property(js_wifi_info, "strength", js_strength); 196 | jerry_release_value(js_strength); 197 | 198 | rt_sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", 199 | wifi_info->bssid[0], 200 | wifi_info->bssid[1], 201 | wifi_info->bssid[2], 202 | wifi_info->bssid[3], 203 | wifi_info->bssid[4], 204 | wifi_info->bssid[5]); 205 | 206 | js_bssid = jerry_create_string((const jerry_char_t*)buffer); 207 | js_set_property(js_wifi_info, "bssid", js_bssid); 208 | jerry_release_value(js_bssid); 209 | 210 | js_secure = jerry_create_boolean(wifi_info->security); 211 | js_set_property(js_wifi_info, "secure", js_secure); 212 | jerry_release_value(js_secure); 213 | 214 | js_ret = jerry_set_property_by_index(js_return, i, js_wifi_info); 215 | jerry_release_value(js_ret); 216 | 217 | jerry_release_value(js_wifi_info); 218 | } 219 | } 220 | } 221 | } 222 | 223 | { 224 | struct event_callback_info cb_info; 225 | 226 | cb_info.event_name = strdup("ScanEvent"); 227 | cb_info.js_target = js_wifi; 228 | cb_info.js_return = js_return; 229 | 230 | if (!js_send_callback(info->event_callback, &cb_info, sizeof(struct event_callback_info))) 231 | { 232 | jerry_release_value(js_return); 233 | } 234 | } 235 | } 236 | } 237 | 238 | static void connectEvent_handler(int event, struct rt_wlan_buff *buff, void *parameter) 239 | { 240 | jerry_value_t js_wifi = (jerry_value_t)parameter; 241 | struct wifi_info *info = RT_NULL; 242 | 243 | get_wifi_info((void**)&info, js_wifi); 244 | if (info) 245 | { 246 | jerry_value_t js_return = 0; 247 | struct rt_wlan_info *wifi_info = (struct rt_wlan_info*)(buff->data); 248 | 249 | if (event == RT_WLAN_EVT_STA_CONNECTED) 250 | { 251 | char buffer[32]; 252 | jerry_value_t js_ssid, js_strength, js_bssid, js_secure; 253 | js_return = jerry_create_object(); 254 | 255 | js_ssid = js_string_to_value((const char*)wifi_info->ssid.val); 256 | js_set_property(js_return, "ssid", js_ssid); 257 | jerry_release_value(js_ssid); 258 | 259 | js_strength = jerry_create_number(wifi_info->rssi); 260 | js_set_property(js_return, "strength", js_strength); 261 | jerry_release_value(js_strength); 262 | 263 | rt_sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", 264 | wifi_info->bssid[0], 265 | wifi_info->bssid[1], 266 | wifi_info->bssid[2], 267 | wifi_info->bssid[3], 268 | wifi_info->bssid[4], 269 | wifi_info->bssid[5]); 270 | 271 | js_bssid = jerry_create_string((const jerry_char_t*)buffer); 272 | js_set_property(js_return, "bssid", js_bssid); 273 | jerry_release_value(js_bssid); 274 | 275 | js_secure = jerry_create_boolean(wifi_info->security); 276 | js_set_property(js_return, "secure", js_secure); 277 | jerry_release_value(js_secure); 278 | } 279 | else 280 | { 281 | js_return = jerry_create_null(); 282 | } 283 | 284 | { 285 | struct event_callback_info cb_info; 286 | 287 | cb_info.event_name = strdup("ConnectEvent"); 288 | cb_info.js_target = js_wifi; 289 | cb_info.js_return = js_return; 290 | 291 | if (!js_send_callback(info->event_callback, &cb_info, sizeof(struct event_callback_info))) 292 | { 293 | jerry_release_value(js_return); 294 | } 295 | } 296 | } 297 | } 298 | 299 | static void networkEvent_handler(int event, struct rt_wlan_buff *buff, void *parameter) 300 | { 301 | jerry_value_t js_wifi = (jerry_value_t)parameter; 302 | struct wifi_info *info= RT_NULL; 303 | 304 | get_wifi_info((void**)&info, js_wifi); 305 | if (info) 306 | { 307 | jerry_value_t js_return = 0; 308 | struct event_callback_info cb_info; 309 | 310 | if (RT_WLAN_EVT_READY == event) 311 | { 312 | js_return = jerry_create_boolean(true); 313 | } 314 | else 315 | { 316 | js_return = jerry_create_boolean(false); 317 | } 318 | 319 | cb_info.event_name = strdup("NetworkEvent"); 320 | cb_info.js_target = js_wifi; 321 | cb_info.js_return = js_return; 322 | 323 | if (!js_send_callback(info->event_callback, &cb_info, sizeof(struct event_callback_info))) 324 | { 325 | jerry_release_value(js_return); 326 | } 327 | } 328 | } 329 | 330 | void wifi_free_callback(void *native_p) 331 | { 332 | struct wifi_info *info = (struct wifi_info*)native_p; 333 | if (info) 334 | { 335 | if (info->wifi_list.info) 336 | free(info->wifi_list.info); 337 | 338 | if (info->event_callback) 339 | js_remove_callback(info->event_callback); 340 | 341 | if (info) 342 | free(info); 343 | } 344 | 345 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_SCAN_DONE); 346 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_STA_CONNECTED); 347 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_STA_CONNECTED_FAIL); 348 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_READY); 349 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_STA_DISCONNECTED); 350 | } 351 | 352 | const static jerry_object_native_info_t wifi_free_info = 353 | { 354 | wifi_free_callback 355 | }; 356 | 357 | void register_handler(jerry_value_t js_wifi) 358 | { 359 | rt_wlan_register_event_handler(RT_WLAN_EVT_SCAN_DONE, scanEvent_handler, (void*)js_wifi); 360 | rt_wlan_register_event_handler(RT_WLAN_EVT_STA_CONNECTED, connectEvent_handler, (void*)js_wifi); 361 | rt_wlan_register_event_handler(RT_WLAN_EVT_STA_CONNECTED_FAIL, connectEvent_handler, (void*)js_wifi); 362 | rt_wlan_register_event_handler(RT_WLAN_EVT_READY, networkEvent_handler, (void*)js_wifi); 363 | rt_wlan_register_event_handler(RT_WLAN_EVT_STA_DISCONNECTED, networkEvent_handler, (void*)js_wifi); 364 | } 365 | 366 | DECLARE_HANDLER(openWifi) 367 | { 368 | if (args_cnt >= 1) 369 | { 370 | char *name = RT_NULL; 371 | 372 | if (jerry_value_is_string(args[0])) 373 | { 374 | name = js_value_to_string(args[0]); 375 | } 376 | 377 | if (name) 378 | { 379 | rt_err_t ret = rt_wlan_set_mode(name, RT_WLAN_STATION); 380 | if (ret == RT_EOK) 381 | { 382 | return jerry_create_boolean(true); 383 | } 384 | } 385 | } 386 | 387 | return jerry_create_boolean(false); 388 | } 389 | 390 | DECLARE_HANDLER(scanWifi) 391 | { 392 | rt_err_t ret = rt_wlan_scan(); 393 | if (ret == RT_EOK) 394 | { 395 | return jerry_create_boolean(true); 396 | } 397 | 398 | return jerry_create_boolean(false); 399 | } 400 | 401 | DECLARE_HANDLER(connectWifi) 402 | { 403 | if (args_cnt >= 1 && jerry_value_is_object(args[0])) 404 | { 405 | char *ssid = RT_NULL; 406 | char *bssid = RT_NULL; 407 | char *password = RT_NULL; 408 | struct wifi_info *info= RT_NULL; 409 | 410 | get_wifi_info((void**)&info, this_value); 411 | if (info) 412 | { 413 | jerry_value_t js_ssid = js_get_property(args[0], "ssid"); 414 | jerry_value_t js_bssid = js_get_property(args[0], "bssid"); 415 | jerry_value_t js_password = js_get_property(args[0], "password"); 416 | 417 | if (jerry_value_is_string(js_ssid)) 418 | { 419 | ssid = js_value_to_string(js_ssid); 420 | } 421 | jerry_release_value(js_ssid); 422 | 423 | if (jerry_value_is_string(js_bssid)) 424 | { 425 | bssid = js_value_to_string(js_bssid); 426 | } 427 | jerry_release_value(js_bssid); 428 | 429 | if (jerry_value_is_string(js_password)) 430 | { 431 | password = js_value_to_string(js_password); 432 | } 433 | jerry_release_value(js_password); 434 | 435 | if (ssid) 436 | { 437 | rt_err_t ret = -1; 438 | 439 | ret = connect_wifi(info, ssid, password, bssid); 440 | if (ret == RT_EOK) 441 | { 442 | free(ssid); 443 | free(password); 444 | free(bssid); 445 | return jerry_create_boolean(true); 446 | } 447 | 448 | if (ret == -2) 449 | { 450 | ret = rt_wlan_scan(); 451 | if (ret == RT_EOK) 452 | { 453 | free(info->ssid); 454 | free(info->password); 455 | free(info->bssid); 456 | info->ssid = ssid; 457 | info->password = password; 458 | info->bssid = bssid; 459 | 460 | return jerry_create_boolean(true); 461 | } 462 | } 463 | } 464 | 465 | free(ssid); 466 | free(password); 467 | free(bssid); 468 | } 469 | } 470 | 471 | return jerry_create_boolean(false); 472 | } 473 | 474 | DECLARE_HANDLER(disconnectWifi) 475 | { 476 | rt_err_t ret = rt_wlan_disconnect(); 477 | if (ret == RT_EOK) 478 | { 479 | return jerry_create_boolean(true); 480 | } 481 | 482 | return jerry_create_boolean(false); 483 | } 484 | 485 | DECLARE_HANDLER(onScanEvent) 486 | { 487 | if (args_cnt == 1 && jerry_value_is_function(args[0])) 488 | { 489 | js_add_event_listener(this_value, "ScanEvent", args[0]); 490 | } 491 | 492 | return jerry_create_undefined(); 493 | } 494 | 495 | DECLARE_HANDLER(onConnectEvent) 496 | { 497 | if (args_cnt == 1 && jerry_value_is_function(args[0])) 498 | { 499 | js_add_event_listener(this_value, "ConnectEvent", args[0]); 500 | } 501 | 502 | return jerry_create_undefined(); 503 | } 504 | 505 | DECLARE_HANDLER(onNetworkEvent) 506 | { 507 | if (args_cnt == 1 && jerry_value_is_function(args[0])) 508 | { 509 | js_add_event_listener(this_value, "NetworkEvent", args[0]); 510 | } 511 | 512 | return jerry_create_undefined(); 513 | } 514 | 515 | DECLARE_HANDLER(getConnectedWifi) 516 | { 517 | struct rt_wlan_info info; 518 | 519 | if (rt_wlan_is_connected()) 520 | { 521 | rt_err_t ret = rt_wlan_get_info(&info); 522 | if (ret == RT_EOK) 523 | { 524 | jerry_value_t js_ssid, js_strength, js_bssid, js_secure; 525 | jerry_value_t js_wifi_info = jerry_create_object(); 526 | if (js_wifi_info) 527 | { 528 | char bssid[32]; 529 | 530 | js_ssid = js_string_to_value((const char*)info.ssid.val); 531 | js_set_property(js_wifi_info, "ssid", js_ssid); 532 | jerry_release_value(js_ssid); 533 | 534 | js_strength = jerry_create_number(info.rssi); 535 | js_set_property(js_wifi_info, "strength", js_strength); 536 | jerry_release_value(js_strength); 537 | 538 | rt_sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", 539 | info.bssid[0], 540 | info.bssid[1], 541 | info.bssid[2], 542 | info.bssid[3], 543 | info.bssid[4], 544 | info.bssid[5]); 545 | 546 | js_bssid = jerry_create_string((const jerry_char_t*)bssid); 547 | js_set_property(js_wifi_info, "bssid", js_bssid); 548 | jerry_release_value(js_bssid); 549 | 550 | js_secure = jerry_create_boolean(info.security); 551 | js_set_property(js_wifi_info, "secure", js_secure); 552 | jerry_release_value(js_secure); 553 | 554 | return js_wifi_info; 555 | } 556 | } 557 | } 558 | 559 | return jerry_create_null(); 560 | } 561 | 562 | DECLARE_HANDLER(destroy) 563 | { 564 | struct wifi_info *info= RT_NULL; 565 | jerry_value_t js_info = js_get_property(this_value, "info"); 566 | 567 | if (js_info) 568 | { 569 | jerry_get_object_native_pointer(js_info, (void **)&info, NULL); 570 | jerry_set_object_native_pointer(js_info, NULL, NULL); 571 | } 572 | jerry_release_value(js_info); 573 | 574 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_SCAN_DONE); 575 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_STA_CONNECTED); 576 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_STA_CONNECTED_FAIL); 577 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_READY); 578 | rt_wlan_unregister_event_handler(RT_WLAN_EVT_STA_DISCONNECTED); 579 | 580 | js_destroy_emitter(this_value); 581 | 582 | if (info) 583 | { 584 | if (info->wifi_list.info) 585 | free(info->wifi_list.info); 586 | 587 | if (info->event_callback) 588 | js_remove_callback(info->event_callback); 589 | 590 | if (info) 591 | free(info); 592 | } 593 | 594 | return jerry_create_undefined(); 595 | } 596 | 597 | DECLARE_HANDLER(createWifi) 598 | { 599 | struct wifi_info* wifi_info = (struct wifi_info*)malloc(sizeof(struct wifi_info)); 600 | 601 | if (wifi_info) 602 | { 603 | jerry_value_t js_wifi = jerry_create_object(); 604 | jerry_value_t js_info = jerry_create_object(); 605 | 606 | if (js_wifi && js_info) 607 | { 608 | memset(wifi_info, 0x00, sizeof(struct wifi_info)); 609 | js_make_emitter(js_wifi, jerry_create_undefined()); 610 | 611 | wifi_info->this_value = js_wifi; 612 | wifi_info->event_callback = js_add_callback(js_event_callback_func_wifi); 613 | 614 | js_set_property(js_wifi, "info", js_info); 615 | jerry_set_object_native_pointer(js_info, wifi_info, &wifi_free_info); 616 | jerry_release_value(js_info); 617 | 618 | REGISTER_METHOD_NAME(js_wifi, "open", openWifi); 619 | REGISTER_METHOD_NAME(js_wifi, "scan", scanWifi); 620 | REGISTER_METHOD_NAME(js_wifi, "connect", connectWifi); 621 | REGISTER_METHOD_NAME(js_wifi, "disconnect", disconnectWifi); 622 | REGISTER_METHOD_NAME(js_wifi, "getConnected", getConnectedWifi); 623 | 624 | REGISTER_METHOD_NAME(js_wifi, "onScanEvent", onScanEvent); 625 | REGISTER_METHOD_NAME(js_wifi, "onConnectEvent", onConnectEvent); 626 | REGISTER_METHOD_NAME(js_wifi, "onNetworkEvent", onNetworkEvent); 627 | REGISTER_METHOD(js_wifi, destroy); 628 | 629 | register_handler(js_wifi); 630 | 631 | return js_wifi; 632 | } 633 | else 634 | { 635 | jerry_release_value(js_wifi); 636 | jerry_release_value(js_info); 637 | } 638 | 639 | free(wifi_info); 640 | } 641 | 642 | return jerry_create_undefined(); 643 | } 644 | 645 | int jerry_wifi_init(jerry_value_t obj) 646 | { 647 | REGISTER_METHOD(obj, createWifi); 648 | 649 | return 0; 650 | } 651 | 652 | #endif 653 | -------------------------------------------------------------------------------- /rtthread-port/jerry_wlan.h: -------------------------------------------------------------------------------- 1 | #ifndef JERRY_WLAN_H__ 2 | #define JERRY_WLAN_H__ 3 | 4 | #include 5 | 6 | #ifdef RT_USING_WIFI 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | struct wifi_ssid 20 | { 21 | char *ssid; 22 | int index; 23 | }; 24 | 25 | struct wifi_info 26 | { 27 | jerry_value_t this_value; 28 | struct js_callback *event_callback; 29 | struct rt_wlan_scan_result wifi_list; 30 | struct wifi_ssid *gb_ssid; 31 | char *ssid; 32 | char *password; 33 | char *bssid; 34 | }; 35 | 36 | struct event_callback_info 37 | { 38 | char *event_name; 39 | jerry_value_t js_return; 40 | jerry_value_t js_target; 41 | }; 42 | 43 | struct close_callback_info 44 | { 45 | jerry_value_t js_target; 46 | }; 47 | 48 | #endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /rtthread-port/port.c: -------------------------------------------------------------------------------- 1 | /* Copyright JS Foundation and other contributors, http://js.foundation 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #include 16 | #include 17 | #include 18 | 19 | #include "jerryscript.h" 20 | #include "jerryscript-port.h" 21 | #include "jerryscript-core.h" 22 | 23 | #ifdef JMEM_STATS 24 | extern void jmem_heap_stats_print (void); 25 | #endif 26 | 27 | /** 28 | * Signal the port that jerry experienced a fatal failure from which it cannot 29 | * recover. 30 | * 31 | * @param code gives the cause of the error. 32 | * 33 | * Note: 34 | * Jerry expects the function not to return. 35 | * 36 | * Example: a libc-based port may implement this with exit() or abort(), or both. 37 | */ 38 | void jerry_port_fatal(jerry_fatal_code_t code) 39 | { 40 | rt_kprintf("jerryScritp fatal ["); 41 | switch (code) 42 | { 43 | case ERR_OUT_OF_MEMORY: 44 | rt_kprintf(" ERR_OUT_OF_MEMORY "); 45 | break; 46 | case ERR_SYSCALL: 47 | rt_kprintf(" ERR_SYSCALL "); 48 | break; 49 | case ERR_REF_COUNT_LIMIT: 50 | rt_kprintf(" ERR_REF_COUNT_LIMIT "); 51 | break; 52 | case ERR_DISABLED_BYTE_CODE: 53 | rt_kprintf(" ERR_DISABLED_BYTE_CODE "); 54 | break; 55 | case ERR_FAILED_INTERNAL_ASSERTION: 56 | rt_kprintf(" ERR_FAILED_INTERNAL_ASSERTION "); 57 | break; 58 | }; 59 | rt_kprintf("]...\n"); 60 | 61 | #ifdef JMEM_STATS 62 | jmem_heap_stats_print(); 63 | #endif 64 | 65 | rt_hw_interrupt_disable(); 66 | while (1); 67 | } 68 | 69 | /* 70 | * I/O Port API 71 | */ 72 | #define RT_JS_CONSOLEBUF_SIZE 256 73 | static char rt_log_buf[RT_JS_CONSOLEBUF_SIZE]; 74 | 75 | /** 76 | * Display or log a debug/error message. The function should implement a printf-like 77 | * interface, where the first argument specifies the log level 78 | * and the second argument specifies a format string on how to stringify the rest 79 | * of the parameter list. 80 | * 81 | * This function is only called with messages coming from the jerry engine as 82 | * the result of some abnormal operation or describing its internal operations 83 | * (e.g., data structure dumps or tracing info). 84 | * 85 | * It should be the port that decides whether error and debug messages are logged to 86 | * the console, or saved to a database or to a file. 87 | * 88 | * Example: a libc-based port may implement this with vfprintf(stderr) or 89 | * vfprintf(logfile), or both, depending on log level. 90 | */ 91 | void jerry_port_log (jerry_log_level_t level, const char *format, ...) 92 | { 93 | va_list args; 94 | rt_size_t length; 95 | 96 | va_start(args, format); 97 | /* the return value of vsnprintf is the number of bytes that would be 98 | * written to buffer had if the size of the buffer been sufficiently 99 | * large excluding the terminating null byte. If the output string 100 | * would be larger than the rt_log_buf, we have to adjust the output 101 | * length. */ 102 | length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, format, args); 103 | if (length > RT_JS_CONSOLEBUF_SIZE - 1) 104 | length = RT_JS_CONSOLEBUF_SIZE - 1; 105 | #ifdef RT_USING_DEVICE 106 | rt_kprintf("%s", rt_log_buf); 107 | #else 108 | rt_hw_console_output(rt_log_buf); 109 | #endif 110 | va_end(args); 111 | } 112 | 113 | /** 114 | * Default implementation of jerryx_port_handler_print_char. Uses 'printf' to 115 | * print a single character to standard output. 116 | */ 117 | void jerryx_port_handler_print_char (char c) /**< the character to print */ 118 | { 119 | rt_kprintf("%c", c); 120 | } /* jerryx_port_handler_print_char */ 121 | 122 | /* 123 | * Date Port API 124 | */ 125 | 126 | /** 127 | * Get timezone and daylight saving data 128 | * 129 | * @return true - if success 130 | * false - otherwise 131 | */ 132 | bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p) 133 | { 134 | tz_p->offset = 0; 135 | tz_p->daylight_saving_time = 0; 136 | return true; 137 | } 138 | 139 | /** 140 | * Get system time 141 | * 142 | * @return milliseconds since Unix epoch 143 | */ 144 | double jerry_port_get_current_time (void) 145 | { 146 | return rt_tick_get() * RT_TICK_PER_SECOND / 1000; 147 | } 148 | 149 | /** 150 | * Pointer to the current instance. 151 | * Note that it is a global variable, and is not a thread safe implementation. 152 | */ 153 | static jerry_context_t *jerry_default_context = NULL; 154 | 155 | /** 156 | * Set the jerry_default_context as the passed pointer. 157 | */ 158 | void 159 | jerry_port_set_default_context(jerry_context_t *context) 160 | { 161 | jerry_default_context = context; 162 | } 163 | 164 | /** 165 | * Get the current context of the engine. Each port should provide its own 166 | * implementation of this interface. 167 | * 168 | * Note: 169 | * This port function is called by jerry-core when 170 | * JERRY_ENABLE_EXTERNAL_CONTEXT is defined. Otherwise this function is not 171 | * used. 172 | * 173 | * @return the pointer to the engine context. 174 | */ 175 | struct jerry_context_t *jerry_port_get_current_context(void) 176 | { 177 | return jerry_default_context; 178 | } 179 | 180 | void jerry_port_sleep(uint32_t sleep_time) 181 | { 182 | rt_thread_delay(rt_tick_from_millisecond(sleep_time)); 183 | } 184 | 185 | #ifdef JMEM_STATS 186 | 187 | void jmem_heap(void) 188 | { 189 | jmem_heap_stats_print(); 190 | } 191 | MSH_CMD_EXPORT(jmem_heap, jerry mem heap stats print); 192 | 193 | #endif 194 | --------------------------------------------------------------------------------