fix: improved inlining

This commit is contained in:
cha0s 2022-04-04 03:11:06 -05:00
parent e05bae167a
commit d24e8d9368
2 changed files with 28 additions and 9 deletions

View File

@ -1,10 +1,10 @@
import {parse} from '@babel/parser'; import {parse} from '@babel/parser';
export default (code) => { export default (code, options) => {
try { try {
return parse(code); return parse(code, options);
} }
catch (error) { catch (error) {
throw new Error(`Error parsing code: ${error.message}\nParsing:\n${code}`); throw new Error(`Error parsing code: ${error.message}\nParsing:\n${code}\nwith options:${JSON.stringify(options)}`);
} }
}; };

View File

@ -8,6 +8,10 @@ import {
types, types,
walkAncestor, walkAncestor,
} from '@avocado/code'; } from '@avocado/code';
import {D} from '@flecks/core';
const debug = D('@avocado/entity/accessors');
const debugSilly = debug.extend('silly');
const blacklistedAccessorKeys = [ const blacklistedAccessorKeys = [
's13nId', 's13nId',
@ -56,28 +60,43 @@ function traitAccessorForProperty(type, property, descriptor) {
} }
let {get, set} = descriptor; let {get, set} = descriptor;
if (get) { if (get) {
const getAst = extractFunction(parse(`(${get.toString()})`)); debugSilly('trying to inline %s.%s.get', type, property);
// @todo instead of this, we could stage it in an object literal, as below.
let getString = get.toString();
if (getString.startsWith('get ')) {
getString = `function ${getString.slice(4)}`;
}
const getAst = extractFunction(parse(`(${getString})`, {allowSuperOutsideMethod: true}));
if (hasExternalDependency(getAst)) { if (hasExternalDependency(getAst)) {
debugSilly('BAIL: external (%s)', type, property, generate(getAst.body).code);
// eslint-disable-next-line no-new-func // eslint-disable-next-line no-new-func
get = new Function('', `return this.traits['${type}']['${property}'];`); get = new Function('', `return this.traits['${type}']['${property}'];`);
} }
else { else {
debugSilly('optimized');
rewriteTraitThisToEntityThis(type)(getAst); rewriteTraitThisToEntityThis(type)(getAst);
// eslint-disable-next-line no-new-func // eslint-disable-next-line no-eval
get = new Function('', generate(getAst.body).code); ({get} = eval(`({ get() ${generate(getAst.body).code} })`));
} }
} }
if (set) { if (set) {
const setAst = extractFunction(parse(`(${set.toString()})`)); debugSilly('trying to inline %s.%s.set', type, property);
let setString = set.toString();
if (setString.startsWith('set ')) {
setString = `function ${setString.slice(4)}`;
}
const setAst = extractFunction(parse(`(${setString})`, {allowSuperOutsideMethod: true}));
if (hasExternalDependency(setAst)) { if (hasExternalDependency(setAst)) {
debugSilly('BAIL: external (%s)', type, property, generate(setAst.body).code);
// eslint-disable-next-line no-new-func // eslint-disable-next-line no-new-func
set = new Function('value', `this.traits['${type}']['${property}'] = value;`); set = new Function('value', `this.traits['${type}']['${property}'] = value;`);
} }
else { else {
debugSilly('optimized');
rewriteTraitThisToEntityThis(type)(setAst); rewriteTraitThisToEntityThis(type)(setAst);
rewriteParams(setAst, [types.identifier('value')]); rewriteParams(setAst, [types.identifier('value')]);
// eslint-disable-next-line no-new-func // eslint-disable-next-line no-eval
set = new Function('value', generate(setAst.body).code); ({set} = eval(`({ set(value) ${generate(setAst.body).code} })`));
} }
} }
if (!(type in traitAccessorForPropertyMap)) { if (!(type in traitAccessorForPropertyMap)) {