AGENTS.md - Module System Guidelines
This file provides guidelines for AI coding agents working on the ES6 Module system implementation.
Build and Test Commands
编译参数说明
| 参数名称 | 描述 | 示例 |
|---|---|---|
--product-name |
指定产品名称 | rk3568 |
--build-target |
指定构建编译对象 | ark_js_host_unittest:单元测试 |
| ark_js_host_linux_tools_packages:工具包 | ||
| ets_frontend_build:前端编译 | ||
--gn-args |
传递编译参数 | is_debug=true:启用调试模式 |
常用编译命令
Release 编译
编译发布版本(无调试信息):
./build.sh --product-name rk3568 \
--build-target ark_js_host_unittest \
--build-target ark_js_unittest \
--build-target ark_js_host_linux_tools_packages
Debug 编译
编译调试版本(包含调试信息):
./build.sh --product-name rk3568 \
--build-target ark_js_host_unittest \
--build-target ark_js_unittest \
--build-target ark_js_host_linux_tools_packages \
--gn-args is_debug=true
运行测试
# 运行所有 Module 测试
./build.sh --product-name rk3568 --build-target ModuleTestAction
# 运行单个测试
./build.sh --product-name rk3568 --build-target ModuleTestAction --gn-args target_test_filters="EcmaModuleTest.TestName"
# 运行测试文件中的所有测试
./build.sh --product-name rk3568 --build-target ModuleTestAction --gn-args target_test_filters="JS_ModuleManagerTest.*"
NOTE: Run all commands from OpenHarmony root directory.
Overview
The ecmascript/module directory implements ES6 (ECMAScript 2015) module system, including:
- SourceTextModule: ES6 module records
- ModuleManager: Module loading and lifecycle management
- ModuleResolver: Module dependency resolution
- Shared modules across worker threads
- Module namespace and exports handling
Module System Architecture
Key Classes
| Class | Purpose |
|---|---|
| SourceTextModule | ES6 module record (ECMAScript spec) |
| ModuleManager | Central module lifecycle manager |
| ModuleResolver | Import/export resolution logic |
| SharedModuleManager | Cross-thread module sharing |
| ModuleNamespace | Export name resolution |
| ImportEntry | Import entry record containing module import information |
| LocalExportEntry | Local export entry record |
| IndirectExportEntry | Indirect export entry record |
| StarExportEntry | Star export entry record |
| ResolvedBinding | Resolved binding record |
| ResolvedIndexBinding | Resolved index binding record |
| SendableClassModule | Sendable class module for cross-thread sharing |
| JSSharedModule | Shared module implementation |
| SharedModuleHelper | Shared module helper utility class |
Module Lifecycle
1. Parse → SourceTextModule created
2. Resolve → ModuleResolver resolves dependencies
3. Instantiate → ModuleNamespace created, imports linked
4. Evaluate → Module executed, exports populated
Code Style Guidelines
File Naming
| Type | Pattern | Examples |
|---|---|---|
| Module classes | js_module_*.cpp/h |
js_module_manager.cpp |
| Helper files | *.cpp/h |
module_path_helper.cpp |
| Test files | *_test.cpp |
js_module_manager_test.cpp |
Class Naming
// Module record classes
class SourceTextModule : public ModuleRecord { ... };
class SharedModule : public ModuleRecord { ... };
// Manager classes
class ModuleManager { ... };
class SharedModuleManager { ... };
// Helper classes
class ModuleResolver { ... };
class ModulePathHelper { ... };
Enum Naming
// Module state - use 'Module' prefix
enum class ModuleStatus : uint8_t {
UNINSTANTIATED,
INSTANTIATING,
INSTANTIATED,
EVALUATING,
EVALUATING_ASYNC,
EVALUATED,
ERRORED
};
// Module types - use 'Module' prefix
enum class ModuleTypes : uint8_t {
ECMA_MODULE,
CJS_MODULE,
JSON_MODULE,
NATIVE_MODULE,
OHOS_MODULE,
APP_MODULE,
INTERNAL_MODULE,
UNKNOWN,
STATIC_MODULE
};
// Loading types
enum class LoadingTypes : uint8_t {
STABLE_MODULE,
DYNAMIC_MODULE,
OTHERS
};
Key Macros
// Module manager macros
NO_COPY_SEMANTIC(ModuleManager);
NO_MOVE_SEMANTIC(ModuleManager);
// Accessor macros (for class layout)
ACCESSORS(Id, JS_CJS_MODULE_OFFSET, ID_OFFSET)
ACCESSORS(Path, ID_OFFSET, PATH_OFFSET)
ACCESSORS(Exports, PATH_OFFSET, EXPORTS_OFFSET)
// Bit field definitions
DEFINE_ALIGN_SIZE(LAST_SIZE);
static constexpr uint32_t DEFAULT_DICTIONARY_CAPACITY = 4;
Atomic Operations
// Use atomic for cross-thread module execute mode
std::atomic<ModuleExecuteMode> isExecuteBuffer_ {ModuleExecuteMode::ExecuteZipMode};
ModuleExecuteMode GetExecuteMode() const {
return isExecuteBuffer_.load(std::memory_order_acquire);
}
inline void SetExecuteMode(ModuleExecuteMode mode) {
isExecuteBuffer_.store(mode, std::memory_order_release);
}
Module Resolution Pattern
// Standard resolution pattern in ModuleManager
JSHandle<SourceTextModule> GetImportedModule(const CString &referencing) {
// Check cache first
if (IsModuleLoaded(referencing)) {
return TryGetImportedModule(referencing);
}
// Resolve and load if not in cache
JSHandle<SourceTextModule> module = ResolveModule(referencing);
AddResolveImportedModule(referencing, module->GetTaggedValue());
return module;
}
Namespace Handling
// Use CUnorderedMultiMap for namespace entries
using ResolvedMultiMap = CUnorderedMultiMap<CString *, JSHandle<JSTaggedValue>>;
// Iterate exports
resolvedModules_.ForEach([](auto it) {
CString key = it->first;
JSTaggedValue module = it->second.Read();
// Process export
});
Module Constants
static constexpr int MODULE_ERROR = 1;
static constexpr int UNDEFINED_INDEX = -1;
static constexpr uint8_t DEREGISTER_MODULE_TAG = 1;
static constexpr uint32_t FIRST_ASYNC_EVALUATING_ORDINAL = 2;
static constexpr uint32_t NOT_ASYNC_EVALUATED = 0;
static constexpr bool SHARED_MODULE_TAG = true;
Public API Methods
Methods exported outside module system use PUBLIC_API macro:
JSHandle<SourceTextModule> PUBLIC_API HostGetImportedModule(const CString &referencing);
JSTaggedValue PUBLIC_API HostGetImportedModule(void *src);
Module Deregistration
Module deregistration is handled by js_module_deregister.cpp:
// When modules are deregistered:
1. Remove from resolved modules cache
2. Clean up lazy import arrays
3. Free module-related strings
4. Clear constant pool literals
Shared Module Support
For worker thread module sharing:
// Shared module manager handles cross-VM access
class SharedModuleManager {
JSHandle<JSTaggedValue> GetSharedModule(const CString &key);
void SetSharedModule(const CString &key, JSHandle<JSTaggedValue> &module);
};
Path Resolution
Module paths are resolved using module_path_helper.cpp:
// Path types:
- Absolute paths
- Relative paths (./, ../)
- Node module paths (node_modules/)
- OHOS app module paths
Module Snapshot
Module state can be serialized via module_snapshot.cpp:
// Snapshot format:
1. Module records
2. Module namespaces
3. Export tables
4. Dependency graphs
Error Handling
// Module errors use specific exception patterns
if (thread->HasPendingException()) {
module->SetStatus(ModuleStatus::ERRORED);
RecordError(thread, module);
}
// Native module failures
JSHandle<NativeModuleFailureInfo> errorInfo =
NativeModuleFailureInfo::CreateNativeModuleFailureInfo(vm, errorMessage);
Module Logging
// Module-specific logging
ModuleLogger::LogModuleLoad(recordName);
ModuleLogger::LogModuleError(recordName, error);