Skip to content

Commit

Permalink
Merge pull request #1488 from mischnic/fixup-fromJSON
Browse files Browse the repository at this point in the history
Fixup JSON AST conversion
  • Loading branch information
ai committed Dec 9, 2020
2 parents 49bb511 + 052e50c commit 2326772
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 29 deletions.
49 changes: 27 additions & 22 deletions lib/fromJSON.js
Expand Up @@ -8,35 +8,40 @@ let Input = require('./input')
let Root = require('./root')
let Rule = require('./rule')

function fromJSON (json) {
let defaults = { ...json }
if (json.nodes) {
defaults.nodes = json.nodes.map(i => fromJSON(i))
}
if (json.type === 'root') {
if (defaults.source) {
defaults.source = { ...defaults.source }
if (defaults.source.input) {
defaults.source.input = {
...defaults.source.input,
__proto__: Input.prototype
}
if (defaults.source.input.map) {
defaults.source.input.map = {
...defaults.source.input.map,
__proto__: PreviousMap.prototype
}
function fromJSON (json, inputs) {
let { inputs: ownInputs, ...defaults } = json
if (ownInputs) {
inputs = []
for (let input of ownInputs) {
let inputHydrated = { ...input, __proto__: Input.prototype }
if (inputHydrated.map) {
inputHydrated.map = {
...inputHydrated.map,
__proto__: PreviousMap.prototype
}
}
inputs.push(inputHydrated)
}
}
if (defaults.nodes) {
defaults.nodes = json.nodes.map(n => fromJSON(n, inputs))
}
if (defaults.source) {
let { inputId, ...source } = defaults.source
defaults.source = source
if (inputId != null) {
defaults.source.input = inputs[inputId]
}
}
if (defaults.type === 'root') {
return new Root(defaults)
} else if (json.type === 'decl') {
} else if (defaults.type === 'decl') {
return new Declaration(defaults)
} else if (json.type === 'rule') {
} else if (defaults.type === 'rule') {
return new Rule(defaults)
} else if (json.type === 'comment') {
} else if (defaults.type === 'comment') {
return new Comment(defaults)
} else if (json.type === 'atrule') {
} else if (defaults.type === 'atrule') {
return new AtRule(defaults)
} else {
throw new Error('Unknown node type: ' + json.type)
Expand Down
26 changes: 20 additions & 6 deletions lib/node.js
Expand Up @@ -166,8 +166,11 @@ class Node {
if (!keepBetween) delete this.raws.between
}

toJSON () {
toJSON (inputs) {
let fixed = {}
let emitInputs = inputs == null
inputs = inputs || new Map()
let inputsNextIndex = 0

for (let name in this) {
if (!Object.prototype.hasOwnProperty.call(this, name)) {
Expand All @@ -180,23 +183,34 @@ class Node {
if (Array.isArray(value)) {
fixed[name] = value.map(i => {
if (typeof i === 'object' && i.toJSON) {
return i.toJSON()
return i.toJSON(inputs)
} else {
return i
}
})
} else if (typeof value === 'object' && value.toJSON) {
fixed[name] = value.toJSON()
} else if (this.type === 'root' && name === 'source') {
fixed[name] = value.toJSON(inputs)
} else if (name === 'source') {
let inputId = inputs.get(value.input)
if (inputId == null) {
inputId = inputsNextIndex
inputs.set(value.input, inputsNextIndex)
inputsNextIndex++
}
fixed[name] = {
input: value.input.toJSON(),
start: value.start
inputId,
start: value.start,
end: value.end
}
} else {
fixed[name] = value
}
}

if (emitInputs) {
fixed.inputs = [...inputs.keys()].map(input => input.toJSON())
}

return fixed
}

Expand Down
13 changes: 12 additions & 1 deletion test/fromJSON.test.ts
Expand Up @@ -6,7 +6,7 @@ it('rehydrates a JSON AST', () => {
let cssWithMap = postcss().process(
'.foo { color: red; font-size: 12pt; } /* abc */ @media (width: 60em) { }',
{
from: undefined,
from: 'x.css',
map: {
inline: true
},
Expand All @@ -24,6 +24,17 @@ it('rehydrates a JSON AST', () => {
rehydrated.nodes[0].remove()

expect(rehydrated.nodes).toHaveLength(3)

expect(
postcss().process(rehydrated, {
from: undefined,
map: {
inline: true
},
stringifier: postcss.stringify
}).css
).toBe(`/* abc */ @media (width: 60em) { }
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInguY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFzQyxRQUFRLEVBQUUsdUJBQXVCIiwiZmlsZSI6InRvLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb28geyBjb2xvcjogcmVkOyBmb250LXNpemU6IDEycHQ7IH0gLyogYWJjICovIEBtZWRpYSAod2lkdGg6IDYwZW0pIHsgfSJdfQ== */`)
})

it('throws when rehydrating an invalid JSON AST', () => {
Expand Down
1 change: 1 addition & 0 deletions test/node.test.ts
Expand Up @@ -292,6 +292,7 @@ it('toJSON() converts custom properties', () => {
nodes: [],
raws: {},
_hack: 'hack',
inputs: [],
_cache: [1]
})
})
Expand Down

0 comments on commit 2326772

Please sign in to comment.