Move RCTRootShadowView creation to main thread - #1344

Merged
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock
Aug 23, 2022
Merged

Move RCTRootShadowView creation to main thread#1344
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock

Conversation

@amgleitman

Copy link
Copy Markdown
Member

Please select one of the following

  • I am removing an existing difference between facebook/react-native and microsoft/react-native-macos 👍
  • I am cherry-picking a change from Facebook's react-native into microsoft/react-native-macos 👍
  • I am making a fix / change for the macOS implementation of react-native
  • I am making a change required for Microsoft usage of react-native

Summary

Solves the same problem that #733 was supposed to solve (originally backed out by 70ddf46).

We've seen a deadlock on iOS with two threads, one main and one background, making simultaneous calls to +[RCTI18nUtil sharedInstance], with a background thread reaching the inside of the dispatch_once block (as seen here) first. It appears that playing around with NSUserDefaults on iOS (as done here) requires use of the main thread to "commit" changes to user defaults.

The solution is to move the initialization of RCTRootShadowView, which depends on our RCTI18n singleton as per this line, to the main thread, and do everything else on the UIManager queue.

This will later be brought upstream.

Changelog

[iOS] [Fixed] - Remove a deadlock involving RCTI18nUtil

Test Plan

The deadlock no longer occurs on iOS, and macOS appears unaffected.

@harrieshin

Copy link
Copy Markdown

do you know which commit actually regress it in .68 version?

@harrieshin

Copy link
Copy Markdown

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

@harrieshin

Copy link
Copy Markdown

should we add an asserts in RCTI18n to make sure some things are called in main thread?

@Saadnajmi

Copy link
Copy Markdown
Collaborator

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

@amgleitman

Copy link
Copy Markdown
MemberAuthor

Harrie Shin (@harrieshin)

do you know which commit actually regress it in .68 version?

Not sure. I haven't looked too deeply into it.

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

Correct. This is a separate thread.

should we add an asserts in RCTI18n to make sure some things are called in main thread?

I considered it, although I don't know if this will have any other adverse side effects, and I want to make sure that requiring main-thread initialization is indeed correct. If this ends up being the case, I'm happy to add an assert in.

@amgleitman

Copy link
Copy Markdown
MemberAuthor

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

The point of this change is to bump up the initialization of our RCTI18nUtil instance to avoid deadlocks. I'd like to think that this change is more surgical than the previous one, but I understand your concern. I can test the scenario that caused the reversion to make sure that still works as intended though.

Sign up for freeto 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.

3 participants

@amgleitman@harrieshin@Saadnajmi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Move RCTRootShadowView creation to main thread - #1344

Merged
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock
Aug 23, 2022
Merged

Move RCTRootShadowView creation to main thread#1344
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock

Conversation

@amgleitman

Copy link
Copy Markdown
Member

Please select one of the following

  • I am removing an existing difference between facebook/react-native and microsoft/react-native-macos 👍
  • I am cherry-picking a change from Facebook's react-native into microsoft/react-native-macos 👍
  • I am making a fix / change for the macOS implementation of react-native
  • I am making a change required for Microsoft usage of react-native

Summary

Solves the same problem that #733 was supposed to solve (originally backed out by 70ddf46).

We've seen a deadlock on iOS with two threads, one main and one background, making simultaneous calls to +[RCTI18nUtil sharedInstance], with a background thread reaching the inside of the dispatch_once block (as seen here) first. It appears that playing around with NSUserDefaults on iOS (as done here) requires use of the main thread to "commit" changes to user defaults.

The solution is to move the initialization of RCTRootShadowView, which depends on our RCTI18n singleton as per this line, to the main thread, and do everything else on the UIManager queue.

This will later be brought upstream.

Changelog

[iOS] [Fixed] - Remove a deadlock involving RCTI18nUtil

Test Plan

The deadlock no longer occurs on iOS, and macOS appears unaffected.

@harrieshin

Copy link
Copy Markdown

do you know which commit actually regress it in .68 version?

@harrieshin

Copy link
Copy Markdown

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

@harrieshin

Copy link
Copy Markdown

should we add an asserts in RCTI18n to make sure some things are called in main thread?

@Saadnajmi

