Why does MXML data binding swallow TypeErrors?

2019-05-27 00:08发布

问题:

The following code shoud throw an Error #1009: Cannot access a property or method of a null object reference:

var label:Label;
label.text = value;

However, it doesn't if it's inside of a setter which is set by MXML data binding:

public function set buggySetter(value:String):void {
    var label:Label;
    label.text = value; //will fail silently
}

To reproduce this weird behaviour, first, create a simple custom component by extending s:Label:

package {
    import spark.components.Label;

    public class BuggyLabel extends Label {
        public function set buggySetter(value:String):void {
            var label:Label;
            label.text = value; //will fail silently
        }
    }
}

Sectond, add BuggyLabel to an Application and bind buggySetter:

<fx:Script>
    <![CDATA[
        [Bindable]
        public var foo:String = 'NULL has no properties';
    ]]>
</fx:Script>

<local:BuggyLabel buggySetter="{foo}"/>

Why does this app fail silently?

回答1:

The answer to that question is actually fairly short: it's an architectural decision made by the Flex SDK engineers. If you take a look at the Flex source code, you'll see a try ... catch block swallowing most errors thrown in a Binding.

Pro: makes it easier to use bindings, since you don't have to account for all possible faulty states

Con: it can be harder to debug (though if you know this can happen and you have good unit tests, you can reduce frustration from that side to nearly zero)


The source code I was talking about can be found in mx.binding.Binding (in the 'framework' project) in method wrapFunctionCall(). Here's the relevant part:

    try {
       ...
    }
    catch(error:Error)
    {
        // Certain errors are normal when executing a srcFunc or destFunc,
        // so we swallow them:
        //   Error #1006: Call attempted on an object that is not a function.
        //   Error #1009: null has no properties.
        //   Error #1010: undefined has no properties.
        //   Error #1055: - has no properties.
        //   Error #1069: Property - not found on - and there is no default value
        // We allow any other errors to be thrown.
        if ((error.errorID != 1006) &&
            (error.errorID != 1009) &&
            (error.errorID != 1010) &&
            (error.errorID != 1055) &&
            (error.errorID != 1069))
        {
            throw error;
        }
        else
        {
            if (BindingManager.debugDestinationStrings[destString])
            {
                trace("Binding: destString = " + destString + ", error = " + error);
            }
        }
    }


回答2:

this Error #1009 is

TypeError: Error #1009: Cannot access a property or method of a null object reference.

in your setter

public function set buggySetter(value:String):void {  
    var label:Label;  // here is the problem
    label.text = value; //will fail silently  
}

here you are setting text to a lable which is not created.... you are just specify the label var but not created that's why it gives you above Error... you should either create lable varibal or set data to parent class

your code might be work if...

public function set buggySetter(value:String):void {  
        var label:Label = new Lable(); 
        label.text = value; //now it ll work
 }

or


public function set buggySetter(value:String):void {  
        this.text = value; 
 }