rollup 0.49.3 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  /*
2
- Rollup.js v0.49.3
3
- Thu Sep 07 2017 21:02:36 GMT-0400 (EDT) - commit 0d20ed12e069b4fc445faecf221ffe5b40fbf90a
2
+ Rollup.js v0.50.0
3
+ Sat Sep 16 2017 09:48:09 GMT-0400 (EDT) - commit b949eb08169115ff66648838cbc4833379bf9440
4
4
 
5
5
 
6
6
  https://github.com/rollup/rollup
@@ -1986,15 +1986,15 @@ var types = {
1986
1986
  eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
1987
1987
  assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
1988
1988
  incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
1989
- prefix: new TokenType("prefix", {beforeExpr: true, prefix: true, startsExpr: true}),
1989
+ prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
1990
1990
  logicalOR: binop("||", 1),
1991
1991
  logicalAND: binop("&&", 2),
1992
1992
  bitwiseOR: binop("|", 3),
1993
1993
  bitwiseXOR: binop("^", 4),
1994
1994
  bitwiseAND: binop("&", 5),
1995
- equality: binop("==/!=", 6),
1996
- relational: binop("</>", 7),
1997
- bitShift: binop("<</>>", 8),
1995
+ equality: binop("==/!=/===/!==", 6),
1996
+ relational: binop("</>/<=/>=", 7),
1997
+ bitShift: binop("<</>>/>>>", 8),
1998
1998
  plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
1999
1999
  modulo: binop("%", 10),
2000
2000
  star: binop("*", 10),
@@ -2344,7 +2344,7 @@ var pp = Parser.prototype;
2344
2344
 
2345
2345
  // ## Parser utilities
2346
2346
 
2347
- var literal = /^(?:'((?:[^']|\.)*)'|"((?:[^"]|\.)*)"|;)/;
2347
+ var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/;
2348
2348
  pp.strictDirective = function(start) {
2349
2349
  var this$1 = this;
2350
2350
 
@@ -4058,7 +4058,7 @@ pp$3.parseTemplate = function(ref) {
4058
4058
 
4059
4059
  pp$3.isAsyncProp = function(prop) {
4060
4060
  return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
4061
- (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL) &&
4061
+ (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword) &&
4062
4062
  !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
4063
4063
  };
4064
4064
 
@@ -4934,7 +4934,7 @@ pp$8.readToken_caret = function() { // '^'
4934
4934
  pp$8.readToken_plus_min = function(code) { // '+-'
4935
4935
  var next = this.input.charCodeAt(this.pos + 1);
4936
4936
  if (next === code) {
4937
- if (next == 45 && this.input.charCodeAt(this.pos + 2) == 62 &&
4937
+ if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 &&
4938
4938
  (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
4939
4939
  // A `-->` line comment
4940
4940
  this.skipLineComment(3);
@@ -4955,9 +4955,8 @@ pp$8.readToken_lt_gt = function(code) { // '<>'
4955
4955
  if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
4956
4956
  return this.finishOp(types.bitShift, size)
4957
4957
  }
4958
- if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 &&
4958
+ if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 &&
4959
4959
  this.input.charCodeAt(this.pos + 3) == 45) {
4960
- if (this.inModule) { this.unexpected(); }
4961
4960
  // `<!--`, an XML-style comment that should be interpreted as a line comment
4962
4961
  this.skipLineComment(4);
4963
4962
  this.skipSpace();
@@ -5563,19 +5562,39 @@ function relativeId ( id ) {
5563
5562
  return relative( process.cwd(), id );
5564
5563
  }
5565
5564
 
5566
- const UNKNOWN_VALUE = { toString: () => '[[UNKNOWN]]' };
5565
+ class Variable {
5566
+ constructor ( name ) {
5567
+ this.name = name;
5568
+ }
5567
5569
 
5568
- const UNKNOWN_ASSIGNMENT = {
5569
- type: 'UNKNOWN',
5570
- hasEffectsWhenMutated: () => true,
5571
- };
5570
+ addCall () {}
5571
+
5572
+ getName () {
5573
+ return this.name;
5574
+ }
5575
+
5576
+ hasEffectsWhenCalled () {
5577
+ return true;
5578
+ }
5579
+
5580
+ hasEffectsWhenMutated () {
5581
+ return true;
5582
+ }
5583
+
5584
+ includeVariable () {
5585
+ if ( this.included ) {
5586
+ return false;
5587
+ }
5588
+ this.included = true;
5589
+ return true;
5590
+ }
5591
+ }
5572
5592
 
5573
- class SyntheticNamespaceDeclaration {
5593
+ class NamespaceVariable extends Variable {
5574
5594
  constructor ( module ) {
5595
+ super( module.basename() );
5575
5596
  this.isNamespace = true;
5576
5597
  this.module = module;
5577
- this.name = module.basename();
5578
-
5579
5598
  this.needsNamespaceBlock = false;
5580
5599
 
5581
5600
  this.originals = blank();
@@ -5588,26 +5607,15 @@ class SyntheticNamespaceDeclaration {
5588
5607
  this.name = node.name;
5589
5608
  }
5590
5609
 
5591
- assignExpression () {
5592
- // This should probably not happen, but not defining this might prevent a more meaningful error message
5593
- }
5594
-
5595
- gatherPossibleValues ( values ) {
5596
- values.add( UNKNOWN_ASSIGNMENT );
5597
- }
5598
-
5599
- getName () {
5600
- return this.name;
5601
- }
5610
+ assignExpression () {}
5602
5611
 
5603
- includeDeclaration () {
5604
- if ( this.included ) {
5605
- return false;
5612
+ includeVariable () {
5613
+ const hasBeenIncluded = super.includeVariable();
5614
+ if ( hasBeenIncluded ) {
5615
+ this.needsNamespaceBlock = true;
5616
+ forOwn( this.originals, original => original.includeVariable() );
5606
5617
  }
5607
- this.included = true;
5608
- this.needsNamespaceBlock = true;
5609
- forOwn( this.originals, original => original.includeDeclaration() );
5610
- return true;
5618
+ return hasBeenIncluded;
5611
5619
  }
5612
5620
 
5613
5621
  renderBlock ( es, legacy, indentString ) {
@@ -5627,55 +5635,6 @@ class SyntheticNamespaceDeclaration {
5627
5635
  }
5628
5636
  }
5629
5637
 
5630
- class ExternalDeclaration {
5631
- constructor ( module, name ) {
5632
- this.module = module;
5633
- this.name = name;
5634
- this.safeName = null;
5635
- this.isExternal = true;
5636
- this.isNamespace = name === '*';
5637
- }
5638
-
5639
- addReference ( reference ) {
5640
- reference.declaration = this;
5641
-
5642
- if ( this.name === 'default' || this.name === '*' ) {
5643
- this.module.suggestName( reference.name );
5644
- }
5645
- }
5646
-
5647
- gatherPossibleValues ( values ) {
5648
- values.add( UNKNOWN_ASSIGNMENT );
5649
- }
5650
-
5651
- getName ( es ) {
5652
- if ( this.name === '*' ) {
5653
- return this.module.name;
5654
- }
5655
-
5656
- if ( this.name === 'default' ) {
5657
- return this.module.exportsNamespace || ( !es && this.module.exportsNames ) ?
5658
- `${this.module.name}__default` :
5659
- this.module.name;
5660
- }
5661
-
5662
- return es ? this.safeName : `${this.module.name}.${this.name}`;
5663
- }
5664
-
5665
- includeDeclaration () {
5666
- if ( this.included ) {
5667
- return false;
5668
- }
5669
- this.included = true;
5670
- this.module.used = true;
5671
- return true;
5672
- }
5673
-
5674
- setSafeName ( name ) {
5675
- this.safeName = name;
5676
- }
5677
- }
5678
-
5679
5638
  function extractNames ( param ) {
5680
5639
  const names = [];
5681
5640
  extractors[ param.type ]( names, param );
@@ -5708,13 +5667,216 @@ const extractors = {
5708
5667
  }
5709
5668
  };
5710
5669
 
5711
- class Node$1 {
5712
- assignExpression () {}
5670
+ const UNKNOWN_VALUE = { toString: () => '[[UNKNOWN]]' };
5671
+
5672
+ const UNKNOWN_ASSIGNMENT = {
5673
+ type: 'UNKNOWN',
5674
+ bindCall: () => {},
5675
+ hasEffectsWhenCalled: () => true,
5676
+ hasEffectsWhenMutated: () => true,
5677
+ };
5678
+
5679
+ const UNDEFINED_ASSIGNMENT = {
5680
+ type: 'UNDEFINED',
5681
+ bindCall: () => {},
5682
+ hasEffectsWhenCalled: () => true,
5683
+ hasEffectsWhenMutated: () => true,
5684
+ };
5685
+
5686
+ const UNKNOWN_OBJECT_LITERAL = {
5687
+ type: 'UNKNOWN_OBJECT_LITERAL',
5688
+ bindCall: () => {},
5689
+ hasEffectsWhenCalled: () => true,
5690
+ hasEffectsWhenMutated: () => false,
5691
+ };
5692
+
5693
+ const OPTION_IGNORE_BREAK_STATEMENTS = 'IGNORE_BREAK_STATEMENTS';
5694
+ const OPTION_IGNORE_RETURN_AWAIT_YIELD = 'IGNORE_RETURN_AWAIT_YIELD';
5695
+ const OPTION_IGNORE_SAFE_THIS_MUTATIONS = 'IGNORE_SAFE_THIS_MUTATIONS';
5696
+ const OPTION_CALLED_NODES = 'CALLED_NODES';
5697
+ const OPTION_MUTATED_NODES = 'MUTATED_NODES';
5698
+ const IGNORED_LABELS = 'IGNORED_LABELS';
5699
+
5700
+ /** Wrapper to ensure immutability */
5701
+ class ExecutionPathOptions {
5702
+ /**
5703
+ * @returns {ExecutionPathOptions}
5704
+ */
5705
+ static create () {
5706
+ return new this( {} );
5707
+ }
5708
+
5709
+ constructor ( optionValues ) {
5710
+ this._optionValues = optionValues;
5711
+ }
5712
+
5713
+ /**
5714
+ * Returns a new ExecutionPathOptions instance with the given option set to a new value.
5715
+ * Does not mutate the current instance. Also works in sub-classes.
5716
+ * @param {string} option - The name of an option
5717
+ * @param {*} value - The new value of the option
5718
+ * @returns {ExecutionPathOptions} A new options instance
5719
+ */
5720
+ set ( option, value ) {
5721
+ return new this.constructor( Object.assign( {}, this._optionValues, { [option]: value } ) );
5722
+ }
5723
+
5724
+ /**
5725
+ * @param {string} option - The name of an option
5726
+ * @returns {*} Its value
5727
+ */
5728
+ get ( option ) {
5729
+ return this._optionValues[ option ];
5730
+ }
5713
5731
 
5732
+ /**
5733
+ * @return {boolean}
5734
+ */
5735
+ ignoreBreakStatements () {
5736
+ return this.get( OPTION_IGNORE_BREAK_STATEMENTS );
5737
+ }
5738
+
5739
+ /**
5740
+ * @param {boolean} [value=true]
5741
+ * @return {ExecutionPathOptions}
5742
+ */
5743
+ setIgnoreBreakStatements ( value ) {
5744
+ if ( value === void 0 ) value = true;
5745
+
5746
+ return this.set( OPTION_IGNORE_BREAK_STATEMENTS, value );
5747
+ }
5748
+
5749
+ /**
5750
+ * @param {string} labelName
5751
+ * @return {boolean}
5752
+ */
5753
+ ignoreLabel ( labelName ) {
5754
+ const ignoredLabels = this.get( IGNORED_LABELS );
5755
+ return ignoredLabels && ignoredLabels.has( labelName );
5756
+ }
5757
+
5758
+ /**
5759
+ * @param {string} labelName
5760
+ * @return {ExecutionPathOptions}
5761
+ */
5762
+ setIgnoreLabel ( labelName ) {
5763
+ return this.set( IGNORED_LABELS, new Set( this.get( IGNORED_LABELS ) ).add( labelName ) );
5764
+ }
5765
+
5766
+ /**
5767
+ * @return {ExecutionPathOptions}
5768
+ */
5769
+ setIgnoreNoLabels () {
5770
+ return this.set( IGNORED_LABELS, null );
5771
+ }
5772
+
5773
+ /**
5774
+ * @return {boolean}
5775
+ */
5776
+ ignoreReturnAwaitYield () {
5777
+ return this.get( OPTION_IGNORE_RETURN_AWAIT_YIELD );
5778
+ }
5779
+
5780
+ /**
5781
+ * @param {boolean} [value=true]
5782
+ * @return {ExecutionPathOptions}
5783
+ */
5784
+ setIgnoreReturnAwaitYield ( value ) {
5785
+ if ( value === void 0 ) value = true;
5786
+
5787
+ return this.set( OPTION_IGNORE_RETURN_AWAIT_YIELD, value );
5788
+ }
5789
+
5790
+ /**
5791
+ * @return {boolean}
5792
+ */
5793
+ ignoreSafeThisMutations () {
5794
+ return this.get( OPTION_IGNORE_SAFE_THIS_MUTATIONS );
5795
+ }
5796
+
5797
+ /**
5798
+ * @param {boolean} [value=true]
5799
+ * @return {ExecutionPathOptions}
5800
+ */
5801
+ setIgnoreSafeThisMutations ( value ) {
5802
+ if ( value === void 0 ) value = true;
5803
+
5804
+ return this.set( OPTION_IGNORE_SAFE_THIS_MUTATIONS, value );
5805
+ }
5806
+
5807
+ /**
5808
+ * @param {Node} node
5809
+ * @return {ExecutionPathOptions}
5810
+ */
5811
+ addMutatedNode ( node ) {
5812
+ return this.set( OPTION_MUTATED_NODES, new Set( this.get( OPTION_MUTATED_NODES ) ).add( node ) );
5813
+ }
5814
+
5815
+ /**
5816
+ * @param {Node} node
5817
+ * @return {boolean}
5818
+ */
5819
+ hasNodeBeenMutated ( node ) {
5820
+ const mutatedNodes = this.get( OPTION_MUTATED_NODES );
5821
+ return mutatedNodes && mutatedNodes.has( node );
5822
+ }
5823
+
5824
+ /**
5825
+ * @param {Node} node
5826
+ * @return {ExecutionPathOptions}
5827
+ */
5828
+ addCalledNode ( node ) {
5829
+ return this.set( OPTION_CALLED_NODES, new Set( this.get( OPTION_CALLED_NODES ) ).add( node ) );
5830
+ }
5831
+
5832
+ /**
5833
+ * @param {Node} node
5834
+ * @return {boolean}
5835
+ */
5836
+ hasNodeBeenCalled ( node ) {
5837
+ const calledNodes = this.get( OPTION_CALLED_NODES );
5838
+ return calledNodes && calledNodes.has( node );
5839
+ }
5840
+
5841
+ /**
5842
+ * @param {Node} calledNode
5843
+ * @return {ExecutionPathOptions}
5844
+ */
5845
+ getHasEffectsWhenCalledOptions ( calledNode ) {
5846
+ return this
5847
+ .addCalledNode( calledNode )
5848
+ .setIgnoreReturnAwaitYield()
5849
+ .setIgnoreBreakStatements( false )
5850
+ .setIgnoreNoLabels();
5851
+ }
5852
+ }
5853
+
5854
+ class Node$1 {
5855
+ /**
5856
+ * Called once all nodes have been initialised and the scopes have been populated.
5857
+ * Use this to bind assignments and calls to variables.
5858
+ */
5714
5859
  bind () {
5715
5860
  this.eachChild( child => child.bind() );
5716
5861
  }
5717
5862
 
5863
+ /**
5864
+ * Bind an expression as an assignment to a node.
5865
+ * The default noop implementation is ok as long as hasEffectsWhenAssigned
5866
+ * always returns true for this node. Otherwise it should be overridden.
5867
+ * @param {Node} expression
5868
+ */
5869
+ bindAssignment () {}
5870
+
5871
+ /**
5872
+ * Binds ways a node is called to a node. Current options are:
5873
+ * - withNew: boolean - Did this call use the "new" operator
5874
+ * The default noop implementation is ok as long as hasEffectsWhenCalled
5875
+ * always returns true for this node. Otherwise it should be overridden.
5876
+ * @param callOptions
5877
+ */
5878
+ bindCall () {}
5879
+
5718
5880
  eachChild ( callback ) {
5719
5881
  this.keys.forEach( key => {
5720
5882
  const value = this[ key ];
@@ -5728,34 +5890,65 @@ class Node$1 {
5728
5890
  } );
5729
5891
  }
5730
5892
 
5731
- gatherPossibleValues ( values ) {
5732
- values.add( UNKNOWN_ASSIGNMENT );
5733
- }
5734
-
5735
5893
  getValue () {
5736
5894
  return UNKNOWN_VALUE;
5737
5895
  }
5738
5896
 
5897
+ /**
5898
+ * Determine if this Node would have an effect on the bundle.
5899
+ * This is usually true for already included nodes. Exceptions are e.g. break statements
5900
+ * which only have an effect if their surrounding loop or switch statement is included.
5901
+ * The options pass on information like this about the current execution path.
5902
+ * @param {ExecutionPathOptions} options
5903
+ * @return {boolean}
5904
+ */
5739
5905
  hasEffects ( options ) {
5740
5906
  return this.included || this.someChild( child => child.hasEffects( options ) );
5741
5907
  }
5742
5908
 
5909
+ /**
5910
+ * Special make-shift logic to treat cases where apparently side-effect free statements
5911
+ * are executed for side-effects. The most important case are getters with side-effects.
5912
+ * Once we can reliably handle this case in member expressions, this function should
5913
+ * probably be removed again.
5914
+ * @param {ExecutionPathOptions} options
5915
+ * @return {boolean}
5916
+ */
5743
5917
  hasEffectsAsExpressionStatement () {
5744
5918
  return true;
5745
5919
  }
5746
5920
 
5921
+ /**
5922
+ * @param {ExecutionPathOptions} options
5923
+ * @return {boolean}
5924
+ */
5747
5925
  hasEffectsWhenAssigned () {
5748
5926
  return true;
5749
5927
  }
5750
5928
 
5751
- hasEffectsWhenMutated () {
5929
+ /**
5930
+ * @param {ExecutionPathOptions} options
5931
+ * @return {boolean}
5932
+ */
5933
+ hasEffectsWhenCalled () {
5752
5934
  return true;
5753
5935
  }
5754
5936
 
5755
- includeDeclaration () {
5756
- return this.includeInBundle();
5937
+ /**
5938
+ * @param {ExecutionPathOptions} options
5939
+ * @return {boolean}
5940
+ */
5941
+ hasEffectsWhenMutated () {
5942
+ return true;
5757
5943
  }
5758
5944
 
5945
+ /**
5946
+ * Includes the node in the bundle. Children are usually included if they are
5947
+ * necessary for this node (e.g. a function body) or if they have effects.
5948
+ * Necessary variables should be included as well. Should return true if any
5949
+ * nodes or variables have been added that were missing before.
5950
+ * @return {boolean}
5951
+ */
5759
5952
  includeInBundle () {
5760
5953
  if ( this.isFullyIncluded() ) { return false; }
5761
5954
  let addedNewNodes = false;
@@ -5771,21 +5964,49 @@ class Node$1 {
5771
5964
  return true;
5772
5965
  }
5773
5966
 
5967
+ /**
5968
+ * Alternative version of includeInBundle to override the default behaviour of
5969
+ * declarations to only include nodes for declarators that have an effect. Necessary
5970
+ * for for-loops that do not use a declared loop variable.
5971
+ * @return {boolean}
5972
+ */
5973
+ includeWithAllDeclarations () {
5974
+ return this.includeInBundle();
5975
+ }
5976
+
5977
+ /**
5978
+ * Assign a scope to this node and make sure all children have the right scopes.
5979
+ * Perform any additional initialisation that does not depend on the scope being
5980
+ * populated with variables.
5981
+ * Usually one should not override this function but override initialiseScope,
5982
+ * initialiseNode and/or initialiseChildren instead. BlockScopes have a special
5983
+ * alternative initialisation initialiseAndReplaceScope.
5984
+ * @param {Scope} parentScope
5985
+ */
5774
5986
  initialise ( parentScope ) {
5775
5987
  this.initialiseScope( parentScope );
5776
5988
  this.initialiseNode( parentScope );
5777
5989
  this.initialiseChildren( parentScope );
5778
5990
  }
5779
5991
 
5780
- // Override if e.g. some children need to be initialised with the parent scope
5992
+ /**
5993
+ * Override to change how and with what scopes children are initialised
5994
+ * @param {Scope} parentScope
5995
+ */
5781
5996
  initialiseChildren () {
5782
5997
  this.eachChild( child => child.initialise( this.scope ) );
5783
5998
  }
5784
5999
 
5785
- // Override to perform special initialisation steps after the scope is initialised
6000
+ /**
6001
+ * Override to perform special initialisation steps after the scope is initialised
6002
+ * @param {Scope} parentScope
6003
+ */
5786
6004
  initialiseNode () {}
5787
6005
 
5788
- // Overwrite to create a new scope
6006
+ /**
6007
+ * Override if this scope should receive a different scope than the parent scope.
6008
+ * @param {Scope} parentScope
6009
+ */
5789
6010
  initialiseScope ( parentScope ) {
5790
6011
  this.scope = parentScope;
5791
6012
  }
@@ -5796,6 +6017,11 @@ class Node$1 {
5796
6017
  }
5797
6018
  }
5798
6019
 
6020
+ /**
6021
+ * Shortcut to skip checking this node for effects when all children have already
6022
+ * been included.
6023
+ * @param {Scope} parentScope
6024
+ */
5799
6025
  isFullyIncluded () {
5800
6026
  if ( this._fullyIncluded ) {
5801
6027
  return true;
@@ -5816,8 +6042,15 @@ class Node$1 {
5816
6042
  this.eachChild( child => child.render( code, es ) );
5817
6043
  }
5818
6044
 
6045
+ /**
6046
+ * Start a new execution path to determine if this node has an effect on the bundle and
6047
+ * should therefore be included. Unless they are fully included, included nodes should
6048
+ * always be included again in subsequent visits as the inclusion of additional variables
6049
+ * may require the inclusion of more child nodes in e.g. block statements.
6050
+ * @return {boolean}
6051
+ */
5819
6052
  shouldBeIncluded () {
5820
- return this.hasEffects( {} );
6053
+ return this.hasEffects( ExecutionPathOptions.create() );
5821
6054
  }
5822
6055
 
5823
6056
  someChild ( callback ) {
@@ -5838,45 +6071,91 @@ class Node$1 {
5838
6071
  }
5839
6072
 
5840
6073
  class ArrayPattern extends Node$1 {
5841
- assignExpression () {
5842
- this.eachChild( child => child.assignExpression( UNKNOWN_ASSIGNMENT ) );
6074
+ bindAssignment () {
6075
+ this.eachChild( child => child.bindAssignment( UNKNOWN_ASSIGNMENT ) );
5843
6076
  }
5844
6077
 
5845
6078
  hasEffectsWhenAssigned ( options ) {
5846
6079
  return this.someChild( child => child.hasEffectsWhenAssigned( options ) );
5847
6080
  }
6081
+
6082
+ initialiseAndDeclare ( parentScope, kind ) {
6083
+ this.initialiseScope( parentScope );
6084
+ this.eachChild( child => child.initialiseAndDeclare( parentScope, kind, UNKNOWN_ASSIGNMENT ) );
6085
+ }
5848
6086
  }
5849
6087
 
5850
- class Parameter {
5851
- constructor ( name ) {
5852
- this.name = name;
5853
- this.isParam = true;
5854
- this.assignedExpressions = new Set( [ UNKNOWN_ASSIGNMENT ] );
6088
+ class LocalVariable extends Variable {
6089
+ constructor ( name, declarator, init ) {
6090
+ super( name );
6091
+ this.isReassigned = false;
6092
+ this.exportName = null;
6093
+ this.declarations = new Set( declarator ? [ declarator ] : null );
6094
+ this.assignedExpressions = new Set( init ? [ init ] : null );
6095
+ this.calls = new Set();
6096
+ }
6097
+
6098
+ addDeclaration ( identifier ) {
6099
+ this.declarations.add( identifier );
5855
6100
  }
5856
6101
 
5857
- addReference () {
5858
- // noop?
6102
+ addCall ( callOptions ) {
6103
+ // To prevent infinite loops
6104
+ if ( this.calls.has( callOptions ) ) { return; }
6105
+ this.calls.add( callOptions );
6106
+ Array.from( this.assignedExpressions ).forEach( expression => expression.bindCall( callOptions ) );
5859
6107
  }
5860
6108
 
6109
+ addReference () {}
6110
+
5861
6111
  assignExpression ( expression ) {
5862
6112
  this.assignedExpressions.add( expression );
5863
6113
  this.isReassigned = true;
6114
+ Array.from( this.calls ).forEach( callOptions => expression.bindCall( callOptions ) );
5864
6115
  }
5865
6116
 
5866
- gatherPossibleValues ( values ) {
5867
- values.add( UNKNOWN_ASSIGNMENT ); // TODO populate this at call time
6117
+ getName ( es ) {
6118
+ if ( es ) { return this.name; }
6119
+ if ( !this.isReassigned || !this.exportName ) { return this.name; }
6120
+
6121
+ return `exports.${this.exportName}`;
5868
6122
  }
5869
6123
 
5870
- getName () {
5871
- return this.name;
6124
+ hasEffectsWhenCalled ( options ) {
6125
+ return Array.from( this.assignedExpressions ).some( node =>
6126
+ !options.hasNodeBeenCalled( node )
6127
+ && node.hasEffectsWhenCalled( options.getHasEffectsWhenCalledOptions( node ) )
6128
+ );
5872
6129
  }
5873
6130
 
5874
- includeDeclaration () {
5875
- if ( this.included ) {
5876
- return false;
6131
+ hasEffectsWhenMutated ( options ) {
6132
+ return this.included
6133
+ || Array.from( this.assignedExpressions ).some( node =>
6134
+ !options.hasNodeBeenMutated( node ) &&
6135
+ node.hasEffectsWhenMutated( options.addMutatedNode( node ) )
6136
+ );
6137
+ }
6138
+
6139
+ includeVariable () {
6140
+ const hasBeenIncluded = super.includeVariable();
6141
+ if ( hasBeenIncluded ) {
6142
+ this.declarations.forEach( identifier => identifier.includeInBundle() );
5877
6143
  }
5878
- this.included = true;
5879
- return true;
6144
+ return hasBeenIncluded;
6145
+ }
6146
+
6147
+ toString () {
6148
+ return this.name;
6149
+ }
6150
+ }
6151
+
6152
+ class ParameterVariable extends LocalVariable {
6153
+ constructor ( name, declarator ) {
6154
+ super( name, declarator, UNKNOWN_ASSIGNMENT );
6155
+ }
6156
+
6157
+ getName () {
6158
+ return this.name;
5880
6159
  }
5881
6160
  }
5882
6161
 
@@ -5885,43 +6164,38 @@ class Scope {
5885
6164
  if ( options === void 0 ) options = {};
5886
6165
 
5887
6166
  this.parent = options.parent;
5888
- this.isBlockScope = !!options.isBlockScope;
5889
- this.isLexicalBoundary = !!options.isLexicalBoundary;
5890
6167
  this.isModuleScope = !!options.isModuleScope;
5891
6168
 
5892
6169
  this.children = [];
5893
6170
  if ( this.parent ) { this.parent.children.push( this ); }
5894
6171
 
5895
- this.declarations = blank();
5896
-
5897
- if ( this.isLexicalBoundary && !this.isModuleScope ) {
5898
- this.declarations.arguments = new Parameter( 'arguments' );
5899
- }
6172
+ this.variables = blank();
5900
6173
  }
5901
6174
 
5902
- addDeclaration ( name, declaration, isVar, isParam ) {
5903
- if ( isVar && this.isBlockScope ) {
5904
- this.parent.addDeclaration( name, declaration, isVar, isParam );
6175
+ addDeclaration ( identifier, isHoisted, init ) {
6176
+ const name = identifier.name;
6177
+ if ( this.variables[ name ] ) {
6178
+ const variable = this.variables[ name ];
6179
+ variable.addDeclaration( identifier );
6180
+ init && variable.assignExpression( init );
5905
6181
  } else {
5906
- const existingDeclaration = this.declarations[ name ];
5907
-
5908
- if ( existingDeclaration && existingDeclaration.duplicates ) {
5909
- // TODO warn/throw on duplicates?
5910
- existingDeclaration.duplicates.push( declaration );
5911
- } else {
5912
- this.declarations[ name ] = isParam ? new Parameter( name ) : declaration;
5913
- }
6182
+ this.variables[ name ] = new LocalVariable( identifier.name, identifier, init );
5914
6183
  }
5915
6184
  }
5916
6185
 
6186
+ addParameterDeclaration ( identifier ) {
6187
+ const name = identifier.name;
6188
+ this.variables[ name ] = new ParameterVariable( name, identifier );
6189
+ }
6190
+
5917
6191
  contains ( name ) {
5918
- return !!this.declarations[ name ] ||
6192
+ return !!this.variables[ name ] ||
5919
6193
  ( this.parent ? this.parent.contains( name ) : false );
5920
6194
  }
5921
6195
 
5922
6196
  deshadow ( names ) {
5923
- keys( this.declarations ).forEach( key => {
5924
- const declaration = this.declarations[ key ];
6197
+ keys( this.variables ).forEach( key => {
6198
+ const declaration = this.variables[ key ];
5925
6199
 
5926
6200
  // we can disregard exports.foo etc
5927
6201
  if ( declaration.exportName && declaration.isReassigned ) { return; }
@@ -5941,61 +6215,52 @@ class Scope {
5941
6215
  this.children.forEach( scope => scope.deshadow( names ) );
5942
6216
  }
5943
6217
 
5944
- findDeclaration ( name ) {
5945
- return this.declarations[ name ] ||
5946
- ( this.parent && this.parent.findDeclaration( name ) );
6218
+ findLexicalBoundary () {
6219
+ return this.parent.findLexicalBoundary();
5947
6220
  }
5948
6221
 
5949
- findLexicalBoundary () {
5950
- return this.isLexicalBoundary ? this : this.parent.findLexicalBoundary();
6222
+ findVariable ( name ) {
6223
+ return this.variables[ name ] ||
6224
+ ( this.parent && this.parent.findVariable( name ) );
5951
6225
  }
5952
6226
  }
5953
6227
 
5954
- class Function extends Node$1 {
5955
- bind () {
5956
- if ( this.id ) { this.id.bind(); }
5957
- this.params.forEach( param => param.bind() );
5958
- this.body.bind();
5959
- }
6228
+ class ArrowFunctionExpression extends Node$1 {
6229
+ // Should receive an implementation once we start tracking parameter values
6230
+ bindCall () {}
5960
6231
 
5961
6232
  hasEffects () {
5962
6233
  return this.included;
5963
6234
  }
5964
6235
 
5965
- initialiseChildren () {
5966
- this.params.forEach( param => {
5967
- param.initialise( this.scope );
5968
- extractNames( param ).forEach( name => this.scope.addDeclaration( name, null, false, true ) );
5969
- } );
5970
- this.body.initialiseAndReplaceScope ?
5971
- this.body.initialiseAndReplaceScope( this.scope ) :
5972
- this.body.initialise( this.scope );
6236
+ hasEffectsWhenCalled ( options ) {
6237
+ return this.params.some( param => param.hasEffects( options ) )
6238
+ || this.body.hasEffects( options );
5973
6239
  }
5974
6240
 
5975
- initialiseScope ( parentScope ) {
5976
- this.scope = new Scope( {
5977
- parent: parentScope,
5978
- isBlockScope: false,
5979
- isLexicalBoundary: true
5980
- } );
6241
+ hasEffectsWhenMutated () {
6242
+ return this.included;
6243
+ }
6244
+
6245
+ initialiseChildren () {
6246
+ this.params.forEach( param => param.initialiseAndDeclare( this.scope, 'parameter' ) );
6247
+ if ( this.body.initialiseAndReplaceScope ) {
6248
+ this.body.initialiseAndReplaceScope( new Scope( { parent: this.scope } ) );
6249
+ } else {
6250
+ this.body.initialise( this.scope );
6251
+ }
5981
6252
  }
5982
- }
5983
6253
 
5984
- class ArrowFunctionExpression extends Function {
5985
6254
  initialiseScope ( parentScope ) {
5986
- this.scope = new Scope( {
5987
- parent: parentScope,
5988
- isBlockScope: false,
5989
- isLexicalBoundary: false
5990
- } );
6255
+ this.scope = new Scope( { parent: parentScope } );
5991
6256
  }
5992
6257
  }
5993
6258
 
5994
6259
  // TODO tidy this up a bit (e.g. they can both use node.module.imports)
5995
6260
  function disallowIllegalReassignment ( scope, node ) {
5996
6261
  if ( node.type === 'MemberExpression' && node.object.type === 'Identifier' ) {
5997
- const declaration = scope.findDeclaration( node.object.name );
5998
- if ( declaration.isNamespace ) {
6262
+ const variable = scope.findVariable( node.object.name );
6263
+ if ( variable.isNamespace ) {
5999
6264
  node.module.error({
6000
6265
  code: 'ILLEGAL_NAMESPACE_REASSIGNMENT',
6001
6266
  message: `Illegal reassignment to import '${node.object.name}'`
@@ -6017,7 +6282,7 @@ class AssignmentExpression extends Node$1 {
6017
6282
  bind () {
6018
6283
  super.bind();
6019
6284
  disallowIllegalReassignment( this.scope, this.left );
6020
- this.left.assignExpression( this.right );
6285
+ this.left.bindAssignment( this.right );
6021
6286
  }
6022
6287
 
6023
6288
  hasEffects ( options ) {
@@ -6030,345 +6295,175 @@ class AssignmentExpression extends Node$1 {
6030
6295
  }
6031
6296
 
6032
6297
  class AssignmentPattern extends Node$1 {
6033
- hasEffectsWhenAssigned ( options ) {
6034
- return this.left.hasEffectsWhenAssigned( options );
6035
- }
6036
- }
6037
-
6038
- class AwaitExpression extends Node$1 {
6039
- hasEffects ( options ) {
6040
- return super.hasEffects( options )
6041
- || !options.inNestedFunctionCall;
6042
- }
6043
-
6044
- hasEffectsAsExpressionStatement ( options ) {
6045
- return this.hasEffects( options );
6046
- }
6047
- }
6048
-
6049
- const operators = {
6050
- '==': ( left, right ) => left == right,
6051
- '!=': ( left, right ) => left != right,
6052
- '===': ( left, right ) => left === right,
6053
- '!==': ( left, right ) => left !== right,
6054
- '<': ( left, right ) => left < right,
6055
- '<=': ( left, right ) => left <= right,
6056
- '>': ( left, right ) => left > right,
6057
- '>=': ( left, right ) => left >= right,
6058
- '<<': ( left, right ) => left << right,
6059
- '>>': ( left, right ) => left >> right,
6060
- '>>>': ( left, right ) => left >>> right,
6061
- '+': ( left, right ) => left + right,
6062
- '-': ( left, right ) => left - right,
6063
- '*': ( left, right ) => left * right,
6064
- '/': ( left, right ) => left / right,
6065
- '%': ( left, right ) => left % right,
6066
- '|': ( left, right ) => left | right,
6067
- '^': ( left, right ) => left ^ right,
6068
- '&': ( left, right ) => left & right,
6069
- '**': ( left, right ) => Math.pow( left, right ),
6070
- in: ( left, right ) => left in right,
6071
- instanceof: ( left, right ) => left instanceof right
6072
- };
6073
-
6074
- class BinaryExpression extends Node$1 {
6075
- getValue () {
6076
- const leftValue = this.left.getValue();
6077
- if ( leftValue === UNKNOWN_VALUE ) { return UNKNOWN_VALUE; }
6078
-
6079
- const rightValue = this.right.getValue();
6080
- if ( rightValue === UNKNOWN_VALUE ) { return UNKNOWN_VALUE; }
6081
-
6082
- if ( !operators[ this.operator ] ) { return UNKNOWN_VALUE; }
6083
-
6084
- return operators[ this.operator ]( leftValue, rightValue );
6085
- }
6086
- }
6087
-
6088
- class Statement extends Node$1 {
6089
- render ( code, es ) {
6090
- if ( !this.module.bundle.treeshake || this.included ) {
6091
- super.render( code, es );
6092
- } else {
6093
- code.remove( this.leadingCommentStart || this.start, this.next || this.end );
6094
- }
6095
- }
6096
- }
6097
-
6098
- class BlockStatement extends Statement {
6099
6298
  bind () {
6100
- this.body.forEach( node => node.bind() );
6101
- }
6102
-
6103
- includeInBundle () {
6104
- if ( this.isFullyIncluded() ) { return false; }
6105
- let addedNewNodes = false;
6106
- this.body.forEach( node => {
6107
- if ( node.shouldBeIncluded() ) {
6108
- if ( node.includeInBundle() ) {
6109
- addedNewNodes = true;
6110
- }
6111
- }
6112
- } );
6113
- if ( !this.included || addedNewNodes ) {
6114
- this.included = true;
6115
- return true;
6116
- }
6117
- return false;
6118
- }
6119
-
6120
- initialiseAndReplaceScope ( scope ) {
6121
- this.scope = scope;
6122
- this.initialiseNode();
6123
- this.initialiseChildren( scope );
6299
+ super.bind();
6300
+ this.left.bindAssignment( this.right );
6124
6301
  }
6125
6302
 
6126
- initialiseChildren () {
6127
- let lastNode;
6128
- for ( const node of this.body ) {
6129
- node.initialise( this.scope );
6130
-
6131
- if ( lastNode ) { lastNode.next = node.start; }
6132
- lastNode = node;
6133
- }
6303
+ bindAssignment ( expression ) {
6304
+ this.left.bindAssignment( expression );
6134
6305
  }
6135
6306
 
6136
- initialiseScope ( parentScope ) {
6137
- this.scope = new Scope( {
6138
- parent: parentScope,
6139
- isBlockScope: true,
6140
- isLexicalBoundary: false
6141
- } );
6307
+ hasEffectsWhenAssigned ( options ) {
6308
+ return this.left.hasEffectsWhenAssigned( options );
6142
6309
  }
6143
6310
 
6144
- render ( code, es ) {
6145
- if ( this.body.length ) {
6146
- for ( const node of this.body ) {
6147
- node.render( code, es );
6148
- }
6149
- } else {
6150
- Statement.prototype.render.call( this, code, es );
6151
- }
6311
+ initialiseAndDeclare ( parentScope, kind, init ) {
6312
+ this.initialiseScope( parentScope );
6313
+ this.right.initialise( parentScope );
6314
+ this.left.initialiseAndDeclare( parentScope, kind, init );
6152
6315
  }
6153
6316
  }
6154
6317
 
6155
- class BreakStatement extends Node$1 {
6318
+ class AwaitExpression extends Node$1 {
6156
6319
  hasEffects ( options ) {
6157
6320
  return super.hasEffects( options )
6158
- || !options.inNestedBreakableStatement;
6159
- }
6160
-
6161
- shouldBeIncluded () {
6162
- return true;
6163
- }
6164
- }
6165
-
6166
- function isReference (node, parent) {
6167
- if (node.type === 'MemberExpression') {
6168
- return !node.computed && isReference(node.object, node);
6169
- }
6170
-
6171
- if (node.type === 'Identifier') {
6172
- // the only time we could have an identifier node without a parent is
6173
- // if it's the entire body of a function without a block statement –
6174
- // i.e. an arrow function expression like `a => a`
6175
- if (!parent) return true;
6176
-
6177
- // TODO is this right?
6178
- if (parent.type === 'MemberExpression' || parent.type === 'MethodDefinition') {
6179
- return parent.computed || node === parent.object;
6180
- }
6181
-
6182
- // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
6183
- if (parent.type === 'Property') return parent.computed || node === parent.value;
6184
-
6185
- // disregard the `bar` in `class Foo { bar () {...} }`
6186
- if (parent.type === 'MethodDefinition') return false;
6187
-
6188
- // disregard the `bar` in `export { foo as bar }`
6189
- if (parent.type === 'ExportSpecifier' && node !== parent.local) return false;
6190
-
6191
- return true;
6192
- }
6193
-
6194
- return false;
6195
- }
6196
-
6197
- function flatten ( node ) {
6198
- const parts = [];
6199
- while ( node.type === 'MemberExpression' ) {
6200
- if ( node.computed ) { return null; }
6201
- parts.unshift( node.property.name );
6202
-
6203
- node = node.object;
6321
+ || !options.ignoreReturnAwaitYield();
6204
6322
  }
6205
6323
 
6206
- if ( node.type !== 'Identifier' ) { return null; }
6207
-
6208
- const name = node.name;
6209
- parts.unshift( name );
6210
-
6211
- return { name, keypath: parts.join( '.' ) };
6212
- }
6213
-
6214
- const pureFunctions = {};
6215
-
6216
- const arrayTypes = 'Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array'.split( ' ' );
6217
- const simdTypes = 'Int8x16 Int16x8 Int32x4 Float32x4 Float64x2'.split( ' ' );
6218
- const simdMethods = 'abs add and bool check div equal extractLane fromFloat32x4 fromFloat32x4Bits fromFloat64x2 fromFloat64x2Bits fromInt16x8Bits fromInt32x4 fromInt32x4Bits fromInt8x16Bits greaterThan greaterThanOrEqual lessThan lessThanOrEqual load max maxNum min minNum mul neg not notEqual or reciprocalApproximation reciprocalSqrtApproximation replaceLane select selectBits shiftLeftByScalar shiftRightArithmeticByScalar shiftRightLogicalByScalar shuffle splat sqrt store sub swizzle xor'.split( ' ' );
6219
- const allSimdMethods = [];
6220
- simdTypes.forEach( t => {
6221
- simdMethods.forEach( m => {
6222
- allSimdMethods.push( `SIMD.${t}.${m}` );
6223
- });
6224
- });
6225
-
6226
- [
6227
- 'Array.isArray',
6228
- 'Error', 'EvalError', 'InternalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError',
6229
- 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape', 'unescape',
6230
- 'Object', 'Object.create', 'Object.getNotifier', 'Object.getOwn', 'Object.getOwnPropertyDescriptor', 'Object.getOwnPropertyNames', 'Object.getOwnPropertySymbols', 'Object.getPrototypeOf', 'Object.is', 'Object.isExtensible', 'Object.isFrozen', 'Object.isSealed', 'Object.keys',
6231
- 'Function', 'Boolean',
6232
- 'Number', 'Number.isFinite', 'Number.isInteger', 'Number.isNaN', 'Number.isSafeInteger', 'Number.parseFloat', 'Number.parseInt',
6233
- 'Symbol', 'Symbol.for', 'Symbol.keyFor',
6234
- 'Math.abs', 'Math.acos', 'Math.acosh', 'Math.asin', 'Math.asinh', 'Math.atan', 'Math.atan2', 'Math.atanh', 'Math.cbrt', 'Math.ceil', 'Math.clz32', 'Math.cos', 'Math.cosh', 'Math.exp', 'Math.expm1', 'Math.floor', 'Math.fround', 'Math.hypot', 'Math.imul', 'Math.log', 'Math.log10', 'Math.log1p', 'Math.log2', 'Math.max', 'Math.min', 'Math.pow', 'Math.random', 'Math.round', 'Math.sign', 'Math.sin', 'Math.sinh', 'Math.sqrt', 'Math.tan', 'Math.tanh', 'Math.trunc',
6235
- 'Date', 'Date.UTC', 'Date.now', 'Date.parse',
6236
- 'String', 'String.fromCharCode', 'String.fromCodePoint', 'String.raw',
6237
- 'RegExp',
6238
- 'Map', 'Set', 'WeakMap', 'WeakSet',
6239
- 'ArrayBuffer', 'ArrayBuffer.isView',
6240
- 'DataView',
6241
- 'JSON.parse', 'JSON.stringify',
6242
- 'Promise.all', 'Promise.race', 'Promise.resolve',
6243
- 'Intl.Collator', 'Intl.Collator.supportedLocalesOf', 'Intl.DateTimeFormat', 'Intl.DateTimeFormat.supportedLocalesOf', 'Intl.NumberFormat', 'Intl.NumberFormat.supportedLocalesOf'
6244
-
6245
- // TODO properties of e.g. window...
6246
- ].concat(
6247
- arrayTypes,
6248
- arrayTypes.map( t => `${t}.from` ),
6249
- arrayTypes.map( t => `${t}.of` ),
6250
- simdTypes.map( t => `SIMD.${t}` ),
6251
- allSimdMethods
6252
- ).forEach( name => pureFunctions[ name ] = true );
6253
-
6254
- const currentlyCalling = new Set();
6255
-
6256
- function isES5Function ( node ) {
6257
- return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration';
6324
+ hasEffectsAsExpressionStatement ( options ) {
6325
+ return this.hasEffects( options );
6326
+ }
6258
6327
  }
6259
6328
 
6260
- function hasEffectsNew ( node ) {
6261
- let inner = node;
6262
-
6263
- if ( inner.type === 'ExpressionStatement' ) {
6264
- inner = inner.expression;
6329
+ const operators = {
6330
+ '==': ( left, right ) => left == right,
6331
+ '!=': ( left, right ) => left != right,
6332
+ '===': ( left, right ) => left === right,
6333
+ '!==': ( left, right ) => left !== right,
6334
+ '<': ( left, right ) => left < right,
6335
+ '<=': ( left, right ) => left <= right,
6336
+ '>': ( left, right ) => left > right,
6337
+ '>=': ( left, right ) => left >= right,
6338
+ '<<': ( left, right ) => left << right,
6339
+ '>>': ( left, right ) => left >> right,
6340
+ '>>>': ( left, right ) => left >>> right,
6341
+ '+': ( left, right ) => left + right,
6342
+ '-': ( left, right ) => left - right,
6343
+ '*': ( left, right ) => left * right,
6344
+ '/': ( left, right ) => left / right,
6345
+ '%': ( left, right ) => left % right,
6346
+ '|': ( left, right ) => left | right,
6347
+ '^': ( left, right ) => left ^ right,
6348
+ '&': ( left, right ) => left & right,
6349
+ '**': ( left, right ) => Math.pow( left, right ),
6350
+ in: ( left, right ) => left in right,
6351
+ instanceof: ( left, right ) => left instanceof right
6352
+ };
6265
6353
 
6266
- if ( inner.type === 'AssignmentExpression' ) {
6267
- if ( inner.right.hasEffects( { inNestedFunctionCall: true } ) ) {
6268
- return true;
6354
+ class BinaryExpression extends Node$1 {
6355
+ getValue () {
6356
+ const leftValue = this.left.getValue();
6357
+ if ( leftValue === UNKNOWN_VALUE ) { return UNKNOWN_VALUE; }
6269
6358
 
6270
- } else {
6271
- inner = inner.left;
6359
+ const rightValue = this.right.getValue();
6360
+ if ( rightValue === UNKNOWN_VALUE ) { return UNKNOWN_VALUE; }
6272
6361
 
6273
- if ( inner.type === 'MemberExpression' ) {
6274
- if ( inner.computed && inner.property.hasEffects( { inNestedFunctionCall: true } ) ) {
6275
- return true;
6362
+ if ( !operators[ this.operator ] ) { return UNKNOWN_VALUE; }
6276
6363
 
6277
- } else {
6278
- inner = inner.object;
6364
+ return operators[ this.operator ]( leftValue, rightValue );
6365
+ }
6366
+ }
6279
6367
 
6280
- if ( inner.type === 'ThisExpression' ) {
6281
- return false;
6282
- }
6283
- }
6284
- }
6285
- }
6368
+ class Statement extends Node$1 {
6369
+ render ( code, es ) {
6370
+ if ( !this.module.bundle.treeshake || this.included ) {
6371
+ super.render( code, es );
6372
+ } else {
6373
+ code.remove( this.leadingCommentStart || this.start, this.next || this.end );
6286
6374
  }
6287
6375
  }
6288
-
6289
- return node.hasEffects( { inNestedFunctionCall: true } );
6290
6376
  }
6291
6377
 
6292
- function fnHasEffects ( fn, isNew ) {
6293
- if ( currentlyCalling.has( fn ) ) { return false; } // prevent infinite loops... TODO there must be a better way
6294
- currentlyCalling.add( fn );
6295
-
6296
- // handle body-less arrow functions
6297
- const body = fn.body.type === 'BlockStatement' ? fn.body.body : [ fn.body ];
6298
-
6299
- for ( const node of body ) {
6300
- if ( isNew ? hasEffectsNew( node ) : node.hasEffects( { inNestedFunctionCall: true } ) ) {
6301
- currentlyCalling.delete( fn );
6302
- return true;
6378
+ class BlockScope extends Scope {
6379
+ addDeclaration ( identifier, isHoisted, init ) {
6380
+ if ( isHoisted ) {
6381
+ this.parent.addDeclaration( identifier, isHoisted, init );
6382
+ } else {
6383
+ super.addDeclaration( identifier, false, init );
6303
6384
  }
6304
6385
  }
6305
-
6306
- currentlyCalling.delete( fn );
6307
- return false;
6308
6386
  }
6309
6387
 
6310
- function callHasEffects ( scope, callee, isNew ) {
6311
- const values = new Set( [ callee ] );
6312
-
6313
- for ( const node of values ) {
6314
- if ( node.type === 'UNKNOWN' ) { return true; } // err on side of caution
6388
+ class BlockStatement extends Statement {
6389
+ bind () {
6390
+ this.body.forEach( node => node.bind() );
6391
+ }
6315
6392
 
6316
- if ( /Function/.test( node.type ) ) {
6317
- if ( fnHasEffects( node, isNew && isES5Function( node ) ) ) { return true; }
6318
- }
6393
+ hasEffects ( options ) {
6394
+ // Empty block statements do not have effects even though they may be included as e.g. function body
6395
+ return this.body.some( child => child.hasEffects( options ) );
6396
+ }
6319
6397
 
6320
- else if ( /Class/.test( node.type ) ) {
6321
- // TODO find constructor (may belong to a superclass)
6398
+ includeInBundle () {
6399
+ if ( this.isFullyIncluded() ) { return false; }
6400
+ let addedNewNodes = false;
6401
+ this.body.forEach( node => {
6402
+ if ( node.shouldBeIncluded() ) {
6403
+ if ( node.includeInBundle() ) {
6404
+ addedNewNodes = true;
6405
+ }
6406
+ }
6407
+ } );
6408
+ if ( !this.included || addedNewNodes ) {
6409
+ this.included = true;
6322
6410
  return true;
6323
6411
  }
6412
+ return false;
6413
+ }
6324
6414
 
6325
- else if ( isReference( node ) ) {
6326
- const flattened = flatten( node );
6327
- const declaration = scope.findDeclaration( flattened.name );
6328
-
6329
- if ( declaration.isGlobal ) {
6330
- if ( !pureFunctions[ flattened.keypath ] ) { return true; }
6331
- }
6415
+ initialiseAndReplaceScope ( scope ) {
6416
+ this.scope = scope;
6417
+ this.initialiseNode();
6418
+ this.initialiseChildren( scope );
6419
+ }
6332
6420
 
6333
- else if ( declaration.isExternal ) {
6334
- return true; // TODO make this configurable? e.g. `path.[whatever]`
6335
- }
6421
+ initialiseChildren () {
6422
+ let lastNode;
6423
+ for ( const node of this.body ) {
6424
+ node.initialise( this.scope );
6336
6425
 
6337
- else {
6338
- if ( node.declaration ) {
6339
- node.declaration.gatherPossibleValues( values );
6340
- } else {
6341
- return true;
6342
- }
6343
- }
6426
+ if ( lastNode ) { lastNode.next = node.start; }
6427
+ lastNode = node;
6344
6428
  }
6429
+ }
6345
6430
 
6346
- else if ( node.gatherPossibleValues ) {
6347
- node.gatherPossibleValues( values );
6348
- }
6431
+ initialiseScope ( parentScope ) {
6432
+ this.scope = new BlockScope( { parent: parentScope } );
6433
+ }
6349
6434
 
6350
- else {
6351
- // probably an error in the user's code — err on side of caution
6352
- return true;
6435
+ render ( code, es ) {
6436
+ if ( this.body.length ) {
6437
+ for ( const node of this.body ) {
6438
+ node.render( code, es );
6439
+ }
6440
+ } else {
6441
+ Statement.prototype.render.call( this, code, es );
6353
6442
  }
6354
6443
  }
6444
+ }
6355
6445
 
6356
- return false;
6446
+ class BreakStatement extends Node$1 {
6447
+ hasEffects ( options ) {
6448
+ return super.hasEffects( options )
6449
+ || !options.ignoreBreakStatements()
6450
+ || (this.label && !options.ignoreLabel( this.label.name ));
6451
+ }
6357
6452
  }
6358
6453
 
6359
6454
  class CallExpression extends Node$1 {
6360
6455
  bind () {
6361
6456
  if ( this.callee.type === 'Identifier' ) {
6362
- const declaration = this.scope.findDeclaration( this.callee.name );
6457
+ const variable = this.scope.findVariable( this.callee.name );
6363
6458
 
6364
- if ( declaration.isNamespace ) {
6459
+ if ( variable.isNamespace ) {
6365
6460
  this.module.error( {
6366
6461
  code: 'CANNOT_CALL_NAMESPACE',
6367
6462
  message: `Cannot call a namespace ('${this.callee.name}')`
6368
6463
  }, this.start );
6369
6464
  }
6370
6465
 
6371
- if ( this.callee.name === 'eval' && declaration.isGlobal ) {
6466
+ if ( this.callee.name === 'eval' && variable.isGlobal ) {
6372
6467
  this.module.warn( {
6373
6468
  code: 'EVAL',
6374
6469
  message: `Use of eval is strongly discouraged, as it poses security risks and may cause issues with minification`,
@@ -6378,12 +6473,13 @@ class CallExpression extends Node$1 {
6378
6473
  }
6379
6474
 
6380
6475
  super.bind();
6476
+ this.callee.bindCall( { withNew: false } );
6381
6477
  }
6382
6478
 
6383
6479
  hasEffects ( options ) {
6384
6480
  return this.included
6385
6481
  || this.arguments.some( child => child.hasEffects( options ) )
6386
- || callHasEffects( this.scope, this.callee, false );
6482
+ || this.callee.hasEffectsWhenCalled( options.getHasEffectsWhenCalledOptions( this.callee ) );
6387
6483
  }
6388
6484
 
6389
6485
  hasEffectsAsExpressionStatement ( options ) {
@@ -6393,27 +6489,49 @@ class CallExpression extends Node$1 {
6393
6489
 
6394
6490
  class CatchClause extends Node$1 {
6395
6491
  initialiseChildren () {
6396
- if ( this.param ) {
6397
- this.param.initialise( this.scope );
6398
- extractNames( this.param ).forEach( name => this.scope.addDeclaration( name, null, false, true ) );
6399
- }
6492
+ this.param && this.param.initialiseAndDeclare( this.scope, 'parameter' );
6400
6493
  this.body.initialiseAndReplaceScope( this.scope );
6401
6494
  }
6402
6495
 
6403
6496
  initialiseScope ( parentScope ) {
6404
- this.scope = new Scope( {
6405
- parent: parentScope,
6406
- isBlockScope: true,
6407
- isLexicalBoundary: false
6408
- } );
6497
+ this.scope = new BlockScope( { parent: parentScope } );
6409
6498
  }
6410
6499
  }
6411
6500
 
6412
- class Class extends Node$1 {
6413
- addReference () {}
6501
+ class ClassBody extends Node$1 {
6502
+ bindCall ( callOptions ) {
6503
+ if ( this.classConstructor ) {
6504
+ this.classConstructor.bindCall( callOptions );
6505
+ }
6506
+ }
6414
6507
 
6415
- getName () {
6416
- return this.name;
6508
+ hasEffectsWhenCalled ( options ) {
6509
+ if ( this.classConstructor ) {
6510
+ return this.classConstructor.hasEffectsWhenCalled( options );
6511
+ }
6512
+ return false;
6513
+ }
6514
+
6515
+ initialiseNode () {
6516
+ this.classConstructor = this.body.find( method => method.kind === 'constructor' );
6517
+ }
6518
+ }
6519
+
6520
+ class ClassNode extends Node$1 {
6521
+ bindCall ( callOptions ) {
6522
+ if ( this.superClass ) {
6523
+ this.superClass.bindCall( callOptions );
6524
+ }
6525
+ this.body.bindCall( callOptions );
6526
+ }
6527
+
6528
+ hasEffectsAsExpressionStatement ( options ) {
6529
+ return this.hasEffects( options );
6530
+ }
6531
+
6532
+ hasEffectsWhenCalled ( options ) {
6533
+ return this.body.hasEffectsWhenCalled( options )
6534
+ || ( this.superClass && this.superClass.hasEffectsWhenCalled( options ) );
6417
6535
  }
6418
6536
 
6419
6537
  initialiseChildren () {
@@ -6424,28 +6542,14 @@ class Class extends Node$1 {
6424
6542
  }
6425
6543
 
6426
6544
  initialiseScope ( parentScope ) {
6427
- this.scope = new Scope( {
6428
- parent: parentScope,
6429
- isBlockScope: true
6430
- } );
6545
+ this.scope = new Scope( { parent: parentScope } );
6431
6546
  }
6432
6547
  }
6433
6548
 
6434
- class ClassDeclaration extends Class {
6435
- gatherPossibleValues ( values ) {
6436
- values.add( this );
6437
- }
6438
-
6439
- hasEffects () {
6440
- return this.included;
6441
- }
6442
-
6549
+ class ClassDeclaration extends ClassNode {
6443
6550
  initialiseChildren ( parentScope ) {
6444
- if ( this.id ) {
6445
- this.name = this.id.name;
6446
- parentScope.addDeclaration( this.name, this, false, false );
6447
- this.id.initialise( parentScope );
6448
- }
6551
+ // Class declarations are like let declarations: Not hoisted, can be reassigned, cannot be redeclared
6552
+ this.id && this.id.initialiseAndDeclare( parentScope, 'class', this );
6449
6553
  super.initialiseChildren( parentScope );
6450
6554
  }
6451
6555
 
@@ -6458,14 +6562,10 @@ class ClassDeclaration extends Class {
6458
6562
  }
6459
6563
  }
6460
6564
 
6461
- class ClassExpression extends Class {
6462
- initialiseChildren (parentScope) {
6463
- if ( this.id ) {
6464
- this.name = this.id.name;
6465
- this.scope.addDeclaration( this.name, this, false, false );
6466
- this.id.initialise( this.scope );
6467
- }
6468
- super.initialiseChildren(parentScope);
6565
+ class ClassExpression extends ClassNode {
6566
+ initialiseChildren ( parentScope ) {
6567
+ this.id && this.id.initialiseAndDeclare( this.scope, 'class', this );
6568
+ super.initialiseChildren( parentScope );
6469
6569
  }
6470
6570
  }
6471
6571
 
@@ -6488,16 +6588,6 @@ class ConditionalExpression extends Node$1 {
6488
6588
  }
6489
6589
  }
6490
6590
 
6491
- gatherPossibleValues ( values ) {
6492
- const testValue = this.test.getValue();
6493
-
6494
- if ( testValue === UNKNOWN_VALUE ) {
6495
- values.add( this.consequent ).add( this.alternate );
6496
- } else {
6497
- values.add( testValue ? this.consequent : this.alternate );
6498
- }
6499
- }
6500
-
6501
6591
  getValue () {
6502
6592
  const testValue = this.test.getValue();
6503
6593
  if ( testValue === UNKNOWN_VALUE ) { return UNKNOWN_VALUE; }
@@ -6541,7 +6631,7 @@ class DoWhileStatement extends Statement {
6541
6631
  return (
6542
6632
  this.included
6543
6633
  || this.test.hasEffects( options )
6544
- || this.body.hasEffects( Object.assign( {}, options, { inNestedBreakableStatement: true } ) )
6634
+ || this.body.hasEffects( options.setIgnoreBreakStatements() )
6545
6635
  );
6546
6636
  }
6547
6637
  }
@@ -6567,6 +6657,10 @@ class ExportAllDeclaration extends Node$1 {
6567
6657
  const functionOrClassDeclaration = /^(?:Function|Class)Declaration/;
6568
6658
 
6569
6659
  class ExportDefaultDeclaration extends Node$1 {
6660
+ addCall ( options ) {
6661
+ this.declaration.bindCall( options );
6662
+ }
6663
+
6570
6664
  addReference ( reference ) {
6571
6665
  this.name = reference.name;
6572
6666
  if ( this.original ) { this.original.addReference( reference ); }
@@ -6574,15 +6668,11 @@ class ExportDefaultDeclaration extends Node$1 {
6574
6668
 
6575
6669
  bind () {
6576
6670
  const name = ( this.declaration.id && this.declaration.id.name ) || this.declaration.name;
6577
- if ( name ) { this.original = this.scope.findDeclaration( name ); }
6671
+ if ( name ) { this.original = this.scope.findVariable( name ); }
6578
6672
 
6579
6673
  this.declaration.bind();
6580
6674
  }
6581
6675
 
6582
- gatherPossibleValues ( values ) {
6583
- this.declaration.gatherPossibleValues( values );
6584
- }
6585
-
6586
6676
  getName ( es ) {
6587
6677
  if ( this.original && !this.original.isReassigned ) {
6588
6678
  return this.original.getName( es );
@@ -6591,7 +6681,11 @@ class ExportDefaultDeclaration extends Node$1 {
6591
6681
  return this.name;
6592
6682
  }
6593
6683
 
6594
- includeDeclaration () {
6684
+ hasEffectsWhenCalled ( options ) {
6685
+ return this.declaration.hasEffectsWhenCalled( options );
6686
+ }
6687
+
6688
+ includeVariable () {
6595
6689
  if ( this.included ) {
6596
6690
  return false;
6597
6691
  }
@@ -6612,7 +6706,7 @@ class ExportDefaultDeclaration extends Node$1 {
6612
6706
  this.isDefault = true;
6613
6707
 
6614
6708
  this.name = ( this.declaration.id && this.declaration.id.name ) || this.declaration.name || this.module.basename();
6615
- this.scope.declarations.default = this;
6709
+ this.scope.variables.default = this;
6616
6710
  }
6617
6711
 
6618
6712
  // TODO this is total chaos, tidy it up
@@ -6660,7 +6754,7 @@ class ExportDefaultDeclaration extends Node$1 {
6660
6754
  if ( functionOrClassDeclaration.test( this.declaration.type ) ) {
6661
6755
  code.remove( this.leadingCommentStart || this.start, this.next || this.end );
6662
6756
  } else {
6663
- const hasEffects = this.declaration.hasEffects( {} );
6757
+ const hasEffects = this.declaration.hasEffects( ExecutionPathOptions.create() );
6664
6758
  code.remove( this.start, hasEffects ? declaration_start : this.next || this.end );
6665
6759
  }
6666
6760
  } else if ( name === this.declaration.name ) {
@@ -6675,11 +6769,12 @@ class ExportDefaultDeclaration extends Node$1 {
6675
6769
 
6676
6770
  class ExportNamedDeclaration extends Node$1 {
6677
6771
  bind () {
6772
+ // Do not bind specifiers
6678
6773
  if ( this.declaration ) { this.declaration.bind(); }
6679
6774
  }
6680
6775
 
6681
- hasEffects () {
6682
- return this.included || (this.declaration && this.declaration.hasEffects());
6776
+ hasEffects ( options ) {
6777
+ return this.included || (this.declaration && this.declaration.hasEffects( options ));
6683
6778
  }
6684
6779
 
6685
6780
  initialiseNode () {
@@ -6727,7 +6822,7 @@ class ForStatement extends Statement {
6727
6822
  || this.init && this.init.hasEffects( options )
6728
6823
  || this.test && this.test.hasEffects( options )
6729
6824
  || this.update && this.update.hasEffects( options )
6730
- || this.body.hasEffects( Object.assign( {}, options, { inNestedBreakableStatement: true } ) )
6825
+ || this.body.hasEffects( options.setIgnoreBreakStatements() )
6731
6826
  );
6732
6827
  }
6733
6828
 
@@ -6745,11 +6840,7 @@ class ForStatement extends Statement {
6745
6840
  }
6746
6841
 
6747
6842
  initialiseScope ( parentScope ) {
6748
- this.scope = new Scope( {
6749
- parent: parentScope,
6750
- isBlockScope: true,
6751
- isLexicalBoundary: false
6752
- } );
6843
+ this.scope = new BlockScope( { parent: parentScope } );
6753
6844
  }
6754
6845
  }
6755
6846
 
@@ -6757,9 +6848,9 @@ class ForInStatement extends Statement {
6757
6848
  hasEffects ( options ) {
6758
6849
  return (
6759
6850
  this.included
6760
- || this.left && this.left.hasEffects( options )
6851
+ || this.left && (this.left.hasEffects( options ) || this.left.hasEffectsWhenAssigned( options ))
6761
6852
  || this.right && this.right.hasEffects( options )
6762
- || this.body.hasEffects( Object.assign( {}, options, { inNestedBreakableStatement: true } ) )
6853
+ || this.body.hasEffects( options.setIgnoreBreakStatements() )
6763
6854
  );
6764
6855
  }
6765
6856
 
@@ -6773,39 +6864,35 @@ class ForInStatement extends Statement {
6773
6864
 
6774
6865
  includeInBundle () {
6775
6866
  let addedNewNodes = super.includeInBundle();
6776
- if ( this.left.includeDeclaration() ) {
6867
+ if ( this.left.includeWithAllDeclarations() ) {
6777
6868
  addedNewNodes = true;
6778
6869
  }
6779
6870
  return addedNewNodes;
6780
6871
  }
6781
6872
 
6782
6873
  initialiseScope ( parentScope ) {
6783
- this.scope = new Scope( {
6784
- parent: parentScope,
6785
- isBlockScope: true,
6786
- isLexicalBoundary: false
6787
- } );
6874
+ this.scope = new BlockScope( { parent: parentScope } );
6788
6875
  }
6789
6876
  }
6790
6877
 
6791
6878
  class ForOfStatement extends Statement {
6792
6879
  bind () {
6793
6880
  super.bind();
6794
- this.left.assignExpression( UNKNOWN_ASSIGNMENT );
6881
+ this.left.bindAssignment( UNKNOWN_ASSIGNMENT );
6795
6882
  }
6796
6883
 
6797
6884
  hasEffects ( options ) {
6798
6885
  return (
6799
6886
  this.included
6800
- || this.left && this.left.hasEffects( options )
6887
+ || this.left && (this.left.hasEffects( options ) || this.left.hasEffectsWhenAssigned( options ))
6801
6888
  || this.right && this.right.hasEffects( options )
6802
- || this.body.hasEffects( Object.assign( {}, options, { inNestedBreakableStatement: true } ) )
6889
+ || this.body.hasEffects( options.setIgnoreBreakStatements() )
6803
6890
  );
6804
6891
  }
6805
6892
 
6806
6893
  includeInBundle () {
6807
6894
  let addedNewNodes = super.includeInBundle();
6808
- if ( this.left.includeDeclaration() ) {
6895
+ if ( this.left.includeWithAllDeclarations() ) {
6809
6896
  addedNewNodes = true;
6810
6897
  }
6811
6898
  return addedNewNodes;
@@ -6820,45 +6907,65 @@ class ForOfStatement extends Statement {
6820
6907
  }
6821
6908
 
6822
6909
  initialiseScope ( parentScope ) {
6823
- this.scope = new Scope( {
6824
- parent: parentScope,
6825
- isBlockScope: true,
6826
- isLexicalBoundary: false
6827
- } );
6910
+ this.scope = new BlockScope( { parent: parentScope } );
6828
6911
  }
6829
6912
  }
6830
6913
 
6831
- class FunctionDeclaration extends Function {
6832
- addReference () {}
6914
+ class FunctionScope extends Scope {
6915
+ constructor ( options ) {
6916
+ if ( options === void 0 ) options = {};
6833
6917
 
6834
- assignExpression ( expression ) {
6835
- this.assignedExpressions.add( expression );
6836
- this.isReassigned = true;
6918
+ super( options );
6919
+ this.variables.arguments = new ParameterVariable( 'arguments' );
6920
+ this.variables.this = new LocalVariable( 'this', null, null );
6837
6921
  }
6838
6922
 
6839
- gatherPossibleValues ( values ) {
6840
- values.add( this );
6923
+ findLexicalBoundary () {
6924
+ return this;
6841
6925
  }
6926
+ }
6842
6927
 
6843
- getName () {
6844
- return this.name;
6845
- }
6928
+ class FunctionNode extends Node$1 {
6929
+ bindCall ( ref ) {
6930
+ var withNew = ref.withNew;
6846
6931
 
6847
- initialiseChildren ( parentScope ) {
6848
- if ( this.id ) {
6849
- this.name = this.id.name; // may be overridden by bundle.deconflict
6850
- parentScope.addDeclaration( this.name, this, false, false );
6851
- this.id.initialise( parentScope );
6932
+ const thisVariable = this.scope.findVariable( 'this' );
6933
+
6934
+ if ( withNew ) {
6935
+ thisVariable.assignExpression( UNKNOWN_OBJECT_LITERAL );
6936
+ } else {
6937
+ thisVariable.assignExpression( UNKNOWN_ASSIGNMENT );
6852
6938
  }
6853
- super.initialiseChildren( parentScope );
6939
+ }
6940
+
6941
+ hasEffects ( options ) {
6942
+ return this.included || (this.id && this.id.hasEffects( options ));
6943
+ }
6944
+
6945
+ hasEffectsAsExpressionStatement ( options ) {
6946
+ return this.hasEffects( options );
6947
+ }
6948
+
6949
+ hasEffectsWhenCalled ( options ) {
6950
+ const innerOptions = options.setIgnoreSafeThisMutations();
6951
+ return this.params.some( param => param.hasEffects( innerOptions ) )
6952
+ || this.body.hasEffects( innerOptions );
6854
6953
  }
6855
6954
 
6856
6955
  hasEffectsWhenMutated () {
6857
6956
  return this.included;
6858
6957
  }
6859
6958
 
6860
- initialiseNode () {
6861
- this.assignedExpressions = new Set( [ this ] );
6959
+ initialiseScope ( parentScope ) {
6960
+ this.scope = new FunctionScope( { parent: parentScope } );
6961
+ }
6962
+ }
6963
+
6964
+ class FunctionDeclaration extends FunctionNode {
6965
+ initialiseChildren ( parentScope ) {
6966
+ this.id && this.id.initialiseAndDeclare( parentScope, 'function', this );
6967
+ this.params.forEach( param => param.initialiseAndDeclare( this.scope, 'parameter' ) );
6968
+ this.body.initialiseAndReplaceScope( new Scope( { parent: this.scope } ) );
6862
6969
  }
6863
6970
 
6864
6971
  render ( code, es ) {
@@ -6870,21 +6977,43 @@ class FunctionDeclaration extends Function {
6870
6977
  }
6871
6978
  }
6872
6979
 
6873
- class FunctionExpression extends Function {
6874
- addReference () {}
6980
+ class FunctionExpression extends FunctionNode {
6981
+ initialiseChildren () {
6982
+ this.id && this.id.initialiseAndDeclare( this.scope, 'function', this );
6983
+ this.params.forEach( param => param.initialiseAndDeclare( this.scope, 'parameter' ) );
6984
+ this.body.initialiseAndReplaceScope( new Scope( { parent: this.scope } ) );
6985
+ }
6986
+ }
6875
6987
 
6876
- getName () {
6877
- return this.name;
6988
+ function isReference (node, parent) {
6989
+ if (node.type === 'MemberExpression') {
6990
+ return !node.computed && isReference(node.object, node);
6878
6991
  }
6879
6992
 
6880
- initialiseChildren ( parentScope ) {
6881
- if ( this.id ) {
6882
- this.name = this.id.name; // may be overridden by bundle.deconflict
6883
- this.scope.addDeclaration( this.name, this, false, false );
6884
- this.id.initialise( this.scope );
6993
+ if (node.type === 'Identifier') {
6994
+ // the only time we could have an identifier node without a parent is
6995
+ // if it's the entire body of a function without a block statement –
6996
+ // i.e. an arrow function expression like `a => a`
6997
+ if (!parent) return true;
6998
+
6999
+ // TODO is this right?
7000
+ if (parent.type === 'MemberExpression' || parent.type === 'MethodDefinition') {
7001
+ return parent.computed || node === parent.object;
6885
7002
  }
6886
- super.initialiseChildren( parentScope );
7003
+
7004
+ // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
7005
+ if (parent.type === 'Property') return parent.computed || node === parent.value;
7006
+
7007
+ // disregard the `bar` in `class Foo { bar () {...} }`
7008
+ if (parent.type === 'MethodDefinition') return false;
7009
+
7010
+ // disregard the `bar` in `export { foo as bar }`
7011
+ if (parent.type === 'ExportSpecifier' && node !== parent.local) return false;
7012
+
7013
+ return true;
6887
7014
  }
7015
+
7016
+ return false;
6888
7017
  }
6889
7018
 
6890
7019
  function isAssignmentPatternLhs ( node, parent ) {
@@ -6903,54 +7032,74 @@ function isAssignmentPatternLhs ( node, parent ) {
6903
7032
  }
6904
7033
 
6905
7034
  class Identifier extends Node$1 {
6906
- assignExpression ( expression ) {
6907
- if ( this.declaration ) {
6908
- this.declaration.assignExpression( expression );
7035
+ bind () {
7036
+ if ( isReference( this, this.parent ) || isAssignmentPatternLhs( this, this.parent ) ) {
7037
+ this.variable = this.scope.findVariable( this.name );
7038
+ this.variable.addReference( this );
6909
7039
  }
6910
7040
  }
6911
7041
 
6912
- bind () {
6913
- if ( isReference( this, this.parent ) || isAssignmentPatternLhs( this, this.parent ) ) {
6914
- this.declaration = this.scope.findDeclaration( this.name );
6915
- this.declaration.addReference( this ); // TODO necessary?
7042
+ bindAssignment ( expression ) {
7043
+ if ( this.variable ) {
7044
+ this.variable.assignExpression( expression );
6916
7045
  }
6917
7046
  }
6918
7047
 
6919
- gatherPossibleValues ( values ) {
6920
- if ( isReference( this, this.parent ) ) {
6921
- values.add( this );
7048
+ bindCall ( callOptions ) {
7049
+ if ( this.variable ) {
7050
+ this.variable.addCall( callOptions );
6922
7051
  }
6923
7052
  }
6924
7053
 
6925
7054
  hasEffectsAsExpressionStatement ( options ) {
6926
- return this.hasEffects( options ) || this.declaration.isGlobal;
7055
+ return this.hasEffects( options ) || this.variable.isGlobal;
6927
7056
  }
6928
7057
 
6929
7058
  hasEffectsWhenAssigned () {
6930
- return this.declaration && this.declaration.included;
7059
+ return this.variable && this.variable.included;
7060
+ }
7061
+
7062
+ hasEffectsWhenCalled ( options ) {
7063
+ if ( !this.variable ) {
7064
+ return true;
7065
+ }
7066
+ return this.variable.hasEffectsWhenCalled( options );
6931
7067
  }
6932
7068
 
6933
7069
  hasEffectsWhenMutated ( options ) {
6934
- return this.declaration &&
6935
- (this.declaration.included ||
6936
- this.declaration.isParam ||
6937
- this.declaration.isGlobal ||
6938
- this.declaration.isExternal ||
6939
- this.declaration.isNamespace ||
6940
- !this.declaration.assignedExpressions ||
6941
- Array.from( this.declaration.assignedExpressions ).some( node => node.hasEffectsWhenMutated( options ) ));
7070
+ return this.variable && this.variable.hasEffectsWhenMutated( options );
6942
7071
  }
6943
7072
 
6944
7073
  includeInBundle () {
6945
7074
  if ( this.included ) { return false; }
6946
7075
  this.included = true;
6947
- this.declaration && this.declaration.includeDeclaration();
7076
+ this.variable && this.variable.includeVariable();
6948
7077
  return true;
6949
7078
  }
6950
7079
 
7080
+ initialiseAndDeclare ( parentScope, kind, init ) {
7081
+ this.initialiseScope( parentScope );
7082
+ switch ( kind ) {
7083
+ case 'var':
7084
+ case 'function':
7085
+ this.scope.addDeclaration( this, true, init );
7086
+ break;
7087
+ case 'let':
7088
+ case 'const':
7089
+ case 'class':
7090
+ this.scope.addDeclaration( this, false, init );
7091
+ break;
7092
+ case 'parameter':
7093
+ this.scope.addParameterDeclaration( this );
7094
+ break;
7095
+ default:
7096
+ throw new Error( 'Unexpected identifier kind', kind );
7097
+ }
7098
+ }
7099
+
6951
7100
  render ( code, es ) {
6952
- if ( this.declaration ) {
6953
- const name = this.declaration.getName( es );
7101
+ if ( this.variable ) {
7102
+ const name = this.variable.getName( es );
6954
7103
  if ( name !== this.name ) {
6955
7104
  code.overwrite( this.start, this.end, name, { storeName: true, contentOnly: false } );
6956
7105
 
@@ -6973,7 +7122,7 @@ const statementsWithIfStatements = new Set( [
6973
7122
  'WhileStatement'
6974
7123
  ] );
6975
7124
 
6976
- function handleVarDeclarations ( node, scope ) {
7125
+ function getHoistedVars ( node, scope ) {
6977
7126
  const hoistedVars = [];
6978
7127
 
6979
7128
  function visit ( node ) {
@@ -6983,7 +7132,7 @@ function handleVarDeclarations ( node, scope ) {
6983
7132
  declarator.initialise( scope );
6984
7133
 
6985
7134
  extractNames( declarator.id ).forEach( name => {
6986
- if ( !~hoistedVars.indexOf( name ) ) { hoistedVars.push( name ); }
7135
+ if ( hoistedVars.indexOf( name ) < 0 ) { hoistedVars.push( name ); }
6987
7136
  } );
6988
7137
  } );
6989
7138
  }
@@ -6998,29 +7147,24 @@ function handleVarDeclarations ( node, scope ) {
6998
7147
  return hoistedVars;
6999
7148
  }
7000
7149
 
7001
- // TODO DRY this out
7002
7150
  class IfStatement extends Statement {
7003
7151
  initialiseChildren ( parentScope ) {
7152
+ super.initialiseChildren( parentScope );
7004
7153
  if ( this.module.bundle.treeshake ) {
7005
7154
  this.testValue = this.test.getValue();
7006
7155
 
7007
7156
  if ( this.testValue === UNKNOWN_VALUE ) {
7008
- super.initialiseChildren( parentScope );
7009
- } else if ( this.testValue ) {
7010
- this.consequent.initialise( this.scope );
7157
+ return;
7158
+ }
7159
+ if ( this.testValue ) {
7011
7160
  if ( this.alternate ) {
7012
- this.hoistedVars = handleVarDeclarations( this.alternate, this.scope );
7161
+ this.hoistedVars = getHoistedVars( this.alternate, this.scope );
7013
7162
  this.alternate = null;
7014
7163
  }
7015
7164
  } else {
7016
- if ( this.alternate ) {
7017
- this.alternate.initialise( this.scope );
7018
- }
7019
- this.hoistedVars = handleVarDeclarations( this.consequent, this.scope );
7165
+ this.hoistedVars = getHoistedVars( this.consequent, this.scope );
7020
7166
  this.consequent = null;
7021
7167
  }
7022
- } else {
7023
- super.initialiseChildren( parentScope );
7024
7168
  }
7025
7169
  }
7026
7170
 
@@ -7039,8 +7183,8 @@ class IfStatement extends Statement {
7039
7183
  if ( this.hoistedVars ) {
7040
7184
  const names = this.hoistedVars
7041
7185
  .map( name => {
7042
- const declaration = this.scope.findDeclaration( name );
7043
- return declaration.included ? declaration.getName() : null;
7186
+ const variable = this.scope.findVariable( name );
7187
+ return variable.included ? variable.getName() : null;
7044
7188
  } )
7045
7189
  .filter( Boolean );
7046
7190
 
@@ -7090,15 +7234,21 @@ class ImportDeclaration extends Node$1 {
7090
7234
  }
7091
7235
  }
7092
7236
 
7237
+ class LabeledStatement extends Statement {
7238
+ hasEffects ( options ) {
7239
+ return this.body.hasEffects(
7240
+ options
7241
+ .setIgnoreLabel( this.label.name )
7242
+ .setIgnoreBreakStatements()
7243
+ );
7244
+ }
7245
+ }
7246
+
7093
7247
  class Literal extends Node$1 {
7094
7248
  getValue () {
7095
7249
  return this.value;
7096
7250
  }
7097
7251
 
7098
- gatherPossibleValues ( values ) {
7099
- values.add( this );
7100
- }
7101
-
7102
7252
  hasEffectsWhenMutated () {
7103
7253
  return false;
7104
7254
  }
@@ -7138,6 +7288,63 @@ class LogicalExpression extends Node$1 {
7138
7288
  }
7139
7289
  }
7140
7290
 
7291
+ function flatten ( node ) {
7292
+ const parts = [];
7293
+ while ( node.type === 'MemberExpression' ) {
7294
+ if ( node.computed ) { return null; }
7295
+ parts.unshift( node.property.name );
7296
+
7297
+ node = node.object;
7298
+ }
7299
+
7300
+ if ( node.type !== 'Identifier' ) { return null; }
7301
+
7302
+ const name = node.name;
7303
+ parts.unshift( name );
7304
+
7305
+ return { name, keypath: parts.join( '.' ) };
7306
+ }
7307
+
7308
+ const pureFunctions = {};
7309
+
7310
+ const arrayTypes = 'Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array'.split( ' ' );
7311
+ const simdTypes = 'Int8x16 Int16x8 Int32x4 Float32x4 Float64x2'.split( ' ' );
7312
+ const simdMethods = 'abs add and bool check div equal extractLane fromFloat32x4 fromFloat32x4Bits fromFloat64x2 fromFloat64x2Bits fromInt16x8Bits fromInt32x4 fromInt32x4Bits fromInt8x16Bits greaterThan greaterThanOrEqual lessThan lessThanOrEqual load max maxNum min minNum mul neg not notEqual or reciprocalApproximation reciprocalSqrtApproximation replaceLane select selectBits shiftLeftByScalar shiftRightArithmeticByScalar shiftRightLogicalByScalar shuffle splat sqrt store sub swizzle xor'.split( ' ' );
7313
+ const allSimdMethods = [];
7314
+ simdTypes.forEach( t => {
7315
+ simdMethods.forEach( m => {
7316
+ allSimdMethods.push( `SIMD.${t}.${m}` );
7317
+ });
7318
+ });
7319
+
7320
+ [
7321
+ 'Array.isArray',
7322
+ 'Error', 'EvalError', 'InternalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError',
7323
+ 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape', 'unescape',
7324
+ 'Object', 'Object.create', 'Object.getNotifier', 'Object.getOwn', 'Object.getOwnPropertyDescriptor', 'Object.getOwnPropertyNames', 'Object.getOwnPropertySymbols', 'Object.getPrototypeOf', 'Object.is', 'Object.isExtensible', 'Object.isFrozen', 'Object.isSealed', 'Object.keys',
7325
+ 'Function', 'Boolean',
7326
+ 'Number', 'Number.isFinite', 'Number.isInteger', 'Number.isNaN', 'Number.isSafeInteger', 'Number.parseFloat', 'Number.parseInt',
7327
+ 'Symbol', 'Symbol.for', 'Symbol.keyFor',
7328
+ 'Math.abs', 'Math.acos', 'Math.acosh', 'Math.asin', 'Math.asinh', 'Math.atan', 'Math.atan2', 'Math.atanh', 'Math.cbrt', 'Math.ceil', 'Math.clz32', 'Math.cos', 'Math.cosh', 'Math.exp', 'Math.expm1', 'Math.floor', 'Math.fround', 'Math.hypot', 'Math.imul', 'Math.log', 'Math.log10', 'Math.log1p', 'Math.log2', 'Math.max', 'Math.min', 'Math.pow', 'Math.random', 'Math.round', 'Math.sign', 'Math.sin', 'Math.sinh', 'Math.sqrt', 'Math.tan', 'Math.tanh', 'Math.trunc',
7329
+ 'Date', 'Date.UTC', 'Date.now', 'Date.parse',
7330
+ 'String', 'String.fromCharCode', 'String.fromCodePoint', 'String.raw',
7331
+ 'RegExp',
7332
+ 'Map', 'Set', 'WeakMap', 'WeakSet',
7333
+ 'ArrayBuffer', 'ArrayBuffer.isView',
7334
+ 'DataView',
7335
+ 'JSON.parse', 'JSON.stringify',
7336
+ 'Promise.all', 'Promise.race', 'Promise.resolve',
7337
+ 'Intl.Collator', 'Intl.Collator.supportedLocalesOf', 'Intl.DateTimeFormat', 'Intl.DateTimeFormat.supportedLocalesOf', 'Intl.NumberFormat', 'Intl.NumberFormat.supportedLocalesOf'
7338
+
7339
+ // TODO properties of e.g. window...
7340
+ ].concat(
7341
+ arrayTypes,
7342
+ arrayTypes.map( t => `${t}.from` ),
7343
+ arrayTypes.map( t => `${t}.of` ),
7344
+ simdTypes.map( t => `SIMD.${t}` ),
7345
+ allSimdMethods
7346
+ ).forEach( name => pureFunctions[ name ] = true );
7347
+
7141
7348
  const validProp = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
7142
7349
 
7143
7350
  class Keypath {
@@ -7170,15 +7377,15 @@ class MemberExpression extends Node$1 {
7170
7377
  const keypath = new Keypath( this );
7171
7378
 
7172
7379
  if ( !keypath.computed && keypath.root.type === 'Identifier' ) {
7173
- let declaration = this.scope.findDeclaration( keypath.root.name );
7380
+ let variable = this.scope.findVariable( keypath.root.name );
7174
7381
 
7175
- while ( declaration.isNamespace && keypath.parts.length ) {
7176
- const exporterId = declaration.module.id;
7382
+ while ( variable.isNamespace && keypath.parts.length ) {
7383
+ const exporterId = variable.module.id;
7177
7384
 
7178
7385
  const part = keypath.parts[ 0 ];
7179
- declaration = declaration.module.traceExport( part.name || part.value );
7386
+ variable = variable.module.traceExport( part.name || part.value );
7180
7387
 
7181
- if ( !declaration ) {
7388
+ if ( !variable ) {
7182
7389
  this.module.warn( {
7183
7390
  code: 'MISSING_EXPORT',
7184
7391
  missing: part.name || part.value,
@@ -7199,10 +7406,10 @@ class MemberExpression extends Node$1 {
7199
7406
  return; // not a namespaced declaration
7200
7407
  }
7201
7408
 
7202
- this.declaration = declaration;
7409
+ this.variable = variable;
7203
7410
 
7204
- if ( declaration.isExternal ) {
7205
- declaration.module.suggestName( keypath.root.name );
7411
+ if ( variable.isExternal ) {
7412
+ variable.module.suggestName( keypath.root.name );
7206
7413
  }
7207
7414
  }
7208
7415
 
@@ -7211,8 +7418,10 @@ class MemberExpression extends Node$1 {
7211
7418
  }
7212
7419
  }
7213
7420
 
7214
- gatherPossibleValues ( values ) {
7215
- values.add( UNKNOWN_ASSIGNMENT ); // TODO
7421
+ bindCall ( callOptions ) {
7422
+ if ( this.variable ) {
7423
+ this.variable.addCall( callOptions );
7424
+ }
7216
7425
  }
7217
7426
 
7218
7427
  hasEffectsWhenAssigned ( options ) {
@@ -7221,16 +7430,27 @@ class MemberExpression extends Node$1 {
7221
7430
 
7222
7431
  includeInBundle () {
7223
7432
  let addedNewNodes = super.includeInBundle();
7224
- if ( this.declaration && !this.declaration.included ) {
7225
- this.declaration.includeDeclaration();
7433
+ if ( this.variable && !this.variable.included ) {
7434
+ this.variable.includeVariable();
7226
7435
  addedNewNodes = true;
7227
7436
  }
7228
7437
  return addedNewNodes;
7229
7438
  }
7230
7439
 
7440
+ hasEffectsWhenCalled ( options ) {
7441
+ if ( this.variable ) {
7442
+ return this.variable.hasEffectsWhenCalled( options );
7443
+ }
7444
+ if ( !isReference( this ) ) {
7445
+ return true;
7446
+ }
7447
+ const flattenedNode = flatten( this );
7448
+ return !(this.scope.findVariable( flattenedNode.name ).isGlobal && pureFunctions[ flattenedNode.keypath ]);
7449
+ }
7450
+
7231
7451
  render ( code, es ) {
7232
- if ( this.declaration ) {
7233
- const name = this.declaration.getName( es );
7452
+ if ( this.variable ) {
7453
+ const name = this.variable.getName( es );
7234
7454
  if ( name !== this.name ) { code.overwrite( this.start, this.end, name, { storeName: true, contentOnly: false } ); }
7235
7455
  }
7236
7456
 
@@ -7242,9 +7462,30 @@ class MemberExpression extends Node$1 {
7242
7462
  }
7243
7463
  }
7244
7464
 
7465
+ class MethodDefinition extends Node$1 {
7466
+ bindCall ( callOptions ) {
7467
+ this.value.bindCall( callOptions );
7468
+ }
7469
+
7470
+ hasEffects ( options ) {
7471
+ return this.key.hasEffects( options );
7472
+ }
7473
+
7474
+ hasEffectsWhenCalled ( options ) {
7475
+ return this.value.hasEffectsWhenCalled( options );
7476
+ }
7477
+ }
7478
+
7245
7479
  class NewExpression extends Node$1 {
7246
- hasEffects () {
7247
- return this.included || callHasEffects( this.scope, this.callee, true );
7480
+ bind () {
7481
+ super.bind();
7482
+ this.callee.bindCall( { withNew: true } );
7483
+ }
7484
+
7485
+ hasEffects ( options ) {
7486
+ return this.included
7487
+ || this.arguments.some( child => child.hasEffects( options ) )
7488
+ || this.callee.hasEffectsWhenCalled( options.getHasEffectsWhenCalledOptions( this.callee ) );
7248
7489
  }
7249
7490
  }
7250
7491
 
@@ -7255,24 +7496,35 @@ class ObjectExpression extends Node$1 {
7255
7496
  }
7256
7497
 
7257
7498
  class ObjectPattern extends Node$1 {
7258
- assignExpression () {
7259
- this.eachChild( child => child.assignExpression( UNKNOWN_ASSIGNMENT ) );
7499
+ bindAssignment ( expression ) {
7500
+ this.properties.forEach( child => child.bindAssignment( expression ) );
7260
7501
  }
7261
7502
 
7262
7503
  hasEffectsWhenAssigned ( options ) {
7263
7504
  return this.someChild( child => child.hasEffectsWhenAssigned( options ) );
7264
7505
  }
7506
+
7507
+ initialiseAndDeclare ( parentScope, kind, init ) {
7508
+ this.initialiseScope( parentScope );
7509
+ this.properties.forEach( child => child.initialiseAndDeclare( parentScope, kind, init ) );
7510
+ }
7265
7511
  }
7266
7512
 
7267
7513
  class Property extends Node$1 {
7268
- assignExpression ( expression ) {
7269
- this.value.assignExpression( expression );
7514
+ bindAssignment () {
7515
+ this.value.bindAssignment( UNKNOWN_ASSIGNMENT );
7270
7516
  }
7271
7517
 
7272
7518
  hasEffectsWhenAssigned ( options ) {
7273
7519
  return this.value.hasEffectsWhenAssigned( options );
7274
7520
  }
7275
7521
 
7522
+ initialiseAndDeclare ( parentScope, kind, init ) {
7523
+ this.initialiseScope( parentScope );
7524
+ this.key.initialise( parentScope );
7525
+ this.value.initialiseAndDeclare( parentScope, kind, init && UNKNOWN_ASSIGNMENT );
7526
+ }
7527
+
7276
7528
  render ( code, es ) {
7277
7529
  if ( !this.shorthand ) {
7278
7530
  this.key.render( code, es );
@@ -7282,23 +7534,24 @@ class Property extends Node$1 {
7282
7534
  }
7283
7535
 
7284
7536
  class RestElement extends Node$1 {
7285
- assignExpression () {
7286
- this.argument.assignExpression( UNKNOWN_ASSIGNMENT );
7537
+ bindAssignment () {
7538
+ this.argument.bindAssignment( UNKNOWN_ASSIGNMENT );
7287
7539
  }
7288
7540
 
7289
7541
  hasEffectsWhenAssigned ( options ) {
7290
7542
  return this.argument.hasEffectsWhenAssigned( options );
7291
7543
  }
7544
+
7545
+ initialiseAndDeclare ( parentScope, kind ) {
7546
+ this.initialiseScope( parentScope );
7547
+ this.argument.initialiseAndDeclare( parentScope, kind, UNKNOWN_ASSIGNMENT );
7548
+ }
7292
7549
  }
7293
7550
 
7294
7551
  class ReturnStatement extends Statement {
7295
7552
  hasEffects ( options ) {
7296
7553
  return super.hasEffects( options )
7297
- || !options.inNestedFunctionCall;
7298
- }
7299
-
7300
- shouldBeIncluded () {
7301
- return true;
7554
+ || !options.ignoreReturnAwaitYield();
7302
7555
  }
7303
7556
  }
7304
7557
 
@@ -7325,32 +7578,28 @@ class SwitchCase extends Node$1 {
7325
7578
  }
7326
7579
 
7327
7580
  class SwitchStatement extends Statement {
7328
- hasEffects(options) {
7329
- return super.hasEffects(Object.assign({}, options, {inNestedBreakableStatement: true}));
7581
+ hasEffects ( options ) {
7582
+ return super.hasEffects( options.setIgnoreBreakStatements() );
7330
7583
  }
7331
7584
 
7332
7585
  initialiseScope ( parentScope ) {
7333
- this.scope = new Scope( {
7334
- parent: parentScope,
7335
- isBlockScope: true,
7336
- isLexicalBoundary: false
7337
- } );
7586
+ this.scope = new BlockScope( { parent: parentScope } );
7338
7587
  }
7339
7588
  }
7340
7589
 
7341
7590
  class TaggedTemplateExpression extends Node$1 {
7342
7591
  bind () {
7343
7592
  if ( this.tag.type === 'Identifier' ) {
7344
- const declaration = this.scope.findDeclaration( this.tag.name );
7593
+ const variable = this.scope.findVariable( this.tag.name );
7345
7594
 
7346
- if ( declaration.isNamespace ) {
7595
+ if ( variable.isNamespace ) {
7347
7596
  this.module.error( {
7348
7597
  code: 'CANNOT_CALL_NAMESPACE',
7349
7598
  message: `Cannot call a namespace ('${this.tag.name}')`
7350
7599
  }, this.start );
7351
7600
  }
7352
7601
 
7353
- if ( this.tag.name === 'eval' && declaration.isGlobal ) {
7602
+ if ( this.tag.name === 'eval' && variable.isGlobal ) {
7354
7603
  this.module.warn( {
7355
7604
  code: 'EVAL',
7356
7605
  message: `Use of eval is strongly discouraged, as it poses security risks and may cause issues with minification`,
@@ -7360,10 +7609,12 @@ class TaggedTemplateExpression extends Node$1 {
7360
7609
  }
7361
7610
 
7362
7611
  super.bind();
7612
+ this.tag.bindCall( { withNew: false } );
7363
7613
  }
7364
7614
 
7365
7615
  hasEffects ( options ) {
7366
- return this.quasi.hasEffects( options ) || callHasEffects( this.scope, this.tag, false );
7616
+ return super.hasEffects( options )
7617
+ || this.tag.hasEffectsWhenCalled( options.getHasEffectsWhenCalledOptions( this.tag ) );
7367
7618
  }
7368
7619
  }
7369
7620
 
@@ -7396,6 +7647,14 @@ class ThisExpression extends Node$1 {
7396
7647
  }
7397
7648
  }
7398
7649
 
7650
+ bind () {
7651
+ this.variable = this.scope.findVariable( 'this' );
7652
+ }
7653
+
7654
+ hasEffectsWhenMutated ( options ) {
7655
+ return !options.ignoreSafeThisMutations() || this.variable.hasEffectsWhenMutated( options );
7656
+ }
7657
+
7399
7658
  render ( code ) {
7400
7659
  if ( this.alias ) {
7401
7660
  code.overwrite( this.start, this.end, this.alias, { storeName: true, contentOnly: false } );
@@ -7453,8 +7712,8 @@ class UpdateExpression extends Node$1 {
7453
7712
  bind () {
7454
7713
  disallowIllegalReassignment( this.scope, this.argument );
7455
7714
  if ( this.argument.type === 'Identifier' ) {
7456
- const declaration = this.scope.findDeclaration( this.argument.name );
7457
- declaration.isReassigned = true;
7715
+ const variable = this.scope.findVariable( this.argument.name );
7716
+ variable.isReassigned = true;
7458
7717
  }
7459
7718
  super.bind();
7460
7719
  }
@@ -7468,88 +7727,25 @@ class UpdateExpression extends Node$1 {
7468
7727
  }
7469
7728
  }
7470
7729
 
7471
- class DeclaratorProxy {
7472
- constructor ( name, declarator, isTopLevel, init ) {
7473
- this.name = name;
7474
- this.declarator = declarator;
7475
-
7476
- this.isReassigned = false;
7477
- this.exportName = null;
7478
-
7479
- this.duplicates = [];
7480
- this.assignedExpressions = new Set( init ? [ init ] : null );
7481
- }
7482
-
7483
- addReference () {
7484
- /* noop? */
7485
- }
7486
-
7487
- assignExpression ( expression ) {
7488
- this.assignedExpressions.add( expression );
7489
- this.isReassigned = true;
7490
- }
7491
-
7492
- gatherPossibleValues ( values ) {
7493
- this.assignedExpressions.forEach( value => values.add( value ) );
7494
- }
7495
-
7496
- getName ( es ) {
7497
- // TODO destructuring...
7498
- if ( es ) { return this.name; }
7499
- if ( !this.isReassigned || !this.exportName ) { return this.name; }
7500
-
7501
- return `exports.${this.exportName}`;
7502
- }
7503
-
7504
- includeDeclaration () {
7505
- if ( this.included ) {
7506
- return false;
7507
- }
7508
- this.included = true;
7509
- this.declarator.includeDeclaration();
7510
- this.duplicates.forEach( duplicate => duplicate.includeDeclaration() );
7511
- return true;
7512
- }
7513
-
7514
- toString () {
7515
- return this.name;
7516
- }
7517
- }
7518
-
7519
7730
  class VariableDeclarator extends Node$1 {
7520
- assignExpression () {
7521
- for ( const proxy of this.proxies.values() ) {
7522
- proxy.assignExpression( UNKNOWN_ASSIGNMENT );
7523
- }
7731
+ bindAssignment ( expression ) {
7732
+ this.id.bindAssignment( expression );
7524
7733
  }
7525
7734
 
7526
- hasEffects ( options ) {
7527
- return super.hasEffects( options )
7528
- || extractNames( this.id ).some( name => this.proxies.get( name ).included );
7529
- }
7530
-
7531
- initialiseNode () {
7532
- this.proxies = new Map();
7533
- const lexicalBoundary = this.scope.findLexicalBoundary();
7534
- const init = this.init
7535
- ? ( this.id.type === 'Identifier' ? this.init : UNKNOWN_ASSIGNMENT )
7536
- : null;
7537
-
7538
- extractNames( this.id ).forEach( name => {
7539
- const proxy = new DeclaratorProxy( name, this, lexicalBoundary.isModuleScope, init );
7540
-
7541
- this.proxies.set( name, proxy );
7542
- this.scope.addDeclaration( name, proxy, this.parent.kind === 'var' );
7543
- } );
7735
+ initialiseDeclarator ( parentScope, kind ) {
7736
+ this.initialiseScope( parentScope );
7737
+ this.init && this.init.initialise( this.scope );
7738
+ this.id.initialiseAndDeclare( this.scope, kind, this.init );
7544
7739
  }
7545
7740
 
7741
+ // TODO Deleting this does not break any tests. Find meaningful test or delete.
7546
7742
  render ( code, es ) {
7547
7743
  extractNames( this.id ).forEach( name => {
7548
- const declaration = this.proxies.get( name );
7744
+ const variable = this.scope.findVariable( name );
7549
7745
 
7550
- if ( !es && declaration.exportName && declaration.isReassigned ) {
7746
+ if ( !es && variable.exportName && variable.isReassigned ) {
7551
7747
  if ( this.init ) {
7552
- code.overwrite( this.start, this.id.end, declaration.getName( es ) );
7748
+ code.overwrite( this.start, this.id.end, variable.getName( es ) );
7553
7749
  } else if ( this.module.bundle.treeshake ) {
7554
7750
  code.remove( this.start, this.end );
7555
7751
  }
@@ -7576,15 +7772,19 @@ function getSeparator ( code, start ) {
7576
7772
  const forStatement = /^For(?:Of|In)?Statement/;
7577
7773
 
7578
7774
  class VariableDeclaration extends Node$1 {
7579
- assignExpression () {
7580
- this.eachChild( child => child.assignExpression( UNKNOWN_ASSIGNMENT ) );
7775
+ bindAssignment () {
7776
+ this.eachChild( child => child.bindAssignment( UNKNOWN_ASSIGNMENT ) );
7581
7777
  }
7582
7778
 
7583
- includeDeclaration () {
7779
+ hasEffectsWhenAssigned () {
7780
+ return false;
7781
+ }
7782
+
7783
+ includeWithAllDeclarations () {
7584
7784
  if ( this.isFullyIncluded() ) { return false; }
7585
7785
  let addedNewNodes = false;
7586
7786
  this.declarations.forEach( declarator => {
7587
- if ( declarator.includeDeclaration() ) {
7787
+ if ( declarator.includeInBundle() ) {
7588
7788
  addedNewNodes = true;
7589
7789
  }
7590
7790
  } );
@@ -7612,6 +7812,10 @@ class VariableDeclaration extends Node$1 {
7612
7812
  return false;
7613
7813
  }
7614
7814
 
7815
+ initialiseChildren () {
7816
+ this.declarations.forEach( child => child.initialiseDeclarator( this.scope, this.kind ) );
7817
+ }
7818
+
7615
7819
  render ( code, es ) {
7616
7820
  const treeshake = this.module.bundle.treeshake;
7617
7821
 
@@ -7632,8 +7836,8 @@ class VariableDeclaration extends Node$1 {
7632
7836
  const prefix = empty ? '' : separator; // TODO indentation
7633
7837
 
7634
7838
  if ( declarator.id.type === 'Identifier' ) {
7635
- const proxy = declarator.proxies.get( declarator.id.name );
7636
- const isExportedAndReassigned = !es && proxy.exportName && proxy.isReassigned;
7839
+ const variable = this.scope.findVariable( declarator.id.name );
7840
+ const isExportedAndReassigned = !es && variable.exportName && variable.isReassigned;
7637
7841
 
7638
7842
  if ( isExportedAndReassigned ) {
7639
7843
  if ( declarator.init ) {
@@ -7641,7 +7845,7 @@ class VariableDeclaration extends Node$1 {
7641
7845
  c = declarator.end;
7642
7846
  empty = false;
7643
7847
  }
7644
- } else if ( !treeshake || proxy.included ) {
7848
+ } else if ( !treeshake || variable.included ) {
7645
7849
  if ( shouldSeparate ) { code.overwrite( c, declarator.start, `${prefix}${this.kind} ` ); } // TODO indentation
7646
7850
  c = declarator.end;
7647
7851
  empty = false;
@@ -7651,8 +7855,8 @@ class VariableDeclaration extends Node$1 {
7651
7855
  let isIncluded = false;
7652
7856
 
7653
7857
  extractNames( declarator.id ).forEach( name => {
7654
- const proxy = declarator.proxies.get( name );
7655
- const isExportedAndReassigned = !es && proxy.exportName && proxy.isReassigned;
7858
+ const variable = this.scope.findVariable( name );
7859
+ const isExportedAndReassigned = !es && variable.exportName && variable.isReassigned;
7656
7860
 
7657
7861
  if ( isExportedAndReassigned ) {
7658
7862
  // code.overwrite( c, declarator.start, prefix );
@@ -7699,11 +7903,22 @@ class WhileStatement extends Statement {
7699
7903
  return (
7700
7904
  this.included
7701
7905
  || this.test.hasEffects( options )
7702
- || this.body.hasEffects( Object.assign( {}, options, { inNestedBreakableStatement: true } ) )
7906
+ || this.body.hasEffects( options.setIgnoreBreakStatements() )
7703
7907
  );
7704
7908
  }
7705
7909
  }
7706
7910
 
7911
+ class YieldExpression extends Node$1 {
7912
+ hasEffects ( options ) {
7913
+ return super.hasEffects( options )
7914
+ || !options.ignoreReturnAwaitYield();
7915
+ }
7916
+
7917
+ hasEffectsAsExpressionStatement ( options ) {
7918
+ return this.hasEffects( options );
7919
+ }
7920
+ }
7921
+
7707
7922
  var nodes = {
7708
7923
  ArrayExpression: Node$1,
7709
7924
  ArrayPattern,
@@ -7716,6 +7931,7 @@ var nodes = {
7716
7931
  BreakStatement,
7717
7932
  CallExpression,
7718
7933
  CatchClause,
7934
+ ClassBody,
7719
7935
  ClassDeclaration,
7720
7936
  ClassExpression,
7721
7937
  ConditionalExpression,
@@ -7733,9 +7949,11 @@ var nodes = {
7733
7949
  Identifier,
7734
7950
  IfStatement,
7735
7951
  ImportDeclaration,
7952
+ LabeledStatement,
7736
7953
  Literal,
7737
7954
  LogicalExpression,
7738
7955
  MemberExpression,
7956
+ MethodDefinition,
7739
7957
  NewExpression,
7740
7958
  ObjectExpression,
7741
7959
  ObjectPattern,
@@ -7754,7 +7972,8 @@ var nodes = {
7754
7972
  UpdateExpression,
7755
7973
  VariableDeclarator,
7756
7974
  VariableDeclaration,
7757
- WhileStatement
7975
+ WhileStatement,
7976
+ YieldExpression
7758
7977
  };
7759
7978
 
7760
7979
  class UnknownNode extends Node$1 {
@@ -7848,14 +8067,13 @@ function clone ( node ) {
7848
8067
 
7849
8068
  class ModuleScope extends Scope {
7850
8069
  constructor ( module ) {
7851
- super({
7852
- isBlockScope: false,
7853
- isLexicalBoundary: true,
8070
+ super( {
7854
8071
  isModuleScope: true,
7855
8072
  parent: module.bundle.scope
7856
- });
8073
+ } );
7857
8074
 
7858
8075
  this.module = module;
8076
+ this.variables.this = new LocalVariable( 'this', null, UNDEFINED_ASSIGNMENT );
7859
8077
  }
7860
8078
 
7861
8079
  deshadow ( names ) {
@@ -7867,21 +8085,21 @@ class ModuleScope extends Scope {
7867
8085
  const addDeclaration = declaration => {
7868
8086
  if ( declaration.isNamespace && !declaration.isExternal ) {
7869
8087
  declaration.module.getExports().forEach( name => {
7870
- addDeclaration( declaration.module.traceExport(name) );
7871
- });
8088
+ addDeclaration( declaration.module.traceExport( name ) );
8089
+ } );
7872
8090
  }
7873
8091
 
7874
8092
  names.add( declaration.name );
7875
8093
  };
7876
8094
 
7877
8095
  specifier.module.getExports().forEach( name => {
7878
- addDeclaration( specifier.module.traceExport(name) );
7879
- });
8096
+ addDeclaration( specifier.module.traceExport( name ) );
8097
+ } );
7880
8098
 
7881
8099
  if ( specifier.name !== '*' ) {
7882
8100
  const declaration = specifier.module.traceExport( specifier.name );
7883
8101
  if ( !declaration ) {
7884
- this.module.warn({
8102
+ this.module.warn( {
7885
8103
  code: 'NON_EXISTENT_EXPORT',
7886
8104
  name: specifier.name,
7887
8105
  source: specifier.module.id,
@@ -7899,22 +8117,22 @@ class ModuleScope extends Scope {
7899
8117
  names.add( specifier.specifier.imported.name );
7900
8118
  }
7901
8119
  }
7902
- });
8120
+ } );
7903
8121
 
7904
8122
  super.deshadow( names );
7905
8123
  }
7906
8124
 
7907
- findDeclaration ( name ) {
7908
- if ( this.declarations[ name ] ) {
7909
- return this.declarations[ name ];
7910
- }
7911
-
7912
- return this.module.trace( name ) || this.parent.findDeclaration( name );
7913
- }
7914
-
7915
8125
  findLexicalBoundary () {
7916
8126
  return this;
7917
8127
  }
8128
+
8129
+ findVariable ( name ) {
8130
+ if ( this.variables[ name ] ) {
8131
+ return this.variables[ name ];
8132
+ }
8133
+
8134
+ return this.module.trace( name ) || this.parent.findVariable( name );
8135
+ }
7918
8136
  }
7919
8137
 
7920
8138
  function tryParse ( module, acornOptions ) {
@@ -7933,6 +8151,11 @@ function tryParse ( module, acornOptions ) {
7933
8151
  }
7934
8152
  }
7935
8153
 
8154
+ function includeFully ( node ) {
8155
+ node.includeInBundle();
8156
+ node.eachChild( includeFully );
8157
+ }
8158
+
7936
8159
  class Module {
7937
8160
  constructor ( ref ) {
7938
8161
  var id = ref.id;
@@ -8067,9 +8290,6 @@ class Module {
8067
8290
  localName: 'default',
8068
8291
  identifier
8069
8292
  };
8070
-
8071
- // create a synthetic declaration
8072
- //this.declarations.default = new SyntheticDefaultDeclaration( node, identifier || this.basename() );
8073
8293
  }
8074
8294
 
8075
8295
  // export var { foo, bar } = ...
@@ -8236,6 +8456,10 @@ class Module {
8236
8456
  return keys( reexports );
8237
8457
  }
8238
8458
 
8459
+ includeAllInBundle () {
8460
+ this.ast.body.forEach( includeFully );
8461
+ }
8462
+
8239
8463
  includeInBundle () {
8240
8464
  let addedNewNodes = false;
8241
8465
  this.ast.body.forEach( node => {
@@ -8250,7 +8474,7 @@ class Module {
8250
8474
 
8251
8475
  namespace () {
8252
8476
  if ( !this.declarations[ '*' ] ) {
8253
- this.declarations[ '*' ] = new SyntheticNamespaceDeclaration( this );
8477
+ this.declarations[ '*' ] = new NamespaceVariable( this );
8254
8478
  }
8255
8479
 
8256
8480
  return this.declarations[ '*' ];
@@ -8286,8 +8510,8 @@ class Module {
8286
8510
 
8287
8511
  trace ( name ) {
8288
8512
  // TODO this is slightly circular
8289
- if ( name in this.scope.declarations ) {
8290
- return this.scope.declarations[ name ];
8513
+ if ( name in this.scope.variables ) {
8514
+ return this.scope.variables[ name ];
8291
8515
  }
8292
8516
 
8293
8517
  if ( name in this.imports ) {
@@ -8342,7 +8566,7 @@ class Module {
8342
8566
  const name = exportDeclaration.localName;
8343
8567
  const declaration = this.trace( name );
8344
8568
 
8345
- return declaration || this.bundle.scope.findDeclaration( name );
8569
+ return declaration || this.bundle.scope.findVariable( name );
8346
8570
  }
8347
8571
 
8348
8572
  if ( name === 'default' ) { return; }
@@ -8372,11 +8596,54 @@ class Module {
8372
8596
  }
8373
8597
  }
8374
8598
 
8599
+ class ExternalVariable extends Variable {
8600
+ constructor ( module, name ) {
8601
+ super( name );
8602
+ this.module = module;
8603
+ this.safeName = null;
8604
+ this.isExternal = true;
8605
+ this.isNamespace = name === '*';
8606
+ }
8607
+
8608
+ addReference ( reference ) {
8609
+ if ( this.name === 'default' || this.name === '*' ) {
8610
+ this.module.suggestName( reference.name );
8611
+ }
8612
+ }
8613
+
8614
+ getName ( es ) {
8615
+ if ( this.name === '*' ) {
8616
+ return this.module.name;
8617
+ }
8618
+
8619
+ if ( this.name === 'default' ) {
8620
+ return this.module.exportsNamespace || ( !es && this.module.exportsNames ) ?
8621
+ `${this.module.name}__default` :
8622
+ this.module.name;
8623
+ }
8624
+
8625
+ return es ? this.safeName : `${this.module.name}.${this.name}`;
8626
+ }
8627
+
8628
+ includeDeclaration () {
8629
+ if ( this.included ) {
8630
+ return false;
8631
+ }
8632
+ this.included = true;
8633
+ this.module.used = true;
8634
+ return true;
8635
+ }
8636
+
8637
+ setSafeName ( name ) {
8638
+ this.safeName = name;
8639
+ }
8640
+ }
8641
+
8375
8642
  class ExternalModule {
8376
8643
  constructor ( id ) {
8377
8644
  this.id = id;
8378
8645
 
8379
- const parts = id.split(/[\\/]/);
8646
+ const parts = id.split( /[\\/]/ );
8380
8647
  this.name = makeLegal( parts.pop() );
8381
8648
 
8382
8649
  this.nameSuggestions = blank();
@@ -8403,9 +8670,8 @@ class ExternalModule {
8403
8670
  if ( name !== 'default' && name !== '*' ) { this.exportsNames = true; }
8404
8671
  if ( name === '*' ) { this.exportsNamespace = true; }
8405
8672
 
8406
- return this.declarations[ name ] || (
8407
- this.declarations[ name ] = new ExternalDeclaration( this, name )
8408
- );
8673
+ return this.declarations[ name ]
8674
+ || (this.declarations[ name ] = new ExternalVariable( this, name ));
8409
8675
  }
8410
8676
  }
8411
8677
 
@@ -9447,9 +9713,9 @@ function callIfFunction ( thing ) {
9447
9713
  return typeof thing === 'function' ? thing() : thing;
9448
9714
  }
9449
9715
 
9450
- class SyntheticGlobalDeclaration {
9716
+ class GlobalVariable extends Variable {
9451
9717
  constructor ( name ) {
9452
- this.name = name;
9718
+ super( name );
9453
9719
  this.isExternal = true;
9454
9720
  this.isGlobal = true;
9455
9721
  this.isReassigned = false;
@@ -9457,33 +9723,23 @@ class SyntheticGlobalDeclaration {
9457
9723
  }
9458
9724
 
9459
9725
  addReference ( reference ) {
9460
- reference.declaration = this;
9461
9726
  if ( reference.isReassignment ) { this.isReassigned = true; }
9462
9727
  }
9463
9728
 
9464
9729
  assignExpression () {}
9465
9730
 
9466
- gatherPossibleValues ( values ) {
9467
- values.add( UNKNOWN_ASSIGNMENT );
9468
- }
9469
-
9470
- getName () {
9471
- return this.name;
9472
- }
9473
-
9474
- includeDeclaration () {
9475
- this.included = true;
9476
- return false;
9731
+ hasEffectsWhenCalled () {
9732
+ return !pureFunctions[ this.name ];
9477
9733
  }
9478
9734
  }
9479
9735
 
9480
9736
  class BundleScope extends Scope {
9481
- findDeclaration ( name ) {
9482
- if ( !this.declarations[ name ] ) {
9483
- this.declarations[ name ] = new SyntheticGlobalDeclaration( name );
9737
+ findVariable ( name ) {
9738
+ if ( !this.variables[ name ] ) {
9739
+ this.variables[ name ] = new GlobalVariable( name );
9484
9740
  }
9485
9741
 
9486
- return this.declarations[ name ];
9742
+ return this.variables[ name ];
9487
9743
  }
9488
9744
  }
9489
9745
 
@@ -9539,7 +9795,7 @@ class Bundle$$1 {
9539
9795
  this.scope = new BundleScope();
9540
9796
  // TODO strictly speaking, this only applies with non-ES6, non-default-only bundles
9541
9797
  [ 'module', 'exports', '_interopDefault' ].forEach( name => {
9542
- this.scope.findDeclaration( name ); // creates global declaration as side-effect
9798
+ this.scope.findVariable( name ); // creates global variable as side-effect
9543
9799
  } );
9544
9800
 
9545
9801
  this.moduleById = new Map();
@@ -9601,7 +9857,7 @@ class Bundle$$1 {
9601
9857
  .then( entryModule => {
9602
9858
  this.entryModule = entryModule;
9603
9859
 
9604
- // Phase 2 – binding. We link references to their declarations
9860
+ // Phase 2 – binding. We link references to their variables
9605
9861
  // to generate a complete picture of the bundle
9606
9862
 
9607
9863
  timeStart( 'phase 2' );
@@ -9611,31 +9867,30 @@ class Bundle$$1 {
9611
9867
 
9612
9868
  timeEnd( 'phase 2' );
9613
9869
 
9614
- // Phase 3 – marking. We 'run' each statement to see which ones
9615
- // need to be included in the generated bundle
9870
+ // Phase 3 – marking. We include all statements that should be included
9616
9871
 
9617
9872
  timeStart( 'phase 3' );
9618
9873
 
9619
9874
  // mark all export statements
9620
9875
  entryModule.getExports().forEach( name => {
9621
- const declaration = entryModule.traceExport( name );
9876
+ const variable = entryModule.traceExport( name );
9622
9877
 
9623
- declaration.exportName = name;
9624
- declaration.includeDeclaration();
9878
+ variable.exportName = name;
9879
+ variable.includeVariable();
9625
9880
 
9626
- if ( declaration.isNamespace ) {
9627
- declaration.needsNamespaceBlock = true;
9881
+ if ( variable.isNamespace ) {
9882
+ variable.needsNamespaceBlock = true;
9628
9883
  }
9629
9884
  } );
9630
9885
 
9631
9886
  entryModule.getReexports().forEach( name => {
9632
- const declaration = entryModule.traceExport( name );
9887
+ const variable = entryModule.traceExport( name );
9633
9888
 
9634
- if ( declaration.isExternal ) {
9635
- declaration.reexported = declaration.module.reexported = true;
9889
+ if ( variable.isExternal ) {
9890
+ variable.reexported = variable.module.reexported = true;
9636
9891
  } else {
9637
- declaration.exportName = name;
9638
- declaration.includeDeclaration();
9892
+ variable.exportName = name;
9893
+ variable.includeVariable();
9639
9894
  }
9640
9895
  } );
9641
9896
 
@@ -9650,6 +9905,9 @@ class Bundle$$1 {
9650
9905
  }
9651
9906
  } );
9652
9907
  } while ( addedNewNodes );
9908
+ } else {
9909
+ // Necessary to properly replace namespace imports
9910
+ this.modules.forEach( module => module.includeAllInBundle() );
9653
9911
  }
9654
9912
 
9655
9913
  timeEnd( 'phase 3' );
@@ -9696,7 +9954,7 @@ class Bundle$$1 {
9696
9954
  const used = blank();
9697
9955
 
9698
9956
  // ensure no conflicts with globals
9699
- keys( this.scope.declarations ).forEach( name => used[ name ] = 1 );
9957
+ keys( this.scope.variables ).forEach( name => used[ name ] = 1 );
9700
9958
 
9701
9959
  function getSafeName ( name ) {
9702
9960
  while ( used[ name ] ) {
@@ -9724,12 +9982,12 @@ class Bundle$$1 {
9724
9982
  } );
9725
9983
 
9726
9984
  this.modules.forEach( module => {
9727
- forOwn( module.scope.declarations, ( declaration ) => {
9728
- if ( declaration.isDefault && declaration.declaration.id ) {
9985
+ forOwn( module.scope.variables, variable => {
9986
+ if ( variable.isDefault && variable.declaration.id ) {
9729
9987
  return;
9730
9988
  }
9731
9989
 
9732
- declaration.name = getSafeName( declaration.name );
9990
+ variable.name = getSafeName( variable.name );
9733
9991
  } );
9734
9992
 
9735
9993
  // deconflict reified namespaces
@@ -9882,12 +10140,12 @@ class Bundle$$1 {
9882
10140
  // need to find the actual import declaration, so we can provide
9883
10141
  // a useful error message. Bit hoop-jumpy but what can you do
9884
10142
  const declaration = module.ast.body.find( node => {
9885
- return node.isImportDeclaration && node.source.value === source;
10143
+ return ( node.isImportDeclaration || node.isExportDeclaration ) && node.source.value === source;
9886
10144
  } );
9887
-
10145
+ const declarationType = /Export/.test( declaration.type ) ? 'export' : 'import';
9888
10146
  module.error( {
9889
10147
  code: 'CANNOT_IMPORT_SELF',
9890
- message: `A module cannot import itself`
10148
+ message: `A module cannot ${declarationType} itself`
9891
10149
  }, declaration.start );
9892
10150
  }
9893
10151
 
@@ -10357,7 +10615,7 @@ function rollup ( options ) {
10357
10615
  }
10358
10616
  }
10359
10617
 
10360
- var version$1 = "0.49.3";
10618
+ var version$1 = "0.50.0";
10361
10619
 
10362
10620
  exports.rollup = rollup;
10363
10621
  exports.VERSION = version$1;