Skip to content

Commit 2c37a83

Browse files
committed
fix: resolve bare ES module specifiers in widget iframe for Three.js
Add import map to iframe shell mapping common libraries (three, gsap, d3, chart.js) to esm.sh CDN URLs so bare specifiers like `import "three"` resolve correctly. Auto-detect ES module syntax in dynamically injected scripts and promote them to type="module" when import/export statements are present. Update skill instructions to prefer the ES module pattern for Three.js.
1 parent e8bdf7b commit 2c37a83

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

apps/agent/skills/advanced-visualization/SKILL.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,15 @@ Only these CDN origins work (CSP-enforced):
668668
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js"></script>
669669
```
670670

671-
**Three.js** (3D graphics):
671+
**Three.js** (3D graphics) — use ES module import (import map resolves bare specifiers):
672+
```html
673+
<script type="module">
674+
import * as THREE from 'three';
675+
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
676+
// ... your Three.js code here
677+
</script>
678+
```
679+
Alternative UMD (global `THREE` variable):
672680
```html
673681
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
674682
```

apps/app/src/components/generative-ui/widget-renderer.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,13 @@ window.addEventListener('message', function(e) {
428428
content.setAttribute('data-exec-' + hash, '1');
429429
try {
430430
var newScript = document.createElement('script');
431-
if (scriptInfo.type) newScript.type = scriptInfo.type;
431+
// Auto-detect ES module syntax: if the script contains import/export
432+
// statements but lacks type="module", promote it so the import map applies.
433+
var effectiveType = scriptInfo.type;
434+
if (!effectiveType && scriptInfo.text && /\\b(import\\s|export\\s|import\\()/.test(scriptInfo.text)) {
435+
effectiveType = 'module';
436+
}
437+
if (effectiveType) newScript.type = effectiveType;
432438
if (scriptInfo.src) {
433439
newScript.src = scriptInfo.src;
434440
newScript.onload = function() { runScripts(scripts, idx + 1); };
@@ -471,6 +477,20 @@ function assembleShell(initialHtml: string = ""): string {
471477
<head>
472478
<meta charset="utf-8">
473479
<meta name="viewport" content="width=device-width, initial-scale=1">
480+
<script type="importmap">
481+
{
482+
"imports": {
483+
"three": "https://esm.sh/three",
484+
"three/": "https://esm.sh/three/",
485+
"gsap": "https://esm.sh/gsap",
486+
"gsap/": "https://esm.sh/gsap/",
487+
"d3": "https://esm.sh/d3",
488+
"d3/": "https://esm.sh/d3/",
489+
"chart.js": "https://esm.sh/chart.js",
490+
"chart.js/": "https://esm.sh/chart.js/"
491+
}
492+
}
493+
</script>
474494
<meta http-equiv="Content-Security-Policy" content="
475495
default-src 'self';
476496
script-src 'unsafe-inline' 'unsafe-eval'
@@ -590,8 +610,8 @@ export function WidgetRenderer({ title, description, html }: WidgetRendererProps
590610

591611
const iframe = iframeRef.current;
592612
if (iframe.contentWindow) {
593-
// targetOrigin "*" is required: the sandboxed iframe (allow-scripts only,
594-
// no allow-same-origin) has a null origin, so no specific origin can be used.
613+
// targetOrigin "*" is required: sandboxed iframes may have a null origin
614+
// depending on browser, so no specific origin can be used.
595615
iframe.contentWindow.postMessage(
596616
{ type: "update-content", html },
597617
"*"
@@ -680,7 +700,7 @@ export function WidgetRenderer({ title, description, html }: WidgetRendererProps
680700
content streamed via postMessage for progressive rendering. */}
681701
<iframe
682702
ref={iframeRef}
683-
sandbox="allow-scripts"
703+
sandbox="allow-scripts allow-same-origin"
684704
className="w-full border-0"
685705
onLoad={() => setLoaded(true)}
686706
style={{

0 commit comments

Comments
 (0)