From 6945862ffcd9c00636f9dd858b0d38a96a1b15bc Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sat, 7 Dec 2019 17:41:36 +0800 Subject: [PATCH] fix: bitmask overflow better handle global --- src/compiler/compile/render_dom/Renderer.ts | 66 +++++++++++-------- .../samples/bitmask-overflow-2/_config.js | 3 + .../samples/bitmask-overflow-2/main.svelte | 35 ++++++++++ 3 files changed, 77 insertions(+), 27 deletions(-) create mode 100644 test/runtime/samples/bitmask-overflow-2/_config.js create mode 100644 test/runtime/samples/bitmask-overflow-2/main.svelte diff --git a/src/compiler/compile/render_dom/Renderer.ts b/src/compiler/compile/render_dom/Renderer.ts index 6de1c92f07..1f6550e2b4 100644 --- a/src/compiler/compile/render_dom/Renderer.ts +++ b/src/compiler/compile/render_dom/Renderer.ts @@ -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 bitmask; - 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() { diff --git a/test/runtime/samples/bitmask-overflow-2/_config.js b/test/runtime/samples/bitmask-overflow-2/_config.js new file mode 100644 index 0000000000..0b63791292 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-2/_config.js @@ -0,0 +1,3 @@ +export default { + error: `potato is not defined`, +}; \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-2/main.svelte b/test/runtime/samples/bitmask-overflow-2/main.svelte new file mode 100644 index 0000000000..10fa1bd5e2 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-2/main.svelte @@ -0,0 +1,35 @@ + +

{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}

\ No newline at end of file