Skip to content

Commit

Permalink
optimize ns["foo"] (#841)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Jan 7, 2017
1 parent 40a0ed5 commit 82b284d
Show file tree
Hide file tree
Showing 11 changed files with 63 additions and 6 deletions.
22 changes: 16 additions & 6 deletions src/ast/nodes/MemberExpression.js
@@ -1,14 +1,24 @@
import isReference from 'is-reference';
import relativeId from '../../utils/relativeId.js';
import Node from '../Node.js';
import { UNKNOWN } from '../values.js';

const validProp = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;

class Keypath {
constructor ( node ) {
this.parts = [];

while ( node.type === 'MemberExpression' ) {
this.parts.unshift( node.property );
const prop = node.property;

if ( node.computed ) {
if ( prop.type !== 'Literal' || typeof prop.value !== 'string' || !validProp.test( prop.value ) ) {
this.computed = true;
return;
}
}

this.parts.unshift( prop );
node = node.object;
}

Expand All @@ -21,21 +31,21 @@ export default class MemberExpression extends Node {
// if this resolves to a namespaced declaration, prepare
// to replace it
// TODO this code is a bit inefficient
if ( isReference( this ) ) { // TODO optimise namespace access like `foo['bar']` as well
const keypath = new Keypath( this );
const keypath = new Keypath( this );

if ( !keypath.computed ) {
let declaration = scope.findDeclaration( keypath.root.name );

while ( declaration.isNamespace && keypath.parts.length ) {
const exporterId = declaration.module.id;

const part = keypath.parts[0];
declaration = declaration.module.traceExport( part.name );
declaration = declaration.module.traceExport( part.name || part.value );

if ( !declaration ) {
this.module.warn({
code: 'MISSING_EXPORT',
message: `'${part.name}' is not exported by '${relativeId( exporterId )}'`,
message: `'${part.name || part.value}' is not exported by '${relativeId( exporterId )}'`,
url: `https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module`
}, part.start );
this.replacement = 'undefined';
Expand Down
3 changes: 3 additions & 0 deletions test/form/namespace-optimization-computed-string/_config.js
@@ -0,0 +1,3 @@
module.exports = {
description: 'it does dynamic lookup optimization of internal namespaces for string-literal keys'
};
@@ -0,0 +1,7 @@
define(function () { 'use strict';

function a () {}

a();

});
@@ -0,0 +1,5 @@
'use strict';

function a () {}

a();
@@ -0,0 +1,3 @@
function a () {}

a();
@@ -0,0 +1,8 @@
(function () {
'use strict';

function a () {}

a();

}());
11 changes: 11 additions & 0 deletions test/form/namespace-optimization-computed-string/_expected/umd.js
@@ -0,0 +1,11 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
typeof define === 'function' && define.amd ? define(factory) :
(factory());
}(this, (function () { 'use strict';

function a () {}

a();

})));
3 changes: 3 additions & 0 deletions test/form/namespace-optimization-computed-string/bar.js
@@ -0,0 +1,3 @@
import * as quux from './quux.js';

export { quux };
3 changes: 3 additions & 0 deletions test/form/namespace-optimization-computed-string/foo.js
@@ -0,0 +1,3 @@
import * as bar from './bar.js';

export { bar };
3 changes: 3 additions & 0 deletions test/form/namespace-optimization-computed-string/main.js
@@ -0,0 +1,3 @@
import * as foo from './foo.js';

foo['bar']['quux']['a']();
1 change: 1 addition & 0 deletions test/form/namespace-optimization-computed-string/quux.js
@@ -0,0 +1 @@
export function a () {}

0 comments on commit 82b284d

Please sign in to comment.