mirror of
https://github.com/mdgriffith/elm-optimize-level-2.git
synced 2024-11-25 22:50:42 +03:00
add virtualDom adjustment transformation
This commit is contained in:
parent
e2c4ca289e
commit
a1036c5ca3
@ -24,6 +24,7 @@ import {
|
||||
} from './experiments/modernizeJS';
|
||||
import { createRemoveUnusedLocalsTransform } from './experiments/removeUnusedLocals';
|
||||
import { createPassUnwrappedFunctionsTransformer } from './experiments/passUnwrappedFunctions';
|
||||
import { replaceVDomNode } from './experiments/correctVirtualDom';
|
||||
|
||||
export const compileAndTransform = async (
|
||||
dir: string,
|
||||
@ -54,7 +55,7 @@ export const compileAndTransform = async (
|
||||
|
||||
let parsed = parseDir('elm-packages');
|
||||
parsedVariants = parsedVariants.concat(parsed);
|
||||
const source = ts.createSourceFile(
|
||||
let source = ts.createSourceFile(
|
||||
'elm.js',
|
||||
fs.readFileSync(pathInOutput('elm.opt.js'), 'utf-8'),
|
||||
ts.ScriptTarget.ES2018
|
||||
@ -65,8 +66,15 @@ export const compileAndTransform = async (
|
||||
Mode.Prod
|
||||
);
|
||||
|
||||
// We have to ensure that this transformation takes place before everything else
|
||||
if (options.replaceVDomNode) {
|
||||
const results = ts.transform(source, [replaceVDomNode()]);
|
||||
source = results.transformed[0];
|
||||
}
|
||||
|
||||
let inlineCtx: InlineContext | undefined;
|
||||
const transformations = removeDisabled([
|
||||
const transformations: any[] = removeDisabled([
|
||||
// [options.replaceVDomNode, replaceVDomNode()],
|
||||
[options.variantShapes, normalizeVariantShapes],
|
||||
[
|
||||
options.inlineFunctions,
|
||||
@ -152,6 +160,7 @@ function removeDisabled(list: any[]) {
|
||||
newList.push(item[1]);
|
||||
}
|
||||
});
|
||||
|
||||
return newList;
|
||||
}
|
||||
|
||||
|
111
src/experiments/correctVirtualDom.ts
Normal file
111
src/experiments/correctVirtualDom.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import ts from 'typescript';
|
||||
|
||||
const newVDomNode = `_VirtualDom_node = F3(function (tag, factList, kidList) {
|
||||
for (var kids = [], descendantsCount = 0; kidList.b; kidList = kidList.b) // WHILE_CONS
|
||||
{
|
||||
var kid = kidList.a;
|
||||
descendantsCount += (kid.b || 0);
|
||||
kids.push(kid);
|
||||
}
|
||||
descendantsCount += kids.length;
|
||||
return {
|
||||
$: 1,
|
||||
c: tag,
|
||||
d: _VirtualDom_organizeFacts(factList),
|
||||
e: kids,
|
||||
f: undefined,
|
||||
b: descendantsCount
|
||||
};
|
||||
})`;
|
||||
|
||||
const prename = `_VirtualDom_node_prename = function (tag){
|
||||
return F2(function (factList, kidList) {
|
||||
for (var kids = [], descendantsCount = 0; kidList.b; kidList = kidList.b) // WHILE_CONS
|
||||
{
|
||||
var kid = kidList.a;
|
||||
descendantsCount += (kid.b || 0);
|
||||
kids.push(kid);
|
||||
}
|
||||
descendantsCount += kids.length;
|
||||
return {
|
||||
$: 1,
|
||||
c: tag,
|
||||
d: _VirtualDom_organizeFacts(factList),
|
||||
e: kids,
|
||||
f: undefined,
|
||||
b: descendantsCount
|
||||
};
|
||||
});
|
||||
}`;
|
||||
|
||||
// $elm$virtual_dom$VirtualDom$node
|
||||
// tag == "script" ? "p" : tag
|
||||
|
||||
const apiNewVDomNode = `$elm$virtual_dom$VirtualDom$node = F3(function (tag, factList, kidList) {
|
||||
for (var kids = [], descendantsCount = 0; kidList.b; kidList = kidList.b) // WHILE_CONS
|
||||
{
|
||||
var kid = kidList.a;
|
||||
descendantsCount += (kid.b || 0);
|
||||
kids.push(kid);
|
||||
}
|
||||
descendantsCount += kids.length;
|
||||
return {
|
||||
$: 1,
|
||||
c: tag === "script" ? "p" : tag,
|
||||
d: _VirtualDom_organizeFacts(factList),
|
||||
e: kids,
|
||||
f: undefined,
|
||||
b: descendantsCount
|
||||
};
|
||||
})`;
|
||||
|
||||
const extractAstFromCode = (sourceText: string): ts.Node => {
|
||||
const source = ts.createSourceFile('bla', sourceText, ts.ScriptTarget.ES2018);
|
||||
|
||||
return source.statements[0];
|
||||
};
|
||||
|
||||
export const replaceVDomNode = (): ts.TransformerFactory<ts.SourceFile> => context => {
|
||||
return sourceFile => {
|
||||
const visitor = (node: ts.Node): ts.VisitResult<ts.Node> => {
|
||||
if (ts.isVariableDeclaration(node)) {
|
||||
if (
|
||||
ts.isIdentifier(node.name) &&
|
||||
node.name.text == '_VirtualDom_node'
|
||||
) {
|
||||
let body = extractAstFromCode(newVDomNode);
|
||||
let prenamedNode = extractAstFromCode(prename);
|
||||
|
||||
if (
|
||||
ts.isExpressionStatement(body) &&
|
||||
ts.isBinaryExpression(body.expression)
|
||||
) {
|
||||
return ts.createVariableDeclaration(
|
||||
'_VirtualDom_node',
|
||||
undefined,
|
||||
body.expression.right
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
ts.isIdentifier(node.name) &&
|
||||
node.name.text == '$elm$virtual_dom$VirtualDom$node'
|
||||
) {
|
||||
let body = extractAstFromCode(apiNewVDomNode);
|
||||
if (ts.isExpressionStatement(body)) {
|
||||
if (ts.isBinaryExpression(body.expression)) {
|
||||
return ts.createVariableDeclaration(
|
||||
'$elm$virtual_dom$VirtualDom$node',
|
||||
undefined,
|
||||
body.expression.right
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ts.visitEachChild(node, visitor, context);
|
||||
};
|
||||
|
||||
return ts.visitNode(sourceFile, visitor);
|
||||
};
|
||||
};
|
@ -14,6 +14,7 @@ export interface ElmVariant {
|
||||
|
||||
export type Transforms = {
|
||||
prepack: boolean;
|
||||
replaceVDomNode: boolean;
|
||||
variantShapes: boolean;
|
||||
inlineEquality: boolean;
|
||||
inlineFunctions: boolean;
|
||||
|
Loading…
Reference in New Issue
Block a user