Repository: ice-lab/icestark
Pull request #612 (2022-07-19 07:42:44)

fix: record changed properties in sandbox
cacheDeps 函数加载依赖时调用 sandbox.getAddedProperties 时没能正确获取到上一次执行获得的 window 对象


Patch:
diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts
index b91cf98..cbb57b6 100644
--- a/packages/sandbox/src/index.ts
+++ b/packages/sandbox/src/index.ts
@@ -103,6 +103,8 @@ export default class Sandbox {
         } else if (!originalValues.hasOwnProperty(p)) {
           // if it is already been setted in original window, record it's original value
           originalValues[p] = originalWindow[p];
+          // because target in sandbox will be changed, record the change in propertyAdded, for user can get what has been changed in last-loading
+          propertyAdded[p] = value;
         }
         // set new value to original window in case of jsonp, js bundle which will be execute outof sandbox
         if (!multiMode) {
@@ -214,13 +216,16 @@ export default class Sandbox {
       // clear timeout
       this.timeoutIds.forEach((id) => window.clearTimeout(id));
       this.intervalIds.forEach((id) => window.clearInterval(id));
-      // recover original values
-      Object.keys(this.originalValues).forEach((key) => {
-        window[key] = this.originalValues[key];
-      });
+      // some properties has been in original window, when they're loaded in sandbox
+      // the change has been recorded in propertyAdded
+      // delete the modified properties
       Object.keys(this.propertyAdded).forEach((key) => {
         delete window[key];
       });
+      // then recover original values
+      Object.keys(this.originalValues).forEach((key) => {
+        window[key] = this.originalValues[key];
+      });
     }
   }
 }


Test patch:
diff --git a/packages/sandbox/__tests__/index.spec.ts b/packages/sandbox/__tests__/index.spec.ts
index fea1ee9..5c7d27f 100644
--- a/packages/sandbox/__tests__/index.spec.ts
+++ b/packages/sandbox/__tests__/index.spec.ts
@@ -151,3 +151,47 @@ describe('callable functions in sandbox', () => {
     expect(error).toBe(null);
   });
 });
+
+describe('mock function cacheDeps', () => {
+  // mock window
+  const windowAsAny = (window as any);
+  test('load second dependency with first dependency in multiMode', () => {
+    windowAsAny['test'] = { a: 123, b: 456 };
+  
+    let sandbox = new Sandbox({ multiMode: true });
+
+    sandbox.execScriptInSandbox(`
+      window['test'] = { a: 234, b: 456 };
+    `);
+    const firstDepPropertyAdded = sandbox.getAddedProperties();
+    sandbox.clear();
+    sandbox = new Sandbox({ multiMode: true });
+    sandbox.createProxySandbox(firstDepPropertyAdded);
+    sandbox.execScriptInSandbox(`
+      expect(window.test.a).toBe(234);
+    `);
+    sandbox.clear();
+    expect(windowAsAny.test.a).toBe(123);
+
+  });
+
+  test('load second dependency with first dependency in singleMode', () => {
+    windowAsAny['test'] = { a: 123, b: 456 };
+  
+    let sandbox = new Sandbox({ multiMode: false });
+
+    sandbox.execScriptInSandbox(`
+      window['test'] = { a: 234, b: 456 };
+    `);
+    const firstDepPropertyAdded = sandbox.getAddedProperties();
+    sandbox.clear();
+    sandbox = new Sandbox({ multiMode: true });
+    sandbox.createProxySandbox(firstDepPropertyAdded);
+    sandbox.execScriptInSandbox(`
+      expect(window.test.a).toBe(234);
+    `);
+    sandbox.clear();
+    expect(windowAsAny.test.a).toBe(123);
+  })
+
+})