From 389b10439ba4626d9bec43c6ad88941f41a764ce Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 5 Jan 2016 18:58:28 -0500 Subject: [PATCH] =?UTF-8?q?prevent=20stack=20overflow=20with=20mutual=20st?= =?UTF-8?q?rong=20dependencies=20=E2=80=93=20fixes=20#425?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Bundle.js | 8 +++++++- test/function/cycles-stack-overflow/_config.js | 3 +++ test/function/cycles-stack-overflow/b.js | 11 +++++++++++ test/function/cycles-stack-overflow/c.js | 13 +++++++++++++ test/function/cycles-stack-overflow/d.js | 12 ++++++++++++ test/function/cycles-stack-overflow/main.js | 3 +++ 6 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 test/function/cycles-stack-overflow/_config.js create mode 100644 test/function/cycles-stack-overflow/b.js create mode 100644 test/function/cycles-stack-overflow/c.js create mode 100644 test/function/cycles-stack-overflow/d.js create mode 100644 test/function/cycles-stack-overflow/main.js diff --git a/src/Bundle.js b/src/Bundle.js index fa53ae6..6bc9acc 100644 --- a/src/Bundle.js +++ b/src/Bundle.js @@ -335,19 +335,25 @@ export default class Bundle { let unordered = ordered; ordered = []; + let placed = blank(); + // unordered is actually semi-ordered, as [ fewer dependencies ... more dependencies ] unordered.forEach( module => { // ensure strong dependencies of `module` that don't strongly depend on `module` go first strongDeps[ module.id ].forEach( place ); function place ( dep ) { - if ( !stronglyDependsOn[ dep.id ][ module.id ] && !~ordered.indexOf( dep ) ) { + if ( placed[ dep.id ] ) return; + placed[ dep.id ] = true; + + if ( !stronglyDependsOn[ dep.id ][ module.id ] ) { strongDeps[ dep.id ].forEach( place ); ordered.push( dep ); } } if ( !~ordered.indexOf( module ) ) { + placed[ module.id ] = true; ordered.push( module ); } }); diff --git a/test/function/cycles-stack-overflow/_config.js b/test/function/cycles-stack-overflow/_config.js new file mode 100644 index 0000000..ea40267 --- /dev/null +++ b/test/function/cycles-stack-overflow/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'does not stack overflow on crazy cyclical dependencies' +}; diff --git a/test/function/cycles-stack-overflow/b.js b/test/function/cycles-stack-overflow/b.js new file mode 100644 index 0000000..df7267a --- /dev/null +++ b/test/function/cycles-stack-overflow/b.js @@ -0,0 +1,11 @@ +import { C } from './c.js'; + +export function B () {}; + +B.prototype = { + c: function () { + return function () { + new C(); + }; + }() +}; diff --git a/test/function/cycles-stack-overflow/c.js b/test/function/cycles-stack-overflow/c.js new file mode 100644 index 0000000..5ee8efd --- /dev/null +++ b/test/function/cycles-stack-overflow/c.js @@ -0,0 +1,13 @@ +import { D } from './d.js'; + +export function C () { + this.x = 'x'; +} + +C.prototype = { + d: function () { + return function () { + new D(); + }; + }() +}; diff --git a/test/function/cycles-stack-overflow/d.js b/test/function/cycles-stack-overflow/d.js new file mode 100644 index 0000000..4abd410 --- /dev/null +++ b/test/function/cycles-stack-overflow/d.js @@ -0,0 +1,12 @@ +import { B } from './b.js'; +import { C } from './c.js'; + +export function D () {}; + +D.prototype = { + c: function () { + return function () { + new C(); + }; + }() +}; diff --git a/test/function/cycles-stack-overflow/main.js b/test/function/cycles-stack-overflow/main.js new file mode 100644 index 0000000..1f1d737 --- /dev/null +++ b/test/function/cycles-stack-overflow/main.js @@ -0,0 +1,3 @@ +import { C } from './c.js'; + +assert.equal( new C().x, 'x' );