Browse Source

ignore IIFEs for the purposes of determining strong/weak dependencies

contingency-plan
Rich Harris 10 years ago
parent
commit
94c3852929
  1. 48
      src/Statement.js
  2. 15
      test/function/iife-strong-dependencies/A.js
  3. 11
      test/function/iife-strong-dependencies/B.js
  4. 11
      test/function/iife-strong-dependencies/C.js
  5. 15
      test/function/iife-strong-dependencies/D.js
  6. 15
      test/function/iife-strong-dependencies/_config.js
  7. 14
      test/function/iife-strong-dependencies/main.js

48
src/Statement.js

@ -4,6 +4,10 @@ import getLocation from './utils/getLocation';
import walk from './ast/walk';
import Scope from './ast/Scope';
function isIife ( node, parent ) {
return parent && parent.type === 'CallExpression' && node === parent.callee;
}
export default class Statement {
constructor ( node, magicString, module, index ) {
this.node = node;
@ -38,7 +42,7 @@ export default class Statement {
let scope = this.scope;
walk( this.node, {
enter ( node ) {
enter ( node, parent ) {
let newScope;
magicString.addSourcemapLocation( node.start );
@ -66,10 +70,12 @@ export default class Statement {
break;
case 'BlockStatement':
newScope = new Scope({
parent: scope,
block: true
});
if ( !/Function/.test( parent.type ) ) {
newScope = new Scope({
parent: scope,
block: true
});
}
break;
@ -105,16 +111,35 @@ export default class Statement {
}
});
// This allows us to track whether we're looking at code that will
// be executed immediately (either outside a function, or immediately
// inside an IIFE), for the purposes of determining whether dependencies
// are strong or weak. It's not bulletproof, since it wouldn't catch...
//
// var calledImmediately = function () {
// doSomethingWith( strongDependency );
// }
// calledImmediately();
//
// ...but it's better than nothing
let depth = 0;
if ( !this.isImportDeclaration ) {
walk( this.node, {
enter: ( node, parent ) => {
if ( node._scope ) scope = node._scope;
if ( node._scope ) {
if ( !scope.isBlockScope && !isIife( node, parent ) ) depth += 1;
scope = node._scope;
}
this.checkForReads( scope, node, parent );
this.checkForReads( scope, node, parent, !depth );
this.checkForWrites( scope, node );
},
leave: ( node ) => {
if ( node._scope ) scope = scope.parent;
leave: ( node, parent ) => {
if ( node._scope ) {
if ( !scope.isBlockScope && !isIife( node, parent ) ) depth -= 1;
scope = scope.parent;
}
}
});
}
@ -124,7 +149,7 @@ export default class Statement {
});
}
checkForReads ( scope, node, parent ) {
checkForReads ( scope, node, parent, strong ) {
if ( node.type === 'Identifier' ) {
// disregard the `bar` in `foo.bar` - these appear as Identifier nodes
if ( parent.type === 'MemberExpression' && node !== parent.object ) {
@ -143,8 +168,7 @@ export default class Statement {
if ( ( !definingScope || definingScope.depth === 0 ) && !this.defines[ node.name ] ) {
this.dependsOn[ node.name ] = true;
if ( !scope.parent ) this.stronglyDependsOn[ node.name ] = true;
if ( strong ) this.stronglyDependsOn[ node.name ] = true;
}
}
}

15
test/function/iife-strong-dependencies/A.js

@ -0,0 +1,15 @@
import { B } from './B';
export var A = function () {
this.isA = true;
};
A.prototype = {
b: function () {
var Constructor = B;
return function () {
return new Constructor();
};
}()
};

11
test/function/iife-strong-dependencies/B.js

@ -0,0 +1,11 @@
import { A } from './A';
export var B = function () {
this.isB = true;
};
B.prototype = {
a: function () {
return new A();
}
};

11
test/function/iife-strong-dependencies/C.js

@ -0,0 +1,11 @@
import { D } from './D';
export var C = function () {
this.isC = true;
};
C.prototype = {
d: function () {
return new D();
}
};

15
test/function/iife-strong-dependencies/D.js

@ -0,0 +1,15 @@
import { C } from './C';
export var D = function () {
this.isD = true;
};
D.prototype = {
c: function () {
var Constructor = C;
return function () {
return new Constructor();
};
}()
};

15
test/function/iife-strong-dependencies/_config.js

@ -0,0 +1,15 @@
var assert = require( 'assert' );
module.exports = {
description: 'does not treat references inside IIFEs as weak dependencies', // edge case encountered in THREE.js codebase
exports: function ( exports ) {
assert.ok( exports.a1.isA );
assert.ok( exports.b1.isB );
assert.ok( exports.c1.isC );
assert.ok( exports.d1.isD );
assert.ok( exports.a2.isA );
assert.ok( exports.b2.isB );
assert.ok( exports.c2.isC );
assert.ok( exports.d2.isD );
}
};

14
test/function/iife-strong-dependencies/main.js

@ -0,0 +1,14 @@
import { A } from './A';
import { B } from './B';
import { C } from './C';
import { D } from './D';
export var a1 = new A();
export var b1 = new B();
export var c1 = new C();
export var d1 = new D();
export var a2 = b1.a();
export var b2 = a1.b();
export var c2 = d1.c();
export var d2 = c1.d();
Loading…
Cancel
Save