Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions scripts/define-shims.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Since HTMLDependency()s are designed to be loaded via a <script> tag, we do our best
// to avoid anonymous define() calls (which will error out in a script tag)
// https://requirejs.org/docs/errors.html#mismatch
const oldDefine = window.define;
window.define = function define(name, deps, callback) {
if (typeof name !== "string") {
callback = deps;
deps = name;
const script = document.currentScript;
if (script) {
name = script.getAttribute("data-requiremodule");
if (name) {
console.info(
`Changing an anonymous define() call to named define() using '${name}'`
);
}
}
}
return oldDefine.apply(this, [name, deps, callback]);
};
for (var prop in oldDefine) {
if (oldDefine.hasOwnProperty(prop)) {
window.define[prop] = oldDefine[prop];
}
}

// By default, we want UMD loaders to attach themselves to the window. This seems like
// better/safer default behavior since, the alternative is to have any UMD loader to
// fail if loaded via a <script> tag. If dependencies actually do want to be
// define()/require(), they can opt
window.define.amd = false;

// In case someone want to restore the old define() function
window.define.noConflict = function() {
window.define = oldDefine;
return this;
};

// Users can still encounter this anonymous define() error, and we've actually
// encountered this in shiny-server-client.js because we were inlining an internal
// dependency that contained an anonymous define()
// https://github.com/rstudio/shiny-server-client/blob/5ee5aac/dist/shiny-server-client.js#L4271-L4272).
// In this case, it doesn't seem like there is anything we can do to help the situation
// other than to add some more context to the error.
const oldOnError = window.requirejs.onError;
window.requirejs.onError = function(err) {
if (err.message.includes('Mismatched anonymous define()')) {
err.message = err.message + '\n\nTo avoid this error, consider either: (1) adding a data-requiremodule attribute (with the module name) to the <script> tag containing the anonymous define(), (2) setting define.amd=false, or (3) removing the anonymous define() altogether.';
}

return oldOnError.apply(this, [err]);
}
16 changes: 16 additions & 0 deletions scripts/htmlDependencies.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,19 @@ withr::with_options(
# we still do have bs3compat's CSS on the page, which
# comes in via the bootstrap HTMLDependency()
unlink("shiny/www/shared/bs3compat/", recursive = TRUE)

requirejs <- file.path(www, "shared", "requirejs")
dir.create(requirejs)
download.file(
"https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js",
file.path(requirejs, "require.min.js")
)

shims <- file.path(getwd(), "scripts", "define-shims.js")

cat(
"\n\n",
paste(readLines(shims), collapse = "\n"),
file = file.path(requirejs, "require.min.js"),
append = TRUE
)
6 changes: 4 additions & 2 deletions shiny/_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from ._autoreload import autoreload_url, InjectAutoreloadMiddleware
from ._connection import Connection, StarletteConnection
from .html_dependencies import jquery_deps, shiny_deps
from .html_dependencies import require_deps, jquery_deps, shiny_deps
from .http_staticfiles import StaticFiles
from .reactive import on_flushed
from .session import Inputs, Outputs, Session, session_context
Expand Down Expand Up @@ -327,5 +327,7 @@ def _register_web_dependency(self, dep: HTMLDependency) -> None:

def _render_page(ui: Union[Tag, TagList], lib_prefix: str) -> RenderedHTML:
ui_res = copy.copy(ui)
ui_res.insert(0, [jquery_deps(), shiny_deps()])
# Make sure requirejs, jQuery, and Shiny come before any other dependencies.
# (see require_deps() for a comment about why we even include it)
ui_res.insert(0, [require_deps(), jquery_deps(), shiny_deps()])
return HTMLDocument(ui_res).render(lib_prefix=lib_prefix)
19 changes: 19 additions & 0 deletions shiny/html_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,22 @@ def jquery_deps() -> HTMLDependency:
source={"package": "shiny", "subdir": "www/shared/jquery/"},
script={"src": "jquery-3.6.0.min.js"},
)


# Shiny doesn't (currently) use requirejs directly, but it does include it because a
# custom requirejs setup is need to get HTMLDependency()s (i.e., loading JS via <script>
# tags) to be usable. At the moment, we're just setting `window.define.amd=false` after
# loading requirejs so that the typical UMD pattern won't result in an anonymous
# define() error.
# https://requirejs.org/docs/errors.html#mismatch
# https://github.com/umdjs/umd
#
# Someday, we may want the same/similar thing in R, but this definitely more of an
# immediate issue for Python since many Jupyter extensions use requirejs.
def require_deps() -> HTMLDependency:
return HTMLDependency(
name="requirejs",
version="2.3.6",
source={"package": "shiny", "subdir": "www/shared/requirejs/"},
script={"src": "require.min.js"},
)
3 changes: 1 addition & 2 deletions shiny/ui/_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
h2,
css,
span,
HTML,
)

from .._docstring import add_example
Expand Down Expand Up @@ -449,7 +448,7 @@ def panel_absolute(
divTag.add_class("draggable")
deps = jqui_deps()
deps.stylesheet = []
return TagList(deps, divTag, tags.script(HTML('$(".draggable").draggable();')))
return TagList(deps, divTag, tags.script('$(".draggable").draggable();'))


def help_text(*args: TagChildArg, **kwargs: TagAttrArg) -> Tag:
Expand Down
4 changes: 2 additions & 2 deletions shiny/www/shared/bootstrap/bootstrap.bundle.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion shiny/www/shared/bootstrap/bootstrap.bundle.min.js.map

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion shiny/www/shared/bootstrap/bootstrap.min.css

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions shiny/www/shared/requirejs/require.min.js

Large diffs are not rendered by default.