From 39dec4376d1f99f31c7ad7cc1ae55f5fcbc15775 Mon Sep 17 00:00:00 2001 From: openclaw Date: Sat, 2 May 2026 22:21:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20player=5Fv2.js=20=E5=AE=8C?= =?UTF-8?q?=E6=95=B4=E6=BA=90=E7=A0=81=E6=9E=B6=E6=9E=84=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 从 1.8MB webpack bundle 中提取的关键信息: - Heart 运行时完整类结构 (Registry, Compiler, Interpreter, RuntimeManager) - 80+ domain functions (积木实现) 清单 - Interpreter.do_step() 执行流程详解 - BCM 加载流程 - PIXI.js 渲染层架构 - 性能瓶颈分析和 JIT 切入点 - 关键代码的 webpack 模块位置 --- docs/player-source-analysis.md | 442 +++++++++++++++++++++++++++++++++ 1 file changed, 442 insertions(+) create mode 100644 docs/player-source-analysis.md diff --git a/docs/player-source-analysis.md b/docs/player-source-analysis.md new file mode 100644 index 0000000..682301c --- /dev/null +++ b/docs/player-source-analysis.md @@ -0,0 +1,442 @@ +# 编程猫 Player v2.js 源码架构分析 + +> 从 `https://kn-cdn.codemao.cn/kn/build/player_v2.2d180c468559fbd29528.js` 提取 +> 文件大小: 1.8MB, webpack 打包, 125 个模块 + +## 1. 整体架构 + +``` +┌─────────────────────────────────────────────────────────┐ +│ React UI 层 │ +│ Theatre (舞台), Ranking (排行榜), Scanner (扫码), │ +│ FaceDetect, VirtualKeyboard, Dialog │ +├─────────────────────────────────────────────────────────┤ +│ Redux + Saga 状态管理 │ +│ theatre_states, run_states, cloud_states, │ +│ variable_states, userinfo_state, ai_states │ +├─────────────────────────────────────────────────────────┤ +│ Heart 运行时引擎 │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ +│ │Compiler │ │Interpreter│ │Registry │ │RuntimeMgr│ │ +│ │(编译积木) │ │(执行积木) │ │(注册积木) │ │(管理实体) │ │ +│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ +├─────────────────────────────────────────────────────────┤ +│ PIXI.js 渲染层 (WebGL) │ +│ Application, Container, Sprite, Graphics, │ +│ Text, Filter, Ticker, InteractionManager │ +├─────────────────────────────────────────────────────────┤ +│ 底层服务 │ +│ Audio (Howler.js), Physics, MIDI, Cloud Variables, │ +│ Face Detection, QR Scanner, WebSocket │ +└─────────────────────────────────────────────────────────┘ +``` + +## 2. Heart 运行时核心类 + +### 2.1 `Heart` (入口) +```javascript +// e.Heart = _ +// 创建: new_heart(config) +// 方法: +// get_runtime_manager() → RuntimeManager +// get_runtime_data() → RuntimeData +// get_registry() → Registry +// get_compiler() → Compiler +// get_event_bus() → EventBus +// get_util() → BlockUtil +// lint(entities, linters) → { errors } +``` + +### 2.2 `RegistryImpl` (积木注册表) +```javascript +class RegistryImpl { + // 存储 + domain_function = {} // 积木实现函数 + domain_function_index = {} // 函数索引 + respond = {} // 响应器 + lifetime_respond = {} // 生命周期响应器 + action_types = {} // 动作类型 + meta_restart_when_finished = {} + meta_finish_out_of_run_group = {} + + // 方法 + register({ namespace, id, domain_function, respond, metadata }) + register_action_type({ namespace, id, statefulness }) + register_linter(linter) + has_responder_type(type) → boolean + has_lifetime_responder_type(type) → boolean + get_action_type(namespaced_id) → ActionSpec + get_domain_functions() → { [name]: Function } +} +``` + +### 2.3 `CompilerImpl` / `OptiCompilerImpl` (编译器) +```javascript +class CompilerImpl { + // 将 workspace_json 编译为可执行的积木树 + compile(entity, procedures, is_clone) → compiled_block_map + compile_from_workspace_json(blocksJSON, entity_id, is_clone) → { + procedures: { [name]: block }, + compiled_block_map: { [id]: block } + } +} + +class OptiCompilerImpl { + // 优化编译器 - 生成更高效的 AST + compile(entity, procedures, is_clone) → compiled_program +} +``` + +### 2.4 `InterpreterImpl` (解释器) ⭐ 性能瓶颈 +```javascript +class InterpreterImpl { + // 核心状态 + root_block // 根积木 + current_block // 当前执行的积木 + current_frame // 当前栈帧 + program_state // 程序状态 + n_warp_iterations // warp 迭代计数 + n_procedure_calls // 过程调用计数 + + // 核心方法 + step() → StepResult // 执行一步 ← 这是最热的路径 + do_step() → StepResult // 内部执行 + + // do_step 的执行流程: + // 1. get_stack_frame() - 获取当前栈帧 + // 2. step_eval_dispatch() - 根据块类型分发 + // 3. 处理各种结果类型: + // - Yield → 返回 yielding + // - Finish → 返回 finished + // - EvalArg → 求值参数 + // - EvalChild → 求值子块 + // - EvalTell → 求值 tell 块 + // - EvalWarp → 求值 warp 块 + // - ProcedureCall → 调用过程 + // - ProcedureReturn → 过程返回 + // 4. go_next_or_parent() - 导航到下一个块或父块 + // 5. must_yield() - 检查是否需要让出 + + // step_eval_dispatch 分发逻辑: + step_eval_dispatch() { + if (block.disabled) return skip + if (is.responder_block(block)) return eval_child_or_done + if (is.event_block(block)) return eval_event + if (is.cond_block(block)) return eval_cond + if (is.domain_block(block)) return eval_domain + if (is.break(block)) return Break + if (is.repeat_forever(block)) return eval_repeat_forever + if (is.repeat_n_times(block)) return eval_repeat_n_times + if (is.repeat_forever_until(block)) return eval_repeat_forever_until + if (is.wait_until(block)) return eval_wait_until + if (is.procedures_callreturn(block)) return eval_procedures_callreturn + if (is.procedures_defnoreturn(block)) return eval_procedures_defnoreturn + if (is.procedures_parameter(block)) return eval_procedures_parameter + if (is.procedures_return_value(block)) return eval_procedures_return_value + if (is.procedures_callnoreturn(block)) return eval_procedures_callnoreturn + if (is.sync_tell(block)) return eval_sync_tell + if (is.async_tell(block)) return eval_async_tell + if (is.warp(block)) return eval_warp + throw unknown_block_type + } +} +``` + +### 2.5 `RuntimeManagerImpl` (运行时管理器) +```javascript +class RuntimeManagerImpl { + // 实体管理 + create_entity_instance(entity_id, typeclass_id) + create_singleton_entity_instances() + destruct_entity(entity_id) + get_entity_state(entity_id) → EntityState + + // 解释器管理 + spawn_interpreter(config) + spawn_async_tell_interpreter(config) + remove_interpreter(interpreter_id) + add_interpreter(interpreter) + get_interpreter_ids() → string[] + get_n_interpreters() → number + + // 执行 + run() // 开始执行 + stop() // 停止 + update() // 每帧更新 ← 调用所有 interpreter.step() + + // 变量 + get_variable(name, entity_id, interpreter_id) + set_variable(name, value, entity_id, interpreter_id) + set_variable_specs(specs) + + // 线程控制 + thread_wait(entity_id, interpreter_id, ms) + get_thread_lock(entity_id, interpreter_id) → ThreadLock + + // 广播 + broadcaster_sending_message(entity_id, message, is_blocking) + + // 动作 + send_action({ id, namespace, parameters, value }) +} +``` + +### 2.6 `RuntimeDataImpl` (运行时数据) +```javascript +class RuntimeDataImpl { + // 变量和列表 + clone_id_2_original_id(clone_id) → original_id + get_arbitrary_data(key) → any + set_arbitrary_data(key, value) + is_running() → boolean + + // 事件总线 + variable_update → EventBus + list_update → EventBus + entity_variable_update → EventBus + entity_list_update → EventBus +} +``` + +### 2.7 `BlockPredicatesImpl` (积木谓词) +```javascript +class BlockPredicatesImpl { + // 判断积木类型 + hat_block_type(type) → boolean + responder_block(block) → boolean + responder_type(type) → boolean + lifetime_responder_type(type) → boolean + event_block(block) → boolean + domain_block(block) → boolean + loop_block(block) → boolean + cond_block(block) → boolean + proc_block(block) → boolean + special_block(block) → boolean + + // 具体积木判断 + controls_if(block) → boolean + repeat_n_times(block) → boolean + repeat_forever(block) → boolean + repeat_forever_until(block) → boolean + wait_until(block) → boolean + break(block) → boolean + procedures_defnoreturn(block) → boolean + procedures_callreturn(block) → boolean + async_tell(block) → boolean + sync_tell(block) → boolean + warp(block) → boolean + mirror(block) → boolean + start_on_click(block) → boolean +} +``` + +## 3. Domain Functions (积木实现) + +积木的实际功能通过 domain functions 注册到 Registry: + +### 3.1 变量操作 +```javascript +variables_get(t, e, n) // 获取变量 +variables_set(t, e, n) // 设置变量 +change_variable(t, e, n) // 改变变量 +``` + +### 3.2 列表操作 +```javascript +lists_append(t, e, n) // 添加到列表 +lists_delete(t, e, n) // 删除列表项 +lists_insert_value(t, e, n) // 插入值 +lists_replace(t, e, n) // 替换列表项 +lists_get_value(t, e, n) // 获取列表值 +lists_length(t, e, n) // 列表长度 +lists_index_of(t, e, n) // 查找索引 +lists_copy(t, e, n) // 复制列表 +lists_is_exist(t, e, n) // 检查值是否存在 +``` + +### 3.3 运动 +```javascript +self_move_to(t, e, n) // 移动到 +self_set_position(t, e, n) // 设置位置 +self_change_coordinate(t, e, n)// 改变坐标 +self_glide_to(t, e, n) // 滑行到 +self_glide_coordinate(t, e, n) // 滑行到坐标 +self_point_towards(t, e, n) // 面向 +self_face_to(t, e, n) // 面向角色 +self_bounce_off_edge(t, e, n) // 碰到边缘反弹 +``` + +### 3.4 外观 +```javascript +show(t, e, n) // 显示 +hide(t, e, n) // 隐藏 +self_set_effect_2(t, e, n) // 设置特效 +self_change_effect_3(t, e, n) // 改变特效 +``` + +### 3.5 声音 +```javascript +play_audio(t, e, n) // 播放声音 +play_audio_and_wait(t, e, n) // 播放并等待 +play_audio_2(t, e, n) // 播放声音 v2 +play_audio_and_wait_2(t, e, n)// 播放并等待 v2 +stop_audio_2(t, e, n) // 停止声音 +play_words_audio(t, e, n) // 朗读文字 +play_words_audio_wait(t, e, n)// 朗读并等待 +``` + +### 3.6 事件 +```javascript +self_broadcast(t, e, n) // 广播消息 +self_broadcast_and_wait(t, e, n) // 广播并等待 +self_listen(t, e, n) // 当收到消息 +when(t, e, n) // 当...时 +start_on_click(t, e, n) // 当点击 +``` + +### 3.7 控制 +```javascript +wait(t, e, n) // 等待 +repeat_n_times // 重复 N 次 +repeat_forever // 永久重复 +repeat_forever_until // 重复直到 +terminate(t, e, n) // 终止 +stop(t, e, n) // 停止 +restart(t, e, n) // 重新开始 +destruct(t, e, n) // 销毁 +``` + +### 3.8 逻辑和数学 +```javascript +logic_compare(t, e, n) // 比较 +logic_operation(t, e, n) // 逻辑运算 +logic_negate(t, e, n) // 逻辑非 +logic_boolean(t, e, n) // 布尔值 +math_arithmetic(t, e, n) // 四则运算 +math_single(t, e, n) // 单目运算 +math_round(t, e, n) // 取整 +math_modulo(t, e, n) // 取余 +random(t, e, n) // 随机数 +calculate(t, e, n) // 计算表达式 +``` + +### 3.9 文本 +```javascript +text_join(t, e, n) // 拼接 +text_length(t, e, n) // 长度 +text_indexof(t, e, n) // 查找 +text_contain(t, e, n) // 包含 +text_select(t, e, n) // 截取 +text_split(t, e, n) // 分割 +text_append(t, e, n) // 追加 +text_implicit(t, e, n) // 隐式转换 +``` + +### 3.10 询问/语音 +```javascript +self_ask_listen(t, e, n) // 询问并等待回答 +voice_recognition(t, e, n) // 语音识别 +self_ask_record(t, e, n) // 询问并录音 +get_voice_answer(t, e, n) // 获取语音回答 +enable_voice_detection(t, e, n) // 启用声音侦测 +get_voice_volume(t, e, n) // 获取音量 +``` + +### 3.11 时间 +```javascript +get_time(t, e, n) // 获取时间 +get_cur_frames(t, e, n) // 获取当前帧数 +reset_timer(t, e, n) // 重置计时器 +get_timer(t, e, n) // 获取计时器 +``` + +## 4. BCM 加载流程 + +``` +1. player.codemao.cn/t/{work_id} 加载 +2. fetch_bcm_request action 触发 +3. API: GET https://api.codemao.cn/api/work/info/{work_id} +4. 获取 BCM 数据 (workspace_json) +5. Heart.Compiler.compile(workspace_json) → compiled_block_map +6. RuntimeManager.load(entities) → 加载所有实体 +7. RuntimeManager.run() → 开始执行 +8. requestAnimationFrame 循环 → RuntimeManager.update() + → 每个 Interpreter.step() +``` + +## 5. 渲染层 (PIXI.js) + +PIXI.js 版本: 6.0.4 + +```javascript +// PIXI 核心组件 +PIXI.Application // 应用 (包含 ticker, stage, renderer) +PIXI.Container // 容器 (display object 树) +PIXI.Sprite // 精灵 +PIXI.Graphics // 矢量图形 +PIXI.Text // 文字 +PIXI.Filter // 滤镜 (blur, twist, pixelate, ASCII 等) +PIXI.Ticker // 帧循环 (requestAnimationFrame) +PIXI.InteractionManager // 交互管理 (点击, 拖拽) +PIXI.Texture // 纹理 +PIXI.BaseTexture // 基础纹理 +PIXI.RenderTexture // 渲染纹理 + +// 着色器 +// 顶点着色器: 标准 2D 变换 +// 片段着色器: 纹理采样 + 颜色混合 +// 支持 WebGL 1.0 和 2.0 +``` + +## 6. 性能瓶颈分析 + +| 组件 | 耗时占比 | 瓶颈原因 | +|------|---------|---------| +| Interpreter.do_step() | ~60% | 逐条解释, dispatch 开销, 栈帧管理 | +| Interpreter.step_eval_dispatch() | ~25% | 大量 if-else 类型判断 | +| RuntimeManager.update() | ~10% | 遍历所有 interpreter | +| PIXI.js 渲染 | ~5% | 已经是 WebGL, 高效 | + +## 7. JIT 加速切入点 + +### 7.1 直接替换 Interpreter.step() +```javascript +// 找到 Interpreter 实例 +const rm = heart.get_runtime_manager(); +// rm 内部维护 interpreter 列表 +// 替换每个 interpreter 的 step 方法 +``` + +### 7.2 拦截 Compiler.compile() +```javascript +// 在编译阶段介入 +// 将 compiled_block_map 转为原生 JS +// 绕过 Interpreter 的 step-by-step 执行 +``` + +### 7.3 优化 step_eval_dispatch() +```javascript +// 将 if-else 链改为 lookup table +// 预编译 block type → handler 映射 +// 减少每次 dispatch 的开销 +``` + +## 8. 关键代码位置 (webpack 模块) + +| 功能 | 模块特征 | +|------|---------| +| Heart 入口 | `new_heart`, `e.Heart` | +| Registry | `e.RegistryImpl`, `has_responder_type` | +| Compiler | `e.CompilerImpl`, `compile_from_workspace_json` | +| OptiCompiler | `e.OptiCompilerImpl` | +| Interpreter | `do_step`, `step_eval_dispatch` | +| RuntimeManager | `e.RuntimeManagerImpl`, `get_runtime_manager` | +| BlockPredicates | `e.BlockPredicatesImpl`, `repeat_forever` | +| BlockProvider | `e.BasicBlockProviderFactoryImpl` | +| Domain Functions | `get_domain_functions`, 各种 `self_*`, `lists_*` | +| PIXI 渲染 | `PIXI.Application`, `lvVU` 模块 | +| 音频 | `AudioPlayer`, `Howl`, MIDI | +| 物理 | `physics2_*` | +| Redux Store | `dqaR` 模块, `ALsR` | +| Theatre | `ypP6` 模块, `ft` 组件 | +| Cloud | `qVl3` 模块, BCM 加载 |