From 54b713ce5a721736a0be1eaa701d1c37ee079697 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Tue, 22 Nov 2016 16:52:16 -0500 Subject: [PATCH] prevent infinite observe loops --- compiler/generate/index.js | 14 ++++++++-- .../compiler/observe-prevents-loop/_config.js | 27 +++++++++++++++++++ test/compiler/observe-prevents-loop/main.html | 1 + 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 test/compiler/observe-prevents-loop/_config.js create mode 100644 test/compiler/observe-prevents-loop/main.html diff --git a/compiler/generate/index.js b/compiler/generate/index.js index 2db1a3e7c7..86daa25d91 100644 --- a/compiler/generate/index.js +++ b/compiler/generate/index.js @@ -302,7 +302,12 @@ export default function generate ( parsed, source, options ) { if ( !callbacks ) continue; for ( let i = 0; i < callbacks.length; i += 1 ) { - callbacks[i].call( component, newValue, oldValue ); + const callback = callbacks[i]; + if ( callback.__calling ) continue; + + callback.__calling = true; + callback.call( component, newValue, oldValue ); + callback.__calling = false; } } } @@ -328,7 +333,12 @@ export default function generate ( parsed, source, options ) { const group = options.defer ? observers.deferred : observers.immediate; ( group[ key ] || ( group[ key ] = [] ) ).push( callback ); - if ( options.init !== false ) callback( state[ key ] ); + + if ( options.init !== false ) { + callback.__calling = true; + callback.call( component, state[ key ] ); + callback.__calling = false; + } return { cancel () { diff --git a/test/compiler/observe-prevents-loop/_config.js b/test/compiler/observe-prevents-loop/_config.js new file mode 100644 index 0000000000..7f545631ed --- /dev/null +++ b/test/compiler/observe-prevents-loop/_config.js @@ -0,0 +1,27 @@ +export default { + data: { + thing: { a: 1 } + }, + + test ( assert, component ) { + const thing = component.get( 'thing' ); + + component.observe( 'thing', function ( thing ) { + thing.b = thing.a * 2; + this.set({ thing }); // triggers infinite loop, unless observer breaks it + }); + + assert.deepEqual( thing, { + a: 1, + b: 2 + }); + + thing.a = 3; + component.set({ thing }); + + assert.deepEqual( thing, { + a: 3, + b: 6 + }); + } +}; diff --git a/test/compiler/observe-prevents-loop/main.html b/test/compiler/observe-prevents-loop/main.html new file mode 100644 index 0000000000..7c89b545c5 --- /dev/null +++ b/test/compiler/observe-prevents-loop/main.html @@ -0,0 +1 @@ +