-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Optimise parsed AST #3766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimise parsed AST #3766
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export function is_string(node) { | ||
return node.type === 'TemplateLiteral' || (node.type === 'Literal' && typeof node.value === 'string'); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { walk } from 'estree-walker'; | ||
import { Text, MustacheTag } from '../../interfaces'; | ||
|
||
export default function optimise(ast) { | ||
walk(ast, { | ||
enter(node: any) { | ||
if (node.type === 'Element') { | ||
optimise_text_content(node.children); | ||
} | ||
}, | ||
}); | ||
} | ||
|
||
const text_like_node_type = new Set(['MustacheTag', 'Text']); | ||
|
||
function optimise_text_content(children) { | ||
let start = 0; | ||
let end = 0; | ||
|
||
do { | ||
while ( | ||
start < children.length && | ||
!text_like_node_type.has(children[start].type) | ||
) | ||
start++; | ||
|
||
end = start; | ||
|
||
while (end < children.length && text_like_node_type.has(children[end].type)) | ||
end++; | ||
|
||
// based on heuristic, | ||
// require more than 2 neighouring text contents to merge yields smaller content | ||
if (end > start + 2) { | ||
const merged = merge_text_siblings(children.slice(start, end)); | ||
children.splice(start, end - start, merged); | ||
} | ||
start = end; | ||
} while (start < children.length); | ||
} | ||
|
||
function merge_text_siblings(children: Array<Text | MustacheTag>) { | ||
|
||
const literal = { | ||
type: 'TemplateLiteral', | ||
expressions: [], | ||
quasis: [], | ||
}; | ||
const state = { | ||
quasi: { | ||
type: 'TemplateElement', | ||
value: { raw: '' }, | ||
start: children[0].start, | ||
end: children[0].start | ||
}, | ||
}; | ||
|
||
for (const child of children) { | ||
if (child.type === 'MustacheTag') { | ||
literal.quasis.push(state.quasi); | ||
literal.expressions.push(child.expression); | ||
state.quasi = { | ||
type: 'TemplateElement', | ||
value: { raw: '' }, | ||
// @ts-ignore | ||
start: child.expression.end + 1, | ||
// @ts-ignore | ||
end: child.expression.end + 1 | ||
}; | ||
} else if (child.type === 'Text') { | ||
state.quasi.value.raw += child.data; | ||
state.quasi.end = child.end; | ||
} | ||
} | ||
|
||
literal.quasis.push(state.quasi); | ||
|
||
return { | ||
type: 'MustacheTag', | ||
expression: literal, | ||
start: children[0].start, | ||
end: children[children.length - 1].end, | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,18 +19,16 @@ const file = undefined; | |
|
||
function create_fragment(ctx) { | ||
let h1; | ||
let t0_fn = ctx => `Hello ${ctx.name}!`; | ||
let t0_value = t0_fn(ctx); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should be able to hoist these functions out of the block altogether, I think? (I still have an ambition to merge the create/update phases so that we can just 'update' everything to its initial state, rather than having this duplication at all. But that's a future nice-to-have) |
||
let t0; | ||
let t1; | ||
let t2; | ||
let t3; | ||
|
||
const block = { | ||
c: function create() { | ||
h1 = element("h1"); | ||
t0 = text("Hello "); | ||
t1 = text(ctx.name); | ||
t2 = text("!"); | ||
t3 = space(); | ||
t0 = text(t0_value); | ||
t1 = space(); | ||
debugger; | ||
add_location(h1, file, 4, 0, 38); | ||
}, | ||
|
@@ -40,19 +38,17 @@ function create_fragment(ctx) { | |
m: function mount(target, anchor) { | ||
insert_dev(target, h1, anchor); | ||
append_dev(h1, t0); | ||
append_dev(h1, t1); | ||
append_dev(h1, t2); | ||
insert_dev(target, t3, anchor); | ||
insert_dev(target, t1, anchor); | ||
}, | ||
p: function update(changed, ctx) { | ||
if (changed.name) set_data_dev(t1, ctx.name); | ||
if (changed.name && t0_value !== (t0_value = t0_fn(ctx))) set_data_dev(t0, t0_value); | ||
debugger; | ||
}, | ||
i: noop, | ||
o: noop, | ||
d: function destroy(detaching) { | ||
if (detaching) detach_dev(h1); | ||
if (detaching) detach_dev(t3); | ||
if (detaching) detach_dev(t1); | ||
} | ||
}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it'd be good if we didn't have the
+ ""
here, since it's coerced to a string anyway