Skip to content

Commit

Permalink
fix: trusted types (#11325)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack-Works committed Jan 28, 2024
1 parent f8f0163 commit f2524b4
Show file tree
Hide file tree
Showing 14 changed files with 72 additions and 45 deletions.
2 changes: 2 additions & 0 deletions packages/mask/.webpack/config.ts
Expand Up @@ -23,6 +23,7 @@ import { type BuildFlags, normalizeBuildFlags, computedBuildFlags, computeCacheK
import { ProfilingPlugin } from './plugins/ProfilingPlugin.js'

import './clean-hmr.js'
import { TrustedTypesPlugin } from './plugins/TrustedTypesPlugin.js'

const __dirname = fileURLToPath(dirname(import.meta.url))
const require = createRequire(import.meta.url)
Expand Down Expand Up @@ -206,6 +207,7 @@ export async function createConfiguration(_inputFlags: BuildFlags): Promise<webp
}),
flags.reactRefresh && new ReactRefreshWebpackPlugin({ overlay: false, esModule: true }),
flags.profiling && new ProfilingPlugin(),
new TrustedTypesPlugin(),
...emitManifestFile(flags, computedFlags),
new CopyPlugin({
patterns: [
Expand Down
30 changes: 30 additions & 0 deletions packages/mask/.webpack/plugins/TrustedTypesPlugin.ts
@@ -0,0 +1,30 @@
import webpack, { type Compiler } from 'webpack'

const { RuntimeModule, Template } = webpack
class TrustedTypesRuntimeModule extends RuntimeModule {
constructor() {
super('trustedTypes', RuntimeModule.STAGE_TRIGGER)
}
override generate(): string {
const { compilation } = this
if (!compilation)
return Template.asString('/* TrustedTypesRuntimeModule skipped because compilation is undefined. */')
return Template.asString([
'if (typeof trustedTypes !== "undefined" && location.protocol.includes("extension") && !trustedTypes.defaultPolicy) {',
Template.indent([`trustedTypes.createPolicy('default', { createScriptURL: (string) => string });`]),
'}',
])
}
}
export class TrustedTypesPlugin {
apply(compiler: Compiler) {
compiler.hooks.compilation.tap('TrustedTypes', (compilation) => {
compilation.hooks.afterChunks.tap('TrustedTypes', (chunks) => {
for (const c of chunks) {
if (!c.hasEntryModule()) continue
compilation.addRuntimeModule(c, new TrustedTypesRuntimeModule(), compilation.chunkGraph)
}
})
})
}
}
1 change: 1 addition & 0 deletions packages/mask/.webpack/popups.html
Expand Up @@ -15,6 +15,7 @@
<script src="/js/sentry-patch.js"></script>
<script src="/js/polyfill/lockdown.js"></script>
<script src="/js/lockdown.js"></script>
<script src="/js/trusted-types.js"></script>
<script src="/js/module-loader.js"></script>
<style>
body {
Expand Down
1 change: 1 addition & 0 deletions packages/mask/.webpack/template.html
Expand Up @@ -14,6 +14,7 @@
<script src="/js/sentry.js"></script>
<script src="/js/sentry-patch.js"></script>
<script src="/js/polyfill/lockdown.js"></script>
<script src="/js/trusted-types.js"></script>
<script src="/js/lockdown.js"></script>
<script src="/js/module-loader.js"></script>
</head>
Expand Down
7 changes: 4 additions & 3 deletions packages/mask/dashboard/Dashboard.tsx
@@ -1,6 +1,6 @@
import { useEffect } from 'react'
import { CssBaseline, ThemeProvider, StyledEngineProvider, GlobalStyles } from '@mui/material'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
// import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import {
CustomSnackbarProvider,
applyMaskColorVars,
Expand Down Expand Up @@ -70,9 +70,10 @@ export default function Dashboard() {
<>
<CssBaseline />
{GlobalCss}
{process.env.NODE_ENV === 'development' ?
{/* https://github.com/TanStack/query/issues/5417 */}
{/* {process.env.NODE_ENV === 'development' ?
<ReactQueryDevtools buttonPosition="bottom-right" />
: null}
: null} */}
<Modals createWallet={() => Services.Helper.openDashboard(DashboardRoutes.CreateMaskWalletForm)} />
<Pages />
</>,
Expand Down
8 changes: 0 additions & 8 deletions packages/mask/devtools/panels/index.tsx
@@ -1,14 +1,6 @@
/// <reference path="../../../polyfills/types/dom.d.ts" />
import { attachListener } from './utils.js'

if (typeof trustedTypes === 'object' && location.protocol.includes('extension')) {
trustedTypes.createPolicy('default', {
// do not add createHTML or createScript.
// createScriptURL is safe because according to the CSP we have, it is impossible to
// include/create a script from cross-origin.
createScriptURL: (string) => string,
})
}
function init() {
const controller = new AbortController()

Expand Down
1 change: 1 addition & 0 deletions packages/mask/package.json
Expand Up @@ -2,6 +2,7 @@
"name": "@masknet/extension",
"private": true,
"sideEffects": [
"./public/js/trusted-types.js",
"./background/initialization/**",
"./background/tasks/**",
"./content-script/site-adaptor-infra/sandboxed-plugin.ts",
Expand Down
7 changes: 4 additions & 3 deletions packages/mask/popups/Popup.tsx
Expand Up @@ -41,7 +41,7 @@ import { Modals } from './modals/index.js'
import SwitchWallet from './pages/Wallet/SwitchWallet/index.js'
import { noop } from 'lodash-es'
import { UserContext, queryPersistOptions } from '../shared-ui/index.js'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
// import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { queryClient } from '@masknet/shared-base-ui'

Expand Down Expand Up @@ -179,9 +179,10 @@ export default function Popups() {

return (
<PersistQueryClientProvider client={queryClient} persistOptions={queryPersistOptions}>
{process.env.NODE_ENV === 'development' ?
{/* https://github.com/TanStack/query/issues/5417 */}
{/* {process.env.NODE_ENV === 'development' ?
<ReactQueryDevtools buttonPosition="bottom-right" />
: null}
: null} */}
{PageUIProvider(
usePopupTheme,
<PopupSnackbarProvider>
Expand Down
10 changes: 10 additions & 0 deletions packages/mask/public/js/trusted-types.js
@@ -0,0 +1,10 @@
/// <reference path="../../../polyfills/types/dom.d.ts" />

// This file must not be loaded via importScripts in a Worker, doing so the importScripts will fail due to trustedTypes restriction.
// You can import this file (not importScripts) so webpack will bundle this into the initial chunk. This requires the worker have no multiple initial chunks.
if (typeof trustedTypes === 'object' && location.protocol.includes('extension')) {
// DO NOT add createHTML or createScript.
trustedTypes.createPolicy('default', { createScriptURL: (string) => string })
}

undefined
3 changes: 3 additions & 0 deletions packages/mask/public/manifest-v3.entry.js
@@ -1,5 +1,8 @@
// this file must be in the root due to limitation of mv3 service worker.
try {
if (typeof trustedTypes === 'object') {
trustedTypes.createPolicy('default', { createScriptURL: (string) => string })
}
importScripts(
'/worker.js',
'/js/gun.js',
Expand Down
9 changes: 9 additions & 0 deletions packages/mask/public/worker.js
Expand Up @@ -5,3 +5,12 @@ importScripts(
'/js/lockdown.js',
'/js/module-loader.js',
)

// Workaround: Webpack child compiler doesn't inherit plugins but inherit loaders,
// therefore react-refresh (by swc-loader) breaks the worker code.
self.$RefreshReg$ = function () {}
self.$RefreshSig$ = function () {
return function (type) {
return type
}
}
23 changes: 0 additions & 23 deletions packages/mask/web-workers/prepare.ts
@@ -1,25 +1,2 @@
/// <reference path="../../polyfills/types/dom.d.ts" />
if (typeof trustedTypes === 'object' && location.protocol.includes('extension')) {
trustedTypes.createPolicy('default', {
// do not add createHTML or createScript.
// createScriptURL is safe because according to the CSP we have, it is impossible to
// include/create a script from cross-origin.
createScriptURL: (string) => string,
})
}

importScripts('/worker.js')
if (typeof self !== 'undefined') {
/**
* Workaround: Webpack child compiler doesn't inherit plugins but inherit loaders.
* That make loaders/plugins settings mismatch and cause runtime errors.
*/
Reflect.set(self, '$RefreshReg$', function () {})
Reflect.set(self, '$RefreshSig$', function () {
return function (type: any) {
return type
}
})
}
export {}
setTimeout(() => self.postMessage('Alive'), 0)
7 changes: 3 additions & 4 deletions packages/mask/web-workers/wallet.ts
Expand Up @@ -10,11 +10,8 @@ export type Output = {
response: api.MWResponse
}

async function load() {
return import('@dimensiondev/mask-wallet-core/bundle')
}
const promise = (async () => {
const { request } = await load()
const { request } = await import('@dimensiondev/mask-wallet-core/bundle')
const { api } = await import('@dimensiondev/mask-wallet-core/proto')
return { request, api }
})()
Expand All @@ -35,3 +32,5 @@ self.addEventListener('message', async (ev: MessageEvent) => {
self.postMessage(out)
}
})
// see: packages/shared-base/src/onDemandWorker/index.ts
self.postMessage('Alive')
8 changes: 4 additions & 4 deletions packages/shared/src/UI/contexts/SiteUIProvider.tsx
@@ -1,7 +1,6 @@
import { Suspense } from 'react'
import { createPortal } from 'react-dom'
import { QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
// import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { RootWeb3ContextProvider } from '@masknet/web3-hooks-base'
import { DialogStackingProvider } from '@masknet/theme'
import { compose, i18NextInstance } from '@masknet/shared-base'
Expand All @@ -20,9 +19,10 @@ function MaskUIRoot({ children }: React.PropsWithChildren<{}>) {
return (
<DialogStackingProvider hasGlobalBackdrop={false}>
<QueryClientProvider client={queryClient}>
{process.env.NODE_ENV === 'development' ?
{/* https://github.com/TanStack/query/issues/5417 */}
{/* {process.env.NODE_ENV === 'development' ?
createPortal(<ReactQueryDevtools buttonPosition="bottom-right" />, document.body)
: null}
: null} */}
<RootWeb3ContextProvider>
<I18NextProviderHMR i18n={i18NextInstance}>{children}</I18NextProviderHMR>
</RootWeb3ContextProvider>
Expand Down

0 comments on commit f2524b4

Please sign in to comment.