Skip to content

Commit 3330f11

Browse files
authored
feat(sandbox): Support for filtering scripts (#671)
1 parent a09cde7 commit 3330f11

File tree

13 files changed

+5095
-1141
lines changed

13 files changed

+5095
-1141
lines changed

dev/app-main/src/constant.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ export const localApps: AppInfo = [
2626
name: 'react16',
2727
activeWhen: '/react16',
2828
entry: getProxyHost('dev/react16'),
29+
sandbox: {
30+
excludeAssetFilter: (url: string) => {
31+
return url.includes('exclude');
32+
},
33+
},
2934
},
3035
{
3136
name: 'react18',
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
window.dynamic2 = 1;

dev/app-react-16/public/exclude.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
window.dynamic = 1;

dev/app-react-16/public/index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
<head>
44
<meta charset="UTF-8">
55
<title>app react v17</title>
6+
<script src="/exclude.js" ></script>
7+
<script>
8+
const script = document.createElement('script');
9+
script.src = "/exclude-dynamic.js";
10+
document.body.appendChild(script);
11+
</script>
612
</head>
713
<body>
814
<div id="root"></div>

packages/browser-vm/src/dynamicNode/processor.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,11 @@ export class DynamicNodeProcessor {
150150
const isModule = type === 'module';
151151
const code = this.el.textContent || this.el.text || '';
152152

153-
if (!type || isJsType({ src, type })) {
153+
// Returning true indicates that execution in the sandbox is not required
154+
const excludeAssetFilter = this.sandbox.options.excludeAssetFilter;
155+
const excludeUrl = excludeAssetFilter?.(src);
156+
157+
if ((!type || isJsType({ src, type })) && !excludeUrl) {
154158
// The "src" higher priority
155159
const { baseUrl, namespace } = this.sandbox.options;
156160
if (src) {

packages/browser-vm/src/pluginify.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ declare module '@garfish/core' {
2222
}
2323

2424
export interface AppInfo {
25+
excludeAssetFilter?: (url: string) => boolean;
2526
protectVariable?: PropertyKey[];
2627
insulationVariable?: PropertyKey[];
2728
}
@@ -134,6 +135,7 @@ function createOptions(Garfish: interfaces.Garfish) {
134135
disableWith: Boolean(appInfo.sandbox?.disableWith),
135136
disableElementtiming: Boolean(appInfo.sandbox?.disableElementtiming),
136137
strictIsolation: Boolean(appInfo.sandbox?.strictIsolation),
138+
excludeAssetFilter: appInfo.sandbox?.excludeAssetFilter,
137139
// 缓存模式,不收集副作用
138140
disableCollect:
139141
appInfo.cache === undefined ? true : Boolean(appInfo.cache),

packages/browser-vm/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export interface SandboxOptions {
2929
disableElementtiming?: boolean;
3030
disableCollect?: boolean;
3131
modules?: Array<Module>;
32+
excludeAssetFilter?: (url: string) => boolean;
3233
addSourceList?: (
3334
sourceInfo:
3435
| Array<{ tagName: string; url: string | URL | Request }>

packages/core/src/interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export namespace interfaces {
8282
strictIsolation?: boolean;
8383
disableElementtiming?: boolean;
8484
fixOwnerDocument?: boolean;
85+
excludeAssetFilter?: (url: string) => boolean;
8586
}
8687

8788
export interface Config {

packages/core/src/module/app.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,19 @@ export class App {
689689
return DOMApis.createElement(node);
690690
}
691691
}
692+
693+
// Filter out code that does not require sandboxed execution
694+
if (this.appInfo.sandbox) {
695+
const scriptUrl = entryManager.findAttributeValue(node, 'src');
696+
if (
697+
scriptUrl &&
698+
this.appInfo.sandbox?.excludeAssetFilter &&
699+
this.appInfo.sandbox?.excludeAssetFilter(scriptUrl)
700+
) {
701+
return DOMApis.createElement(node);
702+
}
703+
}
704+
692705
const jsManager = resources.js.find((manager) => {
693706
return !manager.async ? manager.isSameOrigin(node) : false;
694707
});

packages/core/src/module/resource.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,35 @@ import type {
55
TemplateManager,
66
JavaScriptManager,
77
} from '@garfish/loader';
8-
import { AppInfo } from './app';
8+
import type { AppInfo } from './app';
9+
import type { interfaces } from '../interface';
910

1011
// Fetch `script`, `link` and `module meta` elements
1112
function fetchStaticResources(
1213
appName: string,
1314
loader: Loader,
1415
entryManager: TemplateManager,
16+
sandboxConfig: false | interfaces.SandboxConfig | undefined,
1517
) {
1618
const toBoolean = (val) => typeof val !== 'undefined' && val !== 'false';
1719

1820
// Get all script elements
1921
const jsNodes = Promise.all(
2022
entryManager
2123
.findAllJsNodes()
24+
.filter((node) => {
25+
if (sandboxConfig && sandboxConfig.excludeAssetFilter) {
26+
const src = entryManager.findAttributeValue(node, 'src');
27+
if (src && sandboxConfig.excludeAssetFilter(src)) {
28+
return false;
29+
}
30+
}
31+
return true;
32+
})
2233
.map((node) => {
2334
const src = entryManager.findAttributeValue(node, 'src');
2435
const type = entryManager.findAttributeValue(node, 'type');
25-
let crossOrigin = entryManager.findAttributeValue(
26-
node,
27-
'crossorigin',
28-
);
36+
let crossOrigin = entryManager.findAttributeValue(node, 'crossorigin');
2937
if (crossOrigin === '') {
3038
crossOrigin = 'anonymous';
3139
}
@@ -150,6 +158,7 @@ export async function processAppResources(loader: Loader, appInfo: AppInfo) {
150158
appInfo.name,
151159
loader,
152160
entryManager,
161+
appInfo.sandbox,
153162
);
154163
resources.js = js;
155164
resources.link = link;

0 commit comments

Comments
 (0)