Copy link
Copy Markdown
Collaborator

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

@amgleitman

Copy link
Copy Markdown
MemberAuthor

Harrie Shin (@harrieshin)

do you know which commit actually regress it in .68 version?

Not sure. I haven't looked too deeply into it.

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

Correct. This is a separate thread.

should we add an asserts in RCTI18n to make sure some things are called in main thread?

I considered it, although I don't know if this will have any other adverse side effects, and I want to make sure that requiring main-thread initialization is indeed correct. If this ends up being the case, I'm happy to add an assert in.

@amgleitman

Copy link
Copy Markdown
MemberAuthor

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

The point of this change is to bump up the initialization of our RCTI18nUtil instance to avoid deadlocks. I'd like to think that this change is more surgical than the previous one, but I understand your concern. I can test the scenario that caused the reversion to make sure that still works as intended though.

Sign up for freeto 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.

3 participants

@amgleitman@harrieshin@Saadnajmi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Move RCTRootShadowView creation to main thread - #1344

Merged
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock
Aug 23, 2022
Merged

Move RCTRootShadowView creation to main thread#1344
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock

Conversation

@amgleitman

Copy link
Copy Markdown
Member

Please select one of the following

  • I am removing an existing difference between facebook/react-native and microsoft/react-native-macos 👍
  • I am cherry-picking a change from Facebook's react-native into microsoft/react-native-macos 👍
  • I am making a fix / change for the macOS implementation of react-native
  • I am making a change required for Microsoft usage of react-native

Summary

Solves the same problem that #733 was supposed to solve (originally backed out by 70ddf46).

We've seen a deadlock on iOS with two threads, one main and one background, making simultaneous calls to +[RCTI18nUtil sharedInstance], with a background thread reaching the inside of the dispatch_once block (as seen here) first. It appears that playing around with NSUserDefaults on iOS (as done here) requires use of the main thread to "commit" changes to user defaults.

The solution is to move the initialization of RCTRootShadowView, which depends on our RCTI18n singleton as per this line, to the main thread, and do everything else on the UIManager queue.

This will later be brought upstream.

Changelog

[iOS] [Fixed] - Remove a deadlock involving RCTI18nUtil

Test Plan

The deadlock no longer occurs on iOS, and macOS appears unaffected.

@harrieshin

Copy link
Copy Markdown

do you know which commit actually regress it in .68 version?

@harrieshin

Copy link
Copy Markdown

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

@harrieshin

Copy link
Copy Markdown

should we add an asserts in RCTI18n to make sure some things are called in main thread?

@Saadnajmi

Copy link
Copy Markdown
Collaborator

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

@amgleitman

Copy link
Copy Markdown
MemberAuthor

Harrie Shin (@harrieshin)

do you know which commit actually regress it in .68 version?

Not sure. I haven't looked too deeply into it.

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

Correct. This is a separate thread.

should we add an asserts in RCTI18n to make sure some things are called in main thread?

I considered it, although I don't know if this will have any other adverse side effects, and I want to make sure that requiring main-thread initialization is indeed correct. If this ends up being the case, I'm happy to add an assert in.

@amgleitman

Copy link
Copy Markdown
MemberAuthor

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

The point of this change is to bump up the initialization of our RCTI18nUtil instance to avoid deadlocks. I'd like to think that this change is more surgical than the previous one, but I understand your concern. I can test the scenario that caused the reversion to make sure that still works as intended though.

Sign up for freeto 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.

3 participants

@amgleitman@harrieshin@Saadnajmi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Move RCTRootShadowView creation to main thread - #1344

Merged
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock
Aug 23, 2022
Merged

Move RCTRootShadowView creation to main thread#1344
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock

Conversation

@amgleitman

Copy link
Copy Markdown
Member

Please select one of the following

  • I am removing an existing difference between facebook/react-native and microsoft/react-native-macos 👍
  • I am cherry-picking a change from Facebook's react-native into microsoft/react-native-macos 👍
  • I am making a fix / change for the macOS implementation of react-native
  • I am making a change required for Microsoft usage of react-native

Summary

Solves the same problem that #733 was supposed to solve (originally backed out by 70ddf46).

