javascript - 一个模块 : OPTIMIZER FAILED: InternalError: missing name after . 运算符(operator)的 Dojo 构建失败

标签 javascript optimization dojo amd dojo-build

我正在使用 Dojo Build 工具成功构建我的项目。但是,我有一个模块 squad_builder/Pilot,每当我包含它时都会导致构建失败,并出现以下错误:

error(356) The optimizer threw an exception; the module probably contains syntax errors. module identifier: /Users/ferg/Dropbox/webdev/x-wing_squadron_builder/www/js/dist/squad_builder/run_deps.js; exception: (compile time:1.247s). OPTIMIZER FAILED: InternalError: missing name after . operator

该模块在开发中运行良好,甚至通过 JS Lint 运行它,其中没有明显的错误,尤其是与错位的“.”无关。我可以在任何地方看到。

这是模块的代码:

define( [ 'dojo/_base/declare', 

          // parents
          'dijit/TitlePane',

          // used modules
          'dojo/_base/lang',
          'dojo/_base/array',
          'dojo/dom-construct',
          'dojo/dom-style',
          'dojo/_base/fx',
          'dojo/_base/event',
          'squad_builder/actionIconParser',
          'dojo/promise/all',
          'dojo/Deferred',

          // dijits
          'dijit/form/Button',

          // stores
          // @todo only load rebels or empire store
          'squad_builder/storeBroker!rebelsStore',
          'squad_builder/storeBroker!empireStore',
          'squad_builder/storeBroker!actionsStore',
          'squad_builder/storeBroker!upgradeTypesStore',
          'squad_builder/storeBroker!setsStore',
          'squad_builder/storeBroker!shipTypesStore',

          // template
          'dojo/text!./Pilot/templates/Pilot.html' // extended TitlePane template

    ],
    function( declare, 
        TitlePane, 
        lang, array, domConstruct, domStyle, fx, event, actionIconParser, all, Deferred, 
        Button, 
        rebelsStore, empireStore, actionsStore, upgradeTypesStore, setsStore, shipTypesStore,
        template )
    {
        return declare( [ TitlePane ], 
        {
            // provided to constructor
            faction: null,

            pilotId: null,
            squadList: null,
            squadPaneId: null, // used for duplicating

            basePoints: null, // initial points
            points: null, // total points of pilot + upgrades

            _loaded: false, // flag to prevent multiple startup() calles

            allUpgradesLoaded: false,

            templateString: template,

            // A class to be applied to the root node in our template
            baseClass: 'pilotWidget dijitTitlePane',

            // used in auto-generated IDs
            declaredClass: 'squad_builder.PilotWidget',

            constructor: function()
            {
                // declared in constructor so all instances have their own copy
                this.pilotData = {};
                this.originalPilotData = {}; // used when removing upgrades so we cannot remove boost from A-Wings for example
                this.initiallySelectedUpgrades = [];
                this.upgradeButtons = [];

                // reference to squad-level caches
                this.uniqueUpgradeCache = {}; 
                this.collection = null;
            },

            // fetch the pilot data before loading template
            postMixInProperties: function()
            {
                this.inherited( arguments );

                // use pilot id to load the rest of the pilot data
                var store = this.faction == 'rebels' ? rebelsStore : empireStore,
                    data = store.get( this.pilotId ); // pilot data

                // save pilot data
                lang.mixin( this.pilotData, lang.clone( data ) ); // bugfix: needs clone or all copies of this ship will be modified by pilot modules
                this.originalPilotData = lang.clone( this.pilotData );

                // set initial points
                this.basePoints = parseInt( this.pilotData.cost ); // base points = pilot cost
                this.points = parseInt( this.pilotData.cost ); // may increase with upgrades
            },          

            postCreate: function()
            {
                // Run any parent postCreate processes - can be done at any point
                this.inherited( arguments );

                // wait until we have child widgets containing upgrades before figuring out points
                this._calculatePoints();

                // info
                this.infoDiv.innerHTML = shipTypesStore.get( this.pilotData.ship_type_id )['name'];

                if( this.pilotData.unique  )
                {
                    this.infoDiv.innerHTML += ', Unique';
                }

                if( !this.pilotData.released )
                {
                    this.infoDiv.innerHTML +=  ', Unreleased';
                }

                // switch between energy and primary stats
                if( !this.pilotData.energy )
                {
                    domStyle.set( this.energyNode, { display: 'none' } );
                }

                if( !this.pilotData.primary )
                {
                    domStyle.set( this.primaryNode, { display: 'none' } );
                }

                // ability
                if( this.pilotData.ability )
                {
                    this.abilityDiv.innerHTML = actionIconParser( this.pilotData.ability );
                }

                // add icons for actions
                this._initActions();

                // sets
                array.forEach( this.pilotData.sets, function( set )
                {
                    var setData = setsStore.get( set );
                    domConstruct.create( 'div',
                    {
                        innerHTML: setData.acronym,
                        title: setData.name
                    },
                    this.setsContainer );
                }, this );

                // clear message if any upgrades
                if( this.pilotData.upgrades.length )
                {
                    this.upgradesDiv.innerHTML = '';
                }
            },

            /*
             * Upgrades added here or watch() doesn't fire!
             */
            startup: function()
            {
                if( this._loaded == false ) // only call this once when first adding pilot, not again when sorting
                {
                    // track all upgrades
                    var allUpgradesLoadedPromises = [];

                    // upgrade buttons
                    array.forEach( this.pilotData.upgrades, function( upgradeTypeId, index )
                    {
                        var deferred = this._addUpgradeButton( upgradeTypeId, this.initiallySelectedUpgrades[ index ], index, false );
                        allUpgradesLoadedPromises.push( deferred.promise );
                    },
                    this );

                    // do we have extra upgrades (eg. added by another upgrade)?
                    var extraUpgrades = array.filter( this.initiallySelectedUpgrades, function( selectedUpgrade )
                    {
                        return selectedUpgrade instanceof Array;
                    } );

                    if( extraUpgrades.length > 0 )
                    {
                        array.forEach( extraUpgrades, function( extraUpgrade, index )
                        {
                            var deferred = this._addUpgradeButton( extraUpgrade[1], extraUpgrade[0], this.pilotData.upgrades.length + index, true );
                            allUpgradesLoadedPromises.push( deferred.promise );
                        },
                        this );
                    }

                    // track when all promises fulfilled
                    // other objects (eg. modules) can use watch('allUpgradesLoaded') to hook into this
                    all( allUpgradesLoadedPromises ).then( lang.hitch( this, function()
                    {
                        this.set( 'allUpgradesLoaded', true );
                    } ) ).otherwise( function()
                    {
                        console.warn( 'Failed to track whether upgrades loaded', arguments );
                    } );

                    // highlight
                    domStyle.set( this.containerNode, { backgroundColor: '#FFF8B5' } );
                    fx.animateProperty(
                    {
                        node: this.containerNode,
                        properties: {
                            backgroundColor: '#FFFFFF'
                        },
                        duration: 500,
                        delay: 1000
                     } ).play();

                    this._loaded = true;
                }
            },

            _initActions: function()
            {
                // show action icons    
                // in function so we can fade out old icons first...
                var show = lang.hitch( this, function()
                {
                    domStyle.set( this.actionsDiv, 'opacity', 0 );

                    array.forEach( this.pilotData.actions, function( action )
                    {
                        var actionData = actionsStore.get( action );

                        domConstruct.create( 'div',
                        {
                            className: 'icon_action ' + actionData.class_name,
                            title: actionData.name
                        },
                        this.actionsDiv );
                    },
                    this );

                    fx.fadeIn(
                    {
                        node: this.actionsDiv
                    } ).play();
                } );

                // already got icons?
                if( this.actionsDiv !== undefined && this.actionsDiv.innerHTML != '' )
                {
                    fx.fadeOut(
                    {
                        node: this.actionsDiv,
                        onEnd: lang.hitch( this, function()
                        {
                            this.actionsDiv.innerHTML = '';
                            show();
                        } )
                    } ).play();
                }   
                else
                {
                    show();
                }   
            },

            _addUpgradeButton: function( upgradeTypeId, selectedId, position, isExtra ) 
            {
                var upgradeTypeData = upgradeTypesStore.get( upgradeTypeId ), // type of upgrade tells us what upgrade store to use
                    upgradeButtonDeferred = new Deferred();

                // get specific upgrade data for this button
                require( [ 'squad_builder/PilotUpgradeButton', 'squad_builder/storeBroker!' + upgradeTypeData.store ], 
                    lang.hitch( this, function( PilotUpgradeButton, upgradeStore )
                {
                    // create button
                    var upgradeButton = new PilotUpgradeButton(
                    {
                        position: position,
                        isExtra: Boolean( isExtra ),
                        pilot: this,
                        upgradeTypeId: upgradeTypeId,
                        name: upgradeTypeData.name,
                        upgradeClass: upgradeTypeData.class,
                        upgradeStore: upgradeStore,
                        selectedId: selectedId, 

                        // reference to squadlist-level cache
                        // used to check if unique upgrades used
                        uniqueUpgradeCache: this.uniqueUpgradeCache,

                        // reference to squadpane-level collection store
                        // used to record component use
                        collection: this.collection
                    } );

                    // watch points changes
                    upgradeButton.watch( 'points', lang.hitch( this, function()
                    {
                        this._calculatePoints();
                    } ) );

                    // store reference
                    this.upgradeButtons.push( upgradeButton );

                    // place
                    upgradeButton.placeAt( this.upgradesDiv );
                    upgradeButton.startup(); // add upgrades after watch() added

                    upgradeButtonDeferred.resolve( upgradeButton );
                } ) );

                return upgradeButtonDeferred; // allows pilot._addUpgradeButton( ... ).then( ... )
            },

            _calculatePoints: function()
            {
                var points = this.get('basePoints');

                // get points from upgrade buttons
                array.forEach( this.upgradeButtons, function( upgradeButton )
                {
                    points += upgradeButton.get( 'points' );
                } );

                this.set( 'points', points );
            },

            _calculateTitle: function()
            {
                var title = this.pilotData.name;
                array.forEach( this.upgradeButtons, function( upgradeButton )
                {
                    var upgradeName = upgradeButton.get( 'selectedName' );
                    if( upgradeName )
                    {
                        title += ' + ' + upgradeName;
                    }   
                } );
                title += ' (' + this.get( 'points' ) + ')';

                this.set( 'title', title );
            },

            // for dojo/Stateful watch/get/set
            _setPointsAttr: function( value ) 
            {
                this._set( 'points', value );
                this._calculateTitle();
            },

            close: function()
            {
                this.set( 'open', false );
            },

            _onDelete: function( e )
            {
                event.stop( e );
                this.onDelete();
                this.destroyRecursive();
            },

            /**
             * Extension point
             */
            onDelete: function()
            {
            },

            _onDuplicate: function( e )
            {
                event.stop( e );
                this.onDuplicate();
                this.squadList.addPilot( this.get( 'squadPaneId' ), this.get('faction'), this.get('pilotId'), this.get('upgrades')  );
            },

            /**
             * Extension point
             */
            onDuplicate: function()
            {
            },

            _onMoveUp: function( e )
            {
                event.stop( e );
                this.onMoveUp();
                this.squadList.movePilot( this.get( 'id' ), -1  );
            },

            /**
             * Extension point
             */
            onMoveUp: function()
            {
            },

            _onMoveDown: function( e )
            {
                event.stop( e );
                this.onMoveDown();
                this.squadList.movePilot( this.get( 'id' ), 1  );
            },

            /**
             * Extension point
             */
            onMoveDown: function()
            {
            },

            /**
             * Data to save/recreate this pilot
             */
            getData: function()
            {
                return { 
                    id: this.get('pilotId'), 
                    points: this.get('points'), 
                    basePoints: this.get('basePoints'), 
                    upgrades: this.get('upgrades') 
                };
            },

            /**
             * allows: this.get('upgrades')
             */
            _getUpgradesAttr: function()
            {
                // get upgrades from buttons
                var upgrades = [];

                // upgradeButton widgets may not be instantiated when this.get('upgrades') first called 
                // if so default to...
                if( this.upgradeButtons.length == 0 ) 
                {
                    // ... initially selected upgrades
                    if( this.initiallySelectedUpgrades.length !== undefined && this.initiallySelectedUpgrades.length > 0 ) 
                    {
                        upgrades = this.initiallySelectedUpgrades;
                    }
                    // ... or create array of nulls
                    else 
                    {   
                        var numUpgrades = this.pilotData.upgrades.length,
                            i = 0;
                        while( i++ < numUpgrades )
                        {
                            upgrades.push( null );
                        }
                    }
                }
                else
                {
                    array.forEach( this.upgradeButtons, function( upgradeButton )
                    {
                        // use position from instantiation to ensure we get them in the right order
                        upgrades[ upgradeButton.get( 'position' ) ] = upgradeButton.get( 'selectedId' ); // id or null or tuple pair
                    } );
                }

                return upgrades;
            },

            _getNameAttr: function()
            {
                return this.pilotData.name;
            },

            _getPilotAttr: function()
            {
                return this.pilotData.pilot;
            },

            _setPilotAttr: function( value )
            {
                this.pilotData.pilot = value;

                // animate change
                fx.fadeOut(
                {
                    node: this.pilotNode,
                    onEnd: lang.hitch( this, function()
                    {
                        this.pilotNode.innerHTML = value;
                        fx.fadeIn(
                        {
                            node: this.pilotNode
                        } ).play();
                    } )
                } ).play();
            },

            _getShieldsAttr: function()
            {
                return this.pilotData.shields;
            },

            _setShieldsAttr: function( value )
            {
                this.pilotData.shields = value;

                // animate change
                var shieldsNode = this.shieldsNode; // was losing scope so use local var
                fx.fadeOut(
                {
                    node: shieldsNode,
                    onEnd: function()
                    {
                        shieldsNode.innerHTML = value;
                        fx.fadeIn(
                        {
                            node: shieldsNode
                        } ).play();
                    }
                } ).play();
            },

            _getAgilityAttr: function()
            {
                return this.pilotData.agility;
            },

            _setAgilityAttr: function( value )
            {
                this.pilotData.agility = value;

                // animate change
                fx.fadeOut(
                {
                    node: this.agilityNode,
                    onEnd: lang.hitch( this, function()
                    {
                        this.agilityNode.innerHTML = value;
                        fx.fadeIn(
                        {
                            node: this.agilityNode
                        } ).play();
                    } )
                } ).play();
            },

            _getHullAttr: function()
            {
                return this.pilotData.hull;
            },

            _setHullAttr: function( value )
            {
                this.pilotData.hull = value;

                // animate change
                fx.fadeOut(
                {
                    node: this.hullNode,
                    onEnd: lang.hitch( this, function()
                    {
                        this.hullNode.innerHTML = value;
                        fx.fadeIn(
                        {
                            node: this.hullNode
                        } ).play();
                    } )
                } ).play();
            },

            _getEnergyAttr: function()
            {
                return this.pilotData.energy;
            },

            _setEnergyAttr: function( value )
            {
                this.pilotData.energy = value;

                // animate change
                fx.fadeOut(
                    {
                        node: this.energyNode,
                        onEnd: lang.hitch( this, function()
                        {
                            this.energyNode.innerHTML = value;
                            fx.fadeIn(
                            {
                                node: this.energyNode
                            } ).play();
                        } )
                    } ).play();
            }

        } );
    } 
);

我一遍又一遍地检查代码,但我就是找不到任何似乎与我收到的错误消息相匹配的东西。有什么想法吗?

最佳答案

我遇到这个错误是因为我使用了 JavaScript 关键字作为对象属性。例如:

object.return.value 而不是 object['return'].value

关于javascript - 一个模块 : OPTIMIZER FAILED: InternalError: missing name after . 运算符(operator)的 Dojo 构建失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24358115/

相关文章:

javascript - Angular : Infinite scroll not working when using ngInclude in masonry

java - JVM 或 JIT 是否能够减少重复的方法调用?

svg - 文本和组节点的 dojox.gfx 边界框

file-upload - dojo.io.iframe.send 文件上传在IE8中发送GET请求

Javascript - 动态对象键(第二个键)

javascript - 如何使用ES6修改嵌套对象的特定元素?

javascript - 单页面主干应用程序中 View 之间的转换

python - Pystan 后验不确定区间

mysql - 优化导出功能

javascript - 道场工具包 : How to animate a fade in while adding a new element to the page?