-
-
Notifications
You must be signed in to change notification settings - Fork 41
Improvement: added error handling using try-catch #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -86,10 +86,16 @@ class SocialShareButton { | |
|
|
||
| this.button = button; | ||
| if (this.options.container) { | ||
| const container = | ||
| typeof this.options.container === "string" | ||
| ? document.querySelector(this.options.container) | ||
| : this.options.container; | ||
| let container = null; | ||
| try { | ||
| // DOM manipulation: querySelector may throw for invalid selectors | ||
| container = | ||
| typeof this.options.container === "string" | ||
| ? document.querySelector(this.options.container) | ||
| : this.options.container; | ||
| } catch (error) { | ||
| console.error("DOM manipulation failed: Invalid container selector", error); | ||
| } | ||
|
|
||
| if (container) { | ||
| container.appendChild(button); | ||
|
|
@@ -404,15 +410,31 @@ class SocialShareButton { | |
| } | ||
|
|
||
| share(platform) { | ||
| const shareUrl = this.getShareURL(platform); | ||
| let shareUrl = ""; | ||
| try { | ||
| // URL handling: encodeURIComponent may throw URIError on lone surrogates | ||
| shareUrl = this.getShareURL(platform); | ||
| } catch (error) { | ||
| console.error("URL handling failed: Data encoding error", error); | ||
| } | ||
|
Comment on lines
+413
to
+419
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not report If URL generation or navigation/open throws, the new catches swallow the failure and this method still falls through to either Also applies to: 425-449 🤖 Prompt for AI Agents |
||
|
|
||
| if (shareUrl) { | ||
| this._emit("social_share_click", "share", { platform }); | ||
|
|
||
| if (platform === "email") { | ||
| window.location.href = shareUrl; | ||
| try { | ||
| // Navigation may be blocked in some restricted contexts | ||
| window.location.href = shareUrl; | ||
| } catch (error) { | ||
| console.error("Sharing failed: Navigation strictly blocked", error); | ||
| } | ||
| } else { | ||
| window.open(shareUrl, "_blank", "noopener,noreferrer,width=600,height=600"); | ||
| try { | ||
| // window.open may throw if blocked by browser settings or in restricted frames | ||
| window.open(shareUrl, "_blank", "noopener,noreferrer,width=600,height=600"); | ||
| } catch (error) { | ||
| console.error("Sharing failed: Popup window blocked", error); | ||
| } | ||
| } | ||
|
|
||
| this._emit("social_share_success", "share", { platform }); | ||
|
|
@@ -434,37 +456,43 @@ class SocialShareButton { | |
|
|
||
| // Check if clipboard API is available | ||
| if (navigator.clipboard && navigator.clipboard.writeText) { | ||
| navigator.clipboard | ||
| .writeText(this.options.url) | ||
| .then(() => { | ||
| // Guard against async callback after destroy | ||
| if (this.isDestroyed) return; | ||
|
|
||
| copyBtn.textContent = "Copied!"; | ||
| copyBtn.classList.add("copied"); | ||
| this._emit("social_share_copy", "copy"); | ||
|
|
||
| if (this.options.onCopy) { | ||
| this.options.onCopy(this.options.url); | ||
| } | ||
|
|
||
| // Clear any existing feedback timeout | ||
| if (this.feedbackTimeout) { | ||
| clearTimeout(this.feedbackTimeout); | ||
| } | ||
|
|
||
| // Track feedback timeout to prevent callback after destroy | ||
| this.feedbackTimeout = setTimeout(() => { | ||
| if (this.isDestroyed || !copyBtn) return; // Safety check | ||
| copyBtn.textContent = "Copy"; | ||
| copyBtn.classList.remove("copied"); | ||
| this.feedbackTimeout = null; | ||
| }, 2000); | ||
| }) | ||
| .catch(() => { | ||
| // Fallback to manual selection | ||
| this.fallbackCopy(input, copyBtn); | ||
| }); | ||
| try { | ||
| navigator.clipboard | ||
| .writeText(this.options.url) | ||
| .then(() => { | ||
| // Guard against async callback after destroy | ||
| if (this.isDestroyed) return; | ||
|
|
||
| copyBtn.textContent = "Copied!"; | ||
| copyBtn.classList.add("copied"); | ||
| this._emit("social_share_copy", "copy"); | ||
|
|
||
| if (this.options.onCopy) { | ||
| this.options.onCopy(this.options.url); | ||
| } | ||
|
|
||
| // Clear any existing feedback timeout | ||
| if (this.feedbackTimeout) { | ||
| clearTimeout(this.feedbackTimeout); | ||
| } | ||
|
|
||
| // Track feedback timeout to prevent callback after destroy | ||
| this.feedbackTimeout = setTimeout(() => { | ||
| if (this.isDestroyed || !copyBtn) return; // Safety check | ||
| copyBtn.textContent = "Copy"; | ||
| copyBtn.classList.remove("copied"); | ||
| this.feedbackTimeout = null; | ||
| }, 2000); | ||
| }) | ||
| .catch((error) => { | ||
| console.error("Clipboard copy failed async:", error); | ||
| // Fallback to manual selection | ||
| this.fallbackCopy(input, copyBtn); | ||
| }); | ||
| } catch (error) { | ||
| console.error("Clipboard wrapper failed synchronously:", error); | ||
| this.fallbackCopy(input, copyBtn); | ||
| } | ||
| } else { | ||
| // Fallback for browsers without clipboard API | ||
| this.fallbackCopy(input, copyBtn); | ||
|
|
@@ -500,7 +528,8 @@ class SocialShareButton { | |
| copyBtn.classList.remove("copied"); | ||
| this.feedbackTimeout = null; | ||
| }, 2000); | ||
| } catch (_err) { | ||
| } catch (error) { | ||
| console.error("Clipboard copy failed (fallback document.execCommand):", error); | ||
| copyBtn.textContent = "Failed"; | ||
|
|
||
| // Clear any existing feedback timeout | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace bare
console.errorcalls with a debug-gated helper.These catch blocks now write directly to consumers' browser consoles. In this repo that both violates the approved library logging pattern and trips the project's
no-consolerule; reuse or generalize a single private helper gated byoptions.debuginstead.Based on learnings: bare console statements in library catch blocks are unacceptable in production, the approved pattern is a debug-gated
_debugWarn(message, err)helper, andeslint.config.jsalready enforcesno-console: error.Also applies to: 417-418, 428-429, 435-436, 487-493, 531-532
🤖 Prompt for AI Agents