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)) {