We've seen a deadlock on iOS with two threads, one main and one background, making simultaneous calls to +[RCTI18nUtil sharedInstance], with a background thread reaching the inside of the dispatch_once block (as seen here) first. It appears that playing around with NSUserDefaults on iOS (as done here) requires use of the main thread to "commit" changes to user defaults.

The solution is to move the initialization of RCTRootShadowView, which depends on our RCTI18n singleton as per this line, to the main thread, and do everything else on the UIManager queue.

This will later be brought upstream.

Changelog

[iOS] [Fixed] - Remove a deadlock involving RCTI18nUtil

Test Plan

The deadlock no longer occurs on iOS, and macOS appears unaffected.

@harrieshin

Copy link
Copy Markdown

do you know which commit actually regress it in .68 version?

@harrieshin

Copy link
Copy Markdown

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

@harrieshin

Copy link
Copy Markdown

should we add an asserts in RCTI18n to make sure some things are called in main thread?

@Saadnajmi

Copy link
Copy Markdown
Collaborator

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

@amgleitman

Copy link
Copy Markdown
MemberAuthor

Harrie Shin (@harrieshin)

do you know which commit actually regress it in .68 version?

Not sure. I haven't looked too deeply into it.

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

Correct. This is a separate thread.

should we add an asserts in RCTI18n to make sure some things are called in main thread?

I considered it, although I don't know if this will have any other adverse side effects, and I want to make sure that requiring main-thread initialization is indeed correct. If this ends up being the case, I'm happy to add an assert in.

@amgleitman

Copy link
Copy Markdown
MemberAuthor

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

The point of this change is to bump up the initialization of our RCTI18nUtil instance to avoid deadlocks. I'd like to think that this change is more surgical than the previous one, but I understand your concern. I can test the scenario that caused the reversion to make sure that still works as intended though.

Sign up for freeto 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.

3 participants

@amgleitman@harrieshin@Saadnajmi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Move RCTRootShadowView creation to main thread - #1344

Merged
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock
Aug 23, 2022
Merged

Move RCTRootShadowView creation to main thread#1344
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock

Conversation

@amgleitman

Copy link
Copy Markdown
Member

Please select one of the following

  • I am removing an existing difference between facebook/react-native and microsoft/react-native-macos 👍
  • I am cherry-picking a change from Facebook's react-native into microsoft/react-native-macos 👍
  • I am making a fix / change for the macOS implementation of react-native
  • I am making a change required for Microsoft usage of react-native

Summary

Solves the same problem that #733 was supposed to solve (originally backed out by 70ddf46).

We've seen a deadlock on iOS with two threads, one main and one background, making simultaneous calls to +[RCTI18nUtil sharedInstance], with a background thread reaching the inside of the dispatch_once block (as seen here) first. It appears that playing around with NSUserDefaults on iOS (as done here) requires use of the main thread to "commit" changes to user defaults.

The solution is to move the initialization of RCTRootShadowView, which depends on our RCTI18n singleton as per this line, to the main thread, and do everything else on the UIManager queue.

This will later be brought upstream.

Changelog

[iOS] [Fixed] - Remove a deadlock involving RCTI18nUtil

Test Plan

The deadlock no longer occurs on iOS, and macOS appears unaffected.

@harrieshin

Copy link
Copy Markdown

do you know which commit actually regress it in .68 version?

@harrieshin

Copy link
Copy Markdown

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

@harrieshin

Copy link
Copy Markdown

should we add an asserts in RCTI18n to make sure some things are called in main thread?

@Saadnajmi

Copy link
Copy Markdown
Collaborator

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

@amgleitman

Copy link
Copy Markdown
MemberAuthor

Harrie Shin (@harrieshin)

do you know which commit actually regress it in .68 version?

Not sure. I haven't looked too deeply into it.

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

Correct. This is a separate thread.

should we add an asserts in RCTI18n to make sure some things are called in main thread?

I considered it, although I don't know if this will have any other adverse side effects, and I want to make sure that requiring main-thread initialization is indeed correct. If this ends up being the case, I'm happy to add an assert in.

@amgleitman

Copy link
Copy Markdown
MemberAuthor

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

The point of this change is to bump up the initialization of our RCTI18nUtil instance to avoid deadlocks. I'd like to think that this change is more surgical than the previous one, but I understand your concern. I can test the scenario that caused the reversion to make sure that still works as intended though.

