Skip to content

Do not throw when navigator.credentials cannot be redefined#52

Merged
dlongley merged 2 commits into
mainfrom
fix-ios-define-property
Jun 12, 2026
Merged

Do not throw when navigator.credentials cannot be redefined#52
dlongley merged 2 commits into
mainfrom
fix-ios-define-property

Conversation

@djscruggs

Copy link
Copy Markdown
Contributor

Fixes #51.

On WebKit (all iOS browsers, desktop Safari), navigator.credentials is a non-configurable property, so the Object.defineProperty() call used since 3.2.1 to install the anti-clobber proxy throws a TypeError, causing load()/loadOnce() to reject and CHAPI to never initialize.

Changes

  • Wrap the defineProperty() call in a try/catch.
  • On failure, fall back to plain assignment of the proxy.
  • If assignment also fails (WebKit can expose the property as getter-only, which throws on assignment in strict mode), continue without the proxy. This is safe because get and store have already been replaced directly on the existing navigator.credentials object earlier in load() — only the protection against subsequent overwrites of the property itself is lost, matching the pre-3.2.1 behavior that works on iOS.
  • Add changelog entry for 4.0.2.

Testing

  • npm run lint passes; webpack build compiles.
  • Verified manually in Safari (WebKit) with a local test page: before the fix, loadOnce() rejects with TypeError: Attempting to change writable attribute of unconfigurable property; with the fix, loadOnce() resolves, window.WebCredential is defined, and navigator.credentials.get/store are patched.

🤖 Generated with Claude Code

On WebKit (all iOS browsers), `navigator.credentials` is a
non-configurable property, so the `Object.defineProperty()` call
used since 3.2.1 to install the anti-clobber proxy throws a
TypeError, causing `load()`/`loadOnce()` to reject and CHAPI to
never initialize. Wrap the call in a try/catch and fall back to
plain assignment; if that also fails, continue without the proxy,
since `get` and `store` have already been replaced on the existing
`navigator.credentials` object and only protection against later
overwrites of the property itself is lost.

Addresses #51.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@djscruggs djscruggs requested a review from dlongley June 12, 2026 15:16

@dlongley dlongley left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Comment thread lib/index.js Outdated
@dlongley dlongley merged commit ba0de44 into main Jun 12, 2026
1 check passed
@dlongley dlongley deleted the fix-ios-define-property branch June 12, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

loadOnce() throws on iOS (WebKit) since 3.2.1: cannot redefine navigator.credentials

2 participants