fix: bitmask overflow better handle global (#4063)

pull/4084/head
Tan Li Hau 5 years ago committed by Conduitry
parent 3e1e6cbd78
commit bb5cf9ada7

@ -15,6 +15,11 @@ interface ContextMember {
priority: number;
}
type BitMasks = Array<{
n: number;
names: string[];
}>;
export default class Renderer {
component: Component; // TODO Maybe Renderer shouldn't know about Component?
options: CompileOptions;
@ -199,26 +204,29 @@ export default class Renderer {
? x`$$self.$$.dirty`
: x`#dirty`) as Identifier | MemberExpression;
const get_bitmask = () => names.reduce((bitmask, name) => {
const member = renderer.context_lookup.get(name);
if (!member) return bitmask;
let bitmask;
const get_bitmask = () => {
const bitmask: BitMasks = [];
names.forEach((name) => {
const member = renderer.context_lookup.get(name);
if (member.index.value === -1) {
throw new Error(`unset index`);
}
if (!member) return;
const value = member.index.value as number;
const i = (value / 31) | 0;
const n = 1 << (value % 31);
if (member.index.value === -1) {
throw new Error(`unset index`);
}
if (!bitmask[i]) bitmask[i] = { n: 0, names: [] };
const value = member.index.value as number;
const i = (value / 31) | 0;
const n = 1 << (value % 31);
bitmask[i].n |= n;
bitmask[i].names.push(name);
if (!bitmask[i]) bitmask[i] = { n: 0, names: [] };
bitmask[i].n |= n;
bitmask[i].names.push(name);
});
return bitmask;
}, Array((this.context.length / 31) | 0).fill(null));
};
let operator;
let left;
@ -231,21 +239,25 @@ export default class Renderer {
// to lazily create the node. TODO would be better if
// context was determined before rendering, so that
// this indirection was unnecessary
const bitmask = get_bitmask();
if (renderer.context_overflow) {
const expression = bitmask
.map((b, i) => ({ b, i }))
.filter(({ b }) => b)
.map(({ b, i }) => x`${dirty}[${i}] & /*${b.names.join(', ')}*/ ${b.n}`)
.reduce((lhs, rhs) => x`${lhs} | ${rhs}`);
({ operator, left, right } = expression);
} else {
({ operator, left, right } = x`${dirty} & /*${names.join(', ')}*/ ${bitmask[0] ? bitmask[0].n : 0}` as BinaryExpression); // TODO the `: 0` case should never apply
if (!bitmask) {
bitmask = get_bitmask();
if (!bitmask.length) {
({ operator, left, right } = x`${dirty} & /*${names.join(', ')}*/ 0` as BinaryExpression);
} else if (renderer.context_overflow) {
const expression = bitmask
.map((b, i) => ({ b, i }))
.filter(({ b }) => b)
.map(({ b, i }) => x`${dirty}[${i}] & /*${b.names.join(', ')}*/ ${b.n}`)
.reduce((lhs, rhs) => x`${lhs} | ${rhs}`);
({ operator, left, right } = expression as BinaryExpression);
} else {
({ operator, left, right } = x`${dirty} & /*${names.join(', ')}*/ ${bitmask[0].n}` as BinaryExpression);
}
}
return 'BinaryExpression';
},
get operator() {

@ -0,0 +1,3 @@
export default {
error: `potato is not defined`,
};

@ -0,0 +1,35 @@
<script>
export let x1;
export let x2;
export let x3;
export let x4;
export let x5;
export let x6;
export let x7;
export let x8;
export let x9;
export let x10;
export let x11;
export let x12;
export let x13;
export let x14;
export let x15;
export let x16;
export let x17;
export let x18;
export let x19;
export let x20;
export let x21;
export let x22;
export let x23;
export let x24;
export let x25;
export let x26;
export let x27;
export let x28;
export let x29;
export let x30;
export let x31;
export let x32;
</script>
<p {...potato}>{x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 + x26 + x27 + x28 + x29 + x30 + x31 + x32}</p>
Loading…
Cancel
Save