Sign up for freeto 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.

3 participants

@amgleitman@harrieshin@Saadnajmi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Move RCTRootShadowView creation to main thread - #1344

Merged
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock
Aug 23, 2022
Merged

Move RCTRootShadowView creation to main thread#1344
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock

Conversation

@amgleitman

Copy link
Copy Markdown
Member

Please select one of the following

  • I am removing an existing difference between facebook/react-native and microsoft/react-native-macos 👍
  • I am cherry-picking a change from Facebook's react-native into microsoft/react-native-macos 👍
  • I am making a fix / change for the macOS implementation of react-native
  • I am making a change required for Microsoft usage of react-native

Summary

Solves the same problem that #733 was supposed to solve (originally backed out by 70ddf46).

We've seen a deadlock on iOS with two threads, one main and one background, making simultaneous calls to +[RCTI18nUtil sharedInstance], with a background thread reaching the inside of the dispatch_once block (as seen here) first. It appears that playing around with NSUserDefaults on iOS (as done here) requires use of the main thread to "commit" changes to user defaults.

The solution is to move the initialization of RCTRootShadowView, which depends on our RCTI18n singleton as per this line, to the main thread, and do everything else on the UIManager queue.

This will later be brought upstream.

Changelog

[iOS] [Fixed] - Remove a deadlock involving RCTI18nUtil

Test Plan

The deadlock no longer occurs on iOS, and macOS appears unaffected.

@harrieshin

Copy link
Copy Markdown

do you know which commit actually regress it in .68 version?

@harrieshin

Copy link
Copy Markdown

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

@harrieshin

Copy link
Copy Markdown

should we add an asserts in RCTI18n to make sure some things are called in main thread?

@Saadnajmi

Copy link
Copy Markdown
Collaborator

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

@amgleitman

Copy link
Copy Markdown
MemberAuthor

Harrie Shin (@harrieshin)

do you know which commit actually regress it in .68 version?

Not sure. I haven't looked too deeply into it.

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

Correct. This is a separate thread.

should we add an asserts in RCTI18n to make sure some things are called in main thread?

I considered it, although I don't know if this will have any other adverse side effects, and I want to make sure that requiring main-thread initialization is indeed correct. If this ends up being the case, I'm happy to add an assert in.

@amgleitman

Copy link
Copy Markdown
MemberAuthor

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

The point of this change is to bump up the initialization of our RCTI18nUtil instance to avoid deadlocks. I'd like to think that this change is more surgical than the previous one, but I understand your concern. I can test the scenario that caused the reversion to make sure that still works as intended though.

Sign up for freeto 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.

3 participants

@amgleitman@harrieshin@Saadnajmi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Move RCTRootShadowView creation to main thread - #1344

Merged
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock
Aug 23, 2022
Merged

Move RCTRootShadowView creation to main thread#1344
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock

Conversation

@amgleitman

Copy link
Copy Markdown
Member

Please select one of the following

  • I am removing an existing difference between facebook/react-native and microsoft/react-native-macos 👍
  • I am cherry-picking a change from Facebook's react-native into microsoft/react-native-macos 👍
  • I am making a fix / change for the macOS implementation of react-native
  • I am making a change required for Microsoft usage of react-native

Summary

Solves the same problem that #733 was supposed to solve (originally backed out by 70ddf46).

We've seen a deadlock on iOS with two threads, one main and one background, making simultaneous calls to +[RCTI18nUtil sharedInstance], with a background thread reaching the inside of the dispatch_once block (as seen here) first. It appears that playing around with NSUserDefaults on iOS (as done here) requires use of the main thread to "commit" changes to user defaults.

The solution is to move the initialization of RCTRootShadowView, which depends on our RCTI18n singleton as per this line, to the main thread, and do everything else on the UIManager queue.

This will later be brought upstream.

Changelog

[iOS] [Fixed] - Remove a deadlock involving RCTI18nUtil

Test Plan

The deadlock no longer occurs on iOS, and macOS appears unaffected.

@harrieshin

Copy link
Copy Markdown

do you know which commit actually regress it in .68 version?

