Embedpdf/feature/thread confined - #29

Merged
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined
Jun 15, 2026
Merged

Embedpdf/feature/thread confined#29
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

No description provided.

Introduce optional per-thread PDFium globals to support a thread-confined runtime for server worker pools. Adds core/fxcrt/epdf_tls.h (EPDF_TLS) and converts numerous process-global singletons to be thread-local when embedpdf_thread_local_globals is enabled. Exposes EPDF_InitThread/EPDF_ShutdownThread as lifecycle entry points, makes localtime usage thread-safe, and adjusts RNG/errno/timer/render/color/font/module globals accordingly. Adds a thread-soak test harness (testing/tools:epdf_thread_soak), build/test scripts (scripts/embedpdf-runtime/*), GN flag (embedpdf_thread_local_globals) and a GitHub Actions workflow (pdfium-tsan-thread-soak.yml) to run the TSAN-backed soak. Default behavior remains unchanged (flag off) so builds are byte-for-byte compatible unless explicitly enabled.
Mark the parser's static recursion depth variable as thread-local (EPDF_TLS) in both the header and source. Adds an #include for core/fxcrt/epdf_tls.h. This ensures each thread has its own s_CurrentRecursionDepth to avoid cross-thread interference when parsing concurrently; kParserMaxRecursionDepth is unchanged.
Add two PDF fixtures under testing/resources/pixel to exercise ICC profile parsing: icc_profile_bad_component.pdf embeds an ICCBased color space with N=1 (one component instead of the expected 3) but still triggers DetectSRGB(); icc_profile_bad_value.pdf contains a profile/value (0x80000000) that overflows when multiplied by 255. These files are used by pixel tests to validate robustness and error handling of ICC profile processing.
Add platform-specific defines for gmtime variants in BUILD.gn (HAVE_GMTIME_R on Linux/ChromeOS/Android/mac/iOS, HAVE_GMTIME_S on Windows). Update cmsplugin.c::_cmsGetTime to guard against gmtime returning NULL: copy the result into ptr_time only if non-NULL and return a boolean success value, avoiding a NULL dereference inside the critical section.
Add clarifying comments about concurrency and ThreadSanitizer findings in two lcms sources. In cmsplugin.c note that gmtime()'s shared static result is copied while holding the LCMS mutex to avoid TSan-reported races when creating ICC profiles concurrently. In cmswtpnt.c document that the D50 XYZ constant is safe for concurrent readers and that the xyY value is computed in a thread-confined way to avoid writing to a shared static on each call.
Introduce new EmbedPDF extension APIs to operate on pages by PDF object number. LoadPageByValidatedIndex gains a `normalize` flag to override page rotation to 0 for normalized coordinates, and EPDFDoc_LoadPageByObjectNumberNormalized is exported. Add EPDFDoc_DeletePageByObjectNumber to delete the first visible page matching an indirect object number (with XFA-backed documents rejected), and EPDFDoc_SetPageRotationByObjectNumber to update a page's /Rotate value (validates rotate in 0..3). Update public/fpdfview.h with API docs, add tests and test registrations in fpdf_view_embeddertest.cpp and fpdf_view_c_api_test.c, and include fpdf_edit.h where needed.
@bobsingor
bobsingor merged commit adc5c20 into embedpdf/feature/read-purityJun 15, 2026
@bobsingor
bobsingor deleted the embedpdf/feature/thread-confined branch August 5, 2026 11:05
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.

1 participant

@bobsingor
, '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

Embedpdf/feature/thread confined - #29

Merged
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined
Jun 15, 2026
Merged

Embedpdf/feature/thread confined#29
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

No description provided.

Introduce optional per-thread PDFium globals to support a thread-confined runtime for server worker pools. Adds core/fxcrt/epdf_tls.h (EPDF_TLS) and converts numerous process-global singletons to be thread-local when embedpdf_thread_local_globals is enabled. Exposes EPDF_InitThread/EPDF_ShutdownThread as lifecycle entry points, makes localtime usage thread-safe, and adjusts RNG/errno/timer/render/color/font/module globals accordingly. Adds a thread-soak test harness (testing/tools:epdf_thread_soak), build/test scripts (scripts/embedpdf-runtime/*), GN flag (embedpdf_thread_local_globals) and a GitHub Actions workflow (pdfium-tsan-thread-soak.yml) to run the TSAN-backed soak. Default behavior remains unchanged (flag off) so builds are byte-for-byte compatible unless explicitly enabled.
Mark the parser's static recursion depth variable as thread-local (EPDF_TLS) in both the header and source. Adds an #include for core/fxcrt/epdf_tls.h. This ensures each thread has its own s_CurrentRecursionDepth to avoid cross-thread interference when parsing concurrently; kParserMaxRecursionDepth is unchanged.
Add two PDF fixtures under testing/resources/pixel to exercise ICC profile parsing: icc_profile_bad_component.pdf embeds an ICCBased color space with N=1 (one component instead of the expected 3) but still triggers DetectSRGB(); icc_profile_bad_value.pdf contains a profile/value (0x80000000) that overflows when multiplied by 255. These files are used by pixel tests to validate robustness and error handling of ICC profile processing.
Add platform-specific defines for gmtime variants in BUILD.gn (HAVE_GMTIME_R on Linux/ChromeOS/Android/mac/iOS, HAVE_GMTIME_S on Windows). Update cmsplugin.c::_cmsGetTime to guard against gmtime returning NULL: copy the result into ptr_time only if non-NULL and return a boolean success value, avoiding a NULL dereference inside the critical section.
Add clarifying comments about concurrency and ThreadSanitizer findings in two lcms sources. In cmsplugin.c note that gmtime()'s shared static result is copied while holding the LCMS mutex to avoid TSan-reported races when creating ICC profiles concurrently. In cmswtpnt.c document that the D50 XYZ constant is safe for concurrent readers and that the xyY value is computed in a thread-confined way to avoid writing to a shared static on each call.
Introduce new EmbedPDF extension APIs to operate on pages by PDF object number. LoadPageByValidatedIndex gains a `normalize` flag to override page rotation to 0 for normalized coordinates, and EPDFDoc_LoadPageByObjectNumberNormalized is exported. Add EPDFDoc_DeletePageByObjectNumber to delete the first visible page matching an indirect object number (with XFA-backed documents rejected), and EPDFDoc_SetPageRotationByObjectNumber to update a page's /Rotate value (validates rotate in 0..3). Update public/fpdfview.h with API docs, add tests and test registrations in fpdf_view_embeddertest.cpp and fpdf_view_c_api_test.c, and include fpdf_edit.h where needed.
@bobsingor
bobsingor merged commit adc5c20 into embedpdf/feature/read-purityJun 15, 2026
@bobsingor
bobsingor deleted the embedpdf/feature/thread-confined branch August 5, 2026 11:05
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.

1 participant

@bobsingor
, '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

Embedpdf/feature/thread confined - #29

Merged
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined
Jun 15, 2026
Merged

Embedpdf/feature/thread confined#29
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

No description provided.

Introduce optional per-thread PDFium globals to support a thread-confined runtime for server worker pools. Adds core/fxcrt/epdf_tls.h (EPDF_TLS) and converts numerous process-global singletons to be thread-local when embedpdf_thread_local_globals is enabled. Exposes EPDF_InitThread/EPDF_ShutdownThread as lifecycle entry points, makes localtime usage thread-safe, and adjusts RNG/errno/timer/render/color/font/module globals accordingly. Adds a thread-soak test harness (testing/tools:epdf_thread_soak), build/test scripts (scripts/embedpdf-runtime/*), GN flag (embedpdf_thread_local_globals) and a GitHub Actions workflow (pdfium-tsan-thread-soak.yml) to run the TSAN-backed soak. Default behavior remains unchanged (flag off) so builds are byte-for-byte compatible unless explicitly enabled.
Mark the parser's static recursion depth variable as thread-local (EPDF_TLS) in both the header and source. Adds an #include for core/fxcrt/epdf_tls.h. This ensures each thread has its own s_CurrentRecursionDepth to avoid cross-thread interference when parsing concurrently; kParserMaxRecursionDepth is unchanged.
Add two PDF fixtures under testing/resources/pixel to exercise ICC profile parsing: icc_profile_bad_component.pdf embeds an ICCBased color space with N=1 (one component instead of the expected 3) but still triggers DetectSRGB(); icc_profile_bad_value.pdf contains a profile/value (0x80000000) that overflows when multiplied by 255. These files are used by pixel tests to validate robustness and error handling of ICC profile processing.
Add platform-specific defines for gmtime variants in BUILD.gn (HAVE_GMTIME_R on Linux/ChromeOS/Android/mac/iOS, HAVE_GMTIME_S on Windows). Update cmsplugin.c::_cmsGetTime to guard against gmtime returning NULL: copy the result into ptr_time only if non-NULL and return a boolean success value, avoiding a NULL dereference inside the critical section.
Add clarifying comments about concurrency and ThreadSanitizer findings in two lcms sources. In cmsplugin.c note that gmtime()'s shared static result is copied while holding the LCMS mutex to avoid TSan-reported races when creating ICC profiles concurrently. In cmswtpnt.c document that the D50 XYZ constant is safe for concurrent readers and that the xyY value is computed in a thread-confined way to avoid writing to a shared static on each call.
Introduce new EmbedPDF extension APIs to operate on pages by PDF object number. LoadPageByValidatedIndex gains a `normalize` flag to override page rotation to 0 for normalized coordinates, and EPDFDoc_LoadPageByObjectNumberNormalized is exported. Add EPDFDoc_DeletePageByObjectNumber to delete the first visible page matching an indirect object number (with XFA-backed documents rejected), and EPDFDoc_SetPageRotationByObjectNumber to update a page's /Rotate value (validates rotate in 0..3). Update public/fpdfview.h with API docs, add tests and test registrations in fpdf_view_embeddertest.cpp and fpdf_view_c_api_test.c, and include fpdf_edit.h where needed.
@bobsingor
bobsingor merged commit adc5c20 into embedpdf/feature/read-purityJun 15, 2026
@bobsingor
bobsingor deleted the embedpdf/feature/thread-confined branch August 5, 2026 11:05
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.

1 participant

@bobsingor
, '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

Embedpdf/feature/thread confined - #29

Merged
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined
Jun 15, 2026
Merged

Embedpdf/feature/thread confined#29
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

No description provided.

Introduce optional per-thread PDFium globals to support a thread-confined runtime for server worker pools. Adds core/fxcrt/epdf_tls.h (EPDF_TLS) and converts numerous process-global singletons to be thread-local when embedpdf_thread_local_globals is enabled. Exposes EPDF_InitThread/EPDF_ShutdownThread as lifecycle entry points, makes localtime usage thread-safe, and adjusts RNG/errno/timer/render/color/font/module globals accordingly. Adds a thread-soak test harness (testing/tools:epdf_thread_soak), build/test scripts (scripts/embedpdf-runtime/*), GN flag (embedpdf_thread_local_globals) and a GitHub Actions workflow (pdfium-tsan-thread-soak.yml) to run the TSAN-backed soak. Default behavior remains unchanged (flag off) so builds are byte-for-byte compatible unless explicitly enabled.
Mark the parser's static recursion depth variable as thread-local (EPDF_TLS) in both the header and source. Adds an #include for core/fxcrt/epdf_tls.h. This ensures each thread has its own s_CurrentRecursionDepth to avoid cross-thread interference when parsing concurrently; kParserMaxRecursionDepth is unchanged.
Add two PDF fixtures under testing/resources/pixel to exercise ICC profile parsing: icc_profile_bad_component.pdf embeds an ICCBased color space with N=1 (one component instead of the expected 3) but still triggers DetectSRGB(); icc_profile_bad_value.pdf contains a profile/value (0x80000000) that overflows when multiplied by 255. These files are used by pixel tests to validate robustness and error handling of ICC profile processing.
Add platform-specific defines for gmtime variants in BUILD.gn (HAVE_GMTIME_R on Linux/ChromeOS/Android/mac/iOS, HAVE_GMTIME_S on Windows). Update cmsplugin.c::_cmsGetTime to guard against gmtime returning NULL: copy the result into ptr_time only if non-NULL and return a boolean success value, avoiding a NULL dereference inside the critical section.
Add clarifying comments about concurrency and ThreadSanitizer findings in two lcms sources. In cmsplugin.c note that gmtime()'s shared static result is copied while holding the LCMS mutex to avoid TSan-reported races when creating ICC profiles concurrently. In cmswtpnt.c document that the D50 XYZ constant is safe for concurrent readers and that the xyY value is computed in a thread-confined way to avoid writing to a shared static on each call.
Introduce new EmbedPDF extension APIs to operate on pages by PDF object number. LoadPageByValidatedIndex gains a `normalize` flag to override page rotation to 0 for normalized coordinates, and EPDFDoc_LoadPageByObjectNumberNormalized is exported. Add EPDFDoc_DeletePageByObjectNumber to delete the first visible page matching an indirect object number (with XFA-backed documents rejected), and EPDFDoc_SetPageRotationByObjectNumber to update a page's /Rotate value (validates rotate in 0..3). Update public/fpdfview.h with API docs, add tests and test registrations in fpdf_view_embeddertest.cpp and fpdf_view_c_api_test.c, and include fpdf_edit.h where needed.
@bobsingor
bobsingor merged commit adc5c20 into embedpdf/feature/read-purityJun 15, 2026
@bobsingor
bobsingor deleted the embedpdf/feature/thread-confined branch August 5, 2026 11:05
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.

1 participant

@bobsingor
, '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

Embedpdf/feature/thread confined - #29

Merged
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined
Jun 15, 2026
Merged

Embedpdf/feature/thread confined#29
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

No description provided.

Introduce optional per-thread PDFium globals to support a thread-confined runtime for server worker pools. Adds core/fxcrt/epdf_tls.h (EPDF_TLS) and converts numerous process-global singletons to be thread-local when embedpdf_thread_local_globals is enabled. Exposes EPDF_InitThread/EPDF_ShutdownThread as lifecycle entry points, makes localtime usage thread-safe, and adjusts RNG/errno/timer/render/color/font/module globals accordingly. Adds a thread-soak test harness (testing/tools:epdf_thread_soak), build/test scripts (scripts/embedpdf-runtime/*), GN flag (embedpdf_thread_local_globals) and a GitHub Actions workflow (pdfium-tsan-thread-soak.yml) to run the TSAN-backed soak. Default behavior remains unchanged (flag off) so builds are byte-for-byte compatible unless explicitly enabled.
Mark the parser's static recursion depth variable as thread-local (EPDF_TLS) in both the header and source. Adds an #include for core/fxcrt/epdf_tls.h. This ensures each thread has its own s_CurrentRecursionDepth to avoid cross-thread interference when parsing concurrently; kParserMaxRecursionDepth is unchanged.
Add two PDF fixtures under testing/resources/pixel to exercise ICC profile parsing: icc_profile_bad_component.pdf embeds an ICCBased color space with N=1 (one component instead of the expected 3) but still triggers DetectSRGB(); icc_profile_bad_value.pdf contains a profile/value (0x80000000) that overflows when multiplied by 255. These files are used by pixel tests to validate robustness and error handling of ICC profile processing.
Add platform-specific defines for gmtime variants in BUILD.gn (HAVE_GMTIME_R on Linux/ChromeOS/Android/mac/iOS, HAVE_GMTIME_S on Windows). Update cmsplugin.c::_cmsGetTime to guard against gmtime returning NULL: copy the result into ptr_time only if non-NULL and return a boolean success value, avoiding a NULL dereference inside the critical section.
Add clarifying comments about concurrency and ThreadSanitizer findings in two lcms sources. In cmsplugin.c note that gmtime()'s shared static result is copied while holding the LCMS mutex to avoid TSan-reported races when creating ICC profiles concurrently. In cmswtpnt.c document that the D50 XYZ constant is safe for concurrent readers and that the xyY value is computed in a thread-confined way to avoid writing to a shared static on each call.
Introduce new EmbedPDF extension APIs to operate on pages by PDF object number. LoadPageByValidatedIndex gains a `normalize` flag to override page rotation to 0 for normalized coordinates, and EPDFDoc_LoadPageByObjectNumberNormalized is exported. Add EPDFDoc_DeletePageByObjectNumber to delete the first visible page matching an indirect object number (with XFA-backed documents rejected), and EPDFDoc_SetPageRotationByObjectNumber to update a page's /Rotate value (validates rotate in 0..3). Update public/fpdfview.h with API docs, add tests and test registrations in fpdf_view_embeddertest.cpp and fpdf_view_c_api_test.c, and include fpdf_edit.h where needed.
@bobsingor
bobsingor merged commit adc5c20 into embedpdf/feature/read-purityJun 15, 2026
@bobsingor
bobsingor deleted the embedpdf/feature/thread-confined branch August 5, 2026 11:05
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.

1 participant

@bobsingor
, '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

Embedpdf/feature/thread confined - #29

Merged
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined
Jun 15, 2026
Merged

Embedpdf/feature/thread confined#29
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

No description provided.

Introduce optional per-thread PDFium globals to support a thread-confined runtime for server worker pools. Adds core/fxcrt/epdf_tls.h (EPDF_TLS) and converts numerous process-global singletons to be thread-local when embedpdf_thread_local_globals is enabled. Exposes EPDF_InitThread/EPDF_ShutdownThread as lifecycle entry points, makes localtime usage thread-safe, and adjusts RNG/errno/timer/render/color/font/module globals accordingly. Adds a thread-soak test harness (testing/tools:epdf_thread_soak), build/test scripts (scripts/embedpdf-runtime/*), GN flag (embedpdf_thread_local_globals) and a GitHub Actions workflow (pdfium-tsan-thread-soak.yml) to run the TSAN-backed soak. Default behavior remains unchanged (flag off) so builds are byte-for-byte compatible unless explicitly enabled.
Mark the parser's static recursion depth variable as thread-local (EPDF_TLS) in both the header and source. Adds an #include for core/fxcrt/epdf_tls.h. This ensures each thread has its own s_CurrentRecursionDepth to avoid cross-thread interference when parsing concurrently; kParserMaxRecursionDepth is unchanged.
Add two PDF fixtures under testing/resources/pixel to exercise ICC profile parsing: icc_profile_bad_component.pdf embeds an ICCBased color space with N=1 (one component instead of the expected 3) but still triggers DetectSRGB(); icc_profile_bad_value.pdf contains a profile/value (0x80000000) that overflows when multiplied by 255. These files are used by pixel tests to validate robustness and error handling of ICC profile processing.
Add platform-specific defines for gmtime variants in BUILD.gn (HAVE_GMTIME_R on Linux/ChromeOS/Android/mac/iOS, HAVE_GMTIME_S on Windows). Update cmsplugin.c::_cmsGetTime to guard against gmtime returning NULL: copy the result into ptr_time only if non-NULL and return a boolean success value, avoiding a NULL dereference inside the critical section.
Add clarifying comments about concurrency and ThreadSanitizer findings in two lcms sources. In cmsplugin.c note that gmtime()'s shared static result is copied while holding the LCMS mutex to avoid TSan-reported races when creating ICC profiles concurrently. In cmswtpnt.c document that the D50 XYZ constant is safe for concurrent readers and that the xyY value is computed in a thread-confined way to avoid writing to a shared static on each call.
Introduce new EmbedPDF extension APIs to operate on pages by PDF object number. LoadPageByValidatedIndex gains a `normalize` flag to override page rotation to 0 for normalized coordinates, and EPDFDoc_LoadPageByObjectNumberNormalized is exported. Add EPDFDoc_DeletePageByObjectNumber to delete the first visible page matching an indirect object number (with XFA-backed documents rejected), and EPDFDoc_SetPageRotationByObjectNumber to update a page's /Rotate value (validates rotate in 0..3). Update public/fpdfview.h with API docs, add tests and test registrations in fpdf_view_embeddertest.cpp and fpdf_view_c_api_test.c, and include fpdf_edit.h where needed.
@bobsingor
bobsingor merged commit adc5c20 into embedpdf/feature/read-purityJun 15, 2026
@bobsingor
bobsingor deleted the embedpdf/feature/thread-confined branch August 5, 2026 11:05
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.

1 participant

@bobsingor
, '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

Embedpdf/feature/thread confined - #29

Merged
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined
Jun 15, 2026
Merged

Embedpdf/feature/thread confined#29
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

No description provided.

Introduce optional per-thread PDFium globals to support a thread-confined runtime for server worker pools. Adds core/fxcrt/epdf_tls.h (EPDF_TLS) and converts numerous process-global singletons to be thread-local when embedpdf_thread_local_globals is enabled. Exposes EPDF_InitThread/EPDF_ShutdownThread as lifecycle entry points, makes localtime usage thread-safe, and adjusts RNG/errno/timer/render/color/font/module globals accordingly. Adds a thread-soak test harness (testing/tools:epdf_thread_soak), build/test scripts (scripts/embedpdf-runtime/*), GN flag (embedpdf_thread_local_globals) and a GitHub Actions workflow (pdfium-tsan-thread-soak.yml) to run the TSAN-backed soak. Default behavior remains unchanged (flag off) so builds are byte-for-byte compatible unless explicitly enabled.
Mark the parser's static recursion depth variable as thread-local (EPDF_TLS) in both the header and source. Adds an #include for core/fxcrt/epdf_tls.h. This ensures each thread has its own s_CurrentRecursionDepth to avoid cross-thread interference when parsing concurrently; kParserMaxRecursionDepth is unchanged.
Add two PDF fixtures under testing/resources/pixel to exercise ICC profile parsing: icc_profile_bad_component.pdf embeds an ICCBased color space with N=1 (one component instead of the expected 3) but still triggers DetectSRGB(); icc_profile_bad_value.pdf contains a profile/value (0x80000000) that overflows when multiplied by 255. These files are used by pixel tests to validate robustness and error handling of ICC profile processing.
Add platform-specific defines for gmtime variants in BUILD.gn (HAVE_GMTIME_R on Linux/ChromeOS/Android/mac/iOS, HAVE_GMTIME_S on Windows). Update cmsplugin.c::_cmsGetTime to guard against gmtime returning NULL: copy the result into ptr_time only if non-NULL and return a boolean success value, avoiding a NULL dereference inside the critical section.
Add clarifying comments about concurrency and ThreadSanitizer findings in two lcms sources. In cmsplugin.c note that gmtime()'s shared static result is copied while holding the LCMS mutex to avoid TSan-reported races when creating ICC profiles concurrently. In cmswtpnt.c document that the D50 XYZ constant is safe for concurrent readers and that the xyY value is computed in a thread-confined way to avoid writing to a shared static on each call.
Introduce new EmbedPDF extension APIs to operate on pages by PDF object number. LoadPageByValidatedIndex gains a `normalize` flag to override page rotation to 0 for normalized coordinates, and EPDFDoc_LoadPageByObjectNumberNormalized is exported. Add EPDFDoc_DeletePageByObjectNumber to delete the first visible page matching an indirect object number (with XFA-backed documents rejected), and EPDFDoc_SetPageRotationByObjectNumber to update a page's /Rotate value (validates rotate in 0..3). Update public/fpdfview.h with API docs, add tests and test registrations in fpdf_view_embeddertest.cpp and fpdf_view_c_api_test.c, and include fpdf_edit.h where needed.
@bobsingor
bobsingor merged commit adc5c20 into embedpdf/feature/read-purityJun 15, 2026
@bobsingor
bobsingor deleted the embedpdf/feature/thread-confined branch August 5, 2026 11:05
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.

1 participant

@bobsingor
, '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

Embedpdf/feature/thread confined - #29

Merged
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined
Jun 15, 2026
Merged

Embedpdf/feature/thread confined#29
bobsingor merged 7 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/thread-confined

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

No description provided.

Introduce optional per-thread PDFium globals to support a thread-confined runtime for server worker pools. Adds core/fxcrt/epdf_tls.h (EPDF_TLS) and converts numerous process-global singletons to be thread-local when embedpdf_thread_local_globals is enabled. Exposes EPDF_InitThread/EPDF_ShutdownThread as lifecycle entry points, makes localtime usage thread-safe, and adjusts RNG/errno/timer/render/color/font/module globals accordingly. Adds a thread-soak test harness (testing/tools:epdf_thread_soak), build/test scripts (scripts/embedpdf-runtime/*), GN flag (embedpdf_thread_local_globals) and a GitHub Actions workflow (pdfium-tsan-thread-soak.yml) to run the TSAN-backed soak. Default behavior remains unchanged (flag off) so builds are byte-for-byte compatible unless explicitly enabled.
Mark the parser's static recursion depth variable as thread-local (EPDF_TLS) in both the header and source. Adds an #include for core/fxcrt/epdf_tls.h. This ensures each thread has its own s_CurrentRecursionDepth to avoid cross-thread interference when parsing concurrently; kParserMaxRecursionDepth is unchanged.
Add two PDF fixtures under testing/resources/pixel to exercise ICC profile parsing: icc_profile_bad_component.pdf embeds an ICCBased color space with N=1 (one component instead of the expected 3) but still triggers DetectSRGB(); icc_profile_bad_value.pdf contains a profile/value (0x80000000) that overflows when multiplied by 255. These files are used by pixel tests to validate robustness and error handling of ICC profile processing.
Add platform-specific defines for gmtime variants in BUILD.gn (HAVE_GMTIME_R on Linux/ChromeOS/Android/mac/iOS, HAVE_GMTIME_S on Windows). Update cmsplugin.c::_cmsGetTime to guard against gmtime returning NULL: copy the result into ptr_time only if non-NULL and return a boolean success value, avoiding a NULL dereference inside the critical section.
Add clarifying comments about concurrency and ThreadSanitizer findings in two lcms sources. In cmsplugin.c note that gmtime()'s shared static result is copied while holding the LCMS mutex to avoid TSan-reported races when creating ICC profiles concurrently. In cmswtpnt.c document that the D50 XYZ constant is safe for concurrent readers and that the xyY value is computed in a thread-confined way to avoid writing to a shared static on each call.
Introduce new EmbedPDF extension APIs to operate on pages by PDF object number. LoadPageByValidatedIndex gains a `normalize` flag to override page rotation to 0 for normalized coordinates, and EPDFDoc_LoadPageByObjectNumberNormalized is exported. Add EPDFDoc_DeletePageByObjectNumber to delete the first visible page matching an indirect object number (with XFA-backed documents rejected), and EPDFDoc_SetPageRotationByObjectNumber to update a page's /Rotate value (validates rotate in 0..3). Update public/fpdfview.h with API docs, add tests and test registrations in fpdf_view_embeddertest.cpp and fpdf_view_c_api_test.c, and include fpdf_edit.h where needed.
@bobsingor
bobsingor merged commit adc5c20 into embedpdf/feature/read-purityJun 15, 2026
@bobsingor
bobsingor deleted the embedpdf/feature/thread-confined branch August 5, 2026 11:05
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.

1 participant

@bobsingor