fix: set sandbox csp & mock localStorage/sessionStorage/cookie for BMap
diff --git a/src/editor/sandbox/index.js b/src/editor/sandbox/index.js
index 1fc936b..2105a27 100644
--- a/src/editor/sandbox/index.js
+++ b/src/editor/sandbox/index.js
@@ -35,17 +35,38 @@
     'sandbox',
     ['allow-pointer-lock', 'allow-scripts', 'allow-downloads'].join(' ')
   );
+  const csp = {
+    'default-src': [
+      `'self'`,
+      `'unsafe-inline'`,
+      `'unsafe-eval'`,
+      '*.apache.org',
+      '*.jsdelivr.net',
+      '*.jsdelivr.com',
+      '*.unpkg.com',
+      '*.baidu.com',
+      '*.bdimg.com',
+      'cdnjs.cloudflare.com'
+    ],
+    'frame-src': [`'self'`, '*.apache.org'],
+    'object-src': [`'none'`]
+  };
+  sandbox.csp = Object.entries(csp)
+    .map(([key, val]) => `${key} ${val.join(' ')}`)
+    .join('; ');
+  sandbox.srcdoc = srcdoc
+    .replace('__CSP__', sandbox.csp)
+    .replace(
+      '<!--SCRIPTS-->',
+      scripts
+        .map((script) =>
+          script.content
+            ? `<script>${script.content}</script>`
+            : `<script src="${script.src}"></script>`
+        )
+        .join('')
+    );
   sandbox.style.cssText = 'width:100%;height:100%;border:none;background:none';
-  sandbox.srcdoc = srcdoc.replace(
-    '<!--SCRIPTS-->',
-    scripts
-      .map((script) =>
-        script.content
-          ? `<script>${script.content}</script>`
-          : `<script src="${script.src}"></script>`
-      )
-      .join('')
-  );
   sandbox.onload = () => {
     // FIXME
     // No good way to prevent the user from trying to redirect the iframe via `document.location.href = xxx`
diff --git a/src/editor/sandbox/srcdoc.html b/src/editor/sandbox/srcdoc.html
index cd0752d..b22b6f0 100644
--- a/src/editor/sandbox/srcdoc.html
+++ b/src/editor/sandbox/srcdoc.html
@@ -1,10 +1,7 @@
 <!DOCTYPE html>
 <html>
   <head>
-    <meta
-      http-equiv="content-security-policy"
-      content="default-src 'self' 'unsafe-inline' 'unsafe-eval' *.apache.org *.jsdelivr.net *.jsdelivr.com *.unpkg.com *.baidu.com cdnjs.cloudflare.com; frame-src 'self' *.apache.org; object-src 'none';"
-    />
+    <meta http-equiv="content-security-policy" content="__CSP__" />
     <style>
       * {
         margin: 0;
@@ -41,6 +38,31 @@
   </head>
   <body>
     <div id="chart-container"></div>
+    <script>
+      // FIXME
+      (() => {
+        const noop = () => {};
+        const fakeStorage = {
+          clear: noop,
+          setItem: noop,
+          removeItem: noop,
+          getItem: noop,
+          key: noop,
+          length: 0
+        };
+        Object.defineProperties(window, {
+          localStorage: {
+            value: fakeStorage
+          },
+          sessionStorage: {
+            value: fakeStorage
+          }
+        });
+        Object.defineProperty(document, 'cookie', {
+          value: ''
+        });
+      })();
+    </script>
     <script src="https://cdn.jsdelivr.net/npm/jquery"></script>
     <script src="https://cdn.jsdelivr.net/npm/seedrandom@3.0.5/seedrandom.min.js"></script>
     <script src="https://cdn.jsdelivr.net/npm/acorn@8.7.1/dist/acorn.min.js"></script>