Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

本地iframe运行无法查看源码 #87

Open
jerrychan7 opened this issue Jan 27, 2025 · 0 comments
Open

本地iframe运行无法查看源码 #87

jerrychan7 opened this issue Jan 27, 2025 · 0 comments

Comments

@jerrychan7
Copy link

[email protected]

我采用 blob+iframe 的形式在本地运行,但无法查看网页源代码。

报错
common.js:1 Uncaught (in promise) SecurityError: Failed to construct 'Worker': Script at 'https://cdn.jsdelivr.net/npm/chii/public/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.js' cannot be accessed from origin 'http://localhost:3000'.
    at common.js:1:95943
    at new Promise (<anonymous>)
    at new pr (common.js:1:95918)
    at pr.fromURL (common.js:1:96079)
    at s.createWorker (formatter.js:1:328)
    at s.processNextTask (formatter.js:1:689)
    at formatter.js:1:1541
    at new Promise (<anonymous>)
    at s.runTask (formatter.js:1:1472)
    at s.format (formatter.js:1:1634)
(anonymous)	@	common.js:1
pr	@	common.js:1
fromURL	@	common.js:1
createWorker	@	formatter.js:1
processNextTask	@	formatter.js:1
(anonymous)	@	formatter.js:1
runTask	@	formatter.js:1
format	@	formatter.js:1
h	@	formatter.js:1
setPretty	@	source_frame.js:1
setDeferredContent	@	source_frame.js:1
await in setDeferredContent		
ensureContentLoaded	@	source_frame.js:1
wasShown	@	source_frame.js:1
wasShown	@	sources.js:1
notify	@	legacy.js:1
processWasShown	@	legacy.js:1
showWidgetInternal	@	legacy.js:1
show	@	legacy.js:1
showTab	@	legacy.js:1
selectTab	@	legacy.js:1
innerShowFile	@	sources.js:1
showFile	@	sources.js:1
showSourceLocation	@	sources.js:1
showUISourceCode	@	sources.js:1
reveal	@	sources.js:1
(anonymous)	@	common.js:1
jt	@	common.js:1
await in jt		
sourceSelected	@	sources.js:1
onclick	@	sources.js:1

报错说是因为安全问题无法在 localhost 中创建 cdn 的 worker?是否可以通过 blob 的方式创建 worker?

源码
<body>
  <script src="https://cdn.jsdelivr.net/npm/chobitsu"></script>
  <script>太长 写在下面</script>
  <script src="/src/index.jsx" type="module"></script>
               ↑ vite 出来的带 source map 的代码
</body>
// 参考:
// https://github.com/solidjs/solid-playground/blob/master/packages/solid-repl/src/components/preview.tsx
// https://github.com/liriliri/chii/blob/master/src/target/DevtoolsFrame.ts

function devToolsSrc(targetOrigin = location.origin) {
  const version = '';
  const cdn = `https://cdn.jsdelivr.net/npm/chii${version? '@' + version: ''}/public`;
  const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
  const html = `
    <!DOCTYPE html>
    <html lang="en">
    <meta charset="utf-8">
    <title>DevTools</title>
    <style>
      @media (prefers-color-scheme: dark) {
        body {
          background-color: #292a2d;
        }
      }
      body .screencast-viewport {
        max-width: 100%;
        flex: 1;
      }
    </style>
    ${isSafari? `<script src="${cdn}/front_end/third_party/polyfill/customElement.js"></scr`+`ipt>`: ''}
    ${!window.requestIdleCallback? `<script src="${cdn}/front_end/third_party/polyfill/requestIdleCallback.js"></scr`+`ipt>`: ''}
    <meta name="referrer" content="no-referrer">
    <script src="https://unpkg.com/@ungap/custom-elements/es.js"></scr`+`ipt>
    <script type="module" src="${cdn}/front_end/entrypoints/chii_app/chii_app.js"></scr`+`ipt>
    <body class="undocked" id="-blink-dev-tools">
  `;
  const devtoolsRawUrl = URL.createObjectURL(new Blob([html], { type: 'text/html' }));
  // URL.revokeObjectURL(devtoolsRawUrl);
  return `${devtoolsRawUrl}#?embedded=${encodeURIComponent(targetOrigin)}`;
}

