add virtualDom adjustment transformation

This commit is contained in:
mdgriffith 2020-08-07 23:44:37 -04:00
parent e2c4ca289e
commit a1036c5ca3
3 changed files with 123 additions and 2 deletions

View File

@ -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;
}

View 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);
};
};

View File

@ -14,6 +14,7 @@ export interface ElmVariant {
export type Transforms = {
prepack: boolean;
replaceVDomNode: boolean;
variantShapes: boolean;
inlineEquality: boolean;
inlineFunctions: boolean;