diff --git a/FA/NapiStudy_HellNapi/.gitignore b/FA/NapiStudy_HellNapi/.gitignore new file mode 100755 index 0000000000000000000000000000000000000000..56f46e5c84708507a4d97cbde11ce5b214f779c7 --- /dev/null +++ b/FA/NapiStudy_HellNapi/.gitignore @@ -0,0 +1,5 @@ +/node_modules +/local.properties +/.idea +**/build +/.hvigor \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/AppScope/app.json5 b/FA/NapiStudy_HellNapi/AppScope/app.json5 new file mode 100755 index 0000000000000000000000000000000000000000..50eafdc2df1876952d4fb5328df5060f369fc596 --- /dev/null +++ b/FA/NapiStudy_HellNapi/AppScope/app.json5 @@ -0,0 +1,11 @@ +{ + "app": { + "bundleName": "com.example.hellnapi", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "distributedNotificationEnabled": true + } +} diff --git a/FA/NapiStudy_HellNapi/AppScope/resources/base/element/string.json b/FA/NapiStudy_HellNapi/AppScope/resources/base/element/string.json new file mode 100755 index 0000000000000000000000000000000000000000..814f7badafb424edcadbeb8b94569ada6362d42a --- /dev/null +++ b/FA/NapiStudy_HellNapi/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "HellNapi" + } + ] +} diff --git a/FA/NapiStudy_HellNapi/AppScope/resources/base/media/app_icon.png b/FA/NapiStudy_HellNapi/AppScope/resources/base/media/app_icon.png new file mode 100755 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/FA/NapiStudy_HellNapi/AppScope/resources/base/media/app_icon.png differ diff --git a/FA/NapiStudy_HellNapi/build-profile.json5 b/FA/NapiStudy_HellNapi/build-profile.json5 new file mode 100755 index 0000000000000000000000000000000000000000..f56eb9ce06906aee9a8483de2bc40438e719af1b --- /dev/null +++ b/FA/NapiStudy_HellNapi/build-profile.json5 @@ -0,0 +1,27 @@ +{ + "app": { + "signingConfigs": [], + "compileSdkVersion": 9, + "compatibleSdkVersion": 9, + "products": [ + { + "name": "default", + "signingConfig": "default", + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/.gitignore b/FA/NapiStudy_HellNapi/entry/.gitignore new file mode 100755 index 0000000000000000000000000000000000000000..4a65948351bcf95d2be1fa983394377e3aaa3a2e --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/.preview +/build +/.cxx \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/build-profile.json5 b/FA/NapiStudy_HellNapi/entry/build-profile.json5 new file mode 100755 index 0000000000000000000000000000000000000000..9fe5360a8a6d0d8d6b7371ae6da258cf14178ef4 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/build-profile.json5 @@ -0,0 +1,22 @@ +{ + "apiType": 'stageMode', + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "abiFilters": [ + "armeabi-v7a", + "arm64-v8a" + ], + "cppFlags": "", + } + }, + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/hvigorfile.js b/FA/NapiStudy_HellNapi/entry/hvigorfile.js new file mode 100755 index 0000000000000000000000000000000000000000..d7720ee6a7aad5c617d1fd2f6fc8c87067bfa32c --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').hapTasks diff --git a/FA/NapiStudy_HellNapi/entry/package-lock.json b/FA/NapiStudy_HellNapi/entry/package-lock.json new file mode 100755 index 0000000000000000000000000000000000000000..8fe0620a2347567342a28f4f60e98db8091dbae6 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/package-lock.json @@ -0,0 +1,12 @@ +{ + "name": "entry", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/libentry.so": { + "version": "file:src/main/cpp/types/libentry", + "dev": true + } + } +} diff --git a/FA/NapiStudy_HellNapi/entry/package.json b/FA/NapiStudy_HellNapi/entry/package.json new file mode 100755 index 0000000000000000000000000000000000000000..660ab23bc8f6e71c0f27aba309b697ace6e8843e --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/package.json @@ -0,0 +1,16 @@ +{ + "name": "entry", + "version": "1.0.0", + "ohos": { + "org": "huawei", + "buildTool": "hvigor", + "directoryLevel": "module" + }, + "description": "example description", + "repository": {}, + "license": "ISC", + "dependencies": {}, + "devDependencies": { + "@types/libentry.so": "file:./src/main/cpp/types/libentry" + } +} diff --git a/FA/NapiStudy_HellNapi/entry/src/main/cpp/CMakeLists.txt b/FA/NapiStudy_HellNapi/entry/src/main/cpp/CMakeLists.txt new file mode 100755 index 0000000000000000000000000000000000000000..1013fd58fd6f518b5947d62628ef89dd9f9d9aca --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,11 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.4.1) +project(HellNapi) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +add_library(entry SHARED hello.cpp) +target_link_libraries(entry PUBLIC libace_napi.z.so) \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/main/cpp/hello.cpp b/FA/NapiStudy_HellNapi/entry/src/main/cpp/hello.cpp new file mode 100755 index 0000000000000000000000000000000000000000..956cb0a04a59513885bdaff2ed13d46bba2e223f --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/cpp/hello.cpp @@ -0,0 +1,62 @@ + +#include + +#include "napi/native_api.h" + +static napi_value Add(napi_env env, napi_callback_info info) +{ + // 获取2个参数,值的类型是js类型(napi_value) + size_t argc = 2; + napi_value args[2]; + napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); + // 将js类型(napi_value)的参数值转换成C++类型double + double value0; + napi_get_value_double(env, args[0], &value0); + double value1; + napi_get_value_double(env, args[1], &value1); + + // 业务逻辑运算 + double sum = value0 + value1; + // 将结果由C++类型(double)转换成js类型(napi_value) + napi_value reuslt; + napi_create_double(env, sum, &reuslt); + + // 将结果返回到JS + return reuslt; +} + +static napi_value getHelloString(napi_env env, napi_callback_info info) { + napi_value result; + std::string words = "Hello Napi"; + if (napi_create_string_utf8(env, words.c_str(), words.length(), &result) != napi_ok) { + return nullptr; + } + return result; +} + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "getHelloString", nullptr, getHelloString, nullptr, nullptr, nullptr, napi_default, nullptr } + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version =1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "hello", + .nm_priv = ((void*)0), + .reserved = { 0 }, +}; + +extern "C" __attribute__((constructor)) void RegisterHelloModule(void) +{ + napi_module_register(&demoModule); +} diff --git a/FA/NapiStudy_HellNapi/entry/src/main/cpp/types/libentry/index.d.ts b/FA/NapiStudy_HellNapi/entry/src/main/cpp/types/libentry/index.d.ts new file mode 100755 index 0000000000000000000000000000000000000000..a724b66437869e457817bec305a988126ca73c15 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/cpp/types/libentry/index.d.ts @@ -0,0 +1,2 @@ +export const getHelloString: () => string; +export const add: (a: number, b: number) => number; \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/main/cpp/types/libentry/package.json b/FA/NapiStudy_HellNapi/entry/src/main/cpp/types/libentry/package.json new file mode 100755 index 0000000000000000000000000000000000000000..395f926a91a01f86098fe39603b1a42d2e1533a8 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/cpp/types/libentry/package.json @@ -0,0 +1,4 @@ +{ + "name": "libentry.so", + "types": "./index.d.ts" +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/main/ets/Application/MyAbilityStage.ts b/FA/NapiStudy_HellNapi/entry/src/main/ets/Application/MyAbilityStage.ts new file mode 100755 index 0000000000000000000000000000000000000000..32dfe93ccff0375201857794de902cec4d239442 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/ets/Application/MyAbilityStage.ts @@ -0,0 +1,7 @@ +import AbilityStage from "@ohos.application.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log("[Demo] MyAbilityStage onCreate") + } +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/main/ets/MainAbility/MainAbility.ts b/FA/NapiStudy_HellNapi/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100755 index 0000000000000000000000000000000000000000..d8f4611e0cfb222c932d7aa06a2b52442967a0fc --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/ets/MainAbility/MainAbility.ts @@ -0,0 +1,51 @@ +import hilog from '@ohos.hilog'; +import Ability from '@ohos.application.Ability' +import Window from '@ohos.window' + +export default class MainAbility extends Ability { + onCreate(want, launchParam) { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); + } + + onDestroy() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: Window.WindowStage) { + // Main window is created, set main page for this ability + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/index', (err, data) => { + if (err.code) { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.ERROR); + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground() { + // Ability has back to background + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +}; diff --git a/FA/NapiStudy_HellNapi/entry/src/main/ets/pages/index.ets b/FA/NapiStudy_HellNapi/entry/src/main/ets/pages/index.ets new file mode 100755 index 0000000000000000000000000000000000000000..113cd6cf17c266a3b05c7fd7b69883b63a243b63 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/ets/pages/index.ets @@ -0,0 +1,28 @@ +import hilog from '@ohos.hilog'; +import testNapi from 'libentry.so' + +@Entry +@Component +struct Index { + @State message: string = 'Hello World' + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + this.message = testNapi.getHelloString() + hilog.info(0x0000, 'Test NAPI', 'Test NAPI get string : ' + this.message); + let num1 = 123 + let num2 = 456 + let result = testNapi.add(num1, num2) + hilog.info(0x0000, 'Test NAPI', 'Test NAPI (123+456) = ' + result); + }) + } + .width('100%') + } + .height('100%') + } +} diff --git a/FA/NapiStudy_HellNapi/entry/src/main/module.json5 b/FA/NapiStudy_HellNapi/entry/src/main/module.json5 new file mode 100755 index 0000000000000000000000000000000000000000..5f9c8d8635d4ffbc778f6fc5ebd79f83843760d4 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/module.json5 @@ -0,0 +1,38 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "srcEntrance": "./ets/Application/MyAbilityStage.ts", + "description": "$string:entry_desc", + "mainElement": "MainAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:MainAbility_desc", + "icon": "$media:icon", + "label": "$string:MainAbility_label", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:white", + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/main/resources/base/element/color.json b/FA/NapiStudy_HellNapi/entry/src/main/resources/base/element/color.json new file mode 100755 index 0000000000000000000000000000000000000000..62a137a61b90c14f109ed8c81d9d551ea0a5888a --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/main/resources/base/element/string.json b/FA/NapiStudy_HellNapi/entry/src/main/resources/base/element/string.json new file mode 100755 index 0000000000000000000000000000000000000000..9868c7395cb8da3f49e03757842312748780962f --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "entry_desc", + "value": "description" + }, + { + "name": "MainAbility_label", + "value": "label" + }, + { + "name": "MainAbility_desc", + "value": "description" + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/main/resources/base/media/icon.png b/FA/NapiStudy_HellNapi/entry/src/main/resources/base/media/icon.png new file mode 100755 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/FA/NapiStudy_HellNapi/entry/src/main/resources/base/media/icon.png differ diff --git a/FA/NapiStudy_HellNapi/entry/src/main/resources/base/profile/main_pages.json b/FA/NapiStudy_HellNapi/entry/src/main/resources/base/profile/main_pages.json new file mode 100755 index 0000000000000000000000000000000000000000..feec276e105eeb8d621c20aaf838f318b0a94150 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/index" + ] +} diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/Application/TestAbilityStage.ts b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/Application/TestAbilityStage.ts new file mode 100755 index 0000000000000000000000000000000000000000..2e8d46539605384ae2d7c63067495ceb3003c0d9 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/Application/TestAbilityStage.ts @@ -0,0 +1,7 @@ +import AbilityStage from "@ohos.application.AbilityStage" + +export default class TestAbilityStage extends AbilityStage { + onCreate() { + console.log("[Demo] TestAbilityStage onCreate") + } +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/TestAbility/TestAbility.ets b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/TestAbility/TestAbility.ets new file mode 100755 index 0000000000000000000000000000000000000000..b1a1a7717a0b74e464b0244323d4c3c465703acf --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/TestAbility/TestAbility.ets @@ -0,0 +1,59 @@ +import hilog from '@ohos.hilog'; +import Ability from '@ohos.application.Ability' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../test/List.test' +import Window from '@ohos.window' + +export default class TestAbility extends Ability { + onCreate(want, launchParam) { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? ''); + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + onDestroy() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: Window.WindowStage) { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('TestAbility/pages/index', (err, data) => { + if (err.code) { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.ERROR); + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + + globalThis.abilityContext = this.context; + } + + onWindowStageDestroy() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/TestAbility/pages/index.ets b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/TestAbility/pages/index.ets new file mode 100755 index 0000000000000000000000000000000000000000..733600abc03d7e777ef1a55eaddd77f4d1d7d66d --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/TestAbility/pages/index.ets @@ -0,0 +1,34 @@ +import router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100755 index 0000000000000000000000000000000000000000..bdbe7cf017a787a625bbf23cc62e825821b16d6b --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,64 @@ +import TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log("onAbilityCreateCallback"); +} + +async function addAbilityMonitorCallback(err: any) { + console.info("addAbilityMonitorCallback : " + JSON.stringify(err)) +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare ") + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + var debug = abilityDelegatorArguments.parameters["-D"] + if (debug == 'true') + { + cmd += ' -D' + } + console.info('cmd : '+cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end') + } +}; \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/test/Ability.test.ets b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100755 index 0000000000000000000000000000000000000000..df49ed0fbb519c98ce90324b482aabaa8745cf6a --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,13 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function abilityTest() { + describe('ActsAbilityTest', function () { + it('assertContain',0, function () { + console.info("it begin") + let a = 'abc' + let b = 'b' + expect(a).assertContain(b) + expect(a).assertEqual(a) + }) + }) +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/test/List.test.ets b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/test/List.test.ets new file mode 100755 index 0000000000000000000000000000000000000000..d766fe249dfc3ada636f27e64d9b64451ce32c93 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test' + +export default function testsuite() { + abilityTest() +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/module.json5 b/FA/NapiStudy_HellNapi/entry/src/ohosTest/module.json5 new file mode 100755 index 0000000000000000000000000000000000000000..15650fcf15aea0f41c35655361507cc8aa01d8cc --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/module.json5 @@ -0,0 +1,38 @@ +{ + "module": { + "name": "entry_test", + "type": "feature", + "srcEntrance": "./ets/Application/TestAbilityStage.ts", + "description": "$string:entry_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntrance": "./ets/TestAbility/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "visible": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:white", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/element/color.json b/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/element/color.json new file mode 100755 index 0000000000000000000000000000000000000000..1bbc9aa9617e97c45440e1d3d66afc1154837012 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/element/string.json b/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/element/string.json new file mode 100755 index 0000000000000000000000000000000000000000..36d4230c53e9f5a07ae343ad8dc9808341975e3b --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "entry_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/media/icon.png b/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/media/icon.png new file mode 100755 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/profile/test_pages.json b/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100755 index 0000000000000000000000000000000000000000..fcef82b4dfc18e28106ff9ecd1c8b48ec74d18a4 --- /dev/null +++ b/FA/NapiStudy_HellNapi/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "TestAbility/pages/index" + ] +} diff --git a/FA/NapiStudy_HellNapi/hvigorfile.js b/FA/NapiStudy_HellNapi/hvigorfile.js new file mode 100755 index 0000000000000000000000000000000000000000..586ced98461bdcdac2b070f2e041e99c7ac678d9 --- /dev/null +++ b/FA/NapiStudy_HellNapi/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').appTasks \ No newline at end of file diff --git a/FA/NapiStudy_HellNapi/package-lock.json b/FA/NapiStudy_HellNapi/package-lock.json new file mode 100755 index 0000000000000000000000000000000000000000..e4adc9d6a7062ccd7634234df8ce38d831fc0cb2 --- /dev/null +++ b/FA/NapiStudy_HellNapi/package-lock.json @@ -0,0 +1,1226 @@ +{ + "name": "hellnapi", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ohos/hos-sdkmanager-common": { + "version": "1.0.4", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hos-sdkmanager-common/-/@ohos/hos-sdkmanager-common-1.0.4.tgz", + "integrity": "sha512-LWrfF8Js+u54BcEAdyjzsA81iGBA4LPvQdQ1ig/pX6mvTieUPSvtjtAzdI8nnGVmJRLrHwAMHEO/syd9d8UAFw==", + "requires": { + "@ohos/sdkmanager-common": "^1.1.8" + } + }, + "@ohos/hvigor": { + "version": "1.2.2", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hvigor/-/@ohos/hvigor-1.2.2.tgz", + "integrity": "sha512-GfXCf7pDnyEcxWkG7Edd23XPxgym1vY37zdNt/Gj0pZmw0f+FrP+blfCzVWfYQYlI76krzd96+kvD4lgWkIPBQ==", + "requires": { + "@ohos/hvigor-base": "1.2.2", + "fs-extra": "10.0.1", + "interpret": "1.4.0", + "liftoff": "4.0.0", + "mute-stdout": "1.0.0", + "pretty-hrtime": "1.0.0", + "v8flags": "3.2.0", + "yargs": "7.1.2" + } + }, + "@ohos/hvigor-base": { + "version": "1.2.2", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hvigor-base/-/@ohos/hvigor-base-1.2.2.tgz", + "integrity": "sha512-omwL/qjTE7DTCQdHZnMKuAxKlH1JOgOxaVAae1ca8j/oPuNgY6Spn+mpYRDHIktvav6axMmHT9zV1hJykY4GEg==", + "requires": { + "fs-extra": "10.0.1", + "json5": "2.2.0", + "log4js": "6.4.1", + "once": "1.4.0", + "pretty-hrtime": "1.0.0" + } + }, + "@ohos/hvigor-ohos-plugin": { + "version": "1.2.2", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hvigor-ohos-plugin/-/@ohos/hvigor-ohos-plugin-1.2.2.tgz", + "integrity": "sha512-gir91UxlhMbf2E/NjTYWJGrsNGBKD/1YYbaEdmswD/qW18UDY7jyuqSVyV/gj0h9+iji+gd53rXWzpLLztG5lg==", + "requires": { + "@ohos/hos-sdkmanager-common": "1.0.4", + "@ohos/hvigor-base": "1.2.2", + "@ohos/sdkmanager-common": "1.1.8", + "adm-zip": "0.5.9", + "ajv": "8.10.0", + "execa": "5.1.1", + "fast-xml-parser": "4.0.3", + "fs-extra": "10.0.1", + "glob": "7.2.0", + "iconv-lite": "0.6.3", + "json5": "2.2.0", + "lodash": "4.17.21", + "pretty-hrtime": "1.0.3", + "resolve-package-path": "4.0.3" + }, + "dependencies": { + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==" + } + } + }, + "@ohos/hypium": { + "version": "1.0.2", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hypium/-/@ohos/hypium-1.0.2.tgz", + "integrity": "sha512-HWW62q6hbd0PhvPTH96lo4j//owFwyCLj6Q2jmVLDW6mOt1dwJJwUQ7qUH+Cni/6MmcnyXKvt9I0moGAPK1aCw==" + }, + "@ohos/sdkmanager-common": { + "version": "1.1.8", + "resolved": "https://repo.harmonyos.com/npm/@ohos/sdkmanager-common/-/@ohos/sdkmanager-common-1.1.8.tgz", + "integrity": "sha512-mxq69+6Zg/ybeQGnOtkBzOTbNBkEdiYehRKWsAD/je53v1W+ahauLqe90pNZEiBuVYugzb6z2EaJtAXYZtE8gQ==" + }, + "adm-zip": { + "version": "0.5.9", + "resolved": "https://repo.huaweicloud.com/repository/npm/adm-zip/-/adm-zip-0.5.9.tgz", + "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==" + }, + "ajv": { + "version": "8.10.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==" + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://repo.huaweicloud.com/repository/npm/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "date-format": { + "version": "4.0.14", + "resolved": "https://repo.huaweicloud.com/repository/npm/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-xml-parser": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/fast-xml-parser/-/fast-xml-parser-4.0.3.tgz", + "integrity": "sha512-xhQbg3a/EYNHwK0cxIG1nZmVkHX/0tWihamn5pU4Mhd9KEVE2ga8ZJiqEUgB2sApElvAATOdMTLjgqIpvYDUkQ==", + "requires": { + "strnum": "^1.0.5" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fined/-/fined-2.0.0.tgz", + "integrity": "sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==", + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^5.0.0", + "object.defaults": "^1.1.0", + "object.pick": "^1.3.0", + "parse-filepath": "^1.0.2" + } + }, + "flagged-respawn": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/flagged-respawn/-/flagged-respawn-2.0.0.tgz", + "integrity": "sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==" + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "requires": { + "for-in": "^1.0.1" + } + }, + "fs-extra": { + "version": "10.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-intrinsic": { + "version": "1.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "glob": { + "version": "7.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://repo.huaweicloud.com/repository/npm/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://repo.huaweicloud.com/repository/npm/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://repo.huaweicloud.com/repository/npm/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==" + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "json5": { + "version": "2.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "liftoff": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/liftoff/-/liftoff-4.0.0.tgz", + "integrity": "sha512-rMGwYF8q7g2XhG2ulBmmJgWv25qBsqRbDn5gH0+wnuyeFt7QBJlHJmtg5qEdn4pN6WVAUMgXnIxytMFRX9c1aA==", + "requires": { + "extend": "^3.0.2", + "findup-sync": "^5.0.0", + "fined": "^2.0.0", + "flagged-respawn": "^2.0.0", + "is-plain-object": "^5.0.0", + "object.map": "^1.0.1", + "rechoir": "^0.8.0", + "resolve": "^1.20.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "log4js": { + "version": "6.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "requires": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mute-stdout": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/mute-stdout/-/mute-stdout-1.0.0.tgz", + "integrity": "sha512-MaSQenn0f9oxIjtCufclpV00MuYTiHaXPbdcfPIM+quMqoa8cXywjHHx4LhhIAZlXqPWMdcUpYviajfmHtHRJw==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "requires": { + "lcid": "^1.0.0" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pretty-hrtime": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/pretty-hrtime/-/pretty-hrtime-1.0.0.tgz", + "integrity": "sha512-CU2l5CYUAptUYq/671ajexQfXuxJFwwg0n243Kdkx8bTjeenedsWgu8TGHPm03vLfNtk3aTXgySKPp3Usykudw==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "rechoir": { + "version": "0.8.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "requires": { + "resolve": "^1.20.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-package-path": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve-package-path/-/resolve-package-path-4.0.3.tgz", + "integrity": "sha512-SRpNAPW4kewOaNUt8VPqhJ0UMxawMwzJD8V7m1cJfdSTK9ieZwS6K7Dabsm4bmLFM96Z5Y/UznrpG5kt1im8yA==", + "requires": { + "path-root": "^0.1.1" + } + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.12", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==" + }, + "streamroller": { + "version": "3.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/streamroller/-/streamroller-3.1.3.tgz", + "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "strnum": { + "version": "1.0.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + }, + "yargs": { + "version": "7.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "yargs-parser": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } +} diff --git a/FA/NapiStudy_HellNapi/package.json b/FA/NapiStudy_HellNapi/package.json new file mode 100755 index 0000000000000000000000000000000000000000..43275f48854c0b8450254abf96752da431c5a389 --- /dev/null +++ b/FA/NapiStudy_HellNapi/package.json @@ -0,0 +1,17 @@ +{ + "name": "hellnapi", + "version": "1.0.0", + "ohos": { + "org": "huawei", + "buildTool": "hvigor", + "directoryLevel": "project" + }, + "description": "example description", + "repository": {}, + "license": "ISC", + "dependencies": { + "@ohos/hypium": "1.0.2", + "@ohos/hvigor": "1.2.2", + "@ohos/hvigor-ohos-plugin": "1.2.2" + } +} diff --git a/FA/NapiStudy_ObjectWrapTest/.gitignore b/FA/NapiStudy_ObjectWrapTest/.gitignore new file mode 100755 index 0000000000000000000000000000000000000000..56f46e5c84708507a4d97cbde11ce5b214f779c7 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/.gitignore @@ -0,0 +1,5 @@ +/node_modules +/local.properties +/.idea +**/build +/.hvigor \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/AppScope/app.json5 b/FA/NapiStudy_ObjectWrapTest/AppScope/app.json5 new file mode 100755 index 0000000000000000000000000000000000000000..3199789b8a3f6a3ffde932c7f3e73d1ff6993236 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/AppScope/app.json5 @@ -0,0 +1,11 @@ +{ + "app": { + "bundleName": "com.example.objectwraptest", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "distributedNotificationEnabled": true + } +} diff --git a/FA/NapiStudy_ObjectWrapTest/AppScope/resources/base/element/string.json b/FA/NapiStudy_ObjectWrapTest/AppScope/resources/base/element/string.json new file mode 100755 index 0000000000000000000000000000000000000000..471ff971e2fb28706c3f73d6dbb284d1f0f8c649 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ObjectWrapTest" + } + ] +} diff --git a/FA/NapiStudy_ObjectWrapTest/AppScope/resources/base/media/app_icon.png b/FA/NapiStudy_ObjectWrapTest/AppScope/resources/base/media/app_icon.png new file mode 100755 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/FA/NapiStudy_ObjectWrapTest/AppScope/resources/base/media/app_icon.png differ diff --git a/FA/NapiStudy_ObjectWrapTest/build-profile.json5 b/FA/NapiStudy_ObjectWrapTest/build-profile.json5 new file mode 100755 index 0000000000000000000000000000000000000000..d1224b47faa034f5d7ae7de37825b6d98619aaa9 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/build-profile.json5 @@ -0,0 +1,40 @@ +{ + "app": { + "signingConfigs": [ + { + "name": "default", + "material": { + "certpath": "C:\\Users\\Administrator\\.ohos\\config\\openharmony\\auto_ohos_default.cer", + "storePassword": "0000001B64CB7B7E97213A27D964F5F9E6CBD1804851C0426F30DFD20B2CEB1C463298B5B1B24B2635F5FC", + "keyAlias": "debugKey", + "keyPassword": "0000001BEF323C95BA551294DEAB23F585D5477575599200AE1D5BD0735D0410ABE6B75C3E7527BD74C159", + "profile": "C:\\Users\\Administrator\\.ohos\\config\\openharmony\\auto_ohos_default_com.example.objectwraptest.p7b", + "signAlg": "SHA256withECDSA", + "storeFile": "C:\\Users\\Administrator\\.ohos\\config\\openharmony\\auto_ohos_default.p12" + } + } + ], + "compileSdkVersion": 9, + "compatibleSdkVersion": 9, + "products": [ + { + "name": "default", + "signingConfig": "default", + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/.gitignore b/FA/NapiStudy_ObjectWrapTest/entry/.gitignore new file mode 100755 index 0000000000000000000000000000000000000000..4a65948351bcf95d2be1fa983394377e3aaa3a2e --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/.preview +/build +/.cxx \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/build-profile.json5 b/FA/NapiStudy_ObjectWrapTest/entry/build-profile.json5 new file mode 100755 index 0000000000000000000000000000000000000000..df0a642d3ed22ab3bb2082c409a712160902fe7f --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/build-profile.json5 @@ -0,0 +1,22 @@ +{ + "apiType": 'stageMode', + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "-v", + "abiFilters": [ + "armeabi-v7a", + "arm64-v8a" + ], + "cppFlags": "", + } + }, + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/hvigorfile.js b/FA/NapiStudy_ObjectWrapTest/entry/hvigorfile.js new file mode 100755 index 0000000000000000000000000000000000000000..d7720ee6a7aad5c617d1fd2f6fc8c87067bfa32c --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').hapTasks diff --git a/FA/NapiStudy_ObjectWrapTest/entry/package-lock.json b/FA/NapiStudy_ObjectWrapTest/entry/package-lock.json new file mode 100755 index 0000000000000000000000000000000000000000..8fe0620a2347567342a28f4f60e98db8091dbae6 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/package-lock.json @@ -0,0 +1,12 @@ +{ + "name": "entry", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/libentry.so": { + "version": "file:src/main/cpp/types/libentry", + "dev": true + } + } +} diff --git a/FA/NapiStudy_ObjectWrapTest/entry/package.json b/FA/NapiStudy_ObjectWrapTest/entry/package.json new file mode 100755 index 0000000000000000000000000000000000000000..55850f65d9824a848abfe33d8d28d78b025f16e5 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/package.json @@ -0,0 +1,16 @@ +{ + "license": "ISC", + "devDependencies": { + "@types/libentry.so": "file:./src/main/cpp/types/libentry" + }, + "name": "entry", + "ohos": { + "org": "huawei", + "directoryLevel": "module", + "buildTool": "hvigor" + }, + "description": "example description", + "repository": {}, + "version": "1.0.0", + "dependencies": {} +} diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/CMakeLists.txt b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/CMakeLists.txt new file mode 100755 index 0000000000000000000000000000000000000000..f385a480eb0886f54d89823e1c58aa49df5d0492 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,11 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.4.1) +project(ObjectWrapTest) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +add_library(entry SHARED hello.cpp NapiTest.cpp) +target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so) \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/NapiTest.cpp b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/NapiTest.cpp new file mode 100755 index 0000000000000000000000000000000000000000..4c37f527fe436599227558345aaeb73c65adcd04 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/NapiTest.cpp @@ -0,0 +1,138 @@ +// +// Created on 2022/9/23. +// + +#include +#include +#include +#include +#include +#include +#include + +#include "NapiTest.h" + +napi_ref NapiTest::sConstructor_ = nullptr; +std::string NapiTest::_msg=""; + +NapiTest::~NapiTest() +{ + // 是否有创建生命周期,有的话释放 + if (mRef != nullptr) { + napi_delete_reference(mEnv, mRef); + } +} + +napi_value NapiTest::SetMsg(napi_env env, napi_callback_info info) { + napi_value result = nullptr; + napi_get_undefined(env, &result); + char msg[128] = {0}; + + napi_value msgvalue; + size_t argc = 1, size = 0; + + if (napi_get_cb_info(env, info, &argc, &msgvalue, nullptr, nullptr) != napi_ok) { + return result; + } + + if (napi_get_value_string_utf8(env, msgvalue, msg, sizeof(msg), &size) != napi_ok) { + return result; + } + + _msg = msg; + + return result; +} + +napi_value NapiTest::GetMsg(napi_env env, napi_callback_info info) { + napi_value result = nullptr; + char *msg= "hello NapiTest"; + + napi_get_undefined(env, &result); + + if (_msg.length() > 0) { + msg = (char *)(_msg.c_str()); + } + + if (napi_create_string_utf8(env, msg, strlen(msg), &result) != napi_ok) { + return result; + } + + return result; +} + +napi_value NapiTest::Create(napi_env env, napi_callback_info info) { + napi_status status; + napi_value constructor = nullptr, result = nullptr; + // 获取生命周期变量 + status = napi_get_reference_value(env, sConstructor_, &constructor); + + // 创建生命周期内的对象并将其返回 + status = napi_new_instance(env, constructor, 0, nullptr, &result); + auto napiTest = new NapiTest(); + // 绑定实例类napiTest到导出的对象result + if (napi_wrap(env, result, reinterpret_cast(napiTest), Destructor, nullptr, &(napiTest->mRef)) == napi_ok) { + return result; + } + + return nullptr; +} + +napi_value NapiTest::Constructor(napi_env env, napi_callback_info info) +{ + napi_value undefineVar = nullptr, thisVar = nullptr; + napi_get_undefined(env, &undefineVar); + + // 获取传入的参数对象,对象不为空,根据该参数创建实例并并绑定到该对象 + if (napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr) == napi_ok && thisVar != nullptr) { + + // 创建NapiTest 实例 + NapiTest *reference = new NapiTest(env); + + // 绑定实例到对象并获取对象的生命周期 + if (napi_wrap(env, thisVar, reinterpret_cast(reference), NapiTest::Destructor, nullptr, &(reference->mRef)) == napi_ok) { + return thisVar; + } + + return thisVar; + } + + return undefineVar; +} + +void NapiTest::Destructor(napi_env env, void *nativeObject, void *finalize) +{ + // 释放资源 + NapiTest *test = reinterpret_cast(nativeObject); + test->~NapiTest(); +} + +napi_value NapiTest::Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "getMsg", nullptr, NapiTest::GetMsg, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "setMsg", nullptr, NapiTest::SetMsg, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "create", nullptr, NapiTest::Create, nullptr, nullptr, nullptr, napi_default, nullptr } + }; + + napi_value constructor = nullptr; + + // 定义 JS的类 + if (napi_define_class(env, NAPI_CLASS_NAME, NAPI_AUTO_LENGTH, Constructor, nullptr, sizeof(desc) / sizeof(desc[0]), + desc, &constructor) != napi_ok) { + return nullptr; + } + + // 创建生命周期,初始引用计数设为1 + if (napi_create_reference(env, constructor, 1, &sConstructor_) != napi_ok) { + return nullptr; + } + + // 设置NapiTest对象相关属性并绑定到导出变量exports + if (napi_set_named_property(env, exports, NAPI_CLASS_NAME, constructor) != napi_ok) { + return nullptr; + } + + // 返回已经绑定对应导出类对象的值 + return exports; +} diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/NapiTest.h b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/NapiTest.h new file mode 100755 index 0000000000000000000000000000000000000000..5cfa6be767ac532adafeffc3ff89fffd235810e0 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/NapiTest.h @@ -0,0 +1,38 @@ + + +#ifndef __NAPI_TEST_H__ +#define __NAPI_TEST_H__ + +#include "napi/native_api.h" +#include + +#include + +#define NAPI_CLASS_NAME "NapiTestClass" + +class NapiTest { +public: + NapiTest() : mEnv(nullptr), mRef(nullptr) { + } + NapiTest(napi_env env) : mEnv(env), mRef(nullptr){ + } + ~NapiTest(); + + static napi_value Create(napi_env env, napi_callback_info info); + static napi_value Init(napi_env env, napi_value exports); + +private: + static napi_value SetMsg(napi_env env, napi_callback_info info); + static napi_value GetMsg(napi_env env, napi_callback_info info); + + static napi_value Constructor(napi_env env, napi_callback_info info); + static void Destructor(napi_env env, void *nativeObject, void *finalize); + + static napi_ref sConstructor_; + static std::string _msg; + + napi_env mEnv = nullptr; + napi_ref mRef = nullptr; +}; + +#endif /* __NAPI_TEST_H__ */ \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/hello.cpp b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/hello.cpp new file mode 100755 index 0000000000000000000000000000000000000000..f35bb23f6542de8a09492c2801f8a2c1e29d9b22 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/hello.cpp @@ -0,0 +1,197 @@ + +#include +#include +#include +#include +#include +#include + +#include "NapiTest.h" +#include "log.h" + +#define TEST_TAG "Test NAPI" + +#define __USE_OBJ__ 1 + +typedef struct { + char msg[128]; + int number; + int (*callback)(void *data); +} Test; + +int checkData(void *data) { + char *msg = (char *)data; + if (msg == nullptr) { + return -1; + } + HILOGD(TEST_TAG":%s\r\n", msg); + return 0; +} + +Test *CreateTestInfo() +{ + Test *t = (Test *)malloc(sizeof(Test)); + if (t == nullptr) { + return nullptr; + } + memset(t, 0x00, sizeof(Test)); + strcpy(t->msg, "test msg 123!"); + t->number = strlen(t->msg); + t->callback = checkData; + HILOGI(TEST_TAG); + return t; +} + +napi_status SetObjectProperty(napi_env env, napi_value &object, const char *name, long type) { + napi_value value = nullptr; + napi_value key; + napi_create_string_utf8(env,name,strlen(name),&key); + napi_create_int64(env, type, &value); + return napi_set_property(env, object, key, value); +} + +static napi_value InitTest(napi_env env, napi_callback_info info) +{ + HILOGI(TEST_TAG"%{public}d \r\n", 1111); + + napi_status status; + napi_value result; + HILOGI(TEST_TAG); + Test *t = CreateTestInfo(); + if (t == nullptr) { + return nullptr; + } +#if (__USE_OBJ__==0) + uint64_t addr = reinterpret_cast(t); + if (napi_create_int64(env, addr, &result) != napi_ok) { + return nullptr; + } + return result; +#else + + status = napi_create_object(env, &result); + if (status != napi_ok) { + return nullptr; + } + + // 将指向“Test”结构的指针存储在JS对象内。 + status = napi_wrap(env, result, t, NULL, NULL, NULL); + if (status != napi_ok) { + return nullptr; + } + + return result; +#endif +} + +static napi_value UnInitTest(napi_env env, napi_callback_info info) +{ + HILOGI(TEST_TAG"%{public}d \r\n", 1111); +#if __USE_OBJ__ + napi_status status; + size_t argc = 1; + napi_value argv; + bool is_test_handle; + + status = napi_get_cb_info(env, info, &argc, &argv , nullptr, nullptr); + if (status != napi_ok) { + return nullptr; + } + + Test *t; + status = napi_unwrap(env, argv, (void **)&t); + if (status != napi_ok || t == nullptr) { + return nullptr; + } + + if (t->callback) { + t->callback(t->msg); + } + + napi_value value; + napi_create_int32(env, 0, &value); + + return value; +#else + napi_value result = nullptr; + size_t argc = 1; + napi_value args = nullptr; + + if (napi_get_cb_info(env, info, &argc, &args, nullptr, nullptr) != napi_ok) { + return nullptr; + } + + int64_t addr; + if (napi_get_value_int64(env, args, &addr) != napi_ok) { + return nullptr; + } + Test *t = (Test *)addr; + if (t->callback) { + t->callback(t->msg); + } + + napi_value value; + napi_create_int32(env, 0, &value); + + return value; +#endif +} + +static napi_value Add(napi_env env, napi_callback_info info) +{ + size_t requireArgc = 2; + size_t argc = 2; + napi_value args[2] = {nullptr}; + + napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); + + napi_valuetype valuetype0; + napi_typeof(env, args[0], &valuetype0); + + napi_valuetype valuetype1; + napi_typeof(env, args[1], &valuetype1); + + double value0; + napi_get_value_double(env, args[0], &value0); + + double value1; + napi_get_value_double(env, args[1], &value1); + + napi_value sum; + napi_create_double(env, value0 + value1, &sum); + + return sum; +} + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + HILOGI(TEST_TAG"%{public}d \r\n", 1111); + + napi_property_descriptor desc[] = { + { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "TestOpen", nullptr, InitTest, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "TestClose", nullptr, UnInitTest, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "create", nullptr, NapiTest::Create, nullptr, nullptr, nullptr, napi_default, nullptr } + }; + + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + + return NapiTest::Init(env, exports); +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version =1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "hello", + .nm_priv = ((void*)0), + .reserved = { 0 }, +}; + +extern "C" __attribute__((constructor)) void RegisterHelloModule(void) +{ + napi_module_register(&demoModule); +} diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/log.h b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/log.h new file mode 100755 index 0000000000000000000000000000000000000000..7a569f21e5de2f32f32a7d86ea65c2c4a9bb33cc --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/log.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_NAPI_COMMON_LOG_H +#define INTERFACES_KITS_NAPI_COMMON_LOG_H + +#include +#include +#include + +#include "hilog/log.h" + +#if __HAVE_DEBUG__ + +#ifdef HILOGD +#undef HILOGD +#endif + +#ifdef HILOGF +#undef HILOGF +#endif + +#ifdef HILOGE +#undef HILOGE +#endif + +#ifdef HILOGW +#undef HILOGW +#endif + +#ifdef HILOGI +#undef HILOGI +#endif + +#define HILOGD(fmt, ...) OH_LOG_DEBUG(LOG_APP, "[%{public}s|%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define HILOGI(fmt, ...) OH_LOG_INFO(LOG_APP, "[%{public}s|%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define HILOGW(fmt, ...) OH_LOG_WARN(LOG_APP, "[%{public}s|%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define HILOGE(fmt, ...) OH_LOG_ERROR(LOG_APP, "[%{public}s|%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define HILOGF(fmt, ...) OH_LOG_FATAL(LOG_APP, "[%{public}s|%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) + +#else +#define HILOGD(fmt, ...) do{}while(0) +#define HILOGI(fmt, ...) do{}while(0) +#define HILOGW(fmt, ...) do{}while(0) +#define HILOGE(fmt, ...) do{}while(0) +#define HILOGF(fmt, ...) do{}while(0) +#endif +#endif \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/types/libentry/index.d.ts b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/types/libentry/index.d.ts new file mode 100755 index 0000000000000000000000000000000000000000..fbf06618ed7d5f3a9cb7f5b2e59ad1f64ce77c8b --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/types/libentry/index.d.ts @@ -0,0 +1,10 @@ + +export const add : (a:number, b:number) => number; +export const TestOpen : () => object; +export const TestClose : (t : object) => void; +export const create : () => NapiTest; +export class NapiTest { + NapiTest(); + setMsg(msg: string): void; + getMsg(): string; +} diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/types/libentry/package.json b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/types/libentry/package.json new file mode 100755 index 0000000000000000000000000000000000000000..395f926a91a01f86098fe39603b1a42d2e1533a8 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/types/libentry/package.json @@ -0,0 +1,4 @@ +{ + "name": "libentry.so", + "types": "./index.d.ts" +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/ets/Application/MyAbilityStage.ts b/FA/NapiStudy_ObjectWrapTest/entry/src/main/ets/Application/MyAbilityStage.ts new file mode 100755 index 0000000000000000000000000000000000000000..32dfe93ccff0375201857794de902cec4d239442 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/ets/Application/MyAbilityStage.ts @@ -0,0 +1,7 @@ +import AbilityStage from "@ohos.application.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log("[Demo] MyAbilityStage onCreate") + } +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/ets/MainAbility/MainAbility.ts b/FA/NapiStudy_ObjectWrapTest/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100755 index 0000000000000000000000000000000000000000..f08a5397f64ace299be7f7b425d25184c9a07c0f --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/ets/MainAbility/MainAbility.ts @@ -0,0 +1,40 @@ +import Ability from '@ohos.application.Ability' + +export default class MainAbility extends Ability { + onCreate(want, launchParam) { + console.log("[Demo] MainAbility onCreate") + globalThis.abilityWant = want; + } + + onDestroy() { + console.log("[Demo] MainAbility onDestroy") + } + + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log("[Demo] MainAbility onWindowStageCreate") + + windowStage.loadContent("pages/index", (err, data) => { + if (err.code) { + console.error('Failed to load the content. Cause:' + JSON.stringify(err)); + return; + } + console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data)) + }); + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + console.log("[Demo] MainAbility onWindowStageDestroy") + } + + onForeground() { + // Ability has brought to foreground + console.log("[Demo] MainAbility onForeground") + } + + onBackground() { + // Ability has back to background + console.log("[Demo] MainAbility onBackground") + } +}; diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/ets/pages/index.ets b/FA/NapiStudy_ObjectWrapTest/entry/src/main/ets/pages/index.ets new file mode 100755 index 0000000000000000000000000000000000000000..3dd3b7efba313ca6f8d974a38653ae9992c57043 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/ets/pages/index.ets @@ -0,0 +1,59 @@ +// @ts-nocheck +import testNapi from "libentry.so"; + +@Entry +@Component + +struct Index { + @State message: string = 'Hello World' + @State nativePointer:number = 0 + + tt = testNapi.create(); + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + console.info("[NapiTest] Test NAPI 2 + 3 = " + testNapi.add(2, 3)); + try{ + if (this.nativePointer == 0) { + // this.nativePointer = testNapi.TestOpen() + // objTest = testNapi.TestOpen() + console.info("[NapiTest] Test NAPI add(2, 3) 1"); + this.nativePointer = testNapi.add(2, 3) + console.info("[NapiTest] Test NAPI add(2, 3) 2"); + + this.tt.setMsg("2+3") + console.info("[NapiTest] Test NAPI add(2, 3) 3"); + + } else { + // testNapi.TestClose(this.nativePointer) + // testNapi.TestClose(objTest) + console.info("[NapiTest] Test NAPI add(0, 0) 1"); + + this.nativePointer = testNapi.add(0, 0) + console.info("[NapiTest] Test NAPI add(0, 0) 2"); + + this.tt.setMsg("4+5") + console.info("[NapiTest] Test NAPI add(0, 0) 3"); + } + } catch(e) { + console.info("[NapiTest]Test NAPI error" + JSON.stringify(e)); + } + + console.info("[NapiTest]Test NAPI " + this.tt.getMsg() + " = " + this.nativePointer); + }) + } + .width('100%') + } + .height('100%') + } +/* + aboutToAppear(){ + this.testApi = new testNapi.NapiTest() + } +*/ +} diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/module.json5 b/FA/NapiStudy_ObjectWrapTest/entry/src/main/module.json5 new file mode 100755 index 0000000000000000000000000000000000000000..f0061c4cdeedfbd26a44ff6be19bd31bffd28c22 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/module.json5 @@ -0,0 +1,39 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "srcEntrance": "./ets/Application/MyAbilityStage.ts", + "description": "$string:entry_desc", + "mainElement": "MainAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "uiSyntax": "ets", + "abilities": [ + { + "name": "MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:MainAbility_desc", + "icon": "$media:icon", + "label": "$string:MainAbility_label", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:white", + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/element/color.json b/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/element/color.json new file mode 100755 index 0000000000000000000000000000000000000000..62a137a61b90c14f109ed8c81d9d551ea0a5888a --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/element/string.json b/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/element/string.json new file mode 100755 index 0000000000000000000000000000000000000000..9868c7395cb8da3f49e03757842312748780962f --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "entry_desc", + "value": "description" + }, + { + "name": "MainAbility_label", + "value": "label" + }, + { + "name": "MainAbility_desc", + "value": "description" + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/media/icon.png b/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/media/icon.png new file mode 100755 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/media/icon.png differ diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/profile/main_pages.json b/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/profile/main_pages.json new file mode 100755 index 0000000000000000000000000000000000000000..feec276e105eeb8d621c20aaf838f318b0a94150 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/index" + ] +} diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/Application/TestAbilityStage.ts b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/Application/TestAbilityStage.ts new file mode 100755 index 0000000000000000000000000000000000000000..2e8d46539605384ae2d7c63067495ceb3003c0d9 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/Application/TestAbilityStage.ts @@ -0,0 +1,7 @@ +import AbilityStage from "@ohos.application.AbilityStage" + +export default class TestAbilityStage extends AbilityStage { + onCreate() { + console.log("[Demo] TestAbilityStage onCreate") + } +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/TestAbility/TestAbility.ts b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/TestAbility/TestAbility.ts new file mode 100755 index 0000000000000000000000000000000000000000..301aaf6099dd794d856d2ab13bf3ef6f13e3ba78 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/TestAbility/TestAbility.ts @@ -0,0 +1,45 @@ +import Ability from '@ohos.application.Ability' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../test/List.test' + +export default class TestAbility extends Ability { + onCreate(want, launchParam) { + console.log('TestAbility onCreate') + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + console.info('start run testcase!!!') + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + onDestroy() { + console.log('TestAbility onDestroy') + } + + onWindowStageCreate(windowStage) { + console.log('TestAbility onWindowStageCreate') + windowStage.loadContent("TestAbility/pages/index", (err, data) => { + if (err.code) { + console.error('Failed to load the content. Cause:' + JSON.stringify(err)); + return; + } + console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data)) + }); + + globalThis.abilityContext = this.context; + } + + onWindowStageDestroy() { + console.log('TestAbility onWindowStageDestroy') + } + + onForeground() { + console.log('TestAbility onForeground') + } + + onBackground() { + console.log('TestAbility onBackground') + } +}; \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/TestAbility/pages/index.ets b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/TestAbility/pages/index.ets new file mode 100755 index 0000000000000000000000000000000000000000..733600abc03d7e777ef1a55eaddd77f4d1d7d66d --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/TestAbility/pages/index.ets @@ -0,0 +1,34 @@ +import router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100755 index 0000000000000000000000000000000000000000..bdbe7cf017a787a625bbf23cc62e825821b16d6b --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,64 @@ +import TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log("onAbilityCreateCallback"); +} + +async function addAbilityMonitorCallback(err: any) { + console.info("addAbilityMonitorCallback : " + JSON.stringify(err)) +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare ") + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + var debug = abilityDelegatorArguments.parameters["-D"] + if (debug == 'true') + { + cmd += ' -D' + } + console.info('cmd : '+cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end') + } +}; \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/test/Ability.test.ets b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100755 index 0000000000000000000000000000000000000000..df49ed0fbb519c98ce90324b482aabaa8745cf6a --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,13 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function abilityTest() { + describe('ActsAbilityTest', function () { + it('assertContain',0, function () { + console.info("it begin") + let a = 'abc' + let b = 'b' + expect(a).assertContain(b) + expect(a).assertEqual(a) + }) + }) +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/test/List.test.ets b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/test/List.test.ets new file mode 100755 index 0000000000000000000000000000000000000000..d766fe249dfc3ada636f27e64d9b64451ce32c93 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test' + +export default function testsuite() { + abilityTest() +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/module.json5 b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/module.json5 new file mode 100755 index 0000000000000000000000000000000000000000..ecb467ef1e859495b2789dfe9965c477417d1a33 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/module.json5 @@ -0,0 +1,39 @@ +{ + "module": { + "name": "entry_test", + "type": "feature", + "srcEntrance": "./ets/Application/TestAbilityStage.ts", + "description": "$string:entry_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "uiSyntax": "ets", + "abilities": [ + { + "name": "TestAbility", + "srcEntrance": "./ets/TestAbility/TestAbility.ts", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "visible": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:white", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/element/color.json b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/element/color.json new file mode 100755 index 0000000000000000000000000000000000000000..1bbc9aa9617e97c45440e1d3d66afc1154837012 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/element/string.json b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/element/string.json new file mode 100755 index 0000000000000000000000000000000000000000..36d4230c53e9f5a07ae343ad8dc9808341975e3b --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "entry_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/media/icon.png b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/media/icon.png new file mode 100755 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/profile/test_pages.json b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100755 index 0000000000000000000000000000000000000000..fcef82b4dfc18e28106ff9ecd1c8b48ec74d18a4 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "TestAbility/pages/index" + ] +} diff --git a/FA/NapiStudy_ObjectWrapTest/hvigorfile.js b/FA/NapiStudy_ObjectWrapTest/hvigorfile.js new file mode 100755 index 0000000000000000000000000000000000000000..586ced98461bdcdac2b070f2e041e99c7ac678d9 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').appTasks \ No newline at end of file diff --git a/FA/NapiStudy_ObjectWrapTest/package-lock.json b/FA/NapiStudy_ObjectWrapTest/package-lock.json new file mode 100755 index 0000000000000000000000000000000000000000..a5fde2b5da29ee75ffaab27779faabe930b2e315 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/package-lock.json @@ -0,0 +1,1227 @@ +{ + "name": "objectwraptest", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ohos/hos-sdkmanager-common": { + "version": "1.0.4", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hos-sdkmanager-common/-/@ohos/hos-sdkmanager-common-1.0.4.tgz", + "integrity": "sha512-LWrfF8Js+u54BcEAdyjzsA81iGBA4LPvQdQ1ig/pX6mvTieUPSvtjtAzdI8nnGVmJRLrHwAMHEO/syd9d8UAFw==", + "requires": { + "@ohos/sdkmanager-common": "^1.1.8" + } + }, + "@ohos/hvigor": { + "version": "1.1.6", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hvigor/-/@ohos/hvigor-1.1.6.tgz", + "integrity": "sha512-/n7cSH3Tc1p5CEgELeJof2MLBYbu96Enmkga8PA1BFoBZnPF+SirHwJyynhtUtOJQOyFkBFQOXmwzq5o2Pdvug==", + "requires": { + "@ohos/hvigor-base": "1.1.6", + "fs-extra": "10.0.0", + "interpret": "1.4.0", + "liftoff": "4.0.0", + "mute-stdout": "1.0.0", + "pretty-hrtime": "1.0.0", + "v8flags": "3.2.0", + "yargs": "7.1.2" + } + }, + "@ohos/hvigor-base": { + "version": "1.1.6", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hvigor-base/-/@ohos/hvigor-base-1.1.6.tgz", + "integrity": "sha512-VU1jdgb+86RZ6fsea1kKP3Dx77DAQmSwGQoFEpjRVPP6aLXpRfM8aLS8DNlpMVEw1dFVQhOOsZ22thcbxinSOA==", + "requires": { + "json5": "2.2.0", + "log4js": "6.4.1", + "once": "1.4.0", + "pretty-hrtime": "1.0.0" + } + }, + "@ohos/hvigor-ohos-plugin": { + "version": "1.1.6", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hvigor-ohos-plugin/-/@ohos/hvigor-ohos-plugin-1.1.6.tgz", + "integrity": "sha512-Bnm1932VypATJf/Cp+sTzsX/oHFojAW7dAbEgfQpwQsyXmQbwXEf0zGnbrjVD0WKtxVVpO+znhpZvrDhOiUXlg==", + "requires": { + "@ohos/hos-sdkmanager-common": "1.0.4", + "@ohos/hvigor-base": "1.1.6", + "@ohos/sdkmanager-common": "1.1.8", + "adm-zip": "0.5.9", + "ajv": "8.10.0", + "execa": "5.1.1", + "fast-xml-parser": "4.0.3", + "fs-extra": "10.0.0", + "glob": "7.2.0", + "iconv-lite": "0.6.3", + "json5": "2.2.0", + "lodash": "4.17.21", + "pretty-hrtime": "1.0.3", + "resolve-package-path": "4.0.3" + }, + "dependencies": { + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==" + } + } + }, + "@ohos/hypium": { + "version": "1.0.1", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hypium/-/@ohos/hypium-1.0.1.tgz", + "integrity": "sha512-HaztFbgwYZCdVlayXirBlmJaNTXUO65qRgYnUmrhWGEzG7wFU2fyFbeXgQeYMVWFXgeezFOoHAPoS96TEE7TIQ==" + }, + "@ohos/sdkmanager-common": { + "version": "1.1.8", + "resolved": "https://repo.harmonyos.com/npm/@ohos/sdkmanager-common/-/@ohos/sdkmanager-common-1.1.8.tgz", + "integrity": "sha512-mxq69+6Zg/ybeQGnOtkBzOTbNBkEdiYehRKWsAD/je53v1W+ahauLqe90pNZEiBuVYugzb6z2EaJtAXYZtE8gQ==" + }, + "adm-zip": { + "version": "0.5.9", + "resolved": "https://repo.huaweicloud.com/repository/npm/adm-zip/-/adm-zip-0.5.9.tgz", + "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==" + }, + "ajv": { + "version": "8.10.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==" + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://repo.huaweicloud.com/repository/npm/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "date-format": { + "version": "4.0.13", + "resolved": "https://repo.huaweicloud.com/repository/npm/date-format/-/date-format-4.0.13.tgz", + "integrity": "sha512-bnYCwf8Emc3pTD8pXnre+wfnjGtfi5ncMDKy7+cWZXbmRAsdWkOQHrfC1yz/KiwP5thDp2kCHWYWKBX4HP1hoQ==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-xml-parser": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/fast-xml-parser/-/fast-xml-parser-4.0.3.tgz", + "integrity": "sha512-xhQbg3a/EYNHwK0cxIG1nZmVkHX/0tWihamn5pU4Mhd9KEVE2ga8ZJiqEUgB2sApElvAATOdMTLjgqIpvYDUkQ==", + "requires": { + "strnum": "^1.0.5" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fined/-/fined-2.0.0.tgz", + "integrity": "sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==", + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^5.0.0", + "object.defaults": "^1.1.0", + "object.pick": "^1.3.0", + "parse-filepath": "^1.0.2" + } + }, + "flagged-respawn": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/flagged-respawn/-/flagged-respawn-2.0.0.tgz", + "integrity": "sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==" + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "requires": { + "for-in": "^1.0.1" + } + }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "dependencies": { + "jsonfile": { + "version": "6.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "glob": { + "version": "7.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://repo.huaweicloud.com/repository/npm/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://repo.huaweicloud.com/repository/npm/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://repo.huaweicloud.com/repository/npm/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==" + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "json5": { + "version": "2.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "liftoff": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/liftoff/-/liftoff-4.0.0.tgz", + "integrity": "sha512-rMGwYF8q7g2XhG2ulBmmJgWv25qBsqRbDn5gH0+wnuyeFt7QBJlHJmtg5qEdn4pN6WVAUMgXnIxytMFRX9c1aA==", + "requires": { + "extend": "^3.0.2", + "findup-sync": "^5.0.0", + "fined": "^2.0.0", + "flagged-respawn": "^2.0.0", + "is-plain-object": "^5.0.0", + "object.map": "^1.0.1", + "rechoir": "^0.8.0", + "resolve": "^1.20.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "log4js": { + "version": "6.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "requires": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mute-stdout": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/mute-stdout/-/mute-stdout-1.0.0.tgz", + "integrity": "sha512-MaSQenn0f9oxIjtCufclpV00MuYTiHaXPbdcfPIM+quMqoa8cXywjHHx4LhhIAZlXqPWMdcUpYviajfmHtHRJw==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "requires": { + "lcid": "^1.0.0" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pretty-hrtime": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/pretty-hrtime/-/pretty-hrtime-1.0.0.tgz", + "integrity": "sha512-CU2l5CYUAptUYq/671ajexQfXuxJFwwg0n243Kdkx8bTjeenedsWgu8TGHPm03vLfNtk3aTXgySKPp3Usykudw==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "rechoir": { + "version": "0.8.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "requires": { + "resolve": "^1.20.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-package-path": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve-package-path/-/resolve-package-path-4.0.3.tgz", + "integrity": "sha512-SRpNAPW4kewOaNUt8VPqhJ0UMxawMwzJD8V7m1cJfdSTK9ieZwS6K7Dabsm4bmLFM96Z5Y/UznrpG5kt1im8yA==", + "requires": { + "path-root": "^0.1.1" + } + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.12", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==" + }, + "streamroller": { + "version": "3.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/streamroller/-/streamroller-3.1.2.tgz", + "integrity": "sha512-wZswqzbgGGsXYIrBYhOE0yP+nQ6XRk7xDcYwuQAGTYXdyAUmvgVFE0YU1g5pvQT0m7GBaQfYcSnlHbapuK0H0A==", + "requires": { + "date-format": "^4.0.13", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "strnum": { + "version": "1.0.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + }, + "yargs": { + "version": "7.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "yargs-parser": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } +} diff --git a/FA/NapiStudy_ObjectWrapTest/package.json b/FA/NapiStudy_ObjectWrapTest/package.json new file mode 100755 index 0000000000000000000000000000000000000000..e3cc2f3754b234c181829f0c96eccecc16d62db3 --- /dev/null +++ b/FA/NapiStudy_ObjectWrapTest/package.json @@ -0,0 +1,18 @@ +{ + "license":"ISC", + "devDependencies":{}, + "name":"objectwraptest", + "ohos":{ + "org":"huawei", + "directoryLevel":"project", + "buildTool":"hvigor" + }, + "description":"example description", + "repository":{}, + "version":"1.0.0", + "dependencies":{ + "@ohos/hypium":"1.0.1", + "@ohos/hvigor-ohos-plugin":"1.1.6", + "@ohos/hvigor":"1.1.6" + } +} \ No newline at end of file diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/ReadMe.md" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/ReadMe.md" new file mode 100755 index 0000000000000000000000000000000000000000..53b378589a1319090af70833ab73967531a9fad8 --- /dev/null +++ "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/ReadMe.md" @@ -0,0 +1,13 @@ +# napi系列学习课程 +## 简介 +NAPI(Native API)是OpenHarmony系统中的一套原生模块扩展开发框架,它基于Node.js N-API规范开发,为开发者提供了JavaScript与C/C++模块之间相互调用的交互能力。本文将通过使用DevEco Studio工具(简称IDE)来学习napi的开发。 +## 学习内容 +### 基础篇 ++ [通过IDE开发一个Napi工程](./docs/hello_napi.md) ++ [napi 数据类型与同步调用学习](./docs/napi_data_type.md) +### 进阶篇 ++ [napi 异步调用学习](./docs/napi_asynchronous_call.md) ++ [napi 生命周期学习](./docs/napi_life_cycle.md) ++ [napi 对象导出学习](./docs/napi_export_object.md) +### 高阶篇 ++ [通过IDE如何适配三方库并开发napi接口](./docs/adapter_thirdlib_with_ide.md) diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/adapter_thirdlib_with_ide.md" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/adapter_thirdlib_with_ide.md" new file mode 100755 index 0000000000000000000000000000000000000000..a746ca7faa548ba13d2af217708537b8eab951e4 --- /dev/null +++ "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/adapter_thirdlib_with_ide.md" @@ -0,0 +1,675 @@ +# 如何通过IDE适配C/C++三方库并开发napi接口 +## 简介 +[如何贡献一个C/C++三方库](https://gitee.com/openharmony-sig/knowledge/blob/master/docs/openharmony_getstarted/port_thirdparty/README.md)一文介绍了我们如何适配一个Rom版的C/C++三方库,Rom版的三方库对于应用调用调不是很友好,尤其需要调试的时候,很不方便。因此本文将通过在IDE上适配openjpeg 三方库为例 介绍IDE上适配C/C++三方库的具体流程。 +## 创建工程 +在开发进行三方库适配以及napi接口开发前,我们需要创建一个三方库对应的工程,具体创建工程方法可以参照文档[通过IDE开发一个Napi工程](./hello_napi.md)。 +## IDE上三方库的适配 +本文中我们已适配 openjpeg 为例介绍 整个适配流程 。 +### 原生库准备 +#### 下载代码 +通过[openjpeg github网址](https://github.com/uclouvain/openjpeg/tree/v2.5.0),通过Code>>Download ZIP选项下载最新版本的源码包,并将其解压后放在IDE工程中的CPP目录下。 +- 下载openjpeg 2.5.0版本的库:
+ ![download lib](media/download_lib.png) +- 将库放在IDE工程:
+  ![openjpeg localtion](media/lib_location.png) +#### 分析编译依赖 +- 分析CMakeLists.txt + 对于库不是很复杂,目录结构简单的库可以通过分析CMakeLists.txt文件来获取库的依赖。在openjpeg库中,
+ 通过分析最外层CMakeLists.txt文件,可以得知编译openjpeg核心代码,需要依赖编译库自带thirdparty,如下图:
+ ![Analyze Dependencies thirdparty](media/analysis_deps0.png) + 而分析thirdparty/CMakeLists.txt文件,如果BUILD_THIRDPARTY开关未打开,将会通过FindPkgConfig自动搜索系统(IDE工具的SDK编译链)中的库文件,如下图:
+  ![thirdparty](media/analysis_deps1.png)
+ 并由此文件可以分析出该库非强制依赖了libz, libpng, libtiff以及liblcms2,如对libpng依赖的分析中:
+ ![analysis libong](media/libpng_analysis.png) + IDE工具的SDK编译链中只有libz库,其他三个库是没有的,所以如果需要其他三个库的功能,我们需要将BUILD_THIRDPARTY开关打开,此开关在库顶层目录的CMakeLists.txt文件中,如下图:
+ ![set thirdparty](media/set_thirdparty.png) + 到此,本库的依赖就已经分析完了。 +- 通过运行cmake分析 + 我们除了分析CMakeLists.txt文件外,也可以通过在linux中通过cmake过程来分析对应的依赖。
+ 我们在执行cmake的时候,会有对相关的依赖库的提示: + ```shell + -- Large File support - found + -- Looking for include file malloc.h + -- Looking for include file malloc.h - found + -- Looking for _aligned_malloc + -- Looking for _aligned_malloc - not found + -- Looking for posix_memalign + -- Looking for posix_memalign - found + -- Looking for memalign + -- Looking for memalign - found + -- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1") + -- Found ZLIB: /usr/lib/x86_64-linux-gnu/libz.so (found version "1.2.11") + -- Your system seems to have a Z lib available, we will use it to generate PNG lib + -- Found PNG: /usr/lib/x86_64-linux-gnu/libpng.so (found version "1.6.37") + -- Your system seems to have a PNG lib available, we will use it + -- Found TIFF: /usr/lib/x86_64-linux-gnu/libtiff.so (found version "4.1.0") + -- Your system seems to have a TIFF lib available, we will use it + -- Could NOT find LCMS2 (missing: LCMS2_LIBRARY LCMS2_INCLUDE_DIR) + -- Could NOT find LCMS (missing: LCMS_LIBRARY LCMS_INCLUDE_DIR) + -- LCMS2 or LCMS lib not found, activate BUILD_THIRDPARTY if you want build it + -- Configuring done + -- Generating done + ``` + 由以上信息可以查看到,编译此库需要依赖libz(found version "1.2.11"),libpng(found version "1.6.37"),libtiff(found version "4.1.0")以及liblcms2(LCMS2 or LCMS lib not found, activate BUILD_THIRDPARTY if you want build it)。从提示中可以看到,如果想要使能对应的功能且系统库中包含该依赖的话,需要打开BUILD_THIRDPARTY 开关。
+ 除了cmake中获取的依赖,我们也可以通过分析make编译过程获取更多的信息,具体方法可以参照[三方库适配依赖分析](https://gitee.com/openharmony-sig/knowledge/blob/master/docs/openharmony_getstarted/port_thirdparty/README.md#%E5%88%86%E6%9E%90%E7%BC%96%E8%AF%91%E4%BE%9D%E8%B5%96)。 +#### 重构CMakeLists + 对于不复杂的库且没有其他四方库依赖的三方库,我们可以使用原生库的CMakeLists.txt文件,但是对于一些复杂的,且强制依赖其他四方库的库,使用其原生CMakeLists.txt文件,无法解决四方库依赖的问题。此时,我们就需要对三方库的CMakeLists.txt文件进行重构。
+ 重构CMakeLists文件主要需涉及以下几点: +- 动态生成配置文件 + 查看原生CMakeLists.txt文件中是否有configure_file配置项,如果没有可直接跳过此步骤。
+ 在openjpeg库的原生CMakeLists.txt文件中,有2个配置文件需要动态生成:
+ ```cmake + # opj_config.h generation (2/2) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_config.h.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/src/lib/openjp2/opj_config.h + @ONLY + ) + + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_config_private.h.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/src/lib/openjp2/opj_config_private.h + @ONLY + ) + ``` + configure_file带了@ONLY参数,该参数限制了变量替换,让其只替换被@VAR@引用的变量。因此我们需要分析两个文件中对应的@VAR@配置规则。首先在opj_config.h.cmake.in文件定义的对应@VAR@的定义: + ```c++ + /* create opj_config.h for CMake */ + #cmakedefine OPJ_HAVE_STDINT_H @OPJ_HAVE_STDINT_H@ + /*--------------------------------------------------------------------------*/ + /* OpenJPEG Versioning */ + + /* Version number. */ + #define OPJ_VERSION_MAJOR @OPENJPEG_VERSION_MAJOR@ + #define OPJ_VERSION_MINOR @OPENJPEG_VERSION_MINOR@ + #define OPJ_VERSION_BUILD @OPENJPEG_VERSION_BUILD@ + ``` + 在分析@VAR@的赋值规则,在顶层CMakeLists.txt中: + ```cmake + # opj_config.h generation (1/2) + + # Check if some include files are provided by the system + include(EnsureFileInclude) + # These files are mandatory + ensure_file_include("string.h" HAVE_STRING_H YES) + ensure_file_include("memory.h" HAVE_MEMORY_H YES) + ensure_file_include("stdlib.h" HAVE_STDLIB_H YES) + ensure_file_include("stdio.h" HAVE_STDIO_H YES) + ensure_file_include("math.h" HAVE_MATH_H YES) + ensure_file_include("float.h" HAVE_FLOAT_H YES) + ensure_file_include("time.h" HAVE_TIME_H YES) + ensure_file_include("stdarg.h" HAVE_STDARG_H YES) + ensure_file_include("ctype.h" HAVE_CTYPE_H YES) + ensure_file_include("assert.h" HAVE_ASSERT_H YES) + + # For the following files, we provide an alternative, they are not mandatory + ensure_file_include("stdint.h" OPJ_HAVE_STDINT_H NO) + ensure_file_include("inttypes.h" OPJ_HAVE_INTTYPES_H NO) + ``` + 从以上内容通过分析ensure_file_include可以知道,在执行cmake时从系统中查找stdint.h文件,如果查找到则将OPJ_HAVE_STDINT_H置起,否则不会改变。而IDE上是没有stdint.h文件的,因此我们需要在配置文件之前手动将OPJ_HAVE_STDINT_H置起,如下: + ```cmake + set(OPJ_HAVE_STDINT_H TRUE) + ``` + 其他变量也是通过类似的方法分析。 +- 相关宏定义的设置 + 通过add_definitions设置三方库的相关宏定义,如下所示: + ```cmake + add_definitions(-DOPJ_HAVE_PNG_H=0 -DOPJ_HAVE_TIFF_H=1 -DOPJ_HAVE_LCMS2_H=1) + ``` +- 源码文件编译 + 三方库编译的源码可以通过在linux执行make的时候查看分析到: + ```shell + [ 0%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/thread.c.o + [ 1%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/bio.c.o + [ 1%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/cio.c.o + [ 2%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/dwt.c.o + [ 3%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/event.c.o + [ 3%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/ht_dec.c.o + [ 4%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/image.c.o + [ 5%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/invert.c.o + [ 5%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/j2k.c.o + [ 6%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/jp2.c.o + [ 7%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/mct.c.o + [ 7%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/mqc.c.o + [ 8%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/openjpeg.c.o + [ 9%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/opj_clock.c.o + [ 9%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/pi.c.o + [ 10%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/t1.c.o + [ 10%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/t2.c.o + [ 11%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/tcd.c.o + [ 12%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/tgt.c.o + [ 12%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/function_list.c.o + [ 13%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/opj_malloc.c.o + [ 14%] Building C object src/lib/openjp2/CMakeFiles/openjp2_static.dir/sparse_array.c.o + [ 14%] Linking C static library ../../../bin/libopenjp2.a + [ 14%] Built target openjp2_static + Scanning dependencies of target openjp2 + [ 14%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/thread.c.o + [ 15%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/bio.c.o + [ 16%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/cio.c.o + [ 16%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/dwt.c.o + [ 17%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/event.c.o + [ 18%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/ht_dec.c.o + [ 18%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/image.c.o + [ 19%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/invert.c.o + [ 20%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/j2k.c.o + [ 20%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/jp2.c.o + [ 21%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/mct.c.o + [ 22%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/mqc.c.o + [ 22%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/openjpeg.c.o + [ 23%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/opj_clock.c.o + [ 23%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/pi.c.o + [ 24%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/t1.c.o + [ 25%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/t2.c.o + [ 25%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/tcd.c.o + [ 26%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/tgt.c.o + [ 27%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/function_list.c.o + [ 27%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/opj_malloc.c.o + [ 28%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/sparse_array.c.o + [ 29%] Linking C shared library ../../../bin/libopenjp2.so + [ 29%] Built target openjp2 + Scanning dependencies of target z + [ 30%] Building C object thirdparty/libz/CMakeFiles/z.dir/adler32.c.o + [ 31%] Building C object thirdparty/libz/CMakeFiles/z.dir/compress.c.o + [ 31%] Building C object thirdparty/libz/CMakeFiles/z.dir/crc32.c.o + [ 32%] Building C object thirdparty/libz/CMakeFiles/z.dir/deflate.c.o + [ 32%] Building C object thirdparty/libz/CMakeFiles/z.dir/gzclose.c.o + [ 33%] Building C object thirdparty/libz/CMakeFiles/z.dir/gzlib.c.o + [ 34%] Building C object thirdparty/libz/CMakeFiles/z.dir/gzread.c.o + [ 34%] Building C object thirdparty/libz/CMakeFiles/z.dir/gzwrite.c.o + [ 35%] Building C object thirdparty/libz/CMakeFiles/z.dir/inflate.c.o + [ 36%] Building C object thirdparty/libz/CMakeFiles/z.dir/infback.c.o + [ 36%] Building C object thirdparty/libz/CMakeFiles/z.dir/inftrees.c.o + [ 37%] Building C object thirdparty/libz/CMakeFiles/z.dir/inffast.c.o + [ 38%] Building C object thirdparty/libz/CMakeFiles/z.dir/trees.c.o + [ 38%] Building C object thirdparty/libz/CMakeFiles/z.dir/uncompr.c.o + [ 39%] Building C object thirdparty/libz/CMakeFiles/z.dir/zutil.c.o + [ 40%] Linking C static library ../lib/libz.a + [ 40%] Built target z + Scanning dependencies of target tiff + [ 40%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_aux.c.o + [ 41%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_close.c.o + [ 42%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_codec.c.o + [ 42%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_color.c.o + [ 43%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_compress.c.o + [ 43%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_dir.c.o + [ 44%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_dirinfo.c.o + [ 45%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_dirread.c.o + [ 45%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_dirwrite.c.o + [ 46%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_dumpmode.c.o + [ 47%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_error.c.o + [ 47%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_extension.c.o + [ 48%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_fax3.c.o + [ 49%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_fax3sm.c.o + [ 49%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_flush.c.o + [ 50%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_getimage.c.o + [ 51%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_jbig.c.o + [ 51%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_jpeg.c.o + [ 52%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_luv.c.o + [ 52%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_lzw.c.o + [ 53%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_next.c.o + [ 54%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_ojpeg.c.o + [ 54%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_open.c.o + [ 55%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_packbits.c.o + [ 56%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_pixarlog.c.o + [ 56%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_predict.c.o + [ 57%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_print.c.o + [ 58%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_read.c.o + [ 58%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_strip.c.o + [ 59%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_swab.c.o + [ 59%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_thunder.c.o + [ 60%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_tile.c.o + [ 61%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_version.c.o + [ 61%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_warning.c.o + [ 62%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_write.c.o + [ 63%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_zip.c.o + [ 63%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_jpeg_12.c.o + [ 64%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_lzma.c.o + [ 65%] Building C object thirdparty/libtiff/CMakeFiles/tiff.dir/tif_unix.c.o + [ 65%] Linking C static library ../lib/libtiff.a + [ 65%] Built target tiff + Scanning dependencies of target lcms2 + [ 65%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsalpha.c.o + [ 66%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmscam02.c.o + [ 66%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmscgats.c.o + [ 67%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmscnvrt.c.o + [ 68%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmserr.c.o + [ 68%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsgamma.c.o + [ 69%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsgmt.c.o + [ 70%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmshalf.c.o + [ 70%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsintrp.c.o + [ 71%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsio0.c.o + [ 72%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsio1.c.o + [ 72%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmslut.c.o + [ 73%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsmd5.c.o + [ 73%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsmtrx.c.o + [ 74%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsnamed.c.o + [ 75%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsopt.c.o + [ 75%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmspack.c.o + [ 76%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmspcs.c.o + [ 77%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsplugin.c.o + [ 77%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsps2.c.o + [ 78%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmssamp.c.o + [ 79%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmssm.c.o + [ 79%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmstypes.c.o + [ 80%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsvirt.c.o + [ 81%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmswtpnt.c.o + [ 81%] Building C object thirdparty/liblcms2/CMakeFiles/lcms2.dir/src/cmsxform.c.o + [ 82%] Linking C static library ../lib/liblcms2.a + [ 82%] Built target lcms2 + Scanning dependencies of target opj_dump + [ 82%] Building C object src/bin/jp2/CMakeFiles/opj_dump.dir/opj_dump.c.o + [ 83%] Building C object src/bin/jp2/CMakeFiles/opj_dump.dir/convert.c.o + [ 84%] Building C object src/bin/jp2/CMakeFiles/opj_dump.dir/convertbmp.c.o + [ 84%] Building C object src/bin/jp2/CMakeFiles/opj_dump.dir/index.c.o + [ 85%] Building C object src/bin/jp2/CMakeFiles/opj_dump.dir/__/common/color.c.o + [ 86%] Building C object src/bin/jp2/CMakeFiles/opj_dump.dir/__/common/opj_getopt.c.o + [ 86%] Building C object src/bin/jp2/CMakeFiles/opj_dump.dir/converttif.c.o + [ 87%] Building C object src/bin/jp2/CMakeFiles/opj_dump.dir/convertpng.c.o + [ 88%] Linking C executable ../../../bin/opj_dump + [ 88%] Built target opj_dump + Scanning dependencies of target opj_compress + [ 89%] Building C object src/bin/jp2/CMakeFiles/opj_compress.dir/opj_compress.c.o + [ 90%] Building C object src/bin/jp2/CMakeFiles/opj_compress.dir/convert.c.o + [ 90%] Building C object src/bin/jp2/CMakeFiles/opj_compress.dir/convertbmp.c.o + [ 91%] Building C object src/bin/jp2/CMakeFiles/opj_compress.dir/index.c.o + [ 92%] Building C object src/bin/jp2/CMakeFiles/opj_compress.dir/__/common/color.c.o + [ 92%] Building C object src/bin/jp2/CMakeFiles/opj_compress.dir/__/common/opj_getopt.c.o + [ 93%] Building C object src/bin/jp2/CMakeFiles/opj_compress.dir/converttif.c.o + [ 93%] Building C object src/bin/jp2/CMakeFiles/opj_compress.dir/convertpng.c.o + [ 94%] Linking C executable ../../../bin/opj_compress + [ 94%] Built target opj_compress + Scanning dependencies of target opj_decompress + [ 95%] Building C object src/bin/jp2/CMakeFiles/opj_decompress.dir/opj_decompress.c.o + [ 95%] Building C object src/bin/jp2/CMakeFiles/opj_decompress.dir/convert.c.o + [ 96%] Building C object src/bin/jp2/CMakeFiles/opj_decompress.dir/convertbmp.c.o + [ 97%] Building C object src/bin/jp2/CMakeFiles/opj_decompress.dir/index.c.o + [ 97%] Building C object src/bin/jp2/CMakeFiles/opj_decompress.dir/__/common/color.c.o + [ 98%] Building C object src/bin/jp2/CMakeFiles/opj_decompress.dir/__/common/opj_getopt.c.o + [ 99%] Building C object src/bin/jp2/CMakeFiles/opj_decompress.dir/converttif.c.o + [ 99%] Building C object src/bin/jp2/CMakeFiles/opj_decompress.dir/convertpng.c.o + [100%] Linking C executable ../../../bin/opj_decompress + [100%] Built target opj_decompress + ``` + 由上面过程可看出,每个编译目标(Built target)所依赖的文件由上一个目标(如果上一个目标由的话)生成后以及该目标生成前的文件组成,如生成libopenjp2.so(Built target openjp)的文件是Built target openjp2_static之后以及Built target openjp之前的文件: + ```shell + [ 14%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/thread.c.o + [ 15%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/bio.c.o + [ 16%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/cio.c.o + [ 16%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/dwt.c.o + [ 17%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/event.c.o + [ 18%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/ht_dec.c.o + [ 18%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/image.c.o + [ 19%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/invert.c.o + [ 20%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/j2k.c.o + [ 20%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/jp2.c.o + [ 21%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/mct.c.o + [ 22%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/mqc.c.o + [ 22%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/openjpeg.c.o + [ 23%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/opj_clock.c.o + [ 23%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/pi.c.o + [ 24%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/t1.c.o + [ 25%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/t2.c.o + [ 25%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/tcd.c.o + [ 26%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/tgt.c.o + [ 27%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/function_list.c.o + [ 27%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/opj_malloc.c.o + [ 28%] Building C object src/lib/openjp2/CMakeFiles/openjp2.dir/sparse_array.c.o + ``` + 因此生成libopenjpeg.so的源文件我们就可以这样写: + ```cmake + set(SHARED_LIB_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/thread.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/bio.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/cio.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/dwt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/event.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/ht_dec.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/image.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/invert.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/j2k.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/jp2.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/mct.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/mqc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/openjpeg.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/pi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/t1.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/t2.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/tcd.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/tgt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/function_list.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_malloc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/sparse_array.c") + ``` + 其中CMAKE_CURRENT_SOURCE_DIR是代表当前CMakeLists.txt文件所在的路径。 +- 目标文件生成 + 这里我们调用add_library生成一个目标文件libopenjpeg_shared.so,其依赖上面分析的源码share_lib_src: + ```cmake + add_library(openjp2 SHARED ${SHARED_LIB_SRC}) + ``` +- 添加其他四方库依赖 + 如果三方库有对其他四方库依赖的话,需要通过target_link_libraries()方法添加对应的依赖。如在工程CPP目录下的CMakeLists.txt文件中的: + ```cmake + target_link_libraries(entry PUBLIC libace_napi.z.so openjg2) # libace_napi.z.so-系统napi库, openjg2-依赖的openjpeg库 + ``` +- 完整的CMakeLists.txt + ```cmake + # the minimum version of CMake. + cmake_minimum_required(VERSION 3.4.1) + set(CMAKE_CXX_STANDARD 17) + project(openjpeg) + + set(OPJ_HAVE_STDINT_H TRUE) + set(OPJ_HAVE_INTTYPES_H TRUE) + set(OPENJPEG_VERSION_MAJOR 2) + set(OPENJPEG_VERSION_MINOR 5) + set(OPENJPEG_VERSION_BUILD 0) + set(OPENJPEG_VERSION + "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}") + set(PACKAGE_VERSION + "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}") + + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_config.h.cmake.in + ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_config.h + @ONLY + ) + + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_config_private.h.cmake.in + ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_config_private.h + @ONLY + ) + + add_definitions(-DOPJ_HAVE_PNG_H=0 -DOPJ_HAVE_TIFF_H=1 -DOPJ_HAVE_LCMS2_H=1) + set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2") + set(SHARED_LIB_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/thread.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/bio.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/cio.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/dwt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/event.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/ht_dec.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/image.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/invert.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/j2k.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/jp2.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/mct.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/mqc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/openjpeg.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/pi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/t1.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/t2.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/tcd.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/tgt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/function_list.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_malloc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/sparse_array.c") + + add_library(openjp2 SHARED ${SHARED_LIB_SRC}) + target_include_directories(openjp2 PRIVATE ${INCLUDE_DIR}) + ``` +### 加入编译构建 +原生库源码准备完后,我们需要将库加入到工程的编译构建中。在工程目录CPP下的CMakeLists.txt文件中,通过add_subdirectory将openjpeg加入到编译中,并通过target_link_libraries添加对openjpeg的链接,如下图: +![引入三方库编译](media/add_lib.png) +特别说明:
+如果使用原生库的CMakeLists文件,编译时会提示添加目标时需要重新更改目标路径:
+ ![errorfor repath](media/err_repath.png) +此时我们就需要在顶层目录的CMakeLists.txt文件中添加 +``` +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +``` +![add repath config](media/add_repath.png) +到此,我们的三方库适配已经完成并可以正常编译成功。 +## 三方库napi接口开发 +三方库napi的接口一般是由需求方提供的,对于无需求或需要自己定义接口的,我们可以根据三方库对外导出的API接口进行封装或是根据原生库的测试用例对外封装测试接口。本文中我们已封装2个openjpeg测试接口为例详细说明napi接口开发的具体流程。 +### 定义napi接口 +根据原生库的测试用例,我们封装2个测试用例接口 +```c++ +typedef struct { + int comps_num; // the number of components of the image. + int comps_prec; // number of bits per component per pixel + int img_width; // the image width + int img_height; // the image height + int title_width; // width of tile + int title_height; // height of title + int irreversible; // 1 : use the irreversible DWT 9-7 + // 0 : use lossless compression (default) + int cblockw_init; // initial code block width, default to 64 + int cblockh_init; // initial code block height, default to 64 + int numresolution; // number of resolutions + int offsetx; // x component offset compared to the whole image + int offsety; // y component offset compared to the whole image + int is_rand; // Whether to generate data randomly + char file[256]; // output filename +} J2K_Info; + +int OpenjpegCompress(const char *input_file, char *output_file) # 图片压缩成J2K格式 +int openjpeg_create_j2k(J2K_Info *info) # 创建一张J2K格式图片 +``` +### 注册接口 +```c++ +napi_property_descriptor desc[] = { + {"openjpeg_compress", nullptr, OpenjpegCompress, nullptr, nullptr, + nullptr, napi_default, nullptr}, + {"openjpeg_create_j2k", nullptr, OpenjpegCreateJ2K , nullptr, nullptr, + nullptr, napi_default, nullptr} + }; +``` +### 接口实现 +- openjpeg_compress接口的实现 + ```c++ + static napi_value OpenjpegCompressMethod(napi_env env, napi_callback_info info) + { + napi_value result = nullptr; + napi_get_undefined(env, &result); + napi_value value; + size_t argc = 2; + napi_value args[2]; + size_t size; + char input_file[256] = {0}; + char output_file[256] = {0}; + // 获取参数 + if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) { + return result; + } + // js类型转换成C/C++类型 + if (napi_get_value_string_utf8(env, args[0], input_file, sizeof(input_file), + &size) != napi_ok) { + return result; + } + // js类型转换成C/C++类型 + if (napi_get_value_string_utf8(env, args[1], output_file, sizeof(output_file), + &size) != napi_ok) { + return result; + } + + // 封装一个通过调用openjpeg接口实现编码的接口 + // 三方库实现调用的业务逻辑接口 + if (OpenjpegCompress(input_file, output_file) != 0) { + return result; + } + // 创建返回的js类型参数 + if (napi_create_int64(env, 0, &result) != napi_ok) { + std::cout << "napi_create_int64" << std::endl; + } + // 返回最终结果。 + return result; + } + ``` +- openjpeg_create_j2k接口的实现 + ```c++ + static napi_value OpenjpegCreateJ2K(napi_env env, napi_callback_info info) + { + napi_value result = nullptr; + napi_get_undefined(env, &result); + napi_value value; + size_t argc = 1; + J2K_Info j2kInfo; + // 获取参数 + if (napi_get_cb_info(env, info, &argc, &value, nullptr, nullptr) != napi_ok) { + return result; + } + // 解析参数 + if (OpenjpegGetJ2kInfo(env, value, &j2kInfo) < 0) { + return result; + } + // 封装一个通过调用openjpeg接口实现创建J2K文件的接口 + // 三方库实现调用的业务逻辑接口 + if (OpenjpegCreateJ2K(&j2kInfo) < 0) { + return result; + } + + if (napi_create_int64(env, 0, &result) != napi_ok) { + std::cout << "napi_create_int64" << std::endl; + } + + return result; + } + ``` + 解析参数接口的实现: + ```c++ + static int OpenjpegGetJ2kInfo(napi_env env, napi_value value, J2K_Info *info) + { + if (info == nullptr) { + return -1; + } + if(GetObjectPropetry(env, value,"output_file", STRING, info->file) != napi_ok) { + return -1; + } + if (GetObjectPropetry(env, value,"comps_prec", NUMBER, &info->comps_prec) != + napi_ok) { + return -1; + } + if (GetObjectPropetry(env, value,"img_width", NUMBER, &info->img_width) != + napi_ok) { + return -1; + } + if (GetObjectPropetry(env, value,"img_height", NUMBER, &info->img_height) != + napi_ok) { + return -1; + } + if (GetObjectPropetry(env, value,"title_width", NUMBER, &info->title_width) != + napi_ok) { + return -1; + } + if (GetObjectPropetry(env, value,"title_height", NUMBER, &info->title_height) != + napi_ok) { + return -1; + } + if (GetObjectPropetry(env, value,"irreversible", NUMBER, &info->irreversible) != + napi_ok) { + return -1; + } + GetObjectPropetry(env, value,"cblockw_init", NUMBER, &info->cblockw_init); + GetObjectPropetry(env, value,"cblockh_init", NUMBER, &info->cblockh_init); + GetObjectPropetry(env, value,"numresolution", NUMBER, &info->numresolution); + GetObjectPropetry(env, value,"offsetx", NUMBER, &info->offsetx); + GetObjectPropetry(env, value,"offsety", NUMBER, &info->offsety); + GetObjectPropetry(env, value,"is_rand", BOOLEAN, &info->is_rand); + + return 0; + } + ``` + 由上代码可以看出,OpenjpegGetJ2kInfo接扣调用了一个封装的接口GetObjectPropetry,该接口实现了通过调用napi的接口获取对应的数据: + ```c++ + static int GetObjectPropetry(napi_env env, napi_value object, std::string key, int keyType, void *retValue) { + napi_value property = nullptr; + napi_value result = nullptr; + bool flag = false; + int ret = -1; + // 通过字符串获取napi_value对象 + if (napi_create_string_utf8(env, key.c_str(), strlen(key.c_str()), &property) + != napi_ok) { + return ret; + } + // 判断该字符串是否对应由属性值 + if (napi_has_property(env, object, property, &flag) != napi_ok && flag == true) { + return ret; + } + // 获取字符串对应的属性值 + if (napi_get_property(env, object, property, &result) != napi_ok) { + return ret; + } + + if (keyType == NUMBER) { + int64_t value = 0; + // JS数据类型转换成C/C++的int数据类型 + if (napi_get_value_int64(env, result, &value) != napi_ok) { + return ret; + } + *(int *)retValue = value; + ret = 0; + } else if (keyType == BOOLEAN) { + bool value = false; + // JS数据类型转换成C/C++ 的bool数据类型 + if (napi_get_value_bool(env, result, &value) != napi_ok) { + return ret; + } + *(int *)retValue = (value == true ? 1 : 0); + }else if (keyType == STRING) { + size_t s = 0; + char buf[256] = {0}; + // JS数据类型转换成C/C++的string数据类型 + if (napi_get_value_string_utf8(env, result, buf, sizeof(buf), &s) != + napi_ok) { + return ret; + } + strncpy((char *)retValue, buf, strlen(buf)); + ret = 0; + } + + return 0; + } + ``` +## 应用调用napi接口 +- 应用申明接口 + 在确定需要封装的接口后,我们需要将这些接口定义在index.d.ts文件中(路径entry/src/main/cpp/types/libentry/index.d.ts) + ```js + export const openjpeg_compress: (srcName:string, desName:string) =>number; + interface openjpegOption{ + comps_num:number // the number of components of the image. + comps_prec:number // number of bits per component per pixel + img_width:number // the image width + img_height:number // the image height + title_width:number // width of tile + title_height:number // height of title + irreversible:number // 1 : use the irreversible DWT 9-7, + // 0 : use lossless compression (default) + output_file:string // output filename + cblockw_init?:number // initial code block width, default to 64 + cblockh_init?:number // initial code block height, default to 64 + numresolution?:number // number of resolutions + offsetx?:number // x component offset compared to the whole image + offsety?:number // y component offset compared to the whole image + is_rand?:boolean // Whether to generate data randomly + } + export const openjpeg_create_j2k: (option:openjpegOption) => number + ``` +- 应用调用接口 + 在ets工程中创建2个按钮,并通过按钮调用相关的接口,具体代码如下: + ```js + Button(this.buttonTxt0) + .fontSize(50) + .margin({top:30}) + .fontWeight(FontWeight.Normal) + .onClick(() => { + testNapi.openjpeg_compress(this.dir + "test_pic.bmp", this.dir + "result.j2k") + }) + Button(this.buttonTxt1) + .fontSize(50) + .margin({top:30}) + .fontWeight(FontWeight.Normal) + .onClick(() => { + testNapi.openjpeg_create_j2k({comps_num:3,comps_prec:8, + img_width:2000,img_height:2000, + title_width:1000,title_height:1000, + irreversible:1, output_file:this.dir + + "newImage.j2k"}) + }) + ``` +## 参考资料 +- [如何通过DevEco Studio开发一个NAPI工程]()。 +- [如何贡献一个C/C++三方库](https://gitee.com/openharmony-sig/knowledge/blob/master/docs/openharmony_getstarted/port_thirdparty/README.md)。 +- [IDE适配三方库Openjpeg源码](../source/openjpeg/)。 +- [OpenHarmony 知识体系](https://gitee.com/openharmony-sig/knowledge/tree/master)。 diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/hello_napi.md" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/hello_napi.md" new file mode 100755 index 0000000000000000000000000000000000000000..a2b3efe6daa4d9021eb5bd64bdd47f7e49501518 --- /dev/null +++ "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/hello_napi.md" @@ -0,0 +1,142 @@ +# 如何通过DevEco Studio开发一个NAPI工程 +## 简介 +NAPI(Native API)是OpenHarmony系统中的一套原生模块扩展开发框架,它基于Node.js N-API规范开发,为开发者提供了JavaScript与C/C++模块之间相互调用的交互能力。这套机制对于鸿蒙系统开发的价值有两方面: +- OpenHarmony系统系统可以将框架层丰富的模块功能通过js接口开放给上层应用使用。 +- 应用开发者也可以选择将一些对性能、底层系统调用有要求的核心功能用C/C++封装实现,再通过js接口使用,提高应用本身的执行效率。 +本文将通过一个Hello world的实例来演示如何在DevEco Studio上开发一个NAPI工程的过程。如何开发一个rom包的napi工程可以参考文档[深入浅出 OpenHarmony NAPI](https://gitee.com/javen678/hello-ohos-napi/blob/master/doc/README.md); +## 工程准备 +### DevEco Studio下载 +本实例中使用的是DevEco Studio 3.0 Release版本的IDE,我们需要在[官网](https://developer.harmonyos.com/cn/develop/deveco-studio#download)下载DevEco Studio 3.0 Release版即可,DevEco Studio的安装使用请参照[DevEco Studio使用指南](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-deveco-studio-overview-0000001267924484)。 +### SDK下载 +下载安装完DevEco Studio工具后,我们需要下载OpenHarmony的SDK,具体步骤如下(更多详细信息请参照[DevEco Studio使用之配置开发环境](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-setting-up-environment-0000001267524540)): +- 运行已安装的DevEco Studio,首次使用,请选择**Do not import settings**,单击OK。 +- 进入DevEco Studio操作向导页面,修改**npm registry**,DevEco Studio已预置对应的仓(默认的npm仓,可能出现部分开发者无法访问或访问速度缓慢的情况),直接单击**Start using DevEco Studio**进入下一步。 + ![config](media/ide_config1.jpg) +- 设置Node.js信息,可以指定本地已安装的Node.js(Node.js版本要求为v14.19.1及以上,且低于v15.0.0;对应的npm版本要求为6.14.16及以上,且低于7.0.0版本);如果本地没有合适的版本,可以选择**Download**按钮,在线下载Node.js。本示例以下载Node.js为例,选择下载源和存储路径后,单击**Next**进入下一步。 + ![ide config2](media/ide_config2.jpg) +- 等待Node.js安装完成,然后单击**Finish**进入下一步。 + ![ide config3](media/ide_config3.jpg) +- 在**SDK Componets Setup**界面,设置OpenHarmony SDK下载路径,如果需要开发HarmonyOS应用,请勾选上HarmonyOS SDK,单击**Next**进入下一步。 + ![ide config4](media/ide_config4.jpg) +- 在弹出的SDK下载信息页面,单击**Next**,并在弹出的**License Agreement**窗口,阅读License协议,需同意License协议后,单击**Next**开始下载SDK。 + ![ide config5](media/ide_config5.jpg) +- 等待OpenHarmony SDK及工具下载完成,单击**Finish**,这样SDK就安装完成。 +## 创建工程 +下载并配置完SDK后,我们就可以开始创建工程了。DevEco Studio已经自带了一个Native C++ hello的模板,我们只需新建该模板的一个工程即可。 +- 打开DevEco Studio,点击左边Create Project,将会弹出对应新建工程界面。 +- 选择OpenHarmony下的Native C++模板,单击Next。 + ![create project](media/create_project.png) +- 配置工程 + 选择完模板后,会弹出配置工程界面,在该界面我们需要配置工程名字,SDK版本以及Model,配置完后点击Finish,这样我们一个helloworld工程就创建完成了。 + [^注意]: SDK我们需要选9,model需要选择Stage + ![config project](media/config_project.png) +## 源码实现 +新建完工程后,实现napi接口的hello.cpp源码在工程的entry/src/main/cpp目录下。 +### 注册napi模块 +先定义一个模块,对应结构体为napi_module,指定当前NAPI模块对应的模块名以及模块注册对外接口的处理函数,具体扩展的接口在该函数中声明,后面说明。 模块定义好后,调用NAPI提供的模块注册函数napi_module_register(napi_module* mod)函数注册到系统中。 +```c++ +static napi_module demoModule = { + .nm_version =1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "hello", + .nm_priv = ((void*)0), + .reserved = { 0 }, +}; +extern "C" __attribute__((constructor)) void RegisterHelloModule(void) +{ + napi_module_register(&demoModule); +} +``` +### 接口定义 +napi_property_descriptor结构体中声明了napi中对应的接口,如下所示,其中Add对应的使Native C++的接口,其应用端的接口对应为add,napi通过napi_define_properties接口将napi_property_descriptor结构体中的2个接口绑定在一起,并通过exports变量对外导出,使应用层可以调用add方法。 +```c++ +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "getHelloString", nullptr, getHelloString, nullptr, nullptr, nullptr, + napi_default, nullptr } + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +``` +### 接口实现 +以下为getHelloString接口业务实现代码: +```c++ +static napi_value getHelloString(napi_env env, napi_callback_info info) { + napi_value result; + std::string words = "Hello Napi"; + if (napi_create_string_utf8(env, words.c_str(), words.length(), &result) != napi_ok) { + return nullptr; + } + return result; +} +``` +到此,我们已经对外导出了1个napi接口,应用端可以调用这个接口。 +## 调用接口 +首先,在调用napi前,我们需要导入napi库: +``` +import testNapi from "libentry.so" +``` +导入完库后,我们就可以通过导入的变量直接调用对应的napi接口: +```c++ +testNapi.getHelloString(); +``` +而工程创建后,在index.ets文件(在工程的entry/src/main/ets/pages目录下)中系统已经默认生成了一个hello world的文本区域,且通过点击文本区域,可以调用getHelloString的napi接口,代码如下: +```js +import testNapi from "libentry.so" +@Entry +@Component +struct Index { + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + this.message = testNapi.getHelloString() + console.log("Test NAPI get string : " + this.message); + }) + } + .width('100%') + } + .height('100%') + } +} +``` +这时DevEco Studio工具会提示getHelloString接口未定义,我们需要在对应的index.d.ts文件(在工程的entry/src/main/cpp/types/libentry目录下)中加上该接口的定义: +``` +export const getHelloString: () => string; +``` +至此,源码实现已完成,我们可以通过点击DevEco Studio工具上Build选项中的Build Hap(s)进行编译。 +## 安装调试 +应用通过DevEco Studio工具安装到开发板的步骤: +### 连接开发板 +将开发板连接电脑,工具会自动识别到设备,如下图 +![device](media/device.png) +### 配置签名 +应用第一次安装到设备上的时候,是需要进行签名配置,否则无法进行安装。具体签名步骤: +- 点击工程配置按钮 + 点击DevEco Studio工具右上角的Project Structure按钮,弹出工程配置界面 + ![config](media/config.png) +- 配置自动签名 + 弹出工程配置界面,选择Project >>Signing Configs页面,在选中自动签名即可,此时工具会自动生成签名信息: + ![auto signing](media/auto_signature.png) +- 确定签名 + 工具在自动生成签名信息后,直接点击ok按钮即可完成自动签名操作 + ![sign ok](media/signing_ok.png) +### 安装运行 +配置完签名后,我们就可以直接点击DevEco Studio工具上运行按钮进行安装运行应用了 +![run](media/run.png) +### 调试 +应用安装运行后,在板子上我们可以在屏幕的中央看到Hello World的显示,并且我们点击Hello World后可以在DevEco Studio工具的Log窗口查看到对应的调试信息 +![log](media/log.png) +由于系统的调试信息也在log窗口显示,且信息量大,不方便我们查看自己的调试信息,所以我们可以在log窗口设置过滤信息,让窗口只显示我们过滤关键字的信息。 +## 参考资料 +- [DevEco Studio使用指南](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-deveco-studio-overview-0000001267924484)。 +- [深入浅出 OpenHarmony NAPI](https://gitee.com/javen678/hello-ohos-napi/blob/master/doc/README.md)。 +- [知识体系](https://gitee.com/openharmony-sig/knowledge/tree/master)。 \ No newline at end of file diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/NAPI-SyncWorkFlow.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/NAPI-SyncWorkFlow.png" new file mode 100755 index 0000000000000000000000000000000000000000..a22bb94eb7d9df50c2c03a536148f5885074ec13 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/NAPI-SyncWorkFlow.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/NAPI-aSyncWorkFlow.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/NAPI-aSyncWorkFlow.png" new file mode 100755 index 0000000000000000000000000000000000000000..cc41ff42c947ada4f5d90999effb065857ea0832 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/NAPI-aSyncWorkFlow.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/NativeEngine.jpg" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/NativeEngine.jpg" new file mode 100755 index 0000000000000000000000000000000000000000..8d903142e04189c90908419692786fc483e540b5 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/NativeEngine.jpg" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/add_lib.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/add_lib.png" new file mode 100755 index 0000000000000000000000000000000000000000..c6c7885d185d032dabc1adeaf74c55cda8892b54 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/add_lib.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/add_repath.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/add_repath.png" new file mode 100755 index 0000000000000000000000000000000000000000..6cbe38fb889154df9c0341c9a4e13364e4b2a5da Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/add_repath.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/analysis_deps0.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/analysis_deps0.png" new file mode 100755 index 0000000000000000000000000000000000000000..cbeace30a06224494078af8c3ddc7af218849d92 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/analysis_deps0.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/analysis_deps1.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/analysis_deps1.png" new file mode 100755 index 0000000000000000000000000000000000000000..3cfd33505161089d00550d007f32c90183d976ef Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/analysis_deps1.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/auto_signature.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/auto_signature.png" new file mode 100755 index 0000000000000000000000000000000000000000..6068125e9be9e560f4c7742dc8deb3fb9aab6093 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/auto_signature.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/confi_file.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/confi_file.png" new file mode 100755 index 0000000000000000000000000000000000000000..0e14021abab43cc2f0e3ced6aadd5e41e561afbf Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/confi_file.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/config.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/config.png" new file mode 100755 index 0000000000000000000000000000000000000000..069f7602406f649d87b505156a3db39b71d7cc4a Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/config.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/config_project.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/config_project.png" new file mode 100755 index 0000000000000000000000000000000000000000..f5b66644dbd1ddea0cfce9dc28c2842fa65601d8 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/config_project.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/config_var.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/config_var.png" new file mode 100755 index 0000000000000000000000000000000000000000..3886f061f3eda070d955035f7a9445e811199041 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/config_var.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/create_project.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/create_project.png" new file mode 100755 index 0000000000000000000000000000000000000000..482388a9f046a8dd6b231f4fb70d7f759fe8db22 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/create_project.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/device.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/device.png" new file mode 100755 index 0000000000000000000000000000000000000000..a7eb6b9502d84d1d10ba79160755736175f4a898 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/device.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/download_lib.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/download_lib.png" new file mode 100755 index 0000000000000000000000000000000000000000..7f3964d122d21498014c3d222a36c41779026a2a Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/download_lib.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/err_repath.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/err_repath.png" new file mode 100755 index 0000000000000000000000000000000000000000..fd1b9caa2fe78c383f3823bd39698e78c3fc9a14 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/err_repath.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config1.jpg" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config1.jpg" new file mode 100755 index 0000000000000000000000000000000000000000..cb997087b404346915e4575f448afac29ed497a2 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config1.jpg" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config2.jpg" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config2.jpg" new file mode 100755 index 0000000000000000000000000000000000000000..2757624ad895b35c1dc71cddc1486f9f6862e8f1 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config2.jpg" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config3.jpg" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config3.jpg" new file mode 100755 index 0000000000000000000000000000000000000000..e1e499a13dab7339e5e6a5303dad67e05d4e7341 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config3.jpg" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config4.jpg" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config4.jpg" new file mode 100755 index 0000000000000000000000000000000000000000..a82af8c5b8b495f4ecd0e4cf1d7870f8c2902bf2 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config4.jpg" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config5.jpg" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config5.jpg" new file mode 100755 index 0000000000000000000000000000000000000000..83aeacaa01f0491e9bd8e3d9a2676795c5f13a5d Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ide_config5.jpg" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/lib_location.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/lib_location.png" new file mode 100755 index 0000000000000000000000000000000000000000..cf396e0c23a03030a0f021f31cb0de11b7890454 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/lib_location.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/libpng_analysis.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/libpng_analysis.png" new file mode 100755 index 0000000000000000000000000000000000000000..cf5bffa0140c747f5aa774d7b44f3220045b452b Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/libpng_analysis.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/log.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/log.png" new file mode 100755 index 0000000000000000000000000000000000000000..0a858450235cea926ae439fe94a45420db7666f0 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/log.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/module_manager_h.jpg" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/module_manager_h.jpg" new file mode 100755 index 0000000000000000000000000000000000000000..51c31594eb0f8122be282b07c885ccf1f7c48180 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/module_manager_h.jpg" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/napi_module.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/napi_module.png" new file mode 100755 index 0000000000000000000000000000000000000000..55d5b97de43b41c13fe30cf7f9eed2104a676f18 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/napi_module.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/run.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/run.png" new file mode 100755 index 0000000000000000000000000000000000000000..24deb570b74ebb72029fed21ee61bd72a07787db Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/run.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/set_thirdparty.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/set_thirdparty.png" new file mode 100755 index 0000000000000000000000000000000000000000..b24ab8fa8ea4ed60c4126ccb36f131338e21b9a6 Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/set_thirdparty.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/signing_ok.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/signing_ok.png" new file mode 100755 index 0000000000000000000000000000000000000000..90897139b4f61e8d94d663dab70dec1ba36c255a Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/signing_ok.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ui_framework.png" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ui_framework.png" new file mode 100755 index 0000000000000000000000000000000000000000..492b4a6066941712a5ebe552cb076c7b3979486f Binary files /dev/null and "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/media/ui_framework.png" differ diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_asynchronous_call.md" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_asynchronous_call.md" new file mode 100755 index 0000000000000000000000000000000000000000..5a3117f8912896530e135a6bea7efb04ab4af02a --- /dev/null +++ "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_asynchronous_call.md" @@ -0,0 +1,411 @@ +# NAPI异步调用 +## 简介 +OpenHarmony Napi 标准系统异步接口实现支持Callback方式和Promise方式。标准系统异步接口实现规范要求,若引擎开启Promise特性支持,则异步方法必须同时支持Callback方式和Promise方式。使用哪种方式由应用开发者决定,通过是否传递Callback函数进行区分。不传递Callback即为Promise方式,方法执行结果为Promise实例对象。 +## 异步方式实现原理 +- 异步方式原理 + 同步方式,所有的代码处理都在原生方法(主线程)中完成。异步方式依赖NAPI框架提供的napi_create_async_work()函数创建异步工作项,原生方法被调用时,原生方法完成数据接收、转换,存入上下文数据,之后创建一个异步工作项,并加入调度队列,由异步工作线程池统一调度,原生方法返回空值(Callback方式)或返回Promise对象(Promise方式)。异步工作项中定义了2个函数,一个用于执行工作项的业务逻辑,异步工作项被调度后,该函数从上下文数据中获取输入数据,在worker线程中完成业务逻辑计算(不阻塞主线程)并将结果写入上下文数据。业务逻辑处理函数执行完成或被取消后,触发EventLoop执行另一函数,函数从上下文数据中获取结果,转换为JS类型,调用JS回调函数或通过Promise resolve()返回结果。 +- 异步方式处理流程图 + ![同步调用实现方法的代码处理流程](media/NAPI-aSyncWorkFlow.png) +- napi_create_async_work() + ```c++ + napi_status napi_create_async_work(napi_env env, + napi_value async_resource, + napi_value async_resource_name, + napi_async_execute_callback execute, + napi_async_complete_callback complete, + void* data, + napi_async_work* result); + ``` + 参数说明: + [in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可。
+ [in] async_resource: 可选项,关联async_hooks。
+ [in] async_resource_name: 异步资源标识符,主要用于async_hooks API暴露断言诊断信息。
+ [in] execute: 执行业务逻辑计算函数,由worker线程池调度执行。在该函数中执行IO、CPU密集型任务,不阻塞主线程。
+ [in] complete: execute参数指定的函数执行完成或取消后,触发执行该函数。此函数在EventLoop线程中执行。
+ [in] data: 用户提供的上下文数据,用于传递数据。
+ [out] result: napi_async_work*指针,用于返回当前此处函数调用创建的异步工作项。 返回值:返回napi_ok表示转换成功,其他值失败。
+## Callback 异步接口 +下面基于napi_create_async_work将add()接口改成Callback方式接口——addCallback(),接口的eTS定义 +```c++ +function addAsyncCallback(numX: number, numY: number, callback:(result: number) => void): void; +``` + ### 初始化上下文数据 +根据业务需求自定义一个上下文数据结构,用于保存和传递数据。本例自定义的上下文数据包含:异步工作项对象、回调函数、2个参数(加数、被加数)、计算结果等4个属性。 +```c++ +struct AddonData { + napi_async_work asyncWork = nullptr; + napi_ref callback = nullptr; + double args[2] = {0}; + double result = nullptr; +}; +``` +在[napi数据类型](./napi_data_type.md)文中,我们已了解对于NAPI框架,所有参数,无论是ECMAScript标准中定义的Boolean、Null、Undefined、Number、BigInt、String、Symbol和Object八种数据类型,还是Function类型,都已统一封装为napi_value类型,故可如获取数据类型的参数一样获取Function类型参数,本例直接调用函数获取3个参数——加数、被加数、回调函数。
+ 接着我们将接收到的参数转换存入上下文数据,number类型的转换为double直接存入即可。Function类型的参数怎么处理?不转换直接存入napi_value类型?答案是不行的!这牵涉到NAPI对象生命周期管理问题。napi_value类型引用对象的生命周期在原生方法退出后结束,后面在work线程无法获取其值。NAPI提供了一种生命期限长于原生方法的对象引用类型—— napi_ref,napi_ref引用对象在原生方法退出后不自动回收,由用户管理此类型对象的生命周期。所以当前方法中,我们调用napi_create_reference()函数将接收到的napi_value类型的回调函数参数args[2]转换为napi_ref类型(生命周期具体定义及使用可参照文档[napi生命周期](./napi_life_cycle.md))。 +```c++ +static napi_value addAsyncCallback(napi_env env, napi_callback_info info) { + // 获取3个参数,值的类型是js类型(napi_value) + size_t argc = 3; + napi_value args[3]; + napi_value thisArg = nullptr; + napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr); + ... + // 异步工作项上下文用户数据,传递到异步工作项的execute、complete中传递数据 + auto addonData = new AddonData{ + .asyncWork = nullptr, + }; + + // 将接收到的参数传入用户自定义上下文数据 + napi_get_value_double(env, args[0], &addonData->args[0]); + napi_get_value_double(env, args[1], &addonData->args[1]); + napi_create_reference(env, args[2], 1, &addonData->callback); + ... +} +``` +### 创建异步工作项 +在创建异步工作项前,我们先分别声明2个函数,分别用作于napi_create_async_work()函数的execute、complete参数。异步工作项创建OK后,将其存入上下文数据的asyncWork属性,并调用napi_queue_async_work()将异步工作项加入调度队列,由异步work线程池统一调度,原生方法返回空值退出。 +```c++ +// 业务逻辑处理函数,由worker线程池调度执行。 +static void addExecuteCB(napi_env env, void *data) { +} + +// 业务逻辑处理完成回调函数,在业务逻辑处理函数执行完成或取消后触发。 +static void addAsyncCompleteCB(napi_env env, napi_status status, void *data) { +} + +static napi_value addAsyncCallback(napi_env env, napi_callback_info info) { + ... + napi_create_reference(env, args[2], 1, &addonData->callback); + + // 创建async work,创建成功后通过最后一个参数接收async work的handle + napi_value resourceName = nullptr; + napi_create_string_utf8(env, "addAsyncCallback", NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work(env, nullptr, resourceName, addExecuteCB, addAsyncCompleteCB, (void *)addonData, &addonData->asyncWork); + + // 将刚创建的async work加到队列,由work thread调度执行 + napi_queue_async_work(env, addonData->asyncWork); + + // 原生方法返回空对象 + napi_value result = 0; + napi_get_null(env, &result); + return result; +} +``` +### execute 函数 +execute函数在异步工作项被调度后在work线程中执行,不阻塞主线程(不阻塞UI界面),可执行IO、CPU密集型等任务。此处仅为演示,我们的业务逻辑计算就是一个简单的加法,并把计算结果存入上下文数据的result属性。 +```c++ +// 业务逻辑处理函数,由worker线程池调度执行。 +static void addExecuteCB(napi_env env, void *data) { + AddonData *addonData = (AddonData *)data; + + // 执行复杂计算,不阻塞主线程。此处用一个加法简单示意。 + addonData->result = addonData->args[0] + addonData[1]; +} +``` +### complete 函数 + 从接收到的上下文数据中获取结果,调用napi_call_function()方法执行JS回调函数返回数据给JS。之后释放过程中创建的napi_ref引用对象、异步工作项等对象。 NAPI框架提供了napi_call_function()函数供扩展Natvie代码(C/C++代码)调用JS函数,用于执行回调函数等场景。函数定义如下: +```c++ +NAPI_EXTERN napi_status napi_call_function(napi_env env, + napi_value recv, + napi_value func, + size_t argc, + const napi_value* argv, + napi_value* result); +``` +参数说明: +- [in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可。 +- [in] recv: 传给被调用的this对象。 +- [in] func: 被调用的函数. +- [in] argc: 函数参数个数(对应函数数组的长度)。 +- [in] argv: 函数参数数组. +- [out] result: func函数执行的返回值。 返回值:返回napi_ok表示转换成功,其他值失败。 +因对象生命周期管理问题,上下文数据的callback属性的类型为napi_ref,需要调用napi_get_reference_value()函数获取其指向的napi_value对象值才调用napi_call_function()函数。napi_get_reference_value()函数介绍参照文档[napi生命周期](./napi_life_cycle.md)。
+complete接口实现: +```c++ +// 业务逻辑处理完成回调函数,在业务逻辑处理函数执行完成或取消后触发,由EventLoop线程中执行。 +static void addAsyncCompleteCB(napi_env env, napi_status status, void *data) { + AddonData *addonData = (AddonData *)data; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, loginAddonData->callback, &callback); + napi_call_function(env, undefined, callback, 0, nullptr, &callbackResult); + + // 删除napi_ref对象 + if (loginAddonData->callback != nullptr) { + napi_delete_reference(env, loginAddonData->callback); + } + + // 删除异步工作项 + napi_delete_async_work(env, loginAddonData->asyncWork); + delete loginAddonData; +} +``` +### eTS调用接口 +```js +import testNapi from "libentry.so"; + +@Entry +@Component +struct Index { + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + let num1 = 123, num2 = 456 + testNapi.addCallback(num1, num2, (result) =>{ + console.info("message: 123 + 456 = " + result) + }) + }) + } + .width('100%') + } + .height('100%') +} +``` +## Promise 接口 +### 创建Promise + 通过前面异步方式实现原理我们可知Promise整体处理流程和Callback方式一样。不同的是,首先要创建一个Promise。NAPI框架中提供了napi_create_promise()函数用于创建Promise,调用该函数输出2个对象——deferred、promise。promise用于原生方法返回,deferred传入异步工作项的上下文数据。complete函数中,应用napi_resolve_deferred()函数 或 napi_reject_deferred() 函数返回数据。
+ 函数定义如下: +```c++ +napi_status napi_create_promise(napi_env env, + napi_deferred* deferred, + napi_value* promise); +``` +参数说明: +- [in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可。 +- [out] deferred: 返回接收刚创建的deferred对象,关联Promise对象,后面使用napi_resolve_deferred() 或 napi_reject_deferred() 返回数据。 +- [out] promise: 关联上面deferred对象的JS Promise对象 返回值:返回napi_ok表示转换成功,其他值失败。 +创建Promise接口的实现: +```c++ +static napi_value addPromise(napi_env env, napi_callback_info info) { + // 创建promise + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + + ... + + // 返回promise + return promise; +} +``` +### 初始化上下文数据 +同Callback方式定义一个上下文数据结构,用于保存和传递数据。Promise方式去掉callback属性,加上deferred属性。 +```c++ +// 用户提供的上下文数据,在原生方法(初始化数据)、executeCB、completeCB之间传递数据 +struct AddonData { + napi_async_work asyncWork = nullptr; + napi_deferred deferred = nullptr; + double args[2] = {0}; + double result = nullptr; +}; + +static napi_value addPromise(napi_env env, napi_callback_info info) { + // 获取2个参数,值的类型是js类型(napi_value) + size_t argc = 2; + napi_value args[2]; + napi_value thisArg = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr)); + ... + // 创建promise + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + + // 异步工作项上下文用户数据,传递到异步工作项的execute、complete之间传递数据 + auto addonData = new AddonData{ + .asyncWork = nullptr, + .deferred = deferred, + }; + + // 将接收到的参数传入 + NAPI_CALL(env, napi_get_value_double(env, args[0], &addonData->args[0])); + NAPI_CALL(env, napi_get_value_double(env, args[1], &addonData->args[1])); + ... +} +``` +### 创建异步工作项 +同Callback方式在创建异步工作项前,我们先分别声明2个函数,分别用作于napi_create_async_work()函数的execute、complete参数。异步工作项创建OK后,将其存入上下文数据的asyncWork属性,并调用napi_queue_async_work()将异步工作项加入调度队列,由异步work线程池统一调度,原生方法返回Promise对象退出。 + +```c++ +// 用户提供的上下文数据,在原生方法(初始化数据)、executeCB、completeCB之间传递数据 +struct AddonData { + napi_async_work asyncWork = nullptr; + napi_deferred deferred = nullptr; + double args[2] = {0}; + double result = 0; +}; + +static napi_value addPromise(napi_env env, napi_callback_info info) { + ... + // 创建async work,创建成功后通过最后一个参数(addonData->asyncWork)返回async work的handle + napi_value resourceName = nullptr; + napi_create_string_utf8(env, "addAsyncCallback", NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work(env, nullptr, resourceName, addExecuteCB, addPromiseCompleteCB, (void *)addonData, + &addonData->asyncWork); + + // 将刚创建的async work加到队列,由底层去调度执行 + napi_queue_async_work(env, addonData->asyncWork); + + // 原生方法返回promise + return promise; +} +``` +### execute 回调处理 +此处完全同Callback方式,无需修改。 +```c++ +// 业务逻辑处理函数,由worker线程池调度执行。 +static void addExecuteCB(napi_env env, void *data) { + AddonData *addonData = (AddonData *)data; + + // 执行复杂计算,不阻塞主线程。此处用一个加法简单示意。 + addonData->result = addonData->args[0] + addonData[1]; +} +``` +### complete 回调处理 +调用NAPI提供的napi_resolve_deferred() 或 napi_reject_deferred() 返回数据。之后释放过程中创建的napi_ref引用对象、异步工作项等对象。 +```c++ +static void addPromiseCompleteCB(napi_env env, napi_status status, void *data) { + AddonData *addonData = (AddonData *)data; + napi_value result = nullptr; + napi_create_double(env, addonData->result, &result); + napi_resolve_deferred(env, addonData->deferred, result); + + // 删除napi_ref对象 + if (addonData->callback != nullptr) { + napi_delete_reference(env, addonData->callback); + } + + // 删除异步工作项 + napi_delete_async_work(env, addonData->asyncWork); + delete addonData; + addonData = nullptr; +} +``` +### eTS调用接口 +```js +import testNapi from "libentry.so"; + +@Entry +@Component +struct Index { + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + let num1 = 123, num2 = 456 + testNapi.addPromise(num1, num2).then((result) =>{ + console.info("message: 123 + 456 = " + result) + }) + }) + } + .width('100%') + } + .height('100%') +} +``` +## 规范异步接口 + 如本文开头所说,若引擎开启Promise特性支持,则异步方法必须同时支持Callback方式和Promise方式,通过判断接收到的参数个数判断是Callback方式还是Promise方式。下面我们将addCallbak()、addPromise() 2个接口合并成一个接口——addAsync(),接口的eTS定义: +```js +function addAsync(num1: number, num2: number, callback:(result: number) => void): void; +function addAsync(num1: number, num2: number): Promise; +``` + +首先修改用户上下文数据结构,同时包含deferred、callback属性。 + +```c++ +struct AddonData { + napi_async_work asyncWork = nullptr; + napi_deferred deferred = nullptr; + napi_ref callback = nullptr; + double args[2] = {0}; + double result = 0; +}; +``` + 修改接口原生方法实现,通过判断实际获取到的参数个数判断是Callback还是Promise,根据上面的接口定义,2个参数是Promise,3个参数是Callback。 +```c++ +static napi_value addAsync(napi_env env, napi_callback_info info) { + // 获取3个参数,值的类型是js类型(napi_value) + size_t argc = 3; + napi_value args[3]; + napi_value thisArg = nullptr; + napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr); + + // 获取并判断js参数类型 + napi_valuetype valuetype0; + napi_typeof(env, args[0], &valuetype0); + napi_valuetype valuetype1; + napi_typeof(env, args[1], &valuetype1); + if (valuetype0 != napi_number || valuetype1 != napi_number) { + napi_throw_type_error(env, nullptr, "Wrong arguments. 2 numbers expected."); + return NULL; + } + + // 异步工作项上下文用户数据,传递到异步工作项的execute、complete中传递数据 + auto addonData = new AddonData{ + .asyncWork = nullptr, + }; + + // 判断事件获取的参数个数,如是2个则按Promise处理。 + if (argc == 2) { + // 创建promise + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + napi_create_promise(env, &deferred, &promise); + addonData->deferred = deferred; + + // 将接收到的参数传入 + napi_get_value_double(env, args[0], &addonData->args[0]); + napi_get_value_double(env, args[1], &addonData->args[1]); + + // 创建async work,创建成功后通过最后一个参数(addonData->asyncWork)返回async work的handle + napi_value resourceName = nullptr; + napi_create_string_utf8(env, "addPromise", NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work(env, nullptr, resourceName, addExecuteCB, addPromiseCompleteCB, (void *)addonData, + &addonData->asyncWork); + + // 将刚创建的async work加到队列,由底层去调度执行 + napi_queue_async_work(env, addonData->asyncWork); + + // 返回promise + return promise; + } else { + napi_valuetype valuetype2; + napi_typeof(env, args[2], &valuetype2); + if (valuetype2 != napi_function) { + napi_throw_type_error(env, nullptr, "Callback function expected."); + return nullptr; + } + + // 将接收到的参数传入用户自定义上下文数据 + napi_get_value_double(env, args[0], &addonData->args[0]); + napi_get_value_double(env, args[1], &addonData->args[1]); + napi_create_reference(env, args[2], 1, &addonData->callback); + + // 创建async work,创建成功后通过最后一个参数接收async work的handle + napi_value resourceName = nullptr; + napi_create_string_utf8(env, "addCallback", NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work(env, nullptr, resourceName, addExecuteCB, addCallbackCompleteCB, (void *)addonData, + &addonData->asyncWork); + + // 将刚创建的async work加到队列,由底层去调度执行 + napi_queue_async_work(env, addonData->asyncWork); + + // 原生方法返回空对象 + napi_value result = 0; + napi_get_null(env, &result); + return result; + } +} +``` +## 参考资料 +- [napi数据类型转换](./hello_napi.md)。 +- [深入浅出 OpenHarmony NAPI 之异步调用](https://gitee.com/javen678/hello-ohos-napi/blob/master/doc/3.Callback&Promise.md)。 +- [OpenHarmony 知识体系](https://gitee.com/openharmony-sig/knowledge)。 + \ No newline at end of file diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_data_type.md" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_data_type.md" new file mode 100755 index 0000000000000000000000000000000000000000..ed8e32eb45765a51c05613340ed442556e81c6c5 --- /dev/null +++ "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_data_type.md" @@ -0,0 +1,123 @@ +# NAPI数据类型转换与同步调用 +## napi的数据类型 +在[通过IDE创建工程](./hello_napi.md)的示例代码中,我们使用napi_create_string_utf8函数将C/C++ string转换成NAPI类型——napi_value 。OpenHarmony NAPI将ECMAScript标准中定义的Boolean、Null、Undefined、Number、BigInt、String、Symbol和Object八种数据类型,以及函数对应的Function类型,统一封装成napi_value类型 (也称为JS类型)。该类型用于接收应用传递过来的数据以及返回数据给应用。 本文将讲述JS类型和C/C++数据类型之间的转换 。 +## napi的数据类型转换接口 +OpenHarmony NAPI提供了很多接口用来napi的数据类型与C/C++数据类型之间的转换。以下列出常用的几种接口 +### C/C++数据类型转napi类型 +- napi_create_double(napi_env env, double value, napi_value* result); +- napi_create_int32(napi_env env, int32_t value, napi_value* result); +- napi_create_uint32(napi_env env, uint32_t value, napi_value* result); +- napi_create_int64(napi_env env, int64_t value, napi_value* result); +- napi_create_string_utf8(napi_env env, const char* str, size_t length, napi_value* result); +### napi类型转C/C++数据类型 +- napi_get_value_double(napi_env env, napi_value value, double* result); +- napi_get_value_int32(napi_env env, napi_value value, int32_t* result); +- napi_get_value_uint32(napi_env env, napi_value value, uint32_t* result); +- napi_get_value_int64(napi_env env, napi_value value, int64_t* result); +- napi_get_value_string_utf8(napi_env env, napi_value value, char* buf, size_t bufsize, size_t* result); +- napi_get_value_bool(napi_env env, napi_value value, bool* result); +## 同步调用 +我们在[通过IDE创建工程](./hello_napi.md)示例中添加一个简单的接口——add(num1, num2)来讲述具体细节,以及接口同步方式的实现。
+NAPI的同步方式调用的扩展API代码处理流程如下图。
+ ![同步调用扩展API实现方法的代码处理流程](media/NAPI-SyncWorkFlow.png) +### 添加NAPI扩展API +- NAPI定义并注册接口 + ```c++ + static napi_value add(napi_env env, napi_callback_info info) { + napi_value reuslt; + return reuslt; + } + static napi_value registerFunc(napi_env env, napi_value exports) + { + static napi_property_descriptor desc[] = { + { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }, + }; + } + ``` +- eTs定义接口 + ``` + function add(num1: number, num2: number): number; + ``` +### 获取JS参数 + NAPI定义API方法时的接收参数为(napi_env, napi_callback_info),其中napi_callback_info为上下文的信息。通过NAPI提供了napi_get_cb_info()方法可从napi_callback_info中获取参数列表、this及其他数据。 + napi_get_cb_info函数说明如下 : +```c++ +napi_status napi_get_cb_info(napi_env env, + napi_callback_info cbinfo, + size_t* argc, + napi_value* argv, + napi_value* thisArg, + void** data) +``` +参数说明: +- [in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可. +- [in] value: napi_callback_info对象,上下文的信息 +- [in-out] argc: argv数组的长度。若napi_callback_info中实际包含的参数的个数大于请求的数量argc,将只复制argc的值所指定数量的参数只argv中。若实际的参数个数小于请求的数量,将复制全部的参数,数组多余的空间用空值填充,并将参数实际长度写入argc。 +- [out] argv: 用于接收参数列表 +- [out] thisArg: 用于接收this对象 +- [out] data: NAPI的上下文数据 返回值:返回napi_ok表示转换成功,其他值失败。下面的返回napi_status方法一样。 +在add方法中,调用napi_get_cb_info函数: +```c++ +// env、info 参数由NAPI框架传入 +static napi_value add(napi_env env, napi_callback_info info) { + size_t argc = 2; + napi_value args[2]; + napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); + napi_value reuslt; + return reuslt; +} +``` +### JS类型值转换为C/C++类型的值 + 因传入的参数是Javascript值类型,并被框架封装成统一的唯一类型——napi_value类型,为了能够进行计算,我们需要获取其对应在C/C++中的类型的值。我们可以用[napi类型转C/C++数据类型](./napi_data_type.md#napi类型转cc数据类型)中的相关接口进行转换。此示例中我们用 napi_get_value_double方式: +```c++ +static napi_value add(napi_env env, napi_callback_info info) { + // 获取2个参数,值的类型是js类型(napi_value) + size_t argc = 2; + napi_value args[2]; + napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); + // 将js类型(napi_value)的参数值转换成C++类型double + double value0; + napi_get_value_double(env, args[0], &value0); + double value1; + napi_get_value_double(env, args[1], &value1); + napi_value reuslt; + return reuslt; +} +``` +### 业务逻辑计算 + 使用Native代码(C/C++代码)完成业务场景逻辑计算。本示例中就简化为2个数字简单相加,代码如下: +```c++ +static napi_value add(napi_env env, napi_callback_info info) { + ... + // 业务逻辑运算 + double sum = value0 + value1; + ... +} +``` +### 计算结果转换为JS类型并返回 + 计算的结果是C/C++ double类型,不能直接返回给JS,需要转换成NAPI node_value类型 。本示例中我们用到 +[C/C++数据类型转napi类型](./napi_data_type.md#cc数据类型转napi类型)中的napi_create_double接口: +```c++ +static napi_value add(napi_env env, napi_callback_info info) { + ... + // 将结果由C++类型(double)转换成js类型(napi_value) + napi_value reuslt; + napi_create_double(env, sum, &reuslt) + // 将结果返回到JS + return result; +} +``` +完整的示例代码参照[完整源码](../../../FA/NapiStudy_HellNapi/entry/src/main/cpp/hello.cpp)。 +### 应用调用 +本示例程序也是在DevEco Studio开发,应用调用可参照[通过IDE创建工程](./hello_napi.md) +``` +import testNapi from "libentry.so" +let num1 = 123 +let num2 = 456 +let result = testNapi.add(num1, num2) +``` +## 参考资料 +- [通过IDE开发一个napi工程之Hello napi](./hello_napi.md) +- [Hello napi完整源码工程](../../../FA/NapiStudy_HellNapi) +- [深入浅出 OpenHarmony NAPI 之数据类型转换](https://gitee.com/javen678/hello-ohos-napi/blob/master/doc/2.%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2.md) +- [OpenHarmony 知识体系](https://gitee.com/openharmony-sig/knowledge/tree/master)。 diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_export_object.md" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_export_object.md" new file mode 100755 index 0000000000000000000000000000000000000000..549f2a7db662574d71939510de6f69518cf0164f --- /dev/null +++ "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_export_object.md" @@ -0,0 +1,300 @@ +# NAPI 导出对象 +## 简介 +导出对象 是指 Napi通过一种绑定C++类和实例的方法,使JS应用可以调用类的构造函数和方法。 +## NAPI导出对象流程 +- 使用`napi_define_class`API 定义一个JS类
+ 其中`napi_define_class`包含与 C++ 类对应的构造函数、静态属性和方法以及实例属性和方法。 +- 通过`napi_wrap`将 C++ 实例绑定在 JS对象中
+ 当 JS代码调用构造函数时,构造函数回调会使用`napi_wrap`将一个新的 C++ 实例绑定在 JS对象中,然后返回绑定对象。 +- 获取目标的 C++ 实例
+ 当 JS代码调用类上的方法或属性访问器时,会调用相应的`napi_callback`C++ 函数。对于实例回调,`napi_unwrap`获取作为调用目标的 C++ 实例 。 +## NAPI导出对象接口说明 +NAPI接口详细说明可以查看[Node.js](https://nodejs.org/api/n-api.html)官网介绍。 +### `napi_define_class` +```c++ +napi_status napi_define_class(napi_env env, + const char* utf8name, + size_t length, + napi_callback constructor, + void* data, + size_t property_count, + const napi_property_descriptor* properties, + napi_value* result); +``` +这个函数用来定义一个js类,包括: +- 具有类名的 JavaScript 构造函数。绑定相应的 C++ 类时,通过传递的回调`constructor`可用于实例化一个新的 C++ 类实例,然后可以将其放置在使用构造的 JavaScript 对象实例中`napi_wrap`。 +- 构造函数上的属性,其实现可以调用 C++ 类的相应*静态*数据属性、访问器和方法(由具有属性的属性描述符定义`napi_static`)。 +- 构造函数`prototype`对象的属性。绑定 C++ 类时,可以从属性描述符中给出的静态函数调用C++ 类的*非静态*`napi_static`数据属性、访问器和方法,而无需使用 `napi_unwrap`。
+绑定 C++ 类时,传递的 C++ 构造函数回调`constructor` 应该是调用实际类构造函数的类上的静态方法,然后将新的 C++ 实例绑定在 js对象中,并返回绑定对象。详情请参阅`napi_wrap`。
+从中返回的 JavaScript 构造函数`napi_define_class`通常被保存并稍后用于从本机代码构造类的新实例,和/或检查提供的值是否是类的实例。在这种情况下,为了防止函数值被垃圾回收,可以使用创建对它的强持久引用 `napi_create_reference`,确保引用计数保持 >= 1。 +### `napi_wrap` +```c +napi_status napi_wrap(napi_env env, + napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + void* finalize_hint, + napi_ref* result); +``` + +这个函数用来将C++实例对象绑定在JS对象中。
+当 JS代码为使用 定义的类调用构造函数时,将 `napi_define_class()`调用`napi_callback`构造函数的 。在构造原生类的实例后,回调必须调用 `napi_wrap()`以将新构造的实例绑定在已创建的 JS 对象中,该对象是`this`构造函数回调的参数。(该`this`对象是从构造函数创建的`prototype`,因此它已经定义了所有实例属性和方法)。
+*特别说明*: +- 绑定C++实例的对象需要注意其生命周期,如果使用的对象其生命周期远大于C++实例,在绑定前需要先通过 + napi_get_reference_value() 获取生命周期。在对象回收时使用napi_delete_reference()清除生命周期。 +- 一个对象智能绑定一个实例。要将另一个C++实例与已绑定过实例的对象再次进行绑定,需要先使用`napi_remove_wrap()`进行解绑。 +### `napi_unwrap` +```c++ +napi_status napi_unwrap(napi_env env, + napi_value js_object, + void** result); +``` +获取绑定在js对象中的C++实例。
+当 JS代码调用类上的方法或属性访问器时,相应`napi_callback`的会被调用。如果回调是针对实例方法或访问器的,则`this`回调的参数是绑定对象;然后可以通过调用`napi_unwrap()`来获得作为调用目标的绑定 C++ 实例。 +### `napi_remove_wrap` +```c++ +napi_status napi_remove_wrap(napi_env env, + napi_value js_object, + void** result); +``` +检索JS对象使用`napi_wrap()`是否绑定过C++实例并删除绑定的C++实例。 +## NAPI导出对象具体实现 +这里我们以NapiTest的为例 +### 定义NapiTest类以及相关方法 +新建一个NapiTest类(NapiTest.h),实现类接口的声明: +```c++ +class NapiTest { +public: + NapiTest() : mEnv(nullptr), mRef(nullptr) { + } + ~NapiTest(); + + // 创建NapiTest类的实体,并将实体返回到应用端 + static napi_value Create(napi_env env, napi_callback_info info); + + // 初始化js类并设置对应属性并将其导出。 + static napi_value Init(napi_env env, napi_value exports); + +private: + // 对外导出的方法 + static napi_value SetMsg(napi_env env, napi_callback_info info); + // 对外导出的方法 + static napi_value GetMsg(napi_env env, napi_callback_info info); + // 定义js结构体时实际的构建函数 + static napi_value Constructor(napi_env env, napi_callback_info info); + // 释放资源的函数(类似类的析构函数) + static void Destructor(napi_env env, void *nativeObject, void *finalize); + + // 生命周期变量 + static napi_ref sConstructor_; + // 对外导出方法使用到的变量 + static std::string _msg; + // 记录环境变量 + napi_env mEnv = nullptr; + // 记录生命周期变量 + napi_ref mRef = nullptr; +}; +``` +### 将NapiTest定义为js类 +- 在定义js类之前,需要先设置类对外导出的方法 + ```c++ + napi_property_descriptor desc[] = { + { "getMsg", nullptr, NapiTest::GetMsg, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "setMsg", nullptr, NapiTest::SetMsg, nullptr, nullptr, nullptr, + napi_default, nullptr }, + } + ``` +- 定义js类 + ```c++ + napi_value mConstructor = nullptr; + if (napi_define_class(env, NAPI_CLASS_NAME, NAPI_AUTO_LENGTH, Constructor, nullptr, + sizeof(desc) / sizeof(desc[0]), desc, &mConstructor) != napi_ok) { + return nullptr; + } + ``` + 其中:
+ ​ NAPI_CLASS_NAME是对外导出的类名
+ ​ Constructor是处理类的构造实例的回调函数
+ ​ desc 属性描述符数组,描述类的静态和实例数据属性和方法
+ ​ mConstructor 代表类的构造函数
+ 当我们从js端new这个类时,我们需要实现构造实例的回调函数Constructor: + ```c++ + napi_value NapiTest::Constructor(napi_env env, napi_callback_info info) + { + napi_value undefineVar = nullptr, thisVar = nullptr; + napi_get_undefined(env, &undefineVar); + + if (napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr) == + napi_ok && thisVar != nullptr) { + // 创建NapiTest 实例 + NapiTest *reference = new NapiTest(env); + // 绑定实例类创建NapiTest到导出的对象result + if (napi_wrap(env, thisVar, reinterpret_cast(reference), + NapiTest::Destructor, nullptr, &(reference->mRef)) == napi_ok) { + return thisVar; + } + + return thisVar; + } + + return undefineVar; + } + ``` + 其中NapiTest::Destructo方法是用来释放创建的对象 + ```c++ + void NapiTest::Destructor(napi_env env, void *nativeObject, void *finalize) + { + NapiTest *test = reinterpret_cast(nativeObject); + test->~NapiTest(); + } + ``` +### 导出js类 +- 创建生命周期(生命周期相关可以参考文档[napi生命周期](./napi_life_cycle.md))
+ 在设置类导出前,需要先创建生命周期 + ```c++ + if (napi_create_reference(env, mConstructor , 1, &sConstructor_) != napi_ok) { + return nullptr; + } + ``` + mConstructor 定义js类时返回的代表类的构造函数的数据
+ sConstructor_ 生命周期变量
+- 将类导出到exports中 + 将类以属性值的方式导出 + ```c++ + if (napi_set_named_property(env, exports, NAPI_CLASS_NAME, constructor) != napi_ok) { + return nullptr; + } + ``` +注意:以上实现都是在类的Init方法中,我们只需要在NAPI注册的接口中调用该Init即可。完整代码可以查看[NapiTest源码](../../../FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/NapiTest.cpp) +### 创建类的实例对象 +为了确保应用能正常获取到类的导出,我们需要确保应用层能够正确获取到类的对象实例。
+应用层获取实例对象的方式有两种,一是应用层直接通过new 该类对象获取,另一种调用napi接口,通过napi实现new一个类的对象。本文将以第二种方式来实现。
+我们在NapiTest类中定义了Create方法,该方法就是返回一个类的实例对象: +```c++ +napi_value NapiTest::Create(napi_env env, napi_callback_info info) { + napi_status status; + napi_value constructor = nullptr, result = nullptr; + // 获取生命周期变量 + status = napi_get_reference_value(env, sConstructor_, &constructor); + + // 创建生命周期内的实例对象并将其返回 + status = napi_new_instance(env, constructor, 0, nullptr, &result); + auto napiTest = new NapiTest(); + // 绑定实例类创建NapiTest到导出的对象result + if (napi_wrap(env, result, reinterpret_cast(napiTest), Destructor, + nullptr, &(napiTest->mRef)) == napi_ok) { + return result; + } + + return nullptr; +} +``` +在NAPI接口的注册中将该方法以接口的方式导出,应用层就可以直接调用该接口并获取到该类的实例对象。 +### 实现NAPI接口的注册 +我们已helloworld为列, +- 新建一个hello.cpp,定义模块 + ```c++ + static napi_module demoModule = { + .nm_version =1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "hello", + .nm_priv = ((void*)0), + .reserved = { 0 }, + }; + ``` +- 实现模块的Init + ```c++ + EXTERN_C_START + static napi_value Init(napi_env env, napi_value exports) + { + // do some init + return exports; + } + EXTERN_C_END + ``` +- 模块注册 + ```c++ + // 注册 hello模块 + extern "C" __attribute__((constructor)) void RegisterHelloModule(void) + { + napi_module_register(&demoModule); + } + ``` +- 在模块中调用NapiTest类的导出
+ 在模块Init中添加上NapiTest的Init,并将类的实例创建方法导出 + ```c++ + EXTERN_C_START + static napi_value Init(napi_env env, napi_value exports) + { + napi_property_descriptor desc[] = { + { "create", nullptr, NapiTest::Create, nullptr, nullptr, nullptr, + napi_default, nullptr } + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return NapiTest::Init(env, exports); + } + EXTERN_C_END + ``` +## 应用调用NAPI实例 +### 导出接口 +在使用该NAPI的时候,我们需要在ts文件(路径在\entry\src\main\cpp\types\libentry\index.d.ts),声明以下内容: +```js +export const create : () => NapiTest; +export class NapiTest { + setMsg(msg: string): void; + getMsg(): string; +} +``` +该文件申明了NAPI接口中导出的方法和类 +### 应用调用 +新建一个helloworld的ETS工程,该工程中包含一个按键 +- 导出napi对应的库(之前NAPI接口生成的库名为libentry.so) + ```js + import testNapi from "libentry.so"; + ``` +- 定义变量 tt + ```js + struct Index { + @State message: string = 'Hello World' + @State flag:number = 0 + tt = testNapi.create(); + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + }) + } + .width('100%') + } + .height('100%') + } + ``` +- 在按键中调用对应的接口并输出内容 + ```js + if (this.falg == 0) { + this.flag = 2 + this.tt.setMsg("1+1") + } else { + this.flag = 0 + this.tt.setMsg("1-1") + } + console.info("[NapiTest]:" + this.tt.getMsg() + " = " + this.flag); + ``` + 通过IDE LOG信息可以查看到,当按多次下按钮时,出现交替以下信息: + ```js + 02200/JsApp: [NapiTest]: 1+1 = 2 + 02200/JsApp: [NapiTest]: 1-1 = 0 + ``` +## 参考资料 +- [NapiTest源码工程](../../../FA/NapiStudy_ObjectWrapTest) +- [通过IDE开发一个napi工程](./hello_napi.md) +- [Node.js](https://nodejs.org/api/n-api.html) +- [napi生命周期](./napi_life_cycle.md) +- [OpenHarmony 知识体系](https://gitee.com/openharmony-sig/knowledge/tree/master) diff --git "a/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_life_cycle.md" "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_life_cycle.md" new file mode 100755 index 0000000000000000000000000000000000000000..d7261901e18c29703ee1269cf3b7b2ca8e37640d --- /dev/null +++ "b/docs/napi\347\263\273\345\210\227\345\255\246\344\271\240/docs/napi_life_cycle.md" @@ -0,0 +1,237 @@ +## 什么是NAPI的生命周期管理 + +我们都知道,程序的生命周期是指程序从启动,运行到最后的结束的整个过程。生命周期的管理自然是指控制程序的启动,调用以及结束的方法。
+而NAPI中的生命周期的管理又是怎样的呢?以下是Node.js官网给出的说明:
+[ECMAScript 语言规范](https://tc39.github.io/ecma262/)将“代理”的概念定义为运行 JavaScript 代码的自包含环境。多个这样的代理可以由进程同时或按顺序启动和终止。
+一个 Node.js 环境对应一个 ECMAScript 代理。在主进程中,在启动时会创建一个环境,并且可以在单独的线程上创建额外的环境作为[工作线程](https://nodejs.org/api/worker_threads.html)。当 Node.js 嵌入到另一个应用程序中时,该应用程序的主线程也可能在应用程序进程的生命周期中多次构建和销毁一个 Node.js 环境,这样应用程序创建的每个 Node.js 环境都可以在反过来,在其生命周期中创建和销毁其他环境作为工作线程。
+从本机插件的角度来看,这意味着它提供的绑定可以从多个上下文甚至从多个线程同时调用多次。
+原生插件可能需要分配它们在整个生命周期中使用的全局状态,这样状态对于插件的每个实例必须是唯一的。
+为此,Node-API 提供了一种分配数据的方法,使其生命周期与代理的生命周期相关联。 +## NAPI生命周期管理的方法 +js调用时,NAPI中对象的句柄可以作为napi_value返回. 这些句柄必须保持对象“活动”,直到本机代码不再需要它们,否则可以在本机代码完成使用它们之前回收对象。
+当返回对象句柄时,它们与“范围”相关联。默认范围的生命周期与本机方法调用的生命周期相关联。结果是,默认情况下,句柄保持有效,并且与这些句柄关联的对象将在本机方法调用的生命周期内保持活动状态。
+但是,在许多情况下,与本地方法相比,句柄必须在更短或更长的生命周期内保持有效。此时,NAPI提供了对应的函数来改变默认句柄的寿命(即生命周期)。 +### 设置局部生命周期 +因为在napi中全部js相关的值都是一个不透明的封装,默认生命周期是和全局一致的,有时候处于安全和性能的考虑,须要将一些值的生命周期限制在必定的范围之内,此时我们就需要用到NAPI相关的接口来napi_open_handle_scope和napi_close_handle_scope建立和关闭一个上下文环境。比如: +``` +for (int i = 0; i < 1000000; i++) { + napi_handle_scope scope; + napi_status status = napi_open_handle_scope(env, &scope); + if (status != napi_ok) { + break; + } + napi_value result; + status = napi_get_element(e object, i, &result); + if (status != napi_ok) { + break; + } + // do something with element + status = napi_close_handle_scope(env, scope); + if (status != napi_ok) { + break; + } +} +``` +此时,因为限制了做用域,因此每一个result的生命周期都被限制在了单次循环以内。 +### 设置全局生命周期 + 在某些情况下,插件需要能够创建和引用具有比单个本地方法调用更长的生命周期的对象。例如,要创建一个构造函数并稍后在请求中使用该构造函数来创建实例,必须可以在许多不同的实例创建请求中引用该构造函数对象。`napi_value`如前面部分所述,如果返回正常的句柄,这是不可能的。普通句柄的生命周期由作用域管理,所有作用域必须在本机方法结束之前关闭。
+ NAPI 提供了创建对对象的持久引用的方法。每个持久引用都有一个关联的计数,其值为 0 或更高。计数确定引用是否会使相应的对象保持活动状态。计数为 0 的引用不会阻止对象被收集,通常称为“弱”引用。任何大于 0 的计数都将阻止对象被收集。
+ 可以使用初始引用计数创建引用。然后可以通过`napi_reference_ref`和`napi_reference_unref`修改计数。如果在引用计数为 0 时收集了一个对象,则所有后续获取与该引用关联的对象的调用`napi_get_reference_value`都将返回`NULL`的`napi_value`. 尝试调用 `napi_reference_ref`其对象已被收集的引用会导致错误。
+ 一旦插件不再需要引用,就必须删除它们。当一个引用被删除时,它不会再阻止相应的对象被收集。未能删除持久引用会导致“内存泄漏”,持久引用的本机内存和堆上的相应对象都将永久保留。
+ 可以创建多个引用同一个对象的持久引用,每个引用都将根据其单独的计数保持对象处于活动状态或不处于活动状态。对同一对象的多个持久引用可能会导致本机内存意外保持活动状态。持久引用的本机结构必须保持活动状态,直到被引用对象的终结器被执行。如果为同一个对象创建了新的持久引用,则该对象的终结器将不会运行,并且早期持久引用指向的本机内存将不会被释放。这可以通过需要的情况下调用`napi_delete_reference`在`napi_reference_unref`来避免。
+## NAPI管理生命周期的相关函数 +生命周期相关函数的具体信息可以参照[Node.js官网](https://nodejs.org/api/n-api.html#object-lifetime-management)。 +### 局部生命周期API +- napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result)
+ 打开一个新的生命周期。 +- napi_status api_close_handle_scope(napi_env env, napi_handle_scope scope)
+ 关闭传入的生命周期,生命周期必须按照创建它们的相反顺序关闭。 +- napi_status napi_open_escapable_handle_scope(napi_env env, napi_handle_scope* result)
+ 打开一个新生命周期,可以将一个对象提升到外部生命周期。 +- napi_status napi_close_escapable_handle_scope(napi_env env, napi_handle_scope scope)
+ 关闭传入的生命周期。生命周期必须按照创建它们的相反顺序关闭.
+- napi_status napi_escape_handle(napi_env env, napi_escapable_handle_scope scope, + napi_value escapee, napi_value* result)
+ 提升 JavaScript 对象的句柄,使其在外部作用域的生命周期内有效。每个生命周期只能调用一次。如果多次调用它,将返回错误。 +### 全局生命周期API +- napi_status napi_create_reference(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref *result)
+ 用指定的引用计数创建一个新引用到`Object`传入的引用. +- napi_status napi_delete_reference(napi_env env, napi_ref ref)
+ 删除传入的引用。 +- napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result)
+ 增加传入引用的引用计数并返回结果引用计数。 +- napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result)
+ 减少传入引用的引用计数并返回结果引用计数。 +- napi_status napi_get_reference_value(napi_env env, napi_ref ref, uint32_t* result)
+ 如果仍然有效,将返回napi_value代表Object与napi_ref. 否则,结果将是NULL。 +## NAPI生命周期管理实现 +这里我们以TestNapi为例(关于工程创建可以参照[通过IDE开发一个Napi工程](./hello_napi.md)) +- 首先新建一个 hello.cpp,实现 NAPI接口模块的注册 + ```c++ + #include "napi/native_api.h" + #include + + EXTERN_C_START + static napi_value Init(napi_env env, napi_value exports) + { + // 暂未实现任何方法 + napi_property_descriptor desc[] = { + }; + return exports; + } + EXTERN_C_END + static napi_module demoModule = { + .nm_version =1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "hello", + .nm_priv = ((void*)0), + .reserved = { 0 }, + }; + // 注册 hello模块 + extern "C" __attribute__((constructor)) void RegisterHelloModule(void) + { + napi_module_register(&demoModule); + } + ``` +- 定义一个测试的类(TestNapi) + ```c++ + class NapiTest{ + public: + NapiTest(){} + ~NapiTest(){} + static napi_value SetMsg(napi_env env, napi_callback_info info) { + napi_value result = nullptr; + napi_get_undefined(env, &result); + char _msg[128] = {0}; + napi_value msgvalue; + size_t argc = 1, size = 0; + + if (napi_get_cb_info(env, info, &argc, &msgvalue, nullptr, nullptr) != + napi_ok) { + return result; + } + + if (napi_get_value_string_utf8(env, msgvalue, _msg, sizeof(_msg), &size) != + napi_ok) { + return result; + } + + return result; + } + + static napi_value GetMsg(napi_env env, napi_callback_info info) { + napi_value result; + char *_msg = "hello NapiTest"; + if (napi_create_string_utf8(env, _msg, strlen(_msg), &result) != napi_ok) { + napi_get_undefined(env, &result); + return nullptr; + } + return result; + } + + napi_value Create(napi_env env, void *data){ + } + }; + ``` +- 定义一个全局的生命周期管理的变量 + ```c++ + static napi_ref g_Constructor = nullptr; + ``` +- 将类的方法定义到一个napi_property_descriptor的数组
+ 特别申明:此步骤及以下步骤都在initi方法中完成。 + ```c++ + static napi_value Init(napi_env env, napi_value exports) + { + napi_property_descriptor desc[] = { + { "SetMsg", nullptr, NapiTest::SetMsg, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "GetMsg", nullptr, NapiTest::GetMsg, nullptr, nullptr, nullptr, + napi_default,nullptr }, + }; + } + ``` +- 将测试类定义到js类,并创建调用测试类的构造函数 + ```c++ + napi_value constructor = nullptr; + if (napi_define_class(env, NAPI_CLASS_NAME, NAPI_AUTO_LENGTH, Constructor, nullptr, sizeof(desc) / sizeof(desc[0]),desc, &constructor) != napi_ok) { + return nullptr; + } + ``` + 其中Constructor构造函数如下: + ```c++ + static napi_value Constructor(napi_env env, napi_callback_info info) { + napi_value thisVar = nullptr; + napi_get_undefined(env, &thisVar); + napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr); + + return thisVar; + } + ``` + 如需要快速释放构建函数中创建的对象,也可以在构造函数中绑定一个类析构函数: + ```c++ + static napi_value Constructor(napi_env env, napi_callback_info info) { + napi_value thisVar = nullptr; + napi_get_undefined(env, &thisVar); + napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr); + + std::unique_ptr reference = std::make_unique(); + status = napi_wrap(env, thisVar, reinterpret_cast(reference), + Destructor, nullptr, nullptr); + + return thisVar; + } + // 类析构函数,释放有Constructor构建时新建的对象 + static void Destructor(napi_env env, void *nativeObject, void *finalize) + { + NapiTest *test = reinterpret_cast(nativeObject); + test->~NapiTest(); + } + ``` +- 创建生命周期 + ```c++ + if (napi_create_reference(env, constructor, 1, &g_Constructor) != napi_ok) { + return nullptr; + } + ``` +- 将生命周期变量作为导出对象的传入属性。 + ```c++ + if (napi_set_named_property(env, exports, NAPI_CLASS_NAME, constructor) != napi_ok) { + return nullptr; + } + ``` +- 设置导出对象的属性。 + ```c++ + if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) { + return nullptr; + } + ``` +到此,我们就完成了js类的定义以及相关生命周期管理的设置,该如何创建生命周期范围内的变量呢?我们可以在NapiTest类中定义一个方法,用于创建在该生命周期范围内的变量: +```c++ +napi_value Create(napi_env env, void *data){ + napi_status status; + napi_value constructor = nullptr, result = nullptr; + // 获取生命周期变量 + status = napi_get_reference_value(env, g_Constructor, &constructor); + if (status != napi_ok) { + return nullptr; + } + /** + do smoethings + */ + // 创建生命周期内的对象并将其返回 + status = napi_new_instance(env, constructor, 0, nullptr, &result); + if (status != napi_ok) { + return nullptr; + } + + return result; +} +``` +[完整示例的代码](../../../FA/NapiStudy_ObjectWrapTest/entry/src/main/cpp/NapiTest.cpp) +## 参考资料 +- [Node.js官网](https://nodejs.org/api/n-api.html#object-lifetime-management) +- [如何通过IDE创建napi工程](./hello_napi.md) +- [TestNap完整工程](../../../FA/NapiStudy_ObjectWrapTest) +- [OpenHarmony 知识体系](https://gitee.com/openharmony-sig/knowledge) \ No newline at end of file diff --git "a/docs/\345\255\246\344\271\240\350\265\204\346\272\220\346\225\264\345\220\210/readme.md" "b/docs/\345\255\246\344\271\240\350\265\204\346\272\220\346\225\264\345\220\210/readme.md" index 4ea84c5e0c4f88a3c4d5a70c03728e7cefa333c6..ad5517cdd66f8a0c48ac3d7273d1cf9d119eac2e 100644 --- "a/docs/\345\255\246\344\271\240\350\265\204\346\272\220\346\225\264\345\220\210/readme.md" +++ "b/docs/\345\255\246\344\271\240\350\265\204\346\272\220\346\225\264\345\220\210/readme.md" @@ -82,6 +82,7 @@ OpenHarmony驱动子系统采用C面向对象编程模型构建,通过平台 ## 技术分享 - [OpenHarmony IoT设备开发](https://growing.openharmony.cn/mainPlay/learnPathMaps?id=44) +- [OpenHarmony Napi学习](../napi%E7%B3%BB%E5%88%97%E5%AD%A6%E4%B9%A0/ReadMe.md) ## 应用样例解析