From eaafabe94f8794e766f70e4629321ff6b8ead3b8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 6 Sep 2026 13:19:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=94=A8=E6=88=B7=E5=90=8D+?= =?UTF-8?q?=E9=82=80=E8=AF=B7=E7=A0=81=E6=B3=A8=E5=86=8C=EF=BC=88=E6=97=A0?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E5=8F=B7=EF=BC=89=E5=BF=85=E7=8E=B0=E5=B4=A9?= =?UTF-8?q?=E6=BA=83=EF=BC=9ATinode.credential(null)=20=E6=8A=9B=E5=BC=82?= =?UTF-8?q?=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象:企业码注册流程走"仅用户名+邀请码,不填手机号"这条路径时,点"注册"必然抛出 原始 JS 报错"Cannot destructure property 'val' of 'meth' as it is null",直接 展示在错误提示条上,注册无法完成。 根因:auth-onboarding-view.jsx 的 Register 组件在没有手机号凭证、只有邀请码时, 把 cred_ 显式传成 null(没有可附加的凭证)。tinode-sdk 的 Tinode.credential(meth,...) 用 `typeof meth == 'object'` 判断参数是不是一个 {meth,val,resp,params} 对象,但 JS 里 `typeof null === 'object'` 也是 true,导致对 null 无条件解构,直接抛异常。 所有走"登录"分支的调用点传的从来都是"字段可能是 undefined 的对象",从未传过字面量 null,所以这个 bug 只在"用户名注册且没有手机号凭证"这一条路径上必现。 修法:cred_ 为空时不再调用 Tinode.credential(),直接把 cred 字段设为 undefined, 绕开 SDK 这个不处理 null 输入的缺陷,不改动 vendored 的 tinode-sdk 代码。 Co-Authored-By: Claude Sonnet 5 --- src/views/tinode-web.jsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/views/tinode-web.jsx b/src/views/tinode-web.jsx index d133e30c..1c95690e 100644 --- a/src/views/tinode-web.jsx +++ b/src/views/tinode-web.jsx @@ -1565,8 +1565,21 @@ class TinodeWeb extends React.Component { if (public_ && public_.photo && public_.photo.ref) { attachments = [public_.photo.ref]; } + // cred_ is `null` on the username-only registration path (auth-onboarding-view.jsx's Register + // passes it literally as `null` when there's no phone credential to attach, only an invite + // code). tinode-sdk's Tinode.credential(meth, ...) checks `typeof meth == 'object'` to decide + // whether its first argument is really a single {meth,val,resp,params} object -- but + // `typeof null === 'object'` is true in JS, so it unconditionally destructures `{val, params, + // resp, meth} = meth` and crashes with a raw "Cannot destructure property 'val' of 'meth' as + // it is null" the moment it receives a real `null` (as opposed to an object with merely + // undefined fields, which every *login* call site here happens to always pass and which + // destructures fine). This made username-only registration (with or without a valid invite + // code -- client-side validation passes either way before reaching here) always throw and + // never send the {acc} message at all, with the raw JS error text leaking into the "注册" + // button's error banner. Not calling Tinode.credential() at all when there is nothing to + // wrap sidesteps the SDK's bug without patching vendored node_modules code. return this.tinode.createAccountBasic(login_, password_, - {public: public_, tags: tags_, cred: Tinode.credential(cred_), attachments: attachments}); + {public: public_, tags: tags_, cred: cred_ ? Tinode.credential(cred_) : undefined, attachments: attachments}); }).then(ctrl => { if (ctrl.code >= 300 && ctrl.text == 'validate credentials') { if (!TinodeWeb.navigateToCredentialsView(ctrl.params)) {