Skip to content

Commit

Permalink
fix: prototype pollution
Browse files Browse the repository at this point in the history
  • Loading branch information
kellymears committed Jun 27, 2023
1 parent 0403a1c commit 542eef5
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 53 deletions.
1 change: 1 addition & 0 deletions sources/@roots/bud-babel/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export default class BabelExtension extends Extension {
? this.app.path(this.app.cache.cacheDirectory, `babel`)
: false
}

/**
* Config file accessor
*/
Expand Down
22 changes: 12 additions & 10 deletions sources/@roots/entrypoints-webpack-plugin/src/html.emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Webpack from 'webpack'
* Emits inline html for each entrypoint
*
* @param compilation - Webpack compilation instance
* @param publicPath - public path for assets
* @param publicPath - public path for entrypoints
*/
export class HtmlEmitter {
/**
Expand All @@ -18,19 +18,19 @@ export class HtmlEmitter {
*/
public constructor(
public compilation: Webpack.Compilation,
public assets: Entrypoints,
public entrypoints: Entrypoints,
public publicPath: string,
) {}

/**
* Reduce entrypoint assets to markup
* Reduce entrypoint entrypoints to markup
*/
@bind
public emit(): void {
Object.entries(this.assets).map(([name, asset]) => {
Object.assign(this.compilation.assets, {
;[...this.entrypoints.entries()].map(([name, entrypoint]) => {
Object.assign(this.compilation, {
[`${name}.html`]: new Webpack.sources.RawSource(
Object.entries(asset).reduce(this.entrypointsReducer, ``),
[...entrypoint.entries()].reduce(this.entrypointsReducer, ``),
),
})
})
Expand All @@ -42,12 +42,12 @@ export class HtmlEmitter {
@bind
public entrypointsReducer(
acc: string,
[type, files]: [string, Array<string>],
[type, files]: [string, Set<string>],
): string {
if ([`js`, `mjs`].includes(type))
return files.reduce(this.scriptReducer, acc)
return [...files].reduce(this.scriptReducer, acc)

if (type === `css`) return files.reduce(this.styleReducer, acc)
if (type === `css`) return [...files].reduce(this.styleReducer, acc)

return acc
}
Expand All @@ -61,7 +61,9 @@ export class HtmlEmitter {
@bind
public getCompiledAsset(file: string) {
const raw =
this.compilation.assets[file.replace(this.publicPath, ``)]?.source()
this.compilation.entrypoints[
file.replace(this.publicPath, ``)
]?.source()

return raw instanceof Buffer ? raw.toString() : raw
}
Expand Down
6 changes: 2 additions & 4 deletions sources/@roots/entrypoints-webpack-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ import type {SyncHook, SyncWaterfallHook} from 'tapable'

export interface CompilationHooks {
compilation: SyncHook<Record<string, any>>
entrypoints: SyncWaterfallHook<Record<string, any>>
entrypoints: SyncWaterfallHook<Entrypoints>
}

/**
* Entrypoints
*/
export interface Entrypoints extends Record<string, unknown> {
[entry: string]: any
}
export type Entrypoints = Map<string, Map<string, Set<string>>>

/**
* EntrypointsWebpackPlugin options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ describe(`entrypoints.json`, () => {
chonk.files = new Set([`foo.js`, `bar.js`])
const files = entrypoints
.getChunkedFiles([chonk])
// @ts-ignore
.map(file => file.file)

expect(files.shift()).toMatchSnapshot(`foo.js`)
Expand All @@ -23,8 +24,6 @@ describe(`entrypoints.json`, () => {
publicPath: `/public/`,
})

entrypoints.entrypoints = {}

entrypoints.addToManifest({
ident: `runtime`,
type: `js`,
Expand Down
52 changes: 29 additions & 23 deletions sources/@roots/entrypoints-webpack-plugin/src/webpack.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import type {
Options,
} from '@roots/entrypoints-webpack-plugin'

import {bind} from 'helpful-decorators'
import uniq from 'lodash/uniq.js'
import {SyncHook, SyncWaterfallHook} from 'tapable'
import Webpack from 'webpack'

Expand Down Expand Up @@ -58,6 +56,12 @@ export class EntrypointsWebpackPlugin {
if (!this.options.name) {
this.options.name = `entrypoints.json`
}

this.entrypoints = new Map()

this.addToManifest = this.addToManifest.bind(this)
this.getChunkedFiles = this.getChunkedFiles.bind(this)
this.apply = this.apply.bind(this)
}

/**
Expand All @@ -82,7 +86,6 @@ export class EntrypointsWebpackPlugin {
return hooks
}

@bind
public addToManifest({
ident,
path,
Expand All @@ -92,26 +95,16 @@ export class EntrypointsWebpackPlugin {
path: string
type: string
}) {
if (this.options.type === `object`) {
if (!this.entrypoints[ident]) this.entrypoints[ident] = {}

if (!this.entrypoints[ident][type])
this.entrypoints[ident][type] = []

this.entrypoints[ident][type] = uniq([
...this.entrypoints[ident][type],
path,
])
} else {
if (!this.entrypoints[ident]) this.entrypoints[ident] = []
this.entrypoints[ident] = uniq([...this.entrypoints[ident], path])
}
!this.entrypoints.has(ident) && this.entrypoints.set(ident, new Map())

!this.entrypoints.get(ident).has(type)
? this.entrypoints.get(ident).set(type, new Set([path]))
: this.entrypoints.get(ident).get(type).add(path)
}

/**
* Webpack plugin API's `apply` hook
*/
@bind
public apply(compiler: Webpack.Compiler): void {
compiler.hooks.thisCompilation.tap(
this.constructor.name,
Expand All @@ -121,7 +114,7 @@ export class EntrypointsWebpackPlugin {
name: this.constructor.name,
stage: Webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
},
async assets => {
async () => {
const hooks =
EntrypointsWebpackPlugin.getCompilationHooks(compilation)
hooks.compilation.call(compilation)
Expand All @@ -133,7 +126,7 @@ export class EntrypointsWebpackPlugin {
)

if (!this.entrypoints) {
this.entrypoints = {}
this.entrypoints = new Map()

for (const entry of compilation.entrypoints.values()) {
this.getChunkedFiles(entry.chunks).map(({file}) => {
Expand Down Expand Up @@ -162,10 +155,23 @@ export class EntrypointsWebpackPlugin {
).emit()
}

assets[this.options.name] =
let source = {}
for (const [name, entry] of this.entrypoints.entries()) {
if (!source[name]) source[name] = {}

for (const [type, assets] of entry.entries()) {
if (!source[name][type]) source[name][type] = []

source[name][type] = [...assets]
}
}

compilation.emitAsset(
this.options.name,
new compiler.webpack.sources.RawSource(
JSON.stringify(this.entrypoints, null, 2),
)
JSON.stringify(source, null, 2),
),
)
},
)
},
Expand Down
31 changes: 17 additions & 14 deletions sources/@roots/wordpress-dependencies-webpack-plugin/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type {EntrypointsWebpackPlugin} from '@roots/entrypoints-webpack-plugin'
import type {
Entrypoints,
EntrypointsWebpackPlugin,
} from '@roots/entrypoints-webpack-plugin'
import type {Compilation} from 'webpack'

import {handle, wordpress} from '@roots/wordpress-transforms'
Expand Down Expand Up @@ -42,16 +45,16 @@ export default class WordPressDependenciesWebpackPlugin {
* Works for both our map of requests and our map of dependencies.
*/
public addItemToMap(
map: Map<string, Set<string>>,
obj: Map<string, Set<string>>,
key: string,
item: string,
) {
if (!map.has(key)) {
map.set(key, new Set([item]))
if (!obj.has(key)) {
obj.set(key, new Set([item]))
return
}

map.set(key, map.get(key).add(item))
obj.set(key, obj.get(key).add(item))
}

/**
Expand Down Expand Up @@ -140,14 +143,14 @@ export default class WordPressDependenciesWebpackPlugin {
* Tap entrypoints manifest object
*/
@bind
public tapEntrypointsManifestObject(assets: Record<string, any>) {
return Object.entries(assets)
.map(([k, v]) => {
v.dependencies = this.dependencies.has(k)
? [...this.dependencies.get(k)]
: []
return [k, v]
})
.reduce((a, [k, v]) => ({...a, [k]: v}), {})
public tapEntrypointsManifestObject(entrypoints: Entrypoints) {
for (const [ident, entrypoint] of entrypoints.entries())
if (this.dependencies.has(ident))
for (const dependency of this.dependencies.get(ident))
entrypoint.has(`dependencies`)
? entrypoint.get(`dependencies`).add(dependency)
: entrypoint.set(`dependencies`, new Set([dependency]))

return entrypoints
}
}

0 comments on commit 542eef5

Please sign in to comment.