diff --git a/dev/app-main/src/constant.ts b/dev/app-main/src/constant.ts
index 1aabd8753..87a4e0c85 100644
--- a/dev/app-main/src/constant.ts
+++ b/dev/app-main/src/constant.ts
@@ -27,6 +27,11 @@ export const localApps: AppInfo = [
name: 'react16',
activeWhen: '/react16',
entry: getProxyHost('dev/react16'),
+ sandbox: {
+ excludeAssetFilter: (url: string) => {
+ return url.includes('exclude');
+ },
+ },
},
{
name: 'react18',
diff --git a/dev/app-react-16/public/exclude-dynamic.js b/dev/app-react-16/public/exclude-dynamic.js
new file mode 100644
index 000000000..236af5ed2
--- /dev/null
+++ b/dev/app-react-16/public/exclude-dynamic.js
@@ -0,0 +1 @@
+window.dynamic2 = 1;
diff --git a/dev/app-react-16/public/exclude.js b/dev/app-react-16/public/exclude.js
new file mode 100644
index 000000000..bb618ed09
--- /dev/null
+++ b/dev/app-react-16/public/exclude.js
@@ -0,0 +1 @@
+window.dynamic = 1;
diff --git a/dev/app-react-16/public/index.html b/dev/app-react-16/public/index.html
index 0bb206616..0966b904b 100644
--- a/dev/app-react-16/public/index.html
+++ b/dev/app-react-16/public/index.html
@@ -3,6 +3,12 @@
app react v17
+
+
diff --git a/package.json b/package.json
index 4de0a8bbc..4133f7f3f 100644
--- a/package.json
+++ b/package.json
@@ -93,7 +93,7 @@
"workspace-tools": "0.16.2",
"zx": "4.2.0"
},
- "version": "1.17.6",
+ "version": "1.18.0",
"packageManager": "pnpm@7.6.0",
"engines": {
"node": ">=16.14.0"
diff --git a/packages/bridge-react-v18/package.json b/packages/bridge-react-v18/package.json
index d9fc0c8da..7a82154e1 100644
--- a/packages/bridge-react-v18/package.json
+++ b/packages/bridge-react-v18/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/bridge-react-v18",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "garfish module.",
"keywords": [
"garfish",
diff --git a/packages/bridge-react/package.json b/packages/bridge-react/package.json
index 5f5b5665d..bdd77c057 100644
--- a/packages/bridge-react/package.json
+++ b/packages/bridge-react/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/bridge-react",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "garfish module.",
"keywords": [
"garfish",
diff --git a/packages/bridge-vue-v2/package.json b/packages/bridge-vue-v2/package.json
index 868f8b733..2308cf1b2 100644
--- a/packages/bridge-vue-v2/package.json
+++ b/packages/bridge-vue-v2/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/bridge-vue-v2",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "garfish vue bridge for v2.",
"keywords": [
"garfish",
diff --git a/packages/bridge-vue-v3/package.json b/packages/bridge-vue-v3/package.json
index ec485895c..dbde61163 100644
--- a/packages/bridge-vue-v3/package.json
+++ b/packages/bridge-vue-v3/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/bridge-vue-v3",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "garfish vue bridge for v3.",
"keywords": [
"garfish",
diff --git a/packages/browser-snapshot/package.json b/packages/browser-snapshot/package.json
index e47d7261f..f8e5ac3f8 100644
--- a/packages/browser-snapshot/package.json
+++ b/packages/browser-snapshot/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/browser-snapshot",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "browser-snapshot module.",
"keywords": [
"garfish",
diff --git a/packages/browser-vm/package.json b/packages/browser-vm/package.json
index 6eba56c0e..992c155fc 100644
--- a/packages/browser-vm/package.json
+++ b/packages/browser-vm/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/browser-vm",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "vm-sandbox module.",
"keywords": [
"garfish",
diff --git a/packages/browser-vm/src/dynamicNode/processor.ts b/packages/browser-vm/src/dynamicNode/processor.ts
index 9efee5c16..a8d77636f 100644
--- a/packages/browser-vm/src/dynamicNode/processor.ts
+++ b/packages/browser-vm/src/dynamicNode/processor.ts
@@ -52,8 +52,16 @@ export class DynamicNodeProcessor {
const src = el.getAttribute('src');
const href = el.getAttribute('href');
if (this.sandbox.options.fixStaticResourceBaseUrl) {
- src && (el.src = transformUrl(baseUrl, src));
- href && (el.href = transformUrl(baseUrl, href));
+ const transformUrlSrc = src && transformUrl(baseUrl, src);
+ const transformUrlHref = href && transformUrl(baseUrl, href);
+ // Consistent values do not need to be overwritten
+ if (transformUrlSrc !== src) {
+ el.src = transformUrlSrc;
+ }
+
+ if (transformUrlHref !== href) {
+ el.href = transformUrlHref;
+ }
}
const url = el.src || el.href;
@@ -150,7 +158,11 @@ export class DynamicNodeProcessor {
const isModule = type === 'module';
const code = this.el.textContent || this.el.text || '';
- if (!type || isJsType({ src, type })) {
+ // Returning true indicates that execution in the sandbox is not required
+ const excludeAssetFilter = this.sandbox.options.excludeAssetFilter;
+ const excludeUrl = excludeAssetFilter?.(src);
+
+ if ((!type || isJsType({ src, type })) && !excludeUrl) {
// The "src" higher priority
const { baseUrl, namespace } = this.sandbox.options;
if (src) {
diff --git a/packages/browser-vm/src/pluginify.ts b/packages/browser-vm/src/pluginify.ts
index debb6fbc0..7b463ab1a 100644
--- a/packages/browser-vm/src/pluginify.ts
+++ b/packages/browser-vm/src/pluginify.ts
@@ -22,6 +22,7 @@ declare module '@garfish/core' {
}
export interface AppInfo {
+ excludeAssetFilter?: (url: string) => boolean;
protectVariable?: PropertyKey[];
insulationVariable?: PropertyKey[];
}
@@ -137,6 +138,7 @@ function createOptions(Garfish: interfaces.Garfish) {
appInfo.sandbox?.disableLinkTransformToStyle,
),
strictIsolation: Boolean(appInfo.sandbox?.strictIsolation),
+ excludeAssetFilter: appInfo.sandbox?.excludeAssetFilter,
// 缓存模式,不收集副作用
disableCollect:
appInfo.cache === undefined ? true : Boolean(appInfo.cache),
diff --git a/packages/browser-vm/src/types.ts b/packages/browser-vm/src/types.ts
index 24dd254aa..9ba67a8e7 100644
--- a/packages/browser-vm/src/types.ts
+++ b/packages/browser-vm/src/types.ts
@@ -30,6 +30,7 @@ export interface SandboxOptions {
disableLinkTransformToStyle?: boolean;
disableCollect?: boolean;
modules?: Array;
+ excludeAssetFilter?: (url: string) => boolean;
addSourceList?: (
sourceInfo:
| Array<{ tagName: string; url: string | URL | Request }>
diff --git a/packages/core/package.json b/packages/core/package.json
index 8c449bba8..c749556cd 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/core",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "core module.",
"keywords": [
"garfish",
diff --git a/packages/core/src/interface.ts b/packages/core/src/interface.ts
index 423580d4b..01e2f336d 100644
--- a/packages/core/src/interface.ts
+++ b/packages/core/src/interface.ts
@@ -83,6 +83,7 @@ export namespace interfaces {
disableElementtiming?: boolean;
disableLinkTransformToStyle?: boolean;
fixOwnerDocument?: boolean;
+ excludeAssetFilter?: (url: string) => boolean;
}
export interface Config {
diff --git a/packages/core/src/module/app.ts b/packages/core/src/module/app.ts
index 58f6b8075..46da21646 100644
--- a/packages/core/src/module/app.ts
+++ b/packages/core/src/module/app.ts
@@ -689,6 +689,19 @@ export class App {
return DOMApis.createElement(node);
}
}
+
+ // Filter out code that does not require sandboxed execution
+ if (this.appInfo.sandbox) {
+ const scriptUrl = entryManager.findAttributeValue(node, 'src');
+ if (
+ scriptUrl &&
+ this.appInfo.sandbox?.excludeAssetFilter &&
+ this.appInfo.sandbox?.excludeAssetFilter(scriptUrl)
+ ) {
+ return DOMApis.createElement(node);
+ }
+ }
+
const jsManager = resources.js.find((manager) => {
return !manager.async ? manager.isSameOrigin(node) : false;
});
diff --git a/packages/core/src/module/resource.ts b/packages/core/src/module/resource.ts
index 6ef90698f..0131527ff 100644
--- a/packages/core/src/module/resource.ts
+++ b/packages/core/src/module/resource.ts
@@ -5,13 +5,15 @@ import type {
TemplateManager,
JavaScriptManager,
} from '@garfish/loader';
-import { AppInfo } from './app';
+import type { AppInfo } from './app';
+import type { interfaces } from '../interface';
// Fetch `script`, `link` and `module meta` elements
function fetchStaticResources(
appInfo: AppInfo,
loader: Loader,
entryManager: TemplateManager,
+ sandboxConfig: false | interfaces.SandboxConfig | undefined,
) {
const toBoolean = (val) => typeof val !== 'undefined' && val !== 'false';
@@ -19,6 +21,15 @@ function fetchStaticResources(
const jsNodes = Promise.all(
entryManager
.findAllJsNodes()
+ .filter((node) => {
+ if (sandboxConfig && sandboxConfig.excludeAssetFilter) {
+ const src = entryManager.findAttributeValue(node, 'src');
+ if (src && sandboxConfig.excludeAssetFilter(src)) {
+ return false;
+ }
+ }
+ return true;
+ })
.map((node) => {
const src = entryManager.findAttributeValue(node, 'src');
const type = entryManager.findAttributeValue(node, 'type');
@@ -153,6 +164,7 @@ export async function processAppResources(loader: Loader, appInfo: AppInfo) {
appInfo,
loader,
entryManager,
+ appInfo.sandbox,
);
resources.js = js;
resources.link = link;
diff --git a/packages/css-scope/package.json b/packages/css-scope/package.json
index 6898624ee..58fce5e74 100644
--- a/packages/css-scope/package.json
+++ b/packages/css-scope/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/css-scope",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "css scope",
"keywords": [
"garfish",
diff --git a/packages/es-module/package.json b/packages/es-module/package.json
index 9fa0aee23..285ce9e23 100644
--- a/packages/es-module/package.json
+++ b/packages/es-module/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/es-module",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "es module polyfill",
"keywords": [
"garfish",
diff --git a/packages/garfish/package.json b/packages/garfish/package.json
index c2cdd807e..bb7ab8161 100644
--- a/packages/garfish/package.json
+++ b/packages/garfish/package.json
@@ -1,6 +1,6 @@
{
"name": "garfish",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "garfish module.",
"keywords": [
"garfish",
diff --git a/packages/hooks/package.json b/packages/hooks/package.json
index ce81d336f..2948820bc 100644
--- a/packages/hooks/package.json
+++ b/packages/hooks/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/hooks",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "hooks module.",
"keywords": [
"garfish",
diff --git a/packages/loader/package.json b/packages/loader/package.json
index 5a6f80781..27b86e8b9 100644
--- a/packages/loader/package.json
+++ b/packages/loader/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/loader",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "loader module.",
"keywords": [
"garfish",
diff --git a/packages/remote-module/package.json b/packages/remote-module/package.json
index 1c8e5a2f1..78603c698 100644
--- a/packages/remote-module/package.json
+++ b/packages/remote-module/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/remote-module",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "remote-module module.",
"keywords": [
"garfish",
diff --git a/packages/router/package.json b/packages/router/package.json
index 6e4b592b2..0a6572007 100644
--- a/packages/router/package.json
+++ b/packages/router/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/router",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "router module.",
"keywords": [
"garfish",
diff --git a/packages/test-suite/package.json b/packages/test-suite/package.json
index 4c064c643..cdc0e4a33 100644
--- a/packages/test-suite/package.json
+++ b/packages/test-suite/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/test-suite",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "garfish test suite.",
"keywords": [
"garfish",
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 8f441b943..eae590af8 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@garfish/utils",
- "version": "1.17.6",
+ "version": "1.18.0",
"description": "utils module.",
"keywords": [
"garfish",
diff --git a/packages/utils/src/utils.ts b/packages/utils/src/utils.ts
index 6013066fb..9482ea32c 100644
--- a/packages/utils/src/utils.ts
+++ b/packages/utils/src/utils.ts
@@ -371,7 +371,11 @@ export function isAbsolute(url: string) {
}
export function transformUrl(resolvePath: string, curPath: string) {
- if (curPath.startsWith('http') || curPath.startsWith('//')) {
+ if (
+ curPath.startsWith('http') ||
+ curPath.startsWith('//') ||
+ curPath.startsWith('blob:')
+ ) {
return curPath;
}
const baseUrl = new URL(resolvePath, location.href);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 93eadf760..3771df748 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -6276,7 +6276,7 @@ packages:
lru-cache: 6.0.0
mkdirp: 1.0.4
npm-pick-manifest: 6.1.1
- promise-inflight: 1.0.1
+ promise-inflight: 1.0.1_bluebird@3.7.2
promise-retry: 2.0.1
semver: 7.3.5
which: 2.0.2
@@ -10575,7 +10575,7 @@ packages:
mkdirp: 0.5.6
move-concurrently: 1.0.1
p-map: 3.0.0
- promise-inflight: 1.0.1
+ promise-inflight: 1.0.1_bluebird@3.7.2
rimraf: 2.7.1
ssri: 7.1.1
unique-filename: 1.1.1
@@ -10626,7 +10626,7 @@ packages:
minipass-pipeline: 1.2.4
mkdirp: 1.0.4
p-map: 4.0.0
- promise-inflight: 1.0.1
+ promise-inflight: 1.0.1_bluebird@3.7.2
rimraf: 3.0.2
ssri: 9.0.1
tar: 6.2.0
diff --git a/website/docs/issues/childApp.md b/website/docs/issues/childApp.md
index acdd69d3f..917245fae 100644
--- a/website/docs/issues/childApp.md
+++ b/website/docs/issues/childApp.md
@@ -28,6 +28,13 @@ if (window.__GARFISH__ && typeof __GARFISH_EXPORTS__ !== 'undefined') {
}
```
+## 微应用 JSONP 跨域错误怎么处理?
+
+在使用 Garfish 时,微应用的动态脚本(如 JSONP)会被转化为 fetch 请求,这要求后端服务支持跨域请求,否则会产生错误。
+
+可以使用 [excludeAssetFilter](/api/registerApp#sandbox) 参数来放行这些资源请求,但请注意,被该参数放行的资源会逃逸出沙箱,可能导致副作用,需自行处理。
+
+
## Uncaught (in promise) TypeError: [Garfish warning]: Cannot read properties of undefined (reading 'call')
- 错误原因
diff --git a/website/src/components/config/_sandbox.mdx b/website/src/components/config/_sandbox.mdx
index 51a772769..2eda8dafb 100644
--- a/website/src/components/config/_sandbox.mdx
+++ b/website/src/components/config/_sandbox.mdx
@@ -22,6 +22,8 @@ interface SandboxConfig {
fixOwnerDocument?: boolean;
// disableLinkTransformToStyle 1.18.0 版本提供 ,默认值 false,禁用掉 link 自动 transform 成 style 的行为
disableLinkTransformToStyle?: boolean;
+ // excludeAssetFilter 1.18.0 版本提供,默认值为 undefined,用于过滤不需要再子应用沙箱中执行的资源例如 jsonp,url 参数为对应 script 的地址,返回 true 则会过滤掉该资源
+ excludeAssetFilter?: (url: string) => boolean;
}
type Module = (sandbox: Sandbox) => OverridesData | void;