@harrieshin

Copy link
Copy Markdown

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

@harrieshin

Copy link
Copy Markdown

should we add an asserts in RCTI18n to make sure some things are called in main thread?

@Saadnajmi

Copy link
Copy Markdown
Collaborator

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

@amgleitman

Copy link
Copy Markdown
MemberAuthor

Harrie Shin (@harrieshin)

do you know which commit actually regress it in .68 version?

Not sure. I haven't looked too deeply into it.

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

Correct. This is a separate thread.

should we add an asserts in RCTI18n to make sure some things are called in main thread?

I considered it, although I don't know if this will have any other adverse side effects, and I want to make sure that requiring main-thread initialization is indeed correct. If this ends up being the case, I'm happy to add an assert in.

@amgleitman

Copy link
Copy Markdown
MemberAuthor

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

The point of this change is to bump up the initialization of our RCTI18nUtil instance to avoid deadlocks. I'd like to think that this change is more surgical than the previous one, but I understand your concern. I can test the scenario that caused the reversion to make sure that still works as intended though.

Sign up for freeto 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.

3 participants

@amgleitman@harrieshin@Saadnajmi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Move RCTRootShadowView creation to main thread - #1344

Merged
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock
Aug 23, 2022
Merged

Move RCTRootShadowView creation to main thread#1344
Adam Gleitman (amgleitman) merged 2 commits into
microsoft:mainfrom
amgleitman:prevent-rct18nutil-deadlock

Conversation

@amgleitman

Copy link
Copy Markdown
Member

Please select one of the following

  • I am removing an existing difference between facebook/react-native and microsoft/react-native-macos 👍
  • I am cherry-picking a change from Facebook's react-native into microsoft/react-native-macos 👍
  • I am making a fix / change for the macOS implementation of react-native
  • I am making a change required for Microsoft usage of react-native

Summary

Solves the same problem that #733 was supposed to solve (originally backed out by 70ddf46).

We've seen a deadlock on iOS with two threads, one main and one background, making simultaneous calls to +[RCTI18nUtil sharedInstance], with a background thread reaching the inside of the dispatch_once block (as seen here) first. It appears that playing around with NSUserDefaults on iOS (as done here) requires use of the main thread to "commit" changes to user defaults.

The solution is to move the initialization of RCTRootShadowView, which depends on our RCTI18n singleton as per this line, to the main thread, and do everything else on the UIManager queue.

This will later be brought upstream.

Changelog

[iOS] [Fixed] - Remove a deadlock involving RCTI18nUtil

Test Plan

The deadlock no longer occurs on iOS, and macOS appears unaffected.

@harrieshin

Copy link
Copy Markdown

do you know which commit actually regress it in .68 version?

@harrieshin

Copy link
Copy Markdown

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

@harrieshin

Copy link
Copy Markdown

should we add an asserts in RCTI18n to make sure some things are called in main thread?

@Saadnajmi

Copy link
Copy Markdown
Collaborator

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

@amgleitman

Copy link
Copy Markdown
MemberAuthor

Harrie Shin (@harrieshin)

do you know which commit actually regress it in .68 version?

Not sure. I haven't looked too deeply into it.

for my own knowledge, RCTExecuteOnUIManagerQueue is not main thread?

Correct. This is a separate thread.

should we add an asserts in RCTI18n to make sure some things are called in main thread?

I considered it, although I don't know if this will have any other adverse side effects, and I want to make sure that requiring main-thread initialization is indeed correct. If this ends up being the case, I'm happy to add an assert in.

@amgleitman

Copy link
Copy Markdown
MemberAuthor

The last time we had a deadlock in RCTI18nUtil, I made a change in both RN-macOS and RN Core to resolve it. The change ended up being incorrect, and I had to back it out. The actual fix was downstream in our internal codebase. I worry that that sequence of events may happen again here. Are we sure there isn't something we can change downstream instead of making the change here?

The point of this change is to bump up the initialization of our RCTI18nUtil instance to avoid deadlocks. I'd like to think that this change is more surgical than the previous one, but I understand your concern. I can test the scenario that caused the reversion to make sure that still works as intended though.

Sign up for freeto 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.

3 participants

@amgleitman@harrieshin@Saadnajmi