fix: limit shared code's access to global vars
diff --git a/src/common/store.js b/src/common/store.js
index 9bb20eb..3179ff6 100644
--- a/src/common/store.js
+++ b/src/common/store.js
@@ -29,6 +29,8 @@
   runCode: '',
   sourceCode: '',
 
+  isSharedCode: false,
+
   runHash: '',
 
   isMobile: window.innerWidth < 600,
@@ -98,6 +100,7 @@
       try {
         // PENDING fallback to `c` if the decompressed code is not available?
         const code = decompressStr(URL_PARAMS.code);
+        store.isSharedCode = !!code;
         return code
           ? resolve(code)
           : reject('code was decompressed but got nothing');
diff --git a/src/editor/Preview.vue b/src/editor/Preview.vue
index a5dd625..a78cd6e 100644
--- a/src/editor/Preview.vue
+++ b/src/editor/Preview.vue
@@ -230,6 +230,7 @@
     this.sandbox = createSandbox(
       this.$refs.chartPanel,
       (this.scripts = scripts),
+      store.isSharedCode,
       () => {
         runCode();
         this.loading = false;
diff --git a/src/editor/sandbox/index.js b/src/editor/sandbox/index.js
index b016aae..cec82b2 100644
--- a/src/editor/sandbox/index.js
+++ b/src/editor/sandbox/index.js
@@ -8,6 +8,7 @@
 export function createSandbox(
   container,
   scripts,
+  isShared,
   onload,
   onerror,
   onCodeError,
@@ -24,7 +25,7 @@
           ${handleLoop}
           ${showDebugDirtyRect}
           ${setup}
-          setup()
+          setup(${isShared})
         })()
       `
     }
diff --git a/src/editor/sandbox/setup.js b/src/editor/sandbox/setup.js
index 56147bd..926a99f 100644
--- a/src/editor/sandbox/setup.js
+++ b/src/editor/sandbox/setup.js
@@ -1,4 +1,4 @@
-export default function setup() {
+export default function setup(isShared) {
   const sendMessage = (payload) => parent.postMessage(payload, '*');
 
   const chartStyleEl = document.head.querySelector('#chart-styles');
@@ -65,50 +65,84 @@
   let appEnv = {};
   let gui;
 
-  // override some potentially dangerous API
-  const win = [
-    'addEventListener',
-    'removeEventListener',
-    'atob',
-    'btoa',
-    'fetch',
-    'getComputedStyle'
-  ].reduce(
-    (prev, curr) => {
-      const val = window[curr];
-      prev[curr] = echarts.util.isFunction(val) ? val.bind(window) : val;
-      return prev;
-    },
-    {
-      location: Object.freeze(JSON.parse(JSON.stringify(location))),
-      history: void 0,
-      parent: void 0,
-      top: void 0,
-      setTimeout,
-      setInterval
-    }
-  );
-  [
-    'innerHeight',
-    'outerHeight',
-    'innerWidth',
-    'outerWidth',
-    'devicePixelRatio',
-    'screen'
-  ].forEach((prop) => {
-    Object.defineProperty(win, prop, {
-      get() {
-        return window[prop];
+  let win;
+  if (isShared) {
+    // override some potentially dangerous API
+    win = [
+      'addEventListener',
+      'removeEventListener',
+      'atob',
+      'btoa',
+      'fetch',
+      'getComputedStyle'
+    ].reduce(
+      (prev, curr) => {
+        const val = window[curr];
+        prev[curr] = echarts.util.isFunction(val) ? val.bind(window) : val;
+        return prev;
+      },
+      {
+        location: Object.freeze(JSON.parse(JSON.stringify(location))),
+        document: (() => {
+          const nativeCreateElement = document.createElement;
+          const nativeCreateElementNS = document.createElementNS;
+          const fakeDoc = document.cloneNode();
+          // To enable the created elements to be inserted to body
+          // Object.defineProperties(fakeDoc, {
+          //   documentElement: {
+          //     get() {
+          //       return document.documentElement;
+          //     }
+          //   },
+          //   body: {
+          //     get() {
+          //       return document.body;
+          //     }
+          //   }
+          // });
+          fakeDoc.createElement = function () {
+            const tagName = arguments[0];
+            if (tagName && tagName.toLowerCase() === 'script') {
+              return console.error(
+                `Disallowed attempting to create dynamic script!`
+              );
+            }
+            return nativeCreateElement.apply(document, arguments);
+          };
+          fakeDoc.nativeCreateElementNS = function () {
+            const tagName = arguments[0];
+            if (tagName && tagName.toLowerCase() === 'script') {
+              return console.error(
+                `Disallowed attempting to create dynamic script!`
+              );
+            }
+            return nativeCreateElementNS.apply(document, arguments);
+          };
+          return fakeDoc;
+        })(),
+        history: void 0,
+        parent: void 0,
+        top: void 0,
+        setTimeout,
+        setInterval
       }
+    );
+    [
+      'innerHeight',
+      'outerHeight',
+      'innerWidth',
+      'outerWidth',
+      'devicePixelRatio',
+      'screen'
+    ].forEach((prop) => {
+      Object.defineProperty(win, prop, {
+        get() {
+          return window[prop];
+        }
+      });
     });
-  });
-  win.self = win.window = win.globalThis = win;
-
-  Object.defineProperty(document, 'defaultView', {
-    value: win,
-    writable: false,
-    configurable: false
-  });
+    win.self = win.window = win.globalThis = win;
+  }
 
   const api = {
     dispose() {
@@ -167,50 +201,78 @@
           // Replace random method
           .replace(/Math.random\([^)]*\)/g, '__ECHARTS_EXAMPLE_RANDOM__()');
         const echartsExampleRandom = new Math.seedrandom(store.randomSeed);
-
-        const func = new Function(
-          'myChart',
-          'app',
-          'setTimeout',
-          'setInterval',
-          'ROOT_PATH',
-          '__ECHARTS_EXAMPLE_RANDOM__',
-          'top',
-          'parent',
-          'window',
-          'self',
-          'globalThis',
-          'location',
-          'histroy',
-          'eval',
-          'execScript',
-          'Function',
-          // PENDING: create a single panel for CSS code?
+        // PENDING: create a single panel for CSS code?
+        const runCode =
           'var css, option;' +
-            handleLoop(compiledCode) +
-            '\nreturn [option, css];'
-        ).bind(win);
+          handleLoop(compiledCode) +
+          '\nreturn [option, css];';
 
-        const res = func(
-          chartInstance,
-          appEnv,
-          setTimeout,
-          setInterval,
-          store.cdnRoot,
-          echartsExampleRandom,
-          // prevent someone from trying to close the parent window via top/parent.close()
-          // or any other unexpected and dangerous behaviors
-          void 0,
-          void 0,
-          win,
-          win,
-          win,
-          win.location,
-          void 0,
-          void 0,
-          void 0,
-          void 0
-        );
+        let func;
+        let res;
+
+        if (isShared) {
+          func = new Function(
+            'myChart',
+            'app',
+            'setTimeout',
+            'setInterval',
+            'ROOT_PATH',
+            '__ECHARTS_EXAMPLE_RANDOM__',
+            'top',
+            'parent',
+            'window',
+            'self',
+            'globalThis',
+            'document',
+            'location',
+            'histroy',
+            'eval',
+            'execScript',
+            'Function',
+            runCode
+          ).bind(win);
+
+          res = func(
+            chartInstance,
+            appEnv,
+            setTimeout,
+            setInterval,
+            store.cdnRoot,
+            echartsExampleRandom,
+            // prevent someone from trying to close the parent window via top/parent.close()
+            // or any other unexpected and dangerous behaviors
+            void 0,
+            void 0,
+            win,
+            win,
+            win,
+            win.document,
+            win.location,
+            void 0,
+            void 0,
+            void 0,
+            void 0
+          );
+        } else {
+          func = new Function(
+            'myChart',
+            'app',
+            'setTimeout',
+            'setInterval',
+            'ROOT_PATH',
+            '__ECHARTS_EXAMPLE_RANDOM__',
+            runCode
+          );
+
+          res = func(
+            chartInstance,
+            appEnv,
+            setTimeout,
+            setInterval,
+            store.cdnRoot,
+            echartsExampleRandom
+          );
+        }
 
         const css = (chartStyleEl.textContent = res[1] || '');
         sendMessage({