Uncaught TypeError: Cannot read property 'buffer' of undefined #3

Closed
jachenry opened this Issue Apr 8, 2012 · 11 comments

Comments

Projects
None yet
2 participants

jachenry commented Apr 8, 2012

After Updating to the latest version of deft I am getting the following error.

Uncaught TypeError: Cannot read property 'buffer' of undefined
Ext.define.doFiresencha-touch-all.js:17366
Ext.define.firesencha-touch-all.js:17316
Ext.define.doDispatchEventsencha-touch-all.js:22436
Ext.define.dispatchsencha-touch-all.js:59135
Ext.define.publishsencha-touch-all.js:59209
Ext.define.doFiresencha-touch-all.js:17389
Ext.define.firesencha-touch-all.js:17316
Ext.define.doDispatchEventsencha-touch-all.js:22436
Ext.define.dispatchEventsencha-touch-all.js:22417
Ext.define.doFireEventsencha-touch-all.js:26678
Ext.define.fireEventsencha-touch-all.js:26637
Ext.define.constructor

My code causing the issue.

Ext.define("App.controller.Activities", {
  extend: "Ext.app.Controller",
  mixins: [ 'Deft.mixin.Injectable' ],

  inject: {
    geo: 'geolocation'
  },

  config: {
    refs: { 
      index: 'activitiesindex'
    },

    control: {
      index: {
        initialize: 'viewPrivateList'
      }
    }
  },

  viewPrivateList: function(){
    ...
  }, 
});

Sencha code throwing the error:

            options = listener.options;            

            ...

            if (!firingFn) {
                firingFn = boundFn;

                if (options.buffer) {
                    firingFn = Ext.Function.createBuffered(firingFn, options.buffer, scope);
                }

                if (options.delay) {
                    firingFn = Ext.Function.createDelayed(firingFn, options.delay, scope);
                }

                listener.firingFn = firingFn;
            }

I'm not sure if this is a Sencha or Deft issue but It only breaks after upgrading Deft to the latest.

Owner

johnyanarella commented Apr 8, 2012

At first glance, that doesn't appear to be a Deft issue.

Using a debugger (such as WebKit's Developer Tools) are you able to determine what class is being constructed and what event is being fired at the time that error is being thrown?

jachenry commented Apr 8, 2012

Yeah - its the 'initialize' event fired at the end of the constructor for the activitiesindex class. With latest deft 'options' is null but with previous version 'options' is an empty object.

me.fireEvent('initialize', me);

jachenry commented Apr 8, 2012

listener.options should never be null according to the code below. Is it possible you are overriding the create function somehow?

Ext.define('Ext.event.ListenerStack', {

    ...

    add: function(fn, scope, options, order) {

        ...

        listener = this.create(fn, scope, options, order);

        ...

        listeners.push(listener);
    },

    create: function(fn, scope, options, order) {
        return {
            stack: this,
            fn: fn,
            firingFn: false,
            boundFn: false,
            isLateBinding: typeof fn == 'string',
            scope: scope,
            options: options || {},
            order: order
        };
    },
Owner

johnyanarella commented Apr 8, 2012

In the code example you provided, the only thing Deft is doing is intercepting the call to the Activities controller constructor, setting any injected property values into the instance and merging any injected config values into the options passed to the constructor before calling it. Deft doesn't add or override methods in the target class.

If the options value in the ListenerStack you referenced is undefined, I would suspect that function is being called in the wrong scope. For it to be null would mean it was explicitly set with that value somewhere. Very odd indeed.

I'm curious if Deft is mangling the config object (where you've defined the control config) before it gets to your Activities controller's constructor.

Could you temporarily add a constructor to your Activities controller?

    constructor: function(config) {
        debugger;
        return this.callParent(arguments);
    }

When paused at that programmatic breakpoint, could you inspect the value of config to see if / how it differs between those two Deft versions? If possible, could you paste the runtime value of that config variable here?

Thanks!

jachenry commented Apr 8, 2012

Object
  application: Ext.apply.create.Class
    _appFolder: "app"
    _application: Ext.apply.create.Class
    _before: Ext.Object.classify.objectClass
    _control: Ext.Object.classify.objectClass
    _controllerInstances: Array[0]
    _controllers: Array[4]
    _history: Ext.apply.create.Class
    _launch: function (){
    _models: Array[2]
    _name: "ParkBeat"
    _profileInstances: Array[0]
    _profiles: Array[0]
    _refs: Ext.Object.classify.objectClass
    _requires: Array[1]
    _router: Ext.apply.create.Class
    _routes: Ext.Object.classify.objectClass
    _stores: Array[3]
    _views: Array[5]
    appFolder: "app"
    application: Ext.apply.create.Class
    config: Ext.Object.classify.objectClass
    configureDevice: function (){
    controllers: Array[4]
    createDevice: function () {
    eventDispatcher: Ext.apply.create.Class
    getEventDispatcher: function () {
    getId: function () {
    getObservableId: function () {
    getUniqueId: function () {
    id: "ext-app-application-1"
    initConfig: function (){}
    initialConfig: Object
    launch: function (){
    loadDevice: function () {
    managedListeners: Object
    models: Array[2]
    name: "ParkBeat"
    observableId: "#ext-app-application-1"
    registerIdentifier: function ( uuid ){
    renderError: function (record, operation) {
    renderViews: function () {
    requires: Array[1]
    stores: Array[3]
    usedSelectors: Array[1]
    viewport: Object
    views: Array[5]
    __proto__: TemplateClass
  __proto__: Object
Owner

johnyanarella commented Apr 8, 2012

That looks good - the Controller is being instantiated with the application config populated to reference the application.

I misspoke earlier - Deft JS injects configuration values by intercepting the initConfig() method and merging the injected values into the configuration options that were originally passed to initConfig(). If the class is already instantiated when injection is requested, it calls the generated config setter functions instead.

Could you add a similar temporary override for initConfig()?

    initConfig: function(config) {
        debugger;
        return this.callParent(arguments);
    }

What is the value for config there?

jachenry commented Apr 9, 2012

config is the same as it was in the constructor. However, I notice 'initConfig' gets called twice for the same controller. Is this common?

I'm really excited to use the new ViewControllers but I can't until this issue is resolved. I created a barebones project at https://github.com/jachenry/DeftJS_Issue3 so you can see the issue first hand.

Owner

johnyanarella commented Apr 25, 2012

Thank you so much for making the barebones example. That will be immensely helpful in diagnosing the problem.

I will look into this today.

@ghost ghost assigned johnyanarella Apr 25, 2012

Owner

johnyanarella commented Apr 25, 2012

Thanks to your sample project, I've tracked down the cause. I'll be pushing a new build with a fix shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment