Просмотр исходного кода

workflow(sfc-playground): make it work in safari and ff

Evan You 5 лет назад
Родитель
Сommit
4dc457dae5

+ 18 - 6
packages/sfc-playground/src/output/Preview.vue

@@ -96,7 +96,7 @@ function createSandbox() {
   }
   importMap.imports.vue = vueRuntimeUrl.value
   const sandboxSrc = srcdoc.replace(/<!--IMPORT_MAP-->/, JSON.stringify(importMap))
-  sandbox.setAttribute('srcdoc', sandboxSrc)
+  sandbox.srcdoc = sandboxSrc
   container.value.appendChild(sandbox)
 
   proxy = new PreviewProxy(sandbox, {
@@ -104,19 +104,30 @@ function createSandbox() {
       // pending_imports = progress;
     },
     on_error: (event: any) => {
-      runtimeError.value = event.value
+      const msg = event.value instanceof Error ? event.value.message : event.value
+      if (
+        msg.includes('Failed to resolve module specifier') ||
+        msg.includes('Error resolving module specifier')
+      ) {
+        runtimeError.value = msg.replace(/\. Relative references must.*$/, '') +
+        `.\nTip: add an "import-map.json" file to specify import paths for dependencies.`
+      } else {
+        runtimeError.value = event.value
+      }
     },
     on_unhandled_rejection: (event: any) => {
       let error = event.value
-      if (typeof error === 'string') error = { message: error }
+      if (typeof error === 'string') {
+        error = { message: error }
+      }
       runtimeError.value = 'Uncaught (in promise): ' + error.message
     },
     on_console: (log: any) => {
       if (log.level === 'error') {
         if (log.args[0] instanceof Error) {
-          runtimeError.value = log.args[0].stack
+          runtimeError.value = log.args[0].message
         } else {
-          runtimeError.value = log.args
+          runtimeError.value = log.args[0]
         }
       } else if (log.level === 'warn') {
         if (log.args[0].toString().includes('[Vue warn]')) {
@@ -145,6 +156,7 @@ function createSandbox() {
 }
 
 async function updatePreview() {
+  console.clear()
   runtimeError.value = null
   runtimeWarning.value = null
   try {
@@ -168,7 +180,7 @@ app.config.errorHandler = e => console.error(e)
 app.mount('#app')`.trim()
     ])
   } catch (e) {
-    runtimeError.value = e.stack
+    runtimeError.value = e.message
   }
 }
 </script>

+ 31 - 11
packages/sfc-playground/src/output/srcdoc.html

@@ -8,11 +8,6 @@
 			}
 		</style>
 		<style id="__sfc-styles"></style>
-
-		<!-- ES Module Shims: Import maps polyfill for modules browsers without import maps support (all except Chrome 89+) -->
-		<script async src="https://ga.jspm.io/npm:es-module-shims@0.10.1/dist/es-module-shims.min.js"></script>
-		<script id="map" type="importmap"><!--IMPORT_MAP--></script>
-
 		<script>
 			(() => {
 				let scriptEls = []
@@ -55,12 +50,12 @@
 								scriptEl.setAttribute('type', 'module')
 								// send ok in the module script to ensure sequential evaluation
 								// of multiple proxy.eval() calls
-								const done = new Promise((resolve, reject) => {
+								const done = new Promise((resolve) => {
 									window.__next__ = resolve
-									scriptEl.onerror = reject
 								})
 								scriptEl.innerHTML = script + `\nwindow.__next__()`
 								document.head.appendChild(scriptEl)
+								scriptEl.onrror = err => send_error(err.message, err.stack)
 								scriptEls.push(scriptEl)
 								await done
 							}
@@ -108,11 +103,27 @@
 				window.addEventListener('message', handle_message, false);
 
 				window.onerror = function (msg, url, lineNo, columnNo, error) {
-					parent.postMessage({ action: 'error', value: error }, '*');
+					if (msg.includes('module specifier “vue”')) {
+						// firefox only error, ignore
+						return false
+					}
+					try {
+						parent.postMessage({ action: 'error', value: error }, '*');
+					} catch (e) {
+						parent.postMessage({ action: 'error', value: msg }, '*');
+					}
 				}
 
 				window.addEventListener("unhandledrejection", event => {
-					parent.postMessage({ action: 'unhandledrejection', value: event.reason }, '*');
+					if (event.reason.message.includes('Cross-origin')) {
+						event.preventDefault()
+						return
+					}
+					try {
+						parent.postMessage({ action: 'unhandledrejection', value: event.reason }, '*');
+					} catch (e) {
+						parent.postMessage({ action: 'unhandledrejection', value: event.reason.message }, '*');
+					}
 				});
 
 				let previous = { level: null, args: null };
@@ -121,7 +132,10 @@
 					const original = console[level];
 					console[level] = (...args) => {
 						const msg = String(args[0])
-						if (msg.includes('You are running a development build of Vue')) {
+						if (
+							msg.includes('You are running a development build of Vue') ||
+							msg.includes('You are running the esm-bundler build of Vue')
+						) {
 							return
 						}
 						const stringifiedArgs = stringify(args);
@@ -137,7 +151,9 @@
 							try {
 								parent.postMessage({ action: 'console', level, args }, '*');
 							} catch (err) {
-								parent.postMessage({ action: 'console', level: 'unclonable' }, '*');
+								parent.postMessage({ action: 'console', level, args: args.map(a => {
+									return a instanceof Error ? a.message : String(a)
+								}) }, '*');
 							}
 						}
 
@@ -232,6 +248,10 @@
 				}
 			})()
 		</script>
+
+		<!-- ES Module Shims: Import maps polyfill for modules browsers without import maps support (all except Chrome 89+) -->
+		<script async src="https://unpkg.com/es-module-shims@0.10.1/dist/es-module-shims.js"></script>
+		<script type="importmap"><!--IMPORT_MAP--></script>
 	</head>
 	<body>
     <div id="app"></div>

+ 2 - 2
packages/sfc-playground/src/sfcCompiler.ts

@@ -14,8 +14,8 @@ let SFCCompiler: typeof defaultCompiler = defaultCompiler
 
 // @ts-ignore
 const defaultVueUrl = import.meta.env.PROD
-  ? '/vue.runtime.esm-browser.js' // to be copied on build
-  : '/src/vue-dev-proxy'
+  ? `${location.origin}/vue.runtime.esm-browser.js` // to be copied on build
+  : `${location.origin}/src/vue-dev-proxy`
 
 export const vueRuntimeUrl = ref(defaultVueUrl)