@ohos-cpf/3rdloop 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +290 -244
- package/bin/3rdloop.mjs +46 -46
- package/lib/cli.js +781 -781
- package/lib/config-cmd.js +451 -451
- package/lib/config.js +318 -318
- package/lib/doctor.js +113 -113
- package/lib/exit-codes.js +30 -30
- package/lib/opencode.js +155 -155
- package/lib/orch.js +426 -426
- package/lib/queries.js +263 -263
- package/lib/step.js +325 -325
- package/lib/ui.js +222 -222
- package/lib/update.js +279 -279
- package/lib/workflow.js +308 -308
- package/lib/workflows.js +131 -131
- package/package.json +50 -50
- package/vendor/Server/Agent/SkillSelector/README.md +343 -343
- package/vendor/Server/Agent/SkillSelector/core/Agent.js +207 -207
- package/vendor/Server/Agent/SkillSelector/index.js +14 -14
- package/vendor/Server/Agent/SkillSelector/llm/llmClient.js +313 -313
- package/vendor/Server/Agent/SkillSelector/llm/prompts.js +161 -161
- package/vendor/Server/Agent/SkillSelector/llm/reactSteps.js +144 -144
- package/vendor/Server/Agent/SkillSelector/matcher/fuzzyMatcher.js +433 -433
- package/vendor/Server/Agent/SkillSelector/scanner/skillScanner.js +382 -382
- package/vendor/Server/Agent/SkillSelector/utils/actionWords.js +59 -59
- package/vendor/Server/Brain/AnalysisStrategies.js +422 -422
- package/vendor/Server/Brain/Brain.js +686 -686
- package/vendor/Server/Brain/DecompositionStrategies.js +621 -621
- package/vendor/Server/Brain/PlanPersistence.js +196 -196
- package/vendor/Server/Brain/SkillExecutor.js +251 -251
- package/vendor/Server/Brain/index.js +11 -11
- package/vendor/Server/CLI/cli.js +275 -275
- package/vendor/Server/CLI/deveco-code/index.js +71 -71
- package/vendor/Server/CLI/deveco-code.js +5 -5
- package/vendor/Server/CLI/opencode/index.js +817 -818
- package/vendor/Server/CLI/opencode.js +5 -5
- package/vendor/Server/DbUse/MessageArchive.js +61 -61
- package/vendor/Server/DbUse/StorageManager.js +107 -107
- package/vendor/Server/DbUse/adapters/BaseAdapter.js +94 -94
- package/vendor/Server/DbUse/adapters/FileAdapter.js +138 -138
- package/vendor/Server/DbUse/adapters/JsonAdapter.js +138 -138
- package/vendor/Server/DbUse/adapters/JsonlAdapter.js +114 -114
- package/vendor/Server/DbUse/adapters/SqliteAdapter.js +157 -157
- package/vendor/Server/DbUse/index.js +160 -160
- package/vendor/Server/DbUse/stores/SessionStore.js +279 -279
- package/vendor/Server/DbUse/stores/TaskExecutionStore.js +133 -133
- package/vendor/Server/DbUse/stores/TaskRegistryStore.js +262 -262
- package/vendor/Server/DbUse/stores/TaskStepStore.js +279 -279
- package/vendor/Server/FlexRunner/FlexRunner.js +1759 -1759
- package/vendor/Server/FlexRunner/index.js +12 -12
- package/vendor/Server/Knowledge/KnowledgeImporter.js +523 -523
- package/vendor/Server/Knowledge/KnowledgeManager.js +341 -341
- package/vendor/Server/Knowledge/index.js +33 -33
- package/vendor/Server/LoopEngine/LoopEngine.js +1133 -1133
- package/vendor/Server/LoopEngine/index.js +11 -11
- package/vendor/Server/Orchestrator/Orchestrator.js +0 -3
- package/vendor/Server/Orchestrator/StepNode.js +312 -312
- package/vendor/Server/Orchestrator/index.js +13 -13
- package/vendor/Server/Routes/controllers/BrainController.js +241 -241
- package/vendor/Server/Routes/controllers/FlexRunnerController.js +1125 -1125
- package/vendor/Server/Routes/controllers/HealthController.js +44 -44
- package/vendor/Server/Routes/controllers/KnowledgeImportController.js +355 -355
- package/vendor/Server/Routes/controllers/LoopEngineController.js +788 -788
- package/vendor/Server/Routes/controllers/StatsController.js +57 -57
- package/vendor/Server/Routes/controllers/StreamController.js +67 -67
- package/vendor/Server/Routes/library/logger.js +179 -179
- package/vendor/Server/Routes/library/zipArchive.js +172 -172
- package/vendor/Server/Routes/router/Router.js +204 -204
- package/vendor/Server/Routes/routes/brain.js +47 -47
- package/vendor/Server/Routes/routes/flexrunner.js +72 -72
- package/vendor/Server/Routes/routes/health.js +28 -28
- package/vendor/Server/Routes/routes/index.js +57 -57
- package/vendor/Server/Routes/routes/knowledge.js +55 -55
- package/vendor/Server/Routes/routes/loopengine.js +58 -58
- package/vendor/Server/Routes/routes/orchestrator.js +61 -61
- package/vendor/Server/Routes/routes/registry.js +97 -97
- package/vendor/Server/Routes/routes/stats.js +23 -23
- package/vendor/Server/Routes/routes/stream.js +30 -30
- package/vendor/Server/Routes/server.js +203 -203
- package/vendor/Server/Routes/sse/SseHub.js +308 -308
- package/vendor/Server/Skills/acceptance-check/SKILL.md +191 -191
- package/vendor/Server/Skills/acceptance-check/references/PHASE1_ARTIFACT_COLLECTION.md +52 -52
- package/vendor/Server/Skills/acceptance-check/references/PHASE2_CRITERIA_EVALUATION.md +77 -77
- package/vendor/Server/Skills/acceptance-check/references/PHASE2_EVIDENCE_VERIFICATION.md +70 -70
- package/vendor/Server/Skills/arkts-code-check/SKILL.md +320 -320
- package/vendor/Server/Skills/arkts-code-check/references/CODE_CHECK_GUIDE.md +210 -210
- package/vendor/Server/Skills/arkts-code-check/references/FILE_TYPE_GUIDE.md +28 -28
- package/vendor/Server/Skills/arkts-code-check/references/PHASE1_INFO_COLLECTION.md +233 -233
- package/vendor/Server/Skills/arkts-code-check/references/REPORT_TEMPLATE.md +219 -219
- package/vendor/Server/Skills/arkts-library-compile-validate/SKILL.md +328 -328
- package/vendor/Server/Skills/arkts-library-compile-validate/scripts/build.ps1 +93 -93
- package/vendor/Server/Skills/arkts-library-compile-validate/scripts/code-linter.cjs +432 -432
- package/vendor/Server/Skills/arkts-library-compile-validate/scripts/migrate.cjs +851 -851
- package/vendor/Server/Skills/arkts-library-compile-validate/scripts/ohpm-switch.cjs +788 -788
- package/vendor/Server/Skills/arkts-library-demo-code/SKILL.md +291 -291
- package/vendor/Server/Skills/arkts-library-demo-code/references/API_SIGNATURE_CHECKS.md +68 -68
- package/vendor/Server/Skills/arkts-library-demo-code/references/BUILD_VALIDATION.md +184 -184
- package/vendor/Server/Skills/arkts-library-demo-code/references/CODE_STANDARDS.md +337 -337
- package/vendor/Server/Skills/arkts-library-demo-code/references/EXAMPLES.md +400 -400
- package/vendor/Server/Skills/arkts-library-demo-code/references/SYSTEM_API_LOOKUP.md +98 -98
- package/vendor/Server/Skills/arkts-library-demo-code/references/TEMPLATE.md +544 -544
- package/vendor/Server/Skills/arkts-library-demo-code/scripts/build.ps1 +93 -93
- package/vendor/Server/Skills/arkts-library-demo-code/scripts/code-linter.cjs +432 -432
- package/vendor/Server/Skills/arkts-library-demo-code/scripts/migrate.cjs +851 -851
- package/vendor/Server/Skills/arkts-library-demo-code/scripts/ohpm-switch.cjs +788 -788
- package/vendor/Server/Skills/arkts-library-demo-coverage/SKILL.md +174 -174
- package/vendor/Server/Skills/arkts-library-demo-scenario/SKILL.md +321 -321
- package/vendor/Server/Skills/arkts-library-demo-scenario/references/EXAMPLES.md +100 -100
- package/vendor/Server/Skills/arkts-library-demo-scenario/references/TEMPLATE.md +185 -185
- package/vendor/Server/Skills/arkts-library-documentation-quality-check/SKILL.md +233 -233
- package/vendor/Server/Skills/arkts-library-documentation-quality-check/assets/REPORT_TEMPLATE.md +102 -102
- package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/CHECK_DIMENSIONS.md +89 -89
- package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/COMPLIANCE_CHECKLIST.md +62 -62
- package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/KB_QUERY_GUIDE.md +107 -107
- package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/MCP_TOOL_DISCOVERY.md +124 -124
- package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/REPORT_TEMPLATE.md +90 -90
- package/vendor/Server/Skills/arkts-library-documentation-quality-check/references/SCORING_FORMULA.md +57 -57
- package/vendor/Server/Skills/arkts-library-documentation-quality-check/scripts/validate-skill.cjs +259 -259
- package/vendor/Server/Skills/arkts-library-interface-spec/SKILL.md +97 -97
- package/vendor/Server/Skills/arkts-library-memory-leak-check/SKILL.md +391 -391
- package/vendor/Server/Skills/arkts-library-source-clone/SKILL.md +113 -113
- package/vendor/Server/Skills/arkts-library-stability-check/SKILL.md +312 -312
- package/vendor/Server/Skills/arkts-library-stability-check/assets/REPORT_TEMPLATE.md +154 -154
- package/vendor/Server/Skills/arkts-library-stability-check/references/CHECKLIST.md +165 -165
- package/vendor/Server/Skills/arkts-library-stability-check/references/CODE_EXAMPLES.md +308 -308
- package/vendor/Server/Skills/arkts-library-stability-check/references/SCORING_RULES.md +90 -90
- package/vendor/Server/Skills/arkts-library-stability-check/scripts/validate-skill.cjs +282 -282
- package/vendor/Server/Skills/arkts-library-test-coverage-check/SKILL.md +360 -360
- package/vendor/Server/Skills/arkts-library-test-coverage-check/assets/REPORT_TEMPLATE.md +145 -145
- package/vendor/Server/Skills/arkts-library-test-coverage-check/references/CHECKLIST.md +252 -252
- package/vendor/Server/Skills/arkts-library-test-coverage-check/references/MCP_TOOL_USAGE.md +114 -114
- package/vendor/Server/Skills/arkts-library-test-coverage-check/scripts/validate-skill.cjs +262 -262
- package/vendor/Server/Skills/arkts-library-xts-code/SKILL.md +455 -455
- package/vendor/Server/Skills/arkts-library-xts-code/assets/report-template.md +60 -60
- package/vendor/Server/Skills/arkts-library-xts-code/references/ACCESS_MODIFIER_PRECHECK.md +76 -76
- package/vendor/Server/Skills/arkts-library-xts-code/references/BUILD_VERIFICATION.md +200 -200
- package/vendor/Server/Skills/arkts-library-xts-code/references/CODE_STANDARDS.md +518 -518
- package/vendor/Server/Skills/arkts-library-xts-code/references/SUBAGENT_PROMPT_TEMPLATE.md +276 -276
- package/vendor/Server/Skills/arkts-library-xts-code/references/SYSTEM_API_LOOKUP.md +92 -92
- package/vendor/Server/Skills/arkts-library-xts-code/references/XTS_TEMPLATE.md +767 -767
- package/vendor/Server/Skills/arkts-library-xts-code/scripts/build.ps1 +93 -93
- package/vendor/Server/Skills/arkts-library-xts-code/scripts/code-linter.cjs +432 -432
- package/vendor/Server/Skills/arkts-library-xts-code/scripts/migrate.cjs +851 -851
- package/vendor/Server/Skills/arkts-library-xts-code/scripts/ohpm-switch.cjs +788 -788
- package/vendor/Server/Skills/arkts-library-xts-code/scripts/precheck-access-modifiers.cjs +221 -221
- package/vendor/Server/Skills/arkts-library-xts-code-fix/SKILL.md +228 -228
- package/vendor/Server/Skills/arkts-library-xts-coverage/SKILL.md +97 -97
- package/vendor/Server/Skills/arkts-library-xts-doc/SKILL.md +194 -194
- package/vendor/Server/Skills/arkts-library-xts-doc/references/EXAMPLES.md +575 -575
- package/vendor/Server/Skills/arkts-library-xts-doc/references/TEMPLATE.md +574 -574
- package/vendor/Server/Skills/arkts-library-xts-doc/references/TESTABILITY_GUIDE.md +182 -182
- package/vendor/Server/Skills/arkts-library-xts-execution/SKILL.md +490 -490
- package/vendor/Server/Skills/arkts-library-xts-execution/references/error-fixing-examples.md +217 -217
- package/vendor/Server/Skills/arkts-library-xts-execution/scripts/build.ps1 +93 -93
- package/vendor/Server/Skills/arkts-library-xts-execution/scripts/code-linter.cjs +432 -432
- package/vendor/Server/Skills/arkts-library-xts-execution/scripts/migrate.cjs +851 -851
- package/vendor/Server/Skills/arkts-library-xts-execution/scripts/ohpm-switch.cjs +788 -788
- package/vendor/Server/Skills/flutter-code-check/SKILL.md +299 -299
- package/vendor/Server/Skills/flutter-code-check/assets/OUTPUT_TEMPLATE.md +311 -311
- package/vendor/Server/Skills/flutter-code-check/references/CHECKLIST.md +190 -190
- package/vendor/Server/Skills/flutter-code-check/references/PLATFORMS.md +133 -133
- package/vendor/Server/Skills/flutter-code-check/scripts/validate-skill.cjs +259 -259
- package/vendor/Server/Skills/flutter-interface/README.md +75 -75
- package/vendor/Server/Skills/flutter-interface/SKILL.md +291 -291
- package/vendor/Server/Skills/flutter-interface/references/EXAMPLES.md +336 -336
- package/vendor/Server/Skills/flutter-interface/references/GIT_CLONE_GUIDE.md +190 -190
- package/vendor/Server/Skills/flutter-interface/references/SCRIPT_REFERENCE.md +258 -258
- package/vendor/Server/Skills/flutter-interface/references/TEMPLATE.md +254 -254
- package/vendor/Server/Skills/flutter-library-consistency-check/SKILL.md +517 -517
- package/vendor/Server/Skills/flutter-library-consistency-check/references/CHECKLIST.md +381 -381
- package/vendor/Server/Skills/flutter-library-consistency-check/references/FUNCTION_COMPARISON_GUIDE.md +341 -341
- package/vendor/Server/Skills/flutter-library-consistency-check/references/PLATFORM_LIMITATION_GUIDE.md +71 -71
- package/vendor/Server/Skills/flutter-library-documentation-quality-check/SKILL.md +518 -518
- package/vendor/Server/Skills/flutter-library-documentation-quality-check/references/CHECKLIST.md +406 -406
- package/vendor/Server/Skills/flutter-library-memory-leak-check/SKILL.md +652 -652
- package/vendor/Server/Skills/flutter-library-memory-leak-check/references/CHECKLIST.md +396 -396
- package/vendor/Server/Skills/flutter-library-stability-check/SKILL.md +744 -744
- package/vendor/Server/Skills/flutter-library-stability-check/references/CHECKLIST.md +720 -720
- package/vendor/Server/Skills/flutter-library-test-coverage-check/SKILL.md +414 -414
- package/vendor/Server/Skills/flutter-library-test-coverage-check/assets/REPORT_TEMPLATE.md +150 -150
- package/vendor/Server/Skills/flutter-library-test-coverage-check/references/CHECKLIST.md +304 -304
- package/vendor/Server/Skills/flutter-library-test-coverage-check/references/SCORING_RULES.md +265 -265
- package/vendor/Server/Skills/flutter-library-test-coverage-check/references/SCRIPT_USAGE.md +286 -286
- package/vendor/Server/Skills/knowledge-import/SKILL.md +383 -383
- package/vendor/Server/Skills/knowledge-import/references/MCP_TOOL_USAGE.md +165 -165
- package/vendor/Server/Skills/knowledge-import/references/SKILL_LOCATOR_GUIDE.md +91 -91
- package/vendor/Server/Skills/knowledge-import/references/SKILL_OPTIMIZATION_GUIDE.md +127 -127
- package/vendor/Server/Skills/ohos-lib-pr-push/SKILL.md +453 -301
- package/vendor/Server/Skills/ohos-lib-pr-push/assets/PR_CHECKLIST.md +151 -0
- package/vendor/Server/Skills/ohos-lib-pr-push/assets/PR_ISSUE_TEMPLATE.md +257 -105
- package/vendor/Server/Skills/ohos-lib-pr-push/references/GITCODE_API.md +191 -127
- package/vendor/Server/Skills/ohos-lib-pr-push/scripts/gitcode-api.cjs +317 -208
- package/vendor/Server/Skills/rn-code-check/SKILL.md +320 -320
- package/vendor/Server/Skills/rn-code-check/references/API-GUIDE.md +234 -234
- package/vendor/Server/Skills/rn-code-check/references/CHECKLIST.md +188 -188
- package/vendor/Server/Skills/rn-code-check/references/REPORT-TEMPLATE.md +246 -246
- package/vendor/Server/Skills/rn-lib-add-example/SKILL.md +198 -198
- package/vendor/Server/Skills/rn-lib-add-example/references/APP_RENAME_GUIDE.md +40 -40
- package/vendor/Server/Skills/rn-lib-add-example/references/SHELL_ADAPTATION_CHECKLIST.md +78 -78
- package/vendor/Server/Skills/rn-lib-add-example/references/TEMPLATE_REPO_GUIDE.md +70 -70
- package/vendor/Server/Skills/rn-lib-add-example/references/VERIFICATION_GUIDE.md +47 -47
- package/vendor/Server/Skills/rn-lib-add-example/scripts/create-example.cjs +252 -252
- package/vendor/Server/Skills/rn-lib-update-doc/SKILL.md +176 -176
- package/vendor/Server/Skills/rn-lib-update-doc/config.json +5 -5
- package/vendor/Server/Skills/rn-lib-update-doc/references/changelog-template.md +35 -35
- package/vendor/Server/Skills/rn-lib-update-doc/references/format-diff.md +137 -137
- package/vendor/Server/Skills/rn-lib-update-doc/references/link-registry.json +33 -33
- package/vendor/Server/Skills/rn-lib-update-doc/references/model-0.4.2-overview.md +40 -40
- package/vendor/Server/Skills/rn-lib-update-doc/references/model-0.4.2.md +429 -429
- package/vendor/Server/Skills/rn-lib-update-doc/scripts/detect-readme-format.cjs +105 -105
- package/vendor/Server/Skills/rn-lib-update-doc/scripts/find-usage-doc.cjs +90 -90
- package/vendor/Server/Skills/rn-lib-update-doc/scripts/link-verify.cjs +213 -213
- package/vendor/Server/Skills/rn-lib-update-doc/scripts/normalize-changelog.cjs +73 -73
- package/vendor/Server/Skills/rn-lib-update-doc/scripts/normalize-package-meta.cjs +258 -258
- package/vendor/Server/Skills/rn-lib-update-doc/scripts/normalize-readme-links.cjs +341 -341
- package/vendor/Server/Skills/rn-lib-update-doc/scripts/resolve-usage-docs.cjs +67 -67
- package/vendor/Server/Skills/rn-library-consistency-check/SKILL.md +299 -299
- package/vendor/Server/Skills/rn-library-consistency-check/assets/REPORT_TEMPLATE.md +293 -293
- package/vendor/Server/Skills/rn-library-consistency-check/references/ARKTS_COMPONENT_CHECK_GUIDE.md +857 -857
- package/vendor/Server/Skills/rn-library-consistency-check/references/ARKTS_TURBOMODULE_CHECK_GUIDE.md +856 -856
- package/vendor/Server/Skills/rn-library-consistency-check/references/CHECKLIST.md +157 -157
- package/vendor/Server/Skills/rn-library-consistency-check/references/CPP_COMPONENT_CHECK_GUIDE.md +801 -801
- package/vendor/Server/Skills/rn-library-consistency-check/references/CPP_TURBOMODULE_CHECK_GUIDE.md +683 -683
- package/vendor/Server/Skills/rn-library-consistency-check/references/FUNCTION_COMPARISON_GUIDE.md +233 -233
- package/vendor/Server/Skills/rn-library-consistency-check/references/NATIVE_COMPONENT_IDENTIFICATION.md +1373 -1373
- package/vendor/Server/Skills/rn-library-consistency-check/references/SCORING_STANDARD.md +220 -220
- package/vendor/Server/Skills/rn-library-consistency-check/scripts/validate-skill.py +245 -245
- package/vendor/Server/Skills/rn-library-documentation-quality-check/SKILL.md +263 -263
- package/vendor/Server/Skills/rn-library-documentation-quality-check/assets/MODEL.md +414 -414
- package/vendor/Server/Skills/rn-library-documentation-quality-check/assets/MODEL_en.md +413 -413
- package/vendor/Server/Skills/rn-library-documentation-quality-check/assets/REPORT_TEMPLATE.md +311 -311
- package/vendor/Server/Skills/rn-library-documentation-quality-check/references/CHECK_CHECKLIST.md +355 -355
- package/vendor/Server/Skills/rn-library-documentation-quality-check/references/CROSS_VALIDATION_GUIDE.md +115 -115
- package/vendor/Server/Skills/rn-library-documentation-quality-check/references/DOC_COLLECTION_GUIDE.md +139 -139
- package/vendor/Server/Skills/rn-library-documentation-quality-check/references/EXAMPLES.md +586 -586
- package/vendor/Server/Skills/rn-library-documentation-quality-check/references/GOTCHAS.md +57 -57
- package/vendor/Server/Skills/rn-library-documentation-quality-check/scripts/validate-skill.py +259 -259
- package/vendor/Server/Skills/rn-library-interface-analyzer/SKILL.md +301 -301
- package/vendor/Server/Skills/rn-library-interface-analyzer/assets/REPORT_TEMPLATE.md +148 -148
- package/vendor/Server/Skills/rn-library-interface-analyzer/references/DOC_ANNOTATION_GUIDE.md +118 -118
- package/vendor/Server/Skills/rn-library-interface-analyzer/references/SCRIPT_USAGE_GUIDE.md +168 -168
- package/vendor/Server/Skills/rn-library-interface-analyzer/references/URL_PARSING_RULES.md +176 -176
- package/vendor/Server/Skills/rn-library-issue-generalizer/SKILL.md +274 -274
- package/vendor/Server/Skills/rn-library-issue-generalizer/assets/case-template.md +45 -45
- package/vendor/Server/Skills/rn-library-issue-generalizer/assets/rule-template.md +25 -25
- package/vendor/Server/Skills/rn-library-issue-generalizer/references/PR_FETCH_GUIDE.md +61 -61
- package/vendor/Server/Skills/rn-library-issue-generalizer/references/RULE_TEMPLATE_GUIDE.md +165 -165
- package/vendor/Server/Skills/rn-library-issue-generalizer/scripts/fetch-pr-info.py +239 -239
- package/vendor/Server/Skills/rn-library-known-issue-check/SKILL.md +263 -263
- package/vendor/Server/Skills/rn-library-known-issue-check/assets/REPORT_TEMPLATE.md +96 -96
- package/vendor/Server/Skills/rn-library-known-issue-check/references/COMPLIANCE_CHECKLIST.md +57 -57
- package/vendor/Server/Skills/rn-library-known-issue-check/references/INSPECTION_GUIDE.md +99 -99
- package/vendor/Server/Skills/rn-library-known-issue-check/references/PRESCREEN_GUIDE.md +64 -64
- package/vendor/Server/Skills/rn-library-known-issue-check/references/SOURCE_PREP_GUIDE.md +74 -74
- package/vendor/Server/Skills/rn-library-known-issue-check/scripts/validate-known-issue-report.py +164 -164
- package/vendor/Server/Skills/rn-library-memory-leak-check/SKILL.md +356 -339
- package/vendor/Server/Skills/rn-library-memory-leak-check/assets/REPORT_TEMPLATE.md +85 -83
- package/vendor/Server/Skills/rn-library-memory-leak-check/references/CHECKLIST.md +905 -859
- package/vendor/Server/Skills/rn-library-memory-leak-check/references/HARMONY_CODE_PATTERNS.md +124 -122
- package/vendor/Server/Skills/rn-library-memory-leak-check/scripts/scan_harmony_code.py +287 -279
- package/vendor/Server/Skills/rn-library-stability-check/SKILL.md +273 -273
- package/vendor/Server/Skills/rn-library-stability-check/assets/REPORT_TEMPLATE.md +129 -129
- package/vendor/Server/Skills/rn-library-stability-check/references/CHECKLIST.md +581 -581
- package/vendor/Server/Skills/rn-library-stability-check/references/SCORING_RULES.md +138 -138
- package/vendor/Server/Skills/rn-library-stability-check/scripts/scan-harmony-code.py +168 -168
- package/vendor/Server/Skills/rn-library-test-coverage-check/SKILL.md +526 -506
- package/vendor/Server/Skills/rn-library-test-coverage-check/references/CHECKLIST.md +321 -280
- package/vendor/Server/Skills/rn-library-test-coverage-check/references/DEMO_LOCATION.md +221 -221
- package/vendor/Server/Skills/rn-library-test-coverage-check/references/REPORT_TEMPLATE.md +220 -209
- package/vendor/Server/Skills/rn-library-test-coverage-check/references/SCRIPT_USAGE.md +325 -325
- package/vendor/Server/Skills/rn-ohos-xts-generator/SKILL.md +279 -279
- package/vendor/Server/Skills/rn-ohos-xts-generator/assets/TEST_FILE_TEMPLATES.md +404 -404
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/BUILD_TROUBLESHOOTING.md +185 -185
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/BUILD_WORKFLOW.md +265 -265
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/COMMON_CONFIG.md +189 -189
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/CONFIG_GUIDE.md +203 -203
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/COVERAGE_ANALYZER.md +147 -147
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/DESIGN_DOC_GUIDE.md +148 -148
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/GENERATION_FLOW.md +165 -165
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/GENERATION_STRATEGY.md +195 -195
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/HARMONY_SCANNER.md +249 -249
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/JEST_FRAMEWORK.md +235 -235
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/PLATFORM_COMPAT.md +161 -161
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/RN_TEST_PATTERNS.md +413 -413
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/SOURCE_PARSER.md +235 -235
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/TEST_CONVENTIONS.md +245 -245
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/TROUBLESHOOTING.md +282 -282
- package/vendor/Server/Skills/rn-ohos-xts-generator/references/USAGE_GUIDE.md +251 -251
- package/vendor/Server/Skills/rnoh-cptf-api-test/SKILL.md +469 -469
- package/vendor/Server/Skills/rnoh-cptf-api-test/assets/CPTF_TEST_TEMPLATE.md +310 -310
- package/vendor/Server/Skills/rnoh-cptf-api-test/assets/DEMO_PAGE_TEMPLATE.md +303 -303
- package/vendor/Server/Skills/rnoh-cptf-api-test/references/CPTF_TEST_GENERATION_GUIDE.md +421 -421
- package/vendor/Server/Skills/rnoh-cptf-api-test/references/DEMO_GENERATION_GUIDE.md +358 -358
- package/vendor/Server/Skills/rnoh-cptf-api-test/references/QUALITY_CHECKLIST.md +114 -114
- package/vendor/Server/Skills/rnoh-cptf-api-test/references/SPEC_PARSING_GUIDE.md +274 -274
- package/vendor/Server/Skills/rnoh-cptf-api-test/scripts/validate-rnoh-cptf-api-test.sh +185 -185
- package/vendor/Server/Skills/rnoh-cptf-demo-test/SKILL.md +191 -191
- package/vendor/Server/Skills/rnoh-cptf-demo-test/assets/TEST_TEMPLATE.md +216 -216
- package/vendor/Server/Skills/rnoh-cptf-demo-test/references/CPTF_SETUP.md +107 -107
- package/vendor/Server/Skills/rnoh-cptf-demo-test/references/DEMO_ANALYSIS.md +120 -120
- package/vendor/Server/Skills/rnoh-cptf-demo-test/scripts/validate-rnoh-cptf-test.sh +108 -108
- package/vendor/Server/Skills/rnoh-cptf-test-run/SKILL.md +237 -237
- package/vendor/Server/Skills/rnoh-cptf-test-run/references/DEBUG_PLAYBOOK.md +261 -261
- package/vendor/Server/Skills/rnoh-cptf-test-run/scripts/validate-run-env.sh +112 -112
- package/vendor/Server/Skills/rnoh-lib-code-adapt/SKILL.md +497 -497
- package/vendor/Server/Skills/rnoh-lib-code-adapt/references/adapt-checklist.md +270 -270
- package/vendor/Server/Skills/rnoh-lib-code-adapt/references/api-migration-checklist.md +164 -164
- package/vendor/Server/Skills/rnoh-lib-code-adapt/references/common-compile-errors.md +556 -556
- package/vendor/Server/Skills/rnoh-lib-code-adapt/references/deveco-cli-tools.md +459 -459
- package/vendor/Server/Skills/rnoh-lib-code-adapt/references/edge-cases.md +65 -65
- package/vendor/Server/Skills/rnoh-lib-code-adapt/references/har-tgz-build.md +512 -512
- package/vendor/Server/Skills/rnoh-lib-code-adapt/references/version-compat-matrix.md +132 -132
- package/vendor/Server/Skills/rnoh-lib-code-adapt/scripts/auto-integrate.sh +424 -424
- package/vendor/Server/Skills/rnoh-lib-demo-coverage/SKILL.md +137 -137
- package/vendor/Server/Skills/rnoh-lib-demo-create/SKILL.md +306 -306
- package/vendor/Server/Skills/rnoh-lib-demo-create/assets/DEMO_PAGE_TEMPLATE.md +485 -485
- package/vendor/Server/Skills/rnoh-lib-demo-create/assets/INDEX_TEMPLATE.md +172 -172
- package/vendor/Server/Skills/rnoh-lib-demo-create/references/DEMO_CODE_RULES.md +422 -422
- package/vendor/Server/Skills/rnoh-lib-demo-create/references/QUALITY_CHECKLIST.md +95 -95
- package/vendor/Server/Skills/rnoh-lib-demo-create/references/SOURCE_EXPLORATION.md +169 -169
- package/vendor/Server/Skills/rnoh-lib-demo-doc/SKILL.md +554 -554
- package/vendor/Server/Skills/rnoh-lib-demo-doc/assets/DEMO_DOC_TEMPLATE.md +106 -106
- package/vendor/Server/Skills/rnoh-lib-demo-doc/references/COVERAGE_INCREMENTAL.md +216 -216
- package/vendor/Server/Skills/rnoh-lib-demo-doc/references/DEMO_DESIGN_RULES.md +413 -413
- package/vendor/Server/Skills/rnoh-lib-demo-doc/references/OUTPUT_FORMAT.md +269 -269
- package/vendor/Server/Skills/rnoh-lib-demo-doc/references/QUALITY_CHECKLIST.md +98 -98
- package/vendor/Server/Skills/rnoh-lib-func-test/SKILL.md +337 -337
- package/vendor/Server/Skills/rnoh-lib-rnt-search/SKILL.md +722 -722
- package/vendor/Server/Skills/rnoh-lib-rnt-search/assets/PORT_REPORT_TEMPLATE.md +219 -219
- package/vendor/Server/Skills/rnoh-lib-rnt-search/references/DEMO_PORTING_GUIDE.md +345 -345
- package/vendor/Server/Skills/rnoh-lib-rnt-search/references/PORT_VERIFICATION.md +269 -269
- package/vendor/Server/Skills/rnoh-lib-rnt-search/references/RNT_PROJECT_STRUCTURE.md +173 -173
- package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/analyze-demo-deps.cjs +267 -267
- package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/detect-rnoh-version.cjs +174 -174
- package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/find-rnt-demo.sh +111 -111
- package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/port-demo.sh +186 -186
- package/vendor/Server/Skills/rnoh-lib-rnt-search/scripts/read-lib-meta.cjs +150 -150
- package/vendor/Server/Skills/rnoh-lib-test-align/SKILL.md +296 -296
- package/vendor/Server/Skills/rnoh-lib-test-align/references/jest-troubleshooting.md +371 -371
- package/vendor/Server/Skills/rnoh-lib-test-align/references/port-test-demo-guide.md +212 -212
- package/vendor/Server/Skills/rnoh-lib-test-align/references/runtime-troubleshooting.md +345 -345
- package/vendor/Server/Skills/rnoh-lib-test-align/references/unit-test-template.md +223 -223
- package/vendor/Server/Skills/rnoh-lib-test-align/scripts/port-test-demo.sh +1053 -1053
- package/vendor/Server/Skills/rnoh-lib-version-diff/SKILL.md +295 -255
- package/vendor/Server/Skills/rnoh-lib-version-diff/references/OHOS_ADAPTATION.md +82 -77
- package/vendor/Server/Skills/rnoh-lib-version-diff/references/OHOS_API_LOOKUP.md +224 -224
- package/vendor/Server/Skills/rnoh-lib-version-diff/references/script-reference.md +175 -174
- package/vendor/Server/Skills/rnoh-lib-version-diff/scripts/detect-upstream-version.js +967 -967
- package/vendor/Server/Skills/rnoh-lib-version-diff/scripts/generate-diff.js +1798 -1798
- package/vendor/Server/Skills/rnoh-lib-version-diff/scripts/package.json +5 -5
- package/vendor/Server/Skills/rnoh-lib-version-diff/templates/report-template.md +180 -137
- package/vendor/Server/Skills/rnoh-lib-xts-coverage/SKILL.md +145 -145
- package/vendor/Server/Skills/skill-generator/SKILL.md +365 -365
- package/vendor/Server/Skills/skill-generator/assets/SKILL_TEMPLATE.md +183 -183
- package/vendor/Server/Skills/skill-generator/references/COMPLIANCE_CHECKLIST.md +82 -82
- package/vendor/Server/Skills/skill-generator/references/KB_QUERY_GUIDE.md +110 -110
- package/vendor/Server/Skills/skill-generator/references/MCP_TOOL_DISCOVERY.md +122 -122
- package/vendor/Server/Skills/skill-generator/references/SKILL_SPEC.md +121 -121
- package/vendor/Server/Skills/skill-generator/scripts/validate-skill.cjs +259 -259
- package/vendor/Server/Skills/task-analysis/SKILL.md +234 -234
- package/vendor/Server/Skills/task-analysis/assets/OUTPUT_EXAMPLES.md +160 -160
- package/vendor/Server/Skills/task-analysis/references/ACCEPTANCE_CRITERIA_GUIDE.md +190 -190
- package/vendor/Server/Skills/task-analysis/references/ANALYSIS_SCHEMA.md +224 -224
- package/vendor/Server/Skills/task-analysis/references/INTEGRATION_CONTEXT.md +162 -162
- package/vendor/Server/Skills/task-analysis/references/LESSONS_LEARNED.md +55 -55
- package/vendor/Server/Skills/task-analysis/references/REPLAN_CONTEXT_GUIDE.md +126 -126
- package/vendor/Server/Skills/task-analysis/scripts/validate-analysis-output.sh +256 -256
- package/vendor/Server/Skills/task-decomposition/SKILL.md +528 -528
- package/vendor/Server/Skills/task-decomposition/assets/OUTPUT_EXAMPLES.md +451 -451
- package/vendor/Server/Skills/task-decomposition/references/ACCEPTANCE_CRITERIA_GUIDE.md +179 -179
- package/vendor/Server/Skills/task-decomposition/references/DEPENDENCY_GRAPH_GUIDE.md +152 -152
- package/vendor/Server/Skills/task-decomposition/references/INTEGRATION_CONTEXT.md +175 -175
- package/vendor/Server/Skills/task-decomposition/references/REPLAN_CONTEXT_GUIDE.md +195 -195
- package/vendor/Server/Skills/task-decomposition/references/TASK_DECOMPOSITION_TEMPLATES.md +226 -226
- package/vendor/Server/Skills/task-decomposition/scripts/list-available-skills.cjs +263 -263
- package/vendor/Server/Skills/task-decomposition/scripts/skill-blacklist.json +29 -29
- package/vendor/Server/Skills/task-decomposition/scripts/validate-decomposition-output.cjs +376 -376
- package/vendor/Server/Skills/task-decomposition/scripts/validate-param-consistency.cjs +259 -259
- package/vendor/Server/Skills/task-decomposition/scripts/validate-specified-skills.cjs +216 -216
- package/vendor/Server/Skills/task-decomposition/scripts/validate-step-graph.cjs +424 -424
- package/vendor/Server/Skills/tpc-cpp-check/SKILL.md +427 -427
- package/vendor/Server/Skills/tpc-cpp-check/references/CHECKLIST.md +214 -214
- package/vendor/Server/Skills/tpc-cpp-check/references/HPKBUILD_GUIDE.md +235 -235
- package/vendor/Server/Skills/tpc-cpp-check/references/REPORT_TEMPLATE.md +250 -250
- package/vendor/Server/TestCheck/TestCheck.js +775 -775
- package/vendor/Server/TestCheck/index.js +11 -11
- package/vendor/Server/library/McpToolGuide.js +280 -280
- package/vendor/Server/library/StatsService.js +126 -126
- package/vendor/Server/library/cstTime.js +16 -16
- package/vendor/VERSION +3 -3
- package/workflows/pr-check.mjs +105 -105
- package/workflows/pr-push.mjs +192 -192
- package/vendor/Server/Agent/SkillSelector/types.js +0 -63
|
@@ -1,859 +1,905 @@
|
|
|
1
|
-
# RN 鸿蒙化代码内存泄露检视清单
|
|
2
|
-
|
|
3
|
-
本文档列出 RN 三方库鸿蒙化代码内存泄露检视的详细检查项、正例/反例代码示例和扣分细则,作为 SKILL.md Phase 1-5 的详细参考。
|
|
4
|
-
|
|
5
|
-
> ⚠️ **核心定位**:本清单**仅检视鸿蒙化代码**,不检视 RN JS 层或非鸿蒙化部分的代码。
|
|
6
|
-
>
|
|
7
|
-
> **重要**:目录名称不固定,需通过源码扫描识别鸿蒙化代码特征(如 `@ohos` 导入、TurboModule 实现、NAPI 函数等),而非仅依赖目录名称。
|
|
8
|
-
|
|
9
|
-
**相关参考文档**:
|
|
10
|
-
- [SKILL.md](../SKILL.md) — 主工作流文件(检视流程概览、Phase 0-5 核心步骤)
|
|
11
|
-
- [HARMONY_CODE_PATTERNS.md](HARMONY_CODE_PATTERNS.md) — Phase 0 鸿蒙代码特征识别模式
|
|
12
|
-
- [REPORT_TEMPLATE.md](../assets/REPORT_TEMPLATE.md) — 输出报告模板和评分等级对照表
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## 1. TurboModule/NativeModule 生命周期管理
|
|
17
|
-
|
|
18
|
-
### 1.1 TurboModule 生命周期绑定
|
|
19
|
-
|
|
20
|
-
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
21
|
-
|--------|----------|----------|------|
|
|
22
|
-
| `initialize` | 资源初始化是否完整 | 高 | 缺失 -5 |
|
|
23
|
-
| `destroy` | 是否释放**所有**资源 | **致命** | 未释放 -20 |
|
|
24
|
-
| Bridge 事件监听清理 | NativeEventEmitter/DeviceEventEmitter 监听是否全部移除 | 高 | 未移除 -15 |
|
|
25
|
-
| Map 数据清理 | 模块级 Map(如 `mConnectedDevices`)是否清空 | 高 | 未清空 -12 |
|
|
26
|
-
| 释放顺序 | 先移除监听→停操作→清数据→释放资源 | 中 | 顺序错误 -8 |
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
// 缺失:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
private
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
|
82
|
-
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
|
132
|
-
|
|
133
|
-
|
|
|
134
|
-
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
|
250
|
-
|
|
251
|
-
|
|
|
252
|
-
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
this.
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
|
305
|
-
|
|
306
|
-
|
|
|
307
|
-
|
|
|
308
|
-
|
|
|
309
|
-
|
|
|
310
|
-
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
|
352
|
-
|
|
353
|
-
|
|
|
354
|
-
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
|
440
|
-
|
|
441
|
-
|
|
|
442
|
-
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
|
494
|
-
|
|
495
|
-
|
|
|
496
|
-
|
|
|
497
|
-
|
|
|
498
|
-
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
|
586
|
-
|
|
587
|
-
|
|
|
588
|
-
|
|
|
589
|
-
|
|
|
590
|
-
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
|
681
|
-
|
|
682
|
-
|
|
|
683
|
-
|
|
|
684
|
-
|
|
|
685
|
-
|
|
|
686
|
-
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
//
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
//
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
|
754
|
-
|
|
755
|
-
|
|
|
756
|
-
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
this.mConnectedDevices.
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
|
816
|
-
|
|
817
|
-
|
|
|
818
|
-
|
|
|
819
|
-
|
|
|
820
|
-
|
|
|
821
|
-
|
|
|
822
|
-
|
|
|
823
|
-
|
|
|
824
|
-
|
|
|
825
|
-
|
|
|
826
|
-
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
|
833
|
-
|
|
834
|
-
|
|
|
835
|
-
|
|
|
836
|
-
|
|
|
837
|
-
|
|
|
838
|
-
|
|
|
839
|
-
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
|
846
|
-
|
|
847
|
-
|
|
|
848
|
-
|
|
|
849
|
-
|
|
|
850
|
-
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
|
857
|
-
|
|
858
|
-
|
|
|
859
|
-
|
|
|
1
|
+
# RN 鸿蒙化代码内存泄露检视清单
|
|
2
|
+
|
|
3
|
+
本文档列出 RN 三方库鸿蒙化代码内存泄露检视的详细检查项、正例/反例代码示例和扣分细则,作为 SKILL.md Phase 1-5 的详细参考。
|
|
4
|
+
|
|
5
|
+
> ⚠️ **核心定位**:本清单**仅检视鸿蒙化代码**,不检视 RN JS 层或非鸿蒙化部分的代码。
|
|
6
|
+
>
|
|
7
|
+
> **重要**:目录名称不固定,需通过源码扫描识别鸿蒙化代码特征(如 `@ohos` 导入、TurboModule 实现、NAPI 函数等),而非仅依赖目录名称。
|
|
8
|
+
|
|
9
|
+
**相关参考文档**:
|
|
10
|
+
- [SKILL.md](../SKILL.md) — 主工作流文件(检视流程概览、Phase 0-5 核心步骤)
|
|
11
|
+
- [HARMONY_CODE_PATTERNS.md](HARMONY_CODE_PATTERNS.md) — Phase 0 鸿蒙代码特征识别模式
|
|
12
|
+
- [REPORT_TEMPLATE.md](../assets/REPORT_TEMPLATE.md) — 输出报告模板和评分等级对照表
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 1. TurboModule/NativeModule 生命周期管理
|
|
17
|
+
|
|
18
|
+
### 1.1 TurboModule 生命周期绑定
|
|
19
|
+
|
|
20
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
21
|
+
|--------|----------|----------|------|
|
|
22
|
+
| `initialize` | 资源初始化是否完整 | 高 | 缺失 -5 |
|
|
23
|
+
| `destroy` | 是否释放**所有**资源 | **致命** | 未释放 -20 |
|
|
24
|
+
| Bridge 事件监听清理 | NativeEventEmitter/DeviceEventEmitter 监听是否全部移除 | 高 | 未移除 -15 |
|
|
25
|
+
| Map 数据清理 | 模块级 Map(如 `mConnectedDevices`)是否清空 | 高 | 未清空 -12 |
|
|
26
|
+
| 释放顺序 | 先移除监听→停操作→清数据→释放资源 | 中 | 顺序错误 -8 |
|
|
27
|
+
|
|
28
|
+
> ⚠️ **无状态模块豁免**:`destroy` 未释放扣 20 分的前提是模块**持有需要释放的资源**(事件监听/系统资源句柄/Map/Set 容器/回调引用/实例字段)。零状态模块未重写 `__onDestroy__`/`destroy` 属正确最小化设计,**不扣分**,报告中注明"无泄露面"。适用豁免前必须先完成[第 10 节零泄露面穷尽验证](#10-零泄露面穷尽验证模式集无状态库确认)。
|
|
29
|
+
|
|
30
|
+
**正确示例**:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// ❌ 致命错误:destroy 未释放所有资源
|
|
34
|
+
class BleTurboModule extends TurboModule {
|
|
35
|
+
private mConnectedDevices: Map<string, GattClientDevice> = new Map();
|
|
36
|
+
private eventEmitter: NativeEventEmitter;
|
|
37
|
+
private scanListener: EventSubscription | null = null;
|
|
38
|
+
|
|
39
|
+
destroy(): void {
|
|
40
|
+
// 仅清空了部分 Map,遗漏了事件监听和系统资源
|
|
41
|
+
this.mConnectedDevices.clear();
|
|
42
|
+
// 缺失:NativeEventEmitter 监听未移除
|
|
43
|
+
// 缺失:ble.stopBLEScan() 未调用
|
|
44
|
+
// 缺失:GattClientDevice 未 close()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ✅ 正确实现
|
|
49
|
+
class BleTurboModule extends TurboModule {
|
|
50
|
+
private mConnectedDevices: Map<string, GattClientDevice> = new Map();
|
|
51
|
+
private eventEmitter: NativeEventEmitter;
|
|
52
|
+
private scanListener: EventSubscription | null = null;
|
|
53
|
+
|
|
54
|
+
destroy(): void {
|
|
55
|
+
// 1. 移除所有 Bridge 事件监听
|
|
56
|
+
if (this.scanListener) {
|
|
57
|
+
this.scanListener.remove();
|
|
58
|
+
this.scanListener = null;
|
|
59
|
+
}
|
|
60
|
+
this.eventEmitter.removeAllListeners('onBleStateChange');
|
|
61
|
+
|
|
62
|
+
// 2. 停止进行中的操作
|
|
63
|
+
ble.stopBLEScan();
|
|
64
|
+
|
|
65
|
+
// 3. 释放系统资源
|
|
66
|
+
for (const device of this.mConnectedDevices.values()) {
|
|
67
|
+
device.close(); // 释放 GattClientDevice
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 4. 清空 Map 数据
|
|
71
|
+
this.mConnectedDevices.clear();
|
|
72
|
+
|
|
73
|
+
// 5. 置空回调引用
|
|
74
|
+
this.scanCallback = null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 1.2 NativeComponent 生命周期绑定
|
|
80
|
+
|
|
81
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
82
|
+
|--------|----------|----------|------|
|
|
83
|
+
| `onDropViewInstance` | 视图销毁时是否释放所有关联资源 | **致命** | 未释放 -15 |
|
|
84
|
+
| View 级监听器清理 | 视图级事件监听是否在视图销毁时移除 | 高 | 未移除 -12 |
|
|
85
|
+
| RCTEventEmitter 引用清除 | 原生侧事件发送器引用是否清除 | 高 | 未清除 -10 |
|
|
86
|
+
| 子组件递归释放 | 自定义 View 的子 View 是否递归释放 | 中 | 未释放 -10 |
|
|
87
|
+
|
|
88
|
+
**关键检查**:
|
|
89
|
+
- `onDropViewInstance` 必须释放视图持有的所有系统资源(Sensor、Location、Timer 等)
|
|
90
|
+
- 视图级的 `on()` 监听不应依赖 TurboModule 的 `destroy()` 释放
|
|
91
|
+
- **多实例场景**:同一 ViewManager 创建的多个 View 实例必须各自独立清理
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
// ❌ 致命错误:onDropViewInstance 未清理视图资源
|
|
95
|
+
class MapViewManager extends ViewManager {
|
|
96
|
+
onDropViewInstance(view: Component): void {
|
|
97
|
+
super.onDropViewInstance(view);
|
|
98
|
+
// 缺失:view 持有的 Sensor 监听未注销
|
|
99
|
+
// 缺失:view 的 Timer 未清除
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ✅ 正确实现
|
|
104
|
+
class MapViewManager extends ViewManager {
|
|
105
|
+
onDropViewInstance(view: Component): void {
|
|
106
|
+
// 1. 注销视图级 Sensor 监听
|
|
107
|
+
sensor.off(sensor.SensorId.ACCELEROMETER, view.accelerometerCallback);
|
|
108
|
+
|
|
109
|
+
// 2. 清除视图级 Timer
|
|
110
|
+
clearInterval(view.updateTimer);
|
|
111
|
+
|
|
112
|
+
// 3. 释放视图级资源
|
|
113
|
+
if (view.mediaPlayer) {
|
|
114
|
+
view.mediaPlayer.release();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 4. 从 ViewManager 的 Map 中移除视图实例
|
|
118
|
+
this.viewInstances.delete(view.getTag());
|
|
119
|
+
|
|
120
|
+
super.onDropViewInstance(view);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 2. RN Bridge 事件机制
|
|
128
|
+
|
|
129
|
+
### 2.1 NativeEventEmitter 监听管理
|
|
130
|
+
|
|
131
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
132
|
+
|--------|----------|----------|------|
|
|
133
|
+
| addListener/removeAllListeners | 每个监听是否在适当时机移除 | 高 | 未移除 -15 |
|
|
134
|
+
| DeviceEventEmitter 监听泄露 | DeviceEventEmitter.addListener 后是否在 destroy 移除 | 高 | 未移除 -15 |
|
|
135
|
+
| RCTEventEmitter 强引用 | 原生侧 RCTEventEmitter 是否持有已销毁 View 引用 | 高 | 持有 -12 |
|
|
136
|
+
| 事件发送器生命周期 | EventEmitter 实例是否随 TurboModule 销毁 | 中 | 未销毁 -10 |
|
|
137
|
+
|
|
138
|
+
**致命问题示例**:
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// ❌ 致命:每次调用都注册新监听器,destroy 时未移除
|
|
142
|
+
class BleTurboModule extends TurboModule {
|
|
143
|
+
startScan(): void {
|
|
144
|
+
this.deviceEventEmitter.addListener('onDeviceFound', (device) => {
|
|
145
|
+
this.handleDeviceFound(device);
|
|
146
|
+
});
|
|
147
|
+
// ⚠️ 多次调用会注册多个监听器,且 destroy 时未移除!
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ✅ 正确实现:使用 EventSubscription 保存监听引用
|
|
152
|
+
class BleTurboModule extends TurboModule {
|
|
153
|
+
private scanListenerSubscription: EventSubscription | null = null;
|
|
154
|
+
|
|
155
|
+
startScan(): void {
|
|
156
|
+
// 先移除旧监听
|
|
157
|
+
if (this.scanListenerSubscription) {
|
|
158
|
+
this.scanListenerSubscription.remove();
|
|
159
|
+
}
|
|
160
|
+
this.scanListenerSubscription = this.deviceEventEmitter.addListener(
|
|
161
|
+
'onDeviceFound', (device) => this.handleDeviceFound(device)
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
destroy(): void {
|
|
166
|
+
if (this.scanListenerSubscription) {
|
|
167
|
+
this.scanListenerSubscription.remove();
|
|
168
|
+
this.scanListenerSubscription = null;
|
|
169
|
+
}
|
|
170
|
+
this.eventEmitter.removeAllListeners('onBleStateChange');
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 2.2 RN Bridge 事件监听的常见泄露场景
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// ❌ 场景1:Promise 回调中的监听器泄露
|
|
179
|
+
class NetworkTurboModule extends TurboModule {
|
|
180
|
+
async waitForConnection(): Promise<boolean> {
|
|
181
|
+
return new Promise((resolve) => {
|
|
182
|
+
this.eventEmitter.addListener('onNetworkChange', (state) => {
|
|
183
|
+
if (state.connected) {
|
|
184
|
+
resolve(true);
|
|
185
|
+
// ⚠️ resolve 后监听器未移除!
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ✅ 正确实现
|
|
193
|
+
class NetworkTurboModule extends TurboModule {
|
|
194
|
+
private networkListener: EventSubscription | null = null;
|
|
195
|
+
|
|
196
|
+
async waitForConnection(): Promise<boolean> {
|
|
197
|
+
return new Promise((resolve) => {
|
|
198
|
+
this.networkListener = this.eventEmitter.addListener('onNetworkChange', (state) => {
|
|
199
|
+
if (state.connected) {
|
|
200
|
+
resolve(true);
|
|
201
|
+
// 移除监听
|
|
202
|
+
if (this.networkListener) {
|
|
203
|
+
this.networkListener.remove();
|
|
204
|
+
this.networkListener = null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// ❌ 场景2:RCTEventEmitter 持有已销毁 View 引用
|
|
213
|
+
class CameraViewManager extends ViewManager {
|
|
214
|
+
private eventEmitter: RCTEventEmitter;
|
|
215
|
+
private viewMap: Map<number, Component> = new Map();
|
|
216
|
+
|
|
217
|
+
// 视图销毁后 eventEmitter 仍可能向该 view 发送事件
|
|
218
|
+
sendEventToView(viewTag: number, eventName: string, data: Object): void {
|
|
219
|
+
this.eventEmitter.emit(eventName, { viewTag, ...data });
|
|
220
|
+
// ⚠️ 如果 view 已被 onDropViewInstance 清理,事件仍会发送
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// ✅ 正确实现:发送事件前检查 view 是否仍存在
|
|
225
|
+
class CameraViewManager extends ViewManager {
|
|
226
|
+
private eventEmitter: RCTEventEmitter;
|
|
227
|
+
private viewMap: Map<number, Component> = new Map();
|
|
228
|
+
|
|
229
|
+
sendEventToView(viewTag: number, eventName: string, data: Object): void {
|
|
230
|
+
if (!this.viewMap.has(viewTag)) {
|
|
231
|
+
return; // 视图已销毁,不再发送事件
|
|
232
|
+
}
|
|
233
|
+
this.eventEmitter.emit(eventName, { viewTag, ...data });
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
onDropViewInstance(view: Component): void {
|
|
237
|
+
this.viewMap.delete(view.getTag()); // 从 Map 中移除
|
|
238
|
+
super.onDropViewInstance(view);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 3. 鸿蒙 API 事件订阅管理
|
|
246
|
+
|
|
247
|
+
### 3.1 @ohos 模块事件订阅
|
|
248
|
+
|
|
249
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
250
|
+
|--------|----------|----------|------|
|
|
251
|
+
| `on/off` 对称性 | 每个 `on()` 是否有对应 `off()` | **致命** | 无对应 -20 |
|
|
252
|
+
| 回调参数匹配 | `off()` 是否传入正确的回调函数引用 | 高 | 参数错误 -12 |
|
|
253
|
+
| 多次注册风险 | 同一事件是否可能被多次注册监听 | 高 | 存在风险 -15 |
|
|
254
|
+
| TurboModule 级 vs View 级监听 | TurboModule 级监听不应在 View 销毁时取消 | 中 | 混淆 -10 |
|
|
255
|
+
|
|
256
|
+
**致命问题示例**:
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
// ❌ 致命:每次调用都注册新监听器,无对应取消
|
|
260
|
+
class BleTurboModule extends TurboModule {
|
|
261
|
+
async setNotifyValue(remoteId: string, characteristic: ble.BLECharacteristic): Promise<void> {
|
|
262
|
+
const gatt = this.mConnectedDevices.get(remoteId);
|
|
263
|
+
gatt.on('BLECharacteristicChange', (data) => {
|
|
264
|
+
this.onCharacteristicReceived(remoteId, data);
|
|
265
|
+
});
|
|
266
|
+
// ⚠️ 每次调用注册新监听器,断开连接时未取消!
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ✅ 正确实现:使用 Map 保存回调引用
|
|
271
|
+
class BleTurboModule extends TurboModule {
|
|
272
|
+
private characteristicCallbacks: Map<string, Function> = new Map();
|
|
273
|
+
|
|
274
|
+
async setNotifyValue(remoteId: string, characteristic: ble.BLECharacteristic): Promise<void> {
|
|
275
|
+
const gatt = this.mConnectedDevices.get(remoteId);
|
|
276
|
+
|
|
277
|
+
// 先取消旧的监听器
|
|
278
|
+
const oldCallback = this.characteristicCallbacks.get(remoteId);
|
|
279
|
+
if (oldCallback) {
|
|
280
|
+
gatt.off('BLECharacteristicChange', oldCallback);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// 注册新的监听器并保存引用
|
|
284
|
+
const newCallback = (data) => this.onCharacteristicReceived(remoteId, data);
|
|
285
|
+
gatt.on('BLECharacteristicChange', newCallback);
|
|
286
|
+
this.characteristicCallbacks.set(remoteId, newCallback);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
destroy(): void {
|
|
290
|
+
// 释放所有特征变化监听
|
|
291
|
+
for (const [remoteId, callback] of this.characteristicCallbacks) {
|
|
292
|
+
const gatt = this.mConnectedDevices.get(remoteId);
|
|
293
|
+
if (gatt) {
|
|
294
|
+
gatt.off('BLECharacteristicChange', callback);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
this.characteristicCallbacks.clear();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### 3.2 特殊系统资源释放
|
|
303
|
+
|
|
304
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
305
|
+
|--------|----------|----------|------|
|
|
306
|
+
| GattClientDevice.close | BLE Gatt 客户端是否调用 close() | **致命** | 未调用 -20 |
|
|
307
|
+
| 扫描状态清理 | `ble.stopBLEScan()` 是否在适当时机调用 | 高 | 未调用 -15 |
|
|
308
|
+
| 地理位置监听 | `geoLocationManager.off()` 是否取消 | 高 | 未取消 -15 |
|
|
309
|
+
| Sensor 注销 | `sensor.off()` 是否取消 | **致命** | 未注销 -20 |
|
|
310
|
+
| 网络状态监听 | `connection.on/off` 是否对称 | 高 | 不对称 -12 |
|
|
311
|
+
| 数据库连接未关闭 | rdb 关闭未调用 close | **致命** | 未关闭 -20 |
|
|
312
|
+
| Timer 未清除 | setInterval/setTimeout 未在 destroy 时清除 | 高 | 未清除 -12 |
|
|
313
|
+
|
|
314
|
+
**致命泄漏场景**:
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
// ❌ 致命:GattClientDevice 创建后未释放
|
|
318
|
+
class BleTurboModule extends TurboModule {
|
|
319
|
+
async scanCallback(device: ble.ScanResult): void {
|
|
320
|
+
const gattClient = ble.createGattClientDevice(device.getMac());
|
|
321
|
+
const deviceName = await gattClient.getDeviceName();
|
|
322
|
+
// ⚠️ gattClient 未调用 close(),每次扫描都泄漏!
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// ❌ 致命:服务查询创建的 GattClientDevice 未释放
|
|
327
|
+
async getServices(remoteId: string): Promise<ble.GattService[]> {
|
|
328
|
+
const gattClient = ble.createGattClientDevice(remoteId);
|
|
329
|
+
const services = await gattClient.getServices();
|
|
330
|
+
return services; // ⚠️ gattClient 未释放
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// ✅ 正确实现:使用 try-finally 确保释放
|
|
334
|
+
async getServices(remoteId: string): Promise<ble.GattService[]> {
|
|
335
|
+
const gattClient = ble.createGattClientDevice(remoteId);
|
|
336
|
+
try {
|
|
337
|
+
const services = await gattClient.getServices();
|
|
338
|
+
return services;
|
|
339
|
+
} finally {
|
|
340
|
+
gattClient.close(); // 必须释放
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## 4. 闭包与上下文泄露
|
|
348
|
+
|
|
349
|
+
### 4.1 闭包循环引用
|
|
350
|
+
|
|
351
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
352
|
+
|--------|----------|----------|------|
|
|
353
|
+
| this 捕获 | 箭头函数是否捕获 `this` 引用且未在 destroy 释放 | 高 | 捕获且未释放 -15 |
|
|
354
|
+
| 闭包保留 | 闭包是否保留外部变量引用且无法释放 | 高 | 保留且无法释放 -12 |
|
|
355
|
+
| RN 回调链泄露 | JS → Native → JS 回调链中的闭包引用是否正确断开 | 高 | 未断开 -12 |
|
|
356
|
+
| 异步回调持有 stale context | setTimeout/Promise 回调中引用已销毁 TurboModule 上下文 | 中 | 引用 -10 |
|
|
357
|
+
|
|
358
|
+
**循环引用检测**:
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
// ❌ 风险:箭头函数捕获 this,形成循环引用
|
|
362
|
+
class BleTurboModule extends TurboModule {
|
|
363
|
+
private gatt: ble.GattClientDevice;
|
|
364
|
+
|
|
365
|
+
connect(): void {
|
|
366
|
+
this.gatt.on('BLEConnectionStateChange', (state) => {
|
|
367
|
+
this.onConnectionStateChanged(state); // this 被捕获
|
|
368
|
+
});
|
|
369
|
+
// 循环链:this.gatt → 回调 → this → this.gatt
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// ✅ 正确实现:在构造函数中预创建回调,destroy 时清除引用
|
|
374
|
+
class BleTurboModule extends TurboModule {
|
|
375
|
+
private gatt: ble.GattClientDevice;
|
|
376
|
+
private connectionCallback: Function;
|
|
377
|
+
|
|
378
|
+
constructor() {
|
|
379
|
+
this.connectionCallback = (state: ble.ProfileConnectionState) => {
|
|
380
|
+
this.onConnectionStateChanged(state);
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
connect(): void {
|
|
385
|
+
this.gatt.on('BLEConnectionStateChange', this.connectionCallback);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
destroy(): void {
|
|
389
|
+
if (this.gatt) {
|
|
390
|
+
this.gatt.off('BLEConnectionStateChange', this.connectionCallback);
|
|
391
|
+
}
|
|
392
|
+
this.connectionCallback = null; // 清除引用,打破循环
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### 4.2 RN 特有回调链泄露
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
// ❌ 风险:TurboModule 级回调持有 View 实例引用
|
|
401
|
+
class CameraTurboModule extends TurboModule {
|
|
402
|
+
private onFrameCallback: ((frameData: Object) => void) | null = null;
|
|
403
|
+
|
|
404
|
+
startCamera(viewTag: number): void {
|
|
405
|
+
const view = this.viewManager.getViewByTag(viewTag);
|
|
406
|
+
this.onFrameCallback = (frameData: Object) => {
|
|
407
|
+
view.updateFrame(frameData); // 持有 view 引用
|
|
408
|
+
};
|
|
409
|
+
// ⚠️ view 销毁后回调仍持有引用
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// ✅ 正确实现:使用 viewTag 而非 view 引用
|
|
414
|
+
class CameraTurboModule extends TurboModule {
|
|
415
|
+
private onFrameCallbacks: Map<number, Function> = new Map();
|
|
416
|
+
|
|
417
|
+
startCamera(viewTag: number): void {
|
|
418
|
+
this.onFrameCallbacks.set(viewTag, (frameData: Object) => {
|
|
419
|
+
const view = this.viewManager.getViewByTag(viewTag);
|
|
420
|
+
if (view) {
|
|
421
|
+
view.updateFrame(frameData); // 按需获取 view
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// View 销毁时移除回调
|
|
427
|
+
removeFrameCallback(viewTag: number): void {
|
|
428
|
+
this.onFrameCallbacks.delete(viewTag);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
destroy(): void {
|
|
432
|
+
this.onFrameCallbacks.clear();
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### 4.3 Map/Set 数据清理
|
|
438
|
+
|
|
439
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
440
|
+
|--------|----------|----------|------|
|
|
441
|
+
| Map.clear() | TurboModule 的 Map 数据是否在 destroy 时调用 clear() | 高 | 未清理 -10 |
|
|
442
|
+
| View 实例 Map | ViewManager 维护的 View 实例 Map 是否在 onDropViewInstance 删除 | 高 | 未删除 -12 |
|
|
443
|
+
| 静态 Map 风险 | 静态 Map 是否无限累积 | **致命** | 累积风险 -15 |
|
|
444
|
+
| 缓存上限 | 是否设置缓存大小上限 | 中 | 无上限 -8 |
|
|
445
|
+
|
|
446
|
+
**Map 清理检查**:
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
// ❌ 问题:ViewManager 的 View 实例 Map 未在 onDropViewInstance 删除
|
|
450
|
+
class CameraViewManager extends ViewManager {
|
|
451
|
+
private viewInstances: Map<number, CameraView> = new Map();
|
|
452
|
+
|
|
453
|
+
createViewInstance(viewTag: number): CameraView {
|
|
454
|
+
const view = new CameraView();
|
|
455
|
+
this.viewInstances.set(viewTag, view);
|
|
456
|
+
return view;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
onDropViewInstance(view: Component): void {
|
|
460
|
+
super.onDropViewInstance(view);
|
|
461
|
+
// ⚠️ viewInstances 中该 viewTag 对应的条目未删除!
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// ✅ 正确实现
|
|
466
|
+
class CameraViewManager extends ViewManager {
|
|
467
|
+
private viewInstances: Map<number, CameraView> = new Map();
|
|
468
|
+
|
|
469
|
+
createViewInstance(viewTag: number): CameraView {
|
|
470
|
+
const view = new CameraView();
|
|
471
|
+
this.viewInstances.set(viewTag, view);
|
|
472
|
+
return view;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
onDropViewInstance(view: Component): void {
|
|
476
|
+
const viewTag = view.getTag();
|
|
477
|
+
const cameraView = this.viewInstances.get(viewTag);
|
|
478
|
+
if (cameraView) {
|
|
479
|
+
cameraView.release(); // 释放视图资源
|
|
480
|
+
this.viewInstances.delete(viewTag); // 从 Map 中移除
|
|
481
|
+
}
|
|
482
|
+
super.onDropViewInstance(view);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## 5. NAPI 引用管理
|
|
490
|
+
|
|
491
|
+
### 5.1 NAPI 引用生命周期
|
|
492
|
+
|
|
493
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
494
|
+
|--------|----------|----------|------|
|
|
495
|
+
| `napi_ref` 释放 | 是否在 dispose/destroy 时调用 `napi_delete_reference` | **致命** | 未释放 -20 |
|
|
496
|
+
| Handle Scope 清理 | 是否正确关闭 `napi_handle_scope` | **致命** | 未关闭 -20 |
|
|
497
|
+
| finalize 回调 | `napi_wrap` 是否提供 finalize 回调释放 Native 对象 | **致命** | 缺失 -20 |
|
|
498
|
+
| 引用计数平衡 | `napi_create_reference` 和 `napi_delete_reference` 数量是否匹配 | 高 | 不平衡 -18 |
|
|
499
|
+
| ArrayBuffer 外部资源泄露 | `napi_create_external` ArrayBuffer 的 finalize 回调缺失 | 高 | 缺失 -15 |
|
|
500
|
+
| NAPI 线程安全函数引用泄露 | `napi_create_threadsafe_function` 后未调用 `napi_release_threadsafe_function` | 高 | 未释放 -15 |
|
|
501
|
+
|
|
502
|
+
**C++ NAPI 管理示例**:
|
|
503
|
+
|
|
504
|
+
```cpp
|
|
505
|
+
// ❌ 致命:NAPI 引用未释放,且缺少 finalize 回调
|
|
506
|
+
class NativeTurboModule {
|
|
507
|
+
private:
|
|
508
|
+
napi_ref callbackRef;
|
|
509
|
+
|
|
510
|
+
public:
|
|
511
|
+
void registerCallback(napi_env env, napi_value callback) {
|
|
512
|
+
napi_create_reference(env, callback, 1, &this->callbackRef);
|
|
513
|
+
// 缺少释放逻辑!
|
|
514
|
+
// 缺少 finalize 回调!
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
// ✅ 正确实现
|
|
519
|
+
class NativeTurboModule {
|
|
520
|
+
private:
|
|
521
|
+
napi_ref callbackRef = nullptr;
|
|
522
|
+
|
|
523
|
+
public:
|
|
524
|
+
void registerCallback(napi_env env, napi_value callback) {
|
|
525
|
+
if (this->callbackRef) {
|
|
526
|
+
napi_delete_reference(env, this->callbackRef);
|
|
527
|
+
}
|
|
528
|
+
napi_create_reference(env, callback, 1, &this->callbackRef);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
void destroy(napi_env env) {
|
|
532
|
+
if (this->callbackRef) {
|
|
533
|
+
napi_delete_reference(env, this->callbackRef);
|
|
534
|
+
this->callbackRef = nullptr;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
// ✅ 正确实现:napi_wrap 带 finalize 回调
|
|
540
|
+
void NativeObjectFinalize(napi_env env, void* nativeObj, void* hint) {
|
|
541
|
+
auto* obj = static_cast<NativeResource*>(nativeObj);
|
|
542
|
+
delete obj; // 在 finalize 中释放 Native 对象
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
napi_status WrapNativeObject(napi_env env, napi_value jsThis, NativeResource* nativeObj) {
|
|
546
|
+
napi_ref ref;
|
|
547
|
+
return napi_wrap(env, jsThis, nativeObj, NativeObjectFinalize, nullptr, &ref);
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### 5.2 Handle Scope 管理
|
|
552
|
+
|
|
553
|
+
```cpp
|
|
554
|
+
// ❌ 致命:Handle Scope 未关闭
|
|
555
|
+
napi_value ProcessData(napi_env env, napi_callback_info info) {
|
|
556
|
+
napi_handle_scope scope;
|
|
557
|
+
napi_open_handle_scope(env, &scope);
|
|
558
|
+
|
|
559
|
+
napi_value result;
|
|
560
|
+
napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &result);
|
|
561
|
+
|
|
562
|
+
// ⚠️ 缺少 napi_close_handle_scope!
|
|
563
|
+
return result;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// ✅ 正确实现:使用 RAII 或手动关闭
|
|
567
|
+
napi_value ProcessData(napi_env env, napi_callback_info info) {
|
|
568
|
+
napi_handle_scope scope;
|
|
569
|
+
napi_open_handle_scope(env, &scope);
|
|
570
|
+
|
|
571
|
+
napi_value result;
|
|
572
|
+
napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &result);
|
|
573
|
+
|
|
574
|
+
napi_close_handle_scope(env, scope); // 必须关闭
|
|
575
|
+
return result;
|
|
576
|
+
}
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
## 6. TurboModule/JSI 绑定内存
|
|
582
|
+
|
|
583
|
+
### 6.1 TurboModule C++ 生命周期管理
|
|
584
|
+
|
|
585
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
586
|
+
|--------|----------|----------|------|
|
|
587
|
+
| TurboModule C++ 实例释放 | C++ 实例在 JS 对象回收后是否释放 | **致命** | 未释放 -15 |
|
|
588
|
+
| JSI HostFunction 泄露 | HostFunction 绑定在 Runtime 销毁时是否释放 | **致命** | 未释放 -15 |
|
|
589
|
+
| JSI HostObject 属性回调泄露 | HostObject 的 getter/setter 闭包持有外部引用未清理 | 高 | 未清理 -12 |
|
|
590
|
+
| 跨语言回调链泄露 | C++ 层回调引用 JS 函数的双向引用是否正确断开 | 高 | 未断开 -12 |
|
|
591
|
+
| Codegen 生成代码资源释放 | Codegen 自动生成的代码中资源释放逻辑是否完整 | 中 | 不完整 -10 |
|
|
592
|
+
| TurboModule C++ 与 JS 对象生命周期不一致 | C++ 侧实例比 JS 侧对象存活更久,导致悬垂引用 | **致命** | 不一致 -15 |
|
|
593
|
+
|
|
594
|
+
**TurboModule C++ 资源释放示例**:
|
|
595
|
+
|
|
596
|
+
```cpp
|
|
597
|
+
// ❌ 致命:TurboModule C++ 实例未在析构时释放资源
|
|
598
|
+
class BleTurboModule : public TurboModule {
|
|
599
|
+
private:
|
|
600
|
+
std::map<std::string, GattClient*> mConnectedDevices;
|
|
601
|
+
napi_ref mJsCallbackRef;
|
|
602
|
+
|
|
603
|
+
public:
|
|
604
|
+
~BleTurboModule() {
|
|
605
|
+
// ⚠️ 未释放 mConnectedDevices 中的 GattClient
|
|
606
|
+
// ⚠️ 未释放 mJsCallbackRef
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
// ✅ 正确实现
|
|
611
|
+
class BleTurboModule : public TurboModule {
|
|
612
|
+
private:
|
|
613
|
+
std::map<std::string, GattClient*> mConnectedDevices;
|
|
614
|
+
napi_ref mJsCallbackRef = nullptr;
|
|
615
|
+
|
|
616
|
+
public:
|
|
617
|
+
~BleTurboModule() {
|
|
618
|
+
// 1. 释放所有 GattClient
|
|
619
|
+
for (auto& [id, client] : mConnectedDevices) {
|
|
620
|
+
delete client;
|
|
621
|
+
}
|
|
622
|
+
mConnectedDevices.clear();
|
|
623
|
+
|
|
624
|
+
// 2. 释放 NAPI 引用(注意:需要 env,通常在 destroy 中处理)
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
void destroy(napi_env env) {
|
|
628
|
+
// 释放 NAPI 引用
|
|
629
|
+
if (mJsCallbackRef) {
|
|
630
|
+
napi_delete_reference(env, mJsCallbackRef);
|
|
631
|
+
mJsCallbackRef = nullptr;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### 6.2 JSI HostFunction/HostObject 管理
|
|
638
|
+
|
|
639
|
+
```cpp
|
|
640
|
+
// ❌ 风险:HostFunction 闭包持有外部引用
|
|
641
|
+
class MyHostObject : public jsi::HostObject {
|
|
642
|
+
private:
|
|
643
|
+
jsi::Function mCallback; // 持有 JS 函数引用
|
|
644
|
+
|
|
645
|
+
public:
|
|
646
|
+
jsi::Value get(jsi::Runtime& rt, const jsi::PropNameID& name) override {
|
|
647
|
+
if (name.utf8(rt) == "callback") {
|
|
648
|
+
return mCallback; // 返回 JS 函数
|
|
649
|
+
}
|
|
650
|
+
// ⚠️ Runtime 销毁时 mCallback 未释放
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
// ✅ 正确实现:在 Runtime 销毁时清理
|
|
655
|
+
class MyHostObject : public jsi::HostObject {
|
|
656
|
+
private:
|
|
657
|
+
std::optional<jsi::Function> mCallback;
|
|
658
|
+
|
|
659
|
+
public:
|
|
660
|
+
jsi::Value get(jsi::Runtime& rt, const jsi::PropNameID& name) override {
|
|
661
|
+
if (name.utf8(rt) == "callback" && mCallback.has_value()) {
|
|
662
|
+
return mCallback.value();
|
|
663
|
+
}
|
|
664
|
+
return jsi::Value::undefined();
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// Runtime 销毁时由 TurboModule 的 destroy 调用
|
|
668
|
+
void invalidate() {
|
|
669
|
+
mCallback.reset(); // 清除 JS 函数引用
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
## 7. C/C++ 层内存泄露
|
|
677
|
+
|
|
678
|
+
### 7.1 Native 内存分配释放
|
|
679
|
+
|
|
680
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
681
|
+
|--------|----------|----------|------|
|
|
682
|
+
| malloc/free 匹配 | 每个 `malloc` 是否有对应 `free` | **致命** | 不匹配 -15 |
|
|
683
|
+
| new/delete 匹配 | 每个 `new` 是否有对应 `delete` | **致命** | 不匹配 -15 |
|
|
684
|
+
| new[]/delete[] 匹配 | `new[]` 是否使用 `delete[]` 释放 | **致命** | 误用 -15 |
|
|
685
|
+
| 智能指针循环引用 | `shared_ptr` 循环引用导致引用计数永不为零 | **致命** | 循环引用 -15 |
|
|
686
|
+
| 异常路径释放 | 异常发生时是否释放已分配内存 | 高 | 未释放 -12 |
|
|
687
|
+
| RAII 模式 | 是否优先使用智能指针 | 中 | 未使用 -10 |
|
|
688
|
+
| 全局/静态缓冲区无限增长 | 全局 vector/map 无上限增长 | 高 | 无清理 -12 |
|
|
689
|
+
|
|
690
|
+
**RAII 推荐模式**:
|
|
691
|
+
|
|
692
|
+
```cpp
|
|
693
|
+
// ✅ 使用智能指针自动管理
|
|
694
|
+
#include <memory>
|
|
695
|
+
|
|
696
|
+
void processData() {
|
|
697
|
+
std::unique_ptr<Buffer> buffer = std::make_unique<Buffer>(1024);
|
|
698
|
+
// 自动释放,无需手动 delete
|
|
699
|
+
|
|
700
|
+
// 或使用 std::shared_ptr 处理共享所有权
|
|
701
|
+
std::shared_ptr<Resource> resource = std::make_shared<Resource>();
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// ✅ RAII wrapper 模式
|
|
705
|
+
class BufferGuard {
|
|
706
|
+
private:
|
|
707
|
+
void* buf;
|
|
708
|
+
public:
|
|
709
|
+
BufferGuard(size_t size) : buf(malloc(size)) {}
|
|
710
|
+
~BufferGuard() {
|
|
711
|
+
if (buf) free(buf); // 自动释放
|
|
712
|
+
}
|
|
713
|
+
// 禁止拷贝
|
|
714
|
+
BufferGuard(const BufferGuard&) = delete;
|
|
715
|
+
BufferGuard& operator=(const BufferGuard&) = delete;
|
|
716
|
+
};
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
**智能指针循环引用检测**:
|
|
720
|
+
|
|
721
|
+
```cpp
|
|
722
|
+
// ❌ 致命:shared_ptr 循环引用
|
|
723
|
+
class TurboModuleImpl;
|
|
724
|
+
class CallbackHolder : public std::enable_shared_from_this<CallbackHolder> {
|
|
725
|
+
public:
|
|
726
|
+
std::shared_ptr<TurboModuleImpl> module; // 持有 module 引用
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
class TurboModuleImpl : public std::enable_shared_from_this<TurboModuleImpl> {
|
|
730
|
+
public:
|
|
731
|
+
std::shared_ptr<CallbackHolder> callback; // 持有 callback 引用
|
|
732
|
+
// 循环链:module ↔ callback,引用计数永不为零!
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
// ✅ 正确实现:使用 weak_ptr 打破循环
|
|
736
|
+
class CallbackHolder {
|
|
737
|
+
public:
|
|
738
|
+
std::weak_ptr<TurboModuleImpl> module; // 弱引用,不增加引用计数
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
class TurboModuleImpl : public std::enable_shared_from_this<TurboModuleImpl> {
|
|
742
|
+
public:
|
|
743
|
+
std::shared_ptr<CallbackHolder> callback;
|
|
744
|
+
};
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
---
|
|
748
|
+
|
|
749
|
+
## 8. RN 鸿蒙化特有内存风险
|
|
750
|
+
|
|
751
|
+
### 8.1 跨语言生命周期不一致
|
|
752
|
+
|
|
753
|
+
| 检查项 | 问题描述 | 风险等级 | 扣分 |
|
|
754
|
+
|--------|----------|----------|------|
|
|
755
|
+
| ArkTS on/C++ resource 不对称释放 | ArkTS 层调用 off() 但 C++ 层未释放对应资源,或反过来 | **致命** | 不对称 -15 |
|
|
756
|
+
| Native 对象生命周期不一致 | C++ Native 对象与 ArkTS 包装对象生命周期不一致 | **致命** | 不一致 -15 |
|
|
757
|
+
| TurboModule 与 View 生命周期混淆 | TurboModule 级资源不应在 View 销毁时释放,反之亦然 | 高 | 混淆 -12 |
|
|
758
|
+
| RN Bridge 消息队列累积 | 原生模块与 JS 之间的消息队列在模块销毁时未清空 | 中 | 未清空 -10 |
|
|
759
|
+
|
|
760
|
+
**跨语言释放不对称示例**:
|
|
761
|
+
|
|
762
|
+
```typescript
|
|
763
|
+
// ❌ 致命:ArkTS 层 off() 但 C++ 层未释放资源
|
|
764
|
+
class BleTurboModule extends TurboModule {
|
|
765
|
+
disconnect(remoteId: string): void {
|
|
766
|
+
const gatt = this.mConnectedDevices.get(remoteId);
|
|
767
|
+
gatt.off('BLEConnectionStateChange', this.connectionCallback);
|
|
768
|
+
this.mConnectedDevices.delete(remoteId);
|
|
769
|
+
// ⚠️ ArkTS 层取消了监听并从 Map 删除,但 C++ 层的 GattClient 未释放
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// ✅ 正确实现:确保 C++ 层也释放对应资源
|
|
774
|
+
disconnect(remoteId: string): void {
|
|
775
|
+
const gatt = this.mConnectedDevices.get(remoteId);
|
|
776
|
+
if (gatt) {
|
|
777
|
+
gatt.off('BLEConnectionStateChange', this.connectionCallback);
|
|
778
|
+
gatt.close(); // 确保 C++ 层资源也释放
|
|
779
|
+
}
|
|
780
|
+
this.mConnectedDevices.delete(remoteId);
|
|
781
|
+
}
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
### 8.2 Spec Codegen 生成代码
|
|
785
|
+
|
|
786
|
+
```typescript
|
|
787
|
+
// ❌ 风险:Codegen 生成的 TurboModule 代码中未实现资源释放
|
|
788
|
+
// Codegen 生成的接口:
|
|
789
|
+
interface NativeBleModule extends TurboModule {
|
|
790
|
+
startScan(): Promise<void>;
|
|
791
|
+
stopScan(): Promise<void>;
|
|
792
|
+
// ⚠️ 没有 destroy/invalidate 方法来释放资源
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// ✅ 正确做法:在 Codegen 生成的接口基础上,补充资源释放逻辑
|
|
796
|
+
class BleTurboModuleImpl extends TurboModule implements NativeBleModuleSpec {
|
|
797
|
+
// 实现 Codegen 接口方法
|
|
798
|
+
startScan(): Promise<void> { ... }
|
|
799
|
+
stopScan(): Promise<void> { ... }
|
|
800
|
+
|
|
801
|
+
// 补充资源释放方法(在 TurboModule destroy 时调用)
|
|
802
|
+
destroy(): void {
|
|
803
|
+
// 释放 Codegen 未管理的资源
|
|
804
|
+
this.cleanupResources();
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
---
|
|
810
|
+
|
|
811
|
+
## 9. 评分规则汇总
|
|
812
|
+
|
|
813
|
+
### 致命问题(-20 分,最多扣 60 分)
|
|
814
|
+
|
|
815
|
+
| 问题类型 | 扣分 | 直接 0 分条件 |
|
|
816
|
+
|----------|------|---------------|
|
|
817
|
+
| TurboModule destroy 未释放资源 | -20 | ≥ 3 个致命问题 |
|
|
818
|
+
| onDropViewInstance 未清理 | -15 | ≥ 2 个致命 + ≥ 3 个严重 |
|
|
819
|
+
| NAPI 引用未释放 | -20 | 关键路径存在致命 |
|
|
820
|
+
| finalize 回调缺失 | -20 | 累计扣分 > 60 |
|
|
821
|
+
| Handle Scope 未关闭 | -20 | |
|
|
822
|
+
| malloc/free 不匹配 | -15 | |
|
|
823
|
+
| new/delete 不匹配 | -15 | |
|
|
824
|
+
| 鸿蒙 API 事件订阅无对应取消 | -20 | |
|
|
825
|
+
| NativeEventEmitter 监听未移除 | -15 | |
|
|
826
|
+
| GattClientDevice 未释放 | -20 | |
|
|
827
|
+
| Sensor 未注销 | -20 | |
|
|
828
|
+
| 数据库连接未关闭 | -20 | |
|
|
829
|
+
|
|
830
|
+
### 严重问题(-12 分)
|
|
831
|
+
|
|
832
|
+
| 问题类型 | 扣分 |
|
|
833
|
+
|----------|------|
|
|
834
|
+
| Bridge 事件监听未移除 | -15 |
|
|
835
|
+
| 闭包循环引用风险 | -15 |
|
|
836
|
+
| Map 数据未清理 | -10 |
|
|
837
|
+
| View 实例 Map 未删除 | -12 |
|
|
838
|
+
| 跨语言回调链泄露 | -12 |
|
|
839
|
+
| JSI HostObject 属性回调泄露 | -12 |
|
|
840
|
+
| 扫描状态未清理 | -15 |
|
|
841
|
+
| Timer 未清除 | -12 |
|
|
842
|
+
|
|
843
|
+
### 中等问题(-8 分)
|
|
844
|
+
|
|
845
|
+
| 问题类型 | 扣分 |
|
|
846
|
+
|----------|------|
|
|
847
|
+
| 回调参数匹配错误 | -12 |
|
|
848
|
+
| 释放顺序不当 | -8 |
|
|
849
|
+
| 初始化不完整 | -5 |
|
|
850
|
+
| TurboModule 级 vs View 级监听混淆 | -10 |
|
|
851
|
+
| Codegen 生成代码资源释放不完整 | -10 |
|
|
852
|
+
| RN Bridge 消息队列未清空 | -10 |
|
|
853
|
+
|
|
854
|
+
### 轻微问题(-5 分)
|
|
855
|
+
|
|
856
|
+
| 问题类型 | 扣分 |
|
|
857
|
+
|----------|------|
|
|
858
|
+
| 订阅状态未追踪 | -8 |
|
|
859
|
+
| 缓存无上限 | -8 |
|
|
860
|
+
| RAII 未使用 | -10 |
|
|
861
|
+
| 事件发送器未随 TurboModule 销毁 | -10 |
|
|
862
|
+
|
|
863
|
+
### 观察项(0 分,不计入扣分)
|
|
864
|
+
|
|
865
|
+
内存检视中发现的对内存**零影响**的问题,记入泄露风险清单但标注"观察(0 分)",注明不扣分理由及建议归属阶段(编码质量/一致性检视):
|
|
866
|
+
|
|
867
|
+
| 问题类型 | 处理 | 说明 |
|
|
868
|
+
|----------|------|------|
|
|
869
|
+
| 未接线的手写 TurboModule 死代码 | 观察(0 分) | Package 工厂未实例化,运行期零分配零调用(接线验证方法见 SKILL.md 1.3) |
|
|
870
|
+
| codegen 产物滞后(手写与 codegen 方法数不一致) | 观察(0 分) | 无内存影响,属一致性/维护性问题 |
|
|
871
|
+
| 死代码模块级单例(全仓库无 import) | 观察(0 分)或轻微(0~-5) | 运行期零分配,非严格泄露;被 import 的 eager 单例另按"加载即常驻"标定轻微~中等 |
|
|
872
|
+
| 无状态模块未重写 `__onDestroy__` | 豁免,不扣分 | 零监听/零句柄/零容器/零回调引用时属正确最小化设计(见第 1 节豁免规则) |
|
|
873
|
+
|
|
874
|
+
---
|
|
875
|
+
|
|
876
|
+
## 10. 零泄露面穷尽验证模式集(无状态库确认)
|
|
877
|
+
|
|
878
|
+
**用途**:疑似"零状态"库(纯 TurboModule、无 NativeComponent、业务全部映射到系统静态一次性 API)在下"零泄露面"结论前,必须用以下 rg 模式集穷尽验证,**全库 0 命中方可确认**。确认零泄露面后,`__onDestroy__` 缺失适用第 1 节的无状态模块豁免规则。
|
|
879
|
+
|
|
880
|
+
```bash
|
|
881
|
+
# 1. 生命周期/监听/订阅
|
|
882
|
+
rg -n "__onDestroy__|onDestroy|aboutToDisappear|onDropViewInstance|addListener|removeListener|EventEmitter|addEventListener" <ets/cpp/js 目录>
|
|
883
|
+
# 2. 鸿蒙 on/off 订阅对
|
|
884
|
+
rg -n "\.on\(|\.off\(" <ets 目录>
|
|
885
|
+
# 3. 容器与静态状态
|
|
886
|
+
rg -n "Map<|Set<|static |private " <ets 目录> --glob '*.ts' --glob '*.ets'
|
|
887
|
+
# 4. C++ 内存与 NAPI(仅手写文件)
|
|
888
|
+
rg -n "new |malloc|napi_|delete |free\(" <cpp 目录> -g '<手写文件 pattern>'
|
|
889
|
+
# 5. 定时器
|
|
890
|
+
rg -n "setInterval|setTimeout" <ets 目录>
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
**要点**:
|
|
894
|
+
- C++ 检查必须区分手写文件与 `generated/` 目录(用 `-g` 限定只查手写文件,如 `-g 'Cookies*'`);codegen 生成的空壳文件(EventEmitters/Props/ShadowNodes 等)单独确认"空实现无资源"即可,不逐文件深查
|
|
895
|
+
- 扫描范围须排除 `.upstream-cache`、`node_modules`、`oh_modules` 等缓存/依赖目录(与 Phase 0 扫描脚本排除规则一致)
|
|
896
|
+
- 全部 0 命中 → 报告注明"零泄露面,经六组模式穷尽验证";任一命中 → 按对应 Phase 检查项深入分析
|
|
897
|
+
|
|
898
|
+
### 10.1 codegen 组件空壳快速判定
|
|
899
|
+
|
|
900
|
+
无 NativeComponent 的库,codegen 仍会生成组件相关文件(EventEmitters/Props/ShadowNodes/ComponentDescriptor 等)。快速判定整组文件是否为空壳:
|
|
901
|
+
|
|
902
|
+
- 查看 Package 头文件(如 `BaseReactNativeXXXPackage.h`)中 `createComponentDescriptorProviders()` / `createComponentJSIBinderByName()` 的返回值是否为**空集合**
|
|
903
|
+
- 查看 `supportedComponentNames` / `supportedEventNames` 是否为**空 vector**
|
|
904
|
+
|
|
905
|
+
两者均为空 → 整组组件文件按空壳处理,NativeComponent 维度记"**不适用**"而非"通过"(报告中明确标注,避免误读为已检查通过)。
|