const windowLoaded = new Promise((s) => window.addEventListener('load', s));

async function openDevTools() {
  const targetOrigin = location.origin;

  const devtoolsIframe = document.createElement('iframe');
  devtoolsIframe.setAttribute('title', 'DevTools');
  devtoolsIframe.style.border = "none";
  devtoolsIframe.style.height = '50vh';
  devtoolsIframe.style.width = '100vw';
  devtoolsIframe.style.position = 'fixed';
  devtoolsIframe.style.bottom = '0';
  devtoolsIframe.style.left = '0';
  devtoolsIframe.style.zIndex = 9e20 + '';
  devtoolsIframe.src = devToolsSrc(targetOrigin);
  document.body.appendChild(devtoolsIframe);

  let devtoolsLoaded = false;
  const runtimeExeCtxCreated = Promise.withResolvers();

  // 这里等待 devtools 加载完毕再输出,才能保证输出的信息不会丢失
  // 而目前观察到的只有接受到frameTree之后才能正常输出
  // 故而这里缓存所有的控台输出,等待frameTree之后再输出
  const msgBuffer = [];
  const sendToDevtools = (msg, force = false) => {
    if (typeof msg !== 'string') msg = JSON.stringify(msg);
    if (!devtoolsLoaded && msg.includes('frameTree')) {
      runtimeExeCtxCreated.resolve();
    }
    if (!force && !devtoolsLoaded && (
         msg.includes('Runtime.consoleAPICalled')
      || msg.includes('Runtime.exceptionRevoked')
      || msg.includes('Runtime.exceptionThrown')
      // || msg.includes('Runtime.executionContextCreated')
      // || msg.includes('Runtime.executionContextDestroyed')
      // || msg.includes('Runtime.executionContextsCleared')
      // || msg.includes('Runtime.inspectRequested')
      // || msg.includes('Runtime.bindingCalled')
    ))
      msgBuffer.push(msg);
    else devtoolsIframe.contentWindow.postMessage(msg, targetOrigin);
  };
  let id = 0;
  const sendToChobitsu = (msg) => {
    msg.id = 'tmp' + ++id;
    chobitsu.sendRawMessage(JSON.stringify(msg));
  };
  chobitsu.setOnMessage((message) => {
    if (message.includes('"id":"tmp')) return;
    sendToDevtools(message);
  });

  runtimeExeCtxCreated.promise.then(async () => {
    for (let i = 0; i < msgBuffer.length; ++i)
      sendToDevtools(msgBuffer[i], true);
    devtoolsLoaded = true;
    msgBuffer.length = 0;
  });

  sendToDevtools({
    method: 'Page.frameNavigated',
    params: {
      frame: {
        id: '1',
        mimeType: 'text/html',
        securityOrigin: location.origin,
        url: location.href,
      },
      type: 'Navigation',
    },
  });
  sendToChobitsu({ method: 'Network.enable' });
  sendToDevtools({ method: 'Runtime.executionContextsCleared' });
  sendToChobitsu({ method: 'Runtime.enable' });
  sendToChobitsu({ method: 'Debugger.enable' });
  sendToChobitsu({ method: 'DOMStorage.enable' });
  sendToChobitsu({ method: 'DOM.enable' });
  sendToChobitsu({ method: 'CSS.enable' });
  sendToChobitsu({ method: 'Overlay.enable' });
  sendToChobitsu({ method: 'Console.enable' });
  sendToDevtools({ method: 'DOM.documentUpdated' });

  window.addEventListener('message', ({ source, data }) => {
    if (source === devtoolsIframe.contentWindow) {
      chobitsu.sendRawMessage(data);
    }
  });
}

openDevTools();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant