Rather than wiring up the never-called dispose(), remove it entirely.
The method was defined but never invoked for 6+ years, is not documented
in the custom input bindings article, and unsubscribe() already serves
as the teardown hook.
InputBinding.dispose() was defined but never called. Now invoked
after unsubscribe and the shiny:unbound event in unbindInputs().
Also fixes the comment that incorrectly said "output" instead of "input".
* Use ResizeObserver/IntersectionObserver for per-output resize handling
Replace the old window-resize + Bootstrap event listener approach with
per-output ResizeObserver, IntersectionObserver, and MutationObserver.
Each bound output now gets its own observers that handle resize,
visibility, and theme changes independently, rather than relying on
global window resize events and jQuery Bootstrap hooks.
Also renames sendImageSize -> sendOutputInfo, simplifies bind.ts by
removing sendOutputHiddenState/maybeAddThemeObserver from BindInputsCtx,
and makes ImageOutputBinding.resize() actually set width/height on the
img element.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix observer cleanup, zoom-aware sizing, and edge cases in resize handling
- Disconnect ResizeObserver/IntersectionObserver/MutationObserver on unbind
to prevent callbacks firing on stale elements
- Restore getBoundingClientSizeBeforeZoom for size reporting to fix CSS zoom
regression (see #4135)
- Guard doTriggerResize against missing binding during teardown races
- Fix visibleOutputs set to properly remove hidden outputs
- Hoist observer setup out of doSendOutputInfo loop to avoid re-allocating
closures on every call
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix pending output observer callbacks after unbind
* Flush pending output info before input send
* test and restore theme refresh for output observers
* fix: avoid theme mutation observers for non-theme outputs
* Replace custom isHidden() with native el.checkVisibility()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Simplify observer setup: inline outputInfoObserver, consolidate cleanup, guard null IDs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Revert image resize width/height attr setting
The resize() method only needs to trigger the jQuery resize event for
brush re-projection. Setting width/height attrs on the <img> just
briefly stretched the stale plot before the server re-render replaced
it, with no meaningful effect on behavior.
* Restore image resize() to match main exactly
The previous commit over-scoped the revert by changing the method
signature. This restores the original signature from main.
* Remove review doc
* Skip doTriggerResize() during initial output info send
* Add isVisible() fallback for browsers without checkVisibility()
* `npm run build` (GitHub Actions)
* Update NEWS.md
* Remove unnecessary type cast in debounce cancel test
The debounce() function already returns DebouncedFunction with a
required `cancel` property. The cast to an optional `cancel` weakened
type checking.
* Defer sendOutputInfoFns.regular lookup to execution time
Wrap setTimeout callbacks with arrow functions so regular is resolved
at call time rather than captured when it may still be undefined.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
* Increment version number to 1.13.0.9000
* `npm run build` (GitHub Actions)
* Sync package version (GitHub Actions)
---------
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
* test: add failing tests for render* stack trace fence coverage
Add tests for renderPlot, renderPrint, renderText, renderUI,
renderTable, and renderImage verifying that internal rendering
pipeline frames are hidden by stack trace fences.
All 6 tests fail, revealing that:
- All render functions leak `renderFunc` through the fences
- renderPlot additionally leaks `drawPlot`, `drawReactive`
- renderPrint additionally leaks `with_promise_domain`
Relates to #4357
* refactor: move stack trace test helpers to helper-stacks.R
Move extractStackTrace, cleanLocs, dumpTests, and
captureFilteredRenderTrace into helper-stacks.R so they are
available to all test files. Rename causeRenderError to
captureFilteredRenderTrace.
* fix: add stack trace fences to hide internal render pipeline frames
Add ..stacktraceoff../..stacktraceon.. fence pairs so that internal
rendering pipeline frames (renderFunc, hybrid_chain, drawPlot, etc.)
are hidden from filtered stack traces in the debugger.
- markRenderFunction: wrap renderFunc() call with ..stacktraceoff..
- createRenderFunction: wrap func() with ..stacktraceon.. to restore
visibility for user code
- renderPrint: wrap func() with ..stacktraceon.. inside promise domain
For renderPlot, the existing ..stacktraceon from installExprFunction
is sufficient once the outer ..stacktraceoff.. is in place.
Fixes#4357
* fix: Legacy datatable stack traces
* chore: Add news bullet
* chore: Just normalize path in the place that needs it
* chore: don't normalize file path
* fix: Handle srcfilealias in stack traces and telemetry
Following commit 272dda27e, which normalized paths only in the #line
directive, sourceUTF8() now creates srcfilealias objects for user code.
This broke code that assumed only package code had srcfile$original.
## How the new approach works
When sourceUTF8() wraps code with a #line directive:
```r
file <- 'app.R' # Keep original path (relative/symlink/as-typed)
lines <- c(
'..stacktraceon..({',
sprintf('#line 1 "%s"', normalizePath(file, ...)), # Normalize HERE
readLines(file),
'})'
)
src <- srcfilecopy(file, lines, isFile = TRUE) # Uses original path
expr <- parse(text = lines, srcfile = src)
```
The parser sees the #line path differs from srcfilecopy's path, so it
creates a srcfilealias with:
- srcfile$filename = absolute path (from #line, for source refs)
- srcfile$original$filename = original path (from srcfilecopy)
This gives us both: accurate source references + user-friendly paths.
## Changes made
1. Add getSrcfileFilename() helper
- Prefers $original$filename (user-typed path) when available
- Falls back to $filename (absolute) for old-style srcfile objects
- Ensures stack traces show "app.R#10" not "/abs/path/app.R#10"
2. Add isPackageFile() helper
- Checks if absolute path is under .libPaths()
- More reliable than checking for $original presence
3. Fix getCallCategories()
- Now uses isPackageFile() instead of checking $original
- User code properly categorized as "user" (bold blue in traces)
- Package code properly categorized as "pkg" (de-emphasized)
4. Update getLocs() and otel_srcref_attributes()
- Use getSrcfileFilename() to show user-friendly paths
## Benefits
- Stack traces preserve relative paths and symlinks as users typed them
- User vs package code still correctly distinguished
- Better IDE integration (paths match what user entered)
- Telemetry contains meaningful file paths
* fix: Avoid using startsWith()
* fix: Use reverse clamped cumsum for stack trace fence filtering
Replace the forward cumulative sum in stripStackTraces() with a reverse
clamped cumulative sum so that an unmatched `..stacktraceoff..` (one
with no corresponding inner `..stacktraceon..`) is a no-op. This fixes
a regression where markRenderFunction-only callers (e.g. htmlwidgets)
had their user frames hidden when called outside a reactive domain.
The new algorithm concatenates all trace segments into a single vector,
performs vectorized fence scoring, and computes visibility via the
identity: clamped_cumsum = cumsum - pmin(0, cummin(cumsum)).
Fixes#4357
* refactor: Extract skip_if_shiny_otel_tracer_is_enabled() helper
* fix: Handle srcfilealias in reactive auto-labeling
The normalizePath() in sourceUTF8() causes R to create srcfilealias
objects whose $lines is NULL, breaking rassignSrcrefToLabel() and
rexprSrcrefToLabel(). Add getSrcfileLines() helper (alongside
getSrcfileFilename()) to resolve lines from the original srcfilecopy
using srcref[7] for the correct line number.
* fix: Enforce path-boundary check in isPackageFile()
The prefix-only matching in isPackageFile() could misclassify paths
like "/usr/lib/Rcpp/..." as inside "/usr/lib/R". Normalize library
paths with a trailing slash before comparison to ensure proper
path-boundary matching.
* fix: Prefer original filename only for non-package srcfilealias
When a package is installed with keep.source.pkgs = TRUE, the
srcfilecopy original filename may point to a collated build-time path.
For package files (under .libPaths()), keep srcfile$filename to avoid
regressing stack traces and telemetry with install-time paths.
* Update R/conditions.R
---------
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
* chore: avoid testing elapsed time on CRAN
* chore: update tabPanel snapshot for disabled attribute on empty tabs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Change license from GPL-3 to MIT
Updated the project license from GPL-3 to MIT in DESCRIPTION, LICENSE, LICENSE.md, README.md, and package.json. Added LICENSE.md with the MIT license text and updated .Rbuildignore to exclude LICENSE.md from builds.
* `npm run build` (GitHub Actions)
* Update LICENSE and add LICENSE.note
Replaced the LICENSE file content with a summary including year and copyright holder. Moved detailed third-party license information to a new LICENSE.note file.
* Remove R check log file
Deleted the ..Rcheck/00check.log file, likely to clean up generated or temporary files from the repository.
* fix: supply and retain default selectize.js plugins (for py-shiny)
* `npm run build` (GitHub Actions)
* Move more in a 'remove_button' attribute direction
* `npm run build` (GitHub Actions)
* Move to a JSON-only approach
* `npm run build` (GitHub Actions)
* Drop sticky update logic by always sending 'missing' value and resolving client-side
* Cleanup
* Don't mutate options; better typing pattern
* `npm run build` (GitHub Actions)
---------
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
* Revert changes in 8861645d99 from #4252
We compile from R sass. So we should be partial to R's compiler, no the latest in npm
* Restore original compile script (with message) that built using R-sass, not npm
* Add step in build command to update the sass output
* run new command