| // Handle errors around fetching, parsing and registering import maps. |
| window.onScriptError = event => { |
| window.registrationResult = {type: 'FetchError', error: event.error}; |
| return false; |
| }; |
| window.windowErrorHandler = event => { |
| window.registrationResult = {type: 'ParseError', error: event.error}; |
| return false; |
| }; |
| window.addEventListener('error', window.windowErrorHandler); |
| |
| // Handle specifier resolution requests from the parent frame. |
| // For failures, we post error names and messages instead of error |
| // objects themselves and re-create error objects later, to avoid |
| // issues around serializing error objects which is a quite new feature. |
| window.addEventListener('message', event => { |
| if (event.data.action !== 'resolve') { |
| parent.postMessage({ |
| type: 'Failure', |
| result: 'Error', |
| message: 'Invalid Action: ' + event.data.action}, '*'); |
| return; |
| } |
| |
| // To respond to a resolution request, we: |
| // 1. Save the specifier to resolve into a global. |
| // 2. Update the document's base URL to the requested base URL. |
| // 3. Create a new inline script, parsed with that base URL, which |
| // resolves the saved specifier using import.meta.resolve(), and |
| // sents the result to the parent window. |
| window.specifierToResolve = event.data.specifier; |
| document.querySelector('base').href = event.data.baseURL; |
| |
| const inlineScript = document.createElement('script'); |
| inlineScript.type = 'module'; |
| inlineScript.textContent = ` |
| try { |
| const result = import.meta.resolve(window.specifierToResolve); |
| parent.postMessage({type: 'ResolutionSuccess', result}, '*'); |
| } catch (e) { |
| parent.postMessage( |
| {type: 'Failure', result: e.name, message: e.message}, '*'); |
| } |
| `; |
| document.body.append(inlineScript); |
| }); |