Skip to content

Commit 9df5ba7

Browse files
Fix PostCSS crash when using toJSON() (#18083)
When I added source maps to PostCSS I mistakenly assumed that `.source` on a node could be `undefined`. The comment above the property in PostCSS says that `source` can be `undefined` but this is a commentary on the value upon **access** not its expected value on **write**: ```ts declare abstract class Node_ { /** * … * * The nodes that are created manually using the public APIs * provided by PostCSS will have `source` undefined and * will be absent in the source map. * * … */ source?: Node.Source } ``` Rather, what these types mean is that *if the property exists* it must be defined. But otherwise the property can be missing if a node has no source location metadata. This generally wasn't a problem with the string-returning APIs but the `toJSON()` API in PostCSS expects that `source` is defined if present. This caused a crash because our license comment doesn't have a source location. I've addressed this by deleting the `source` property from the node if source location data is not available. Fixes #18082 ref parcel-bundler/parcel#10161
1 parent a42251c commit 9df5ba7

File tree

1 file changed

+18
-4
lines changed
  • packages/@tailwindcss-postcss/src

1 file changed

+18
-4
lines changed

packages/@tailwindcss-postcss/src/ast.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@ export function cssAstToPostCssAst(ast: AstNode[], source: PostcssSource | undef
4949
}
5050
}
5151

52+
function updateSource(astNode: PostCssChildNode, loc: SourceLocation | undefined) {
53+
let source = toSource(loc)
54+
55+
// The `source` property on PostCSS nodes must be defined if present because
56+
// `toJSON()` reads each property and tries to read from source.input if it
57+
// sees a `source` property. This means for a missing or otherwise absent
58+
// source it must be *missing* from the object rather than just `undefined`
59+
if (source) {
60+
astNode.source = source
61+
} else {
62+
delete astNode.source
63+
}
64+
}
65+
5266
function transform(node: AstNode, parent: PostCssContainerNode) {
5367
// Declaration
5468
if (node.kind === 'declaration') {
@@ -57,14 +71,14 @@ export function cssAstToPostCssAst(ast: AstNode[], source: PostcssSource | undef
5771
value: node.value ?? '',
5872
important: node.important,
5973
})
60-
astNode.source = toSource(node.src)
74+
updateSource(astNode, node.src)
6175
parent.append(astNode)
6276
}
6377

6478
// Rule
6579
else if (node.kind === 'rule') {
6680
let astNode = postcss.rule({ selector: node.selector })
67-
astNode.source = toSource(node.src)
81+
updateSource(astNode, node.src)
6882
astNode.raws.semicolon = true
6983
parent.append(astNode)
7084
for (let child of node.nodes) {
@@ -75,7 +89,7 @@ export function cssAstToPostCssAst(ast: AstNode[], source: PostcssSource | undef
7589
// AtRule
7690
else if (node.kind === 'at-rule') {
7791
let astNode = postcss.atRule({ name: node.name.slice(1), params: node.params })
78-
astNode.source = toSource(node.src)
92+
updateSource(astNode, node.src)
7993
astNode.raws.semicolon = true
8094
parent.append(astNode)
8195
for (let child of node.nodes) {
@@ -90,7 +104,7 @@ export function cssAstToPostCssAst(ast: AstNode[], source: PostcssSource | undef
90104
// spaces.
91105
astNode.raws.left = ''
92106
astNode.raws.right = ''
93-
astNode.source = toSource(node.src)
107+
updateSource(astNode, node.src)
94108
parent.append(astNode)
95109
}
96110

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy