Search code examples
javascriptdojo

DOJO error when using this.inherited(arguments) in strict mode


I am declaring a base "Class" for a Dijit Custom widget.

When in 'strict mode' routine this.inherited(arguments); is being called, I receive this error:

Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

I need to keep the usage 'strict mode'.

Any idea how to solve it?

define([
    'dojo/_base/declare',
    'dojo/topic',
    'dojo/_base/lang'
], function (
    declare,
    topic,
    lang
    ) {
    'use strict';
    var attachTo = 'myPanels';
    return declare(null, {
        id: null,
        title: null,
        postCreate: function () {
            // ERROR HERE
            this.inherited(arguments);
            this.placeAt(attachTo);
        },
        constructor: function () {
        },
    });
});

Notes: removing 'strict mode' solve the issue, but is not an option in my case as I need to use 'strict mode'.


Solution

  • This is known issue, Dojo uses arguments.callee for introspection and to determine the inherited (more precisely the next) method. To workaround this issue you need to create your own arguments object then specify arguments.callee property and pass it to Dojo for introspection. The only one problem is to pass the function to itself, but it could be easily solved, for example with this helper, place it in a module, for example override.js:

    "use strict";
    define([], function () {
        var slice = Array.prototype.slice;
        return function (method) {
            var proxy;
    
            /** @this target object */
            proxy = function () {
                var me = this;
                var inherited = (this.getInherited && this.getInherited({
                    // emulating empty arguments
                    callee: proxy,
                    length: 0
                })) || function () {};
    
                return method.apply(me, [function () {
                    return inherited.apply(me, arguments);
                }].concat(slice.apply(arguments)));
            };
    
            proxy.method = method;
            proxy.overrides = true;
    
            return proxy;
        };
    });
    

    now you can use it to call inherited methods

    define([
        'dojo/_base/declare',
        'dojo/topic',
        'dojo/_base/lang',
        './override'
    ], function (
        declare,
        topic,
        lang,
        override
        ) {
        'use strict';
        var attachTo = 'myPanels';
        return declare(null, {
            id: null,
            title: null,
            postCreate: override(function (inherited) {
                inherited(); // the inherited method 
                this.placeAt(attachTo);
            }),
            methodWithArgs : override(function(inherited, arg1, arg2)) {
                inherited(arg1, arg2);
                // pass all arguments to the inherited method
                // inherited.apply(null,Array.prototype.slice.call(arguments, 1));
            }),
            constructor: function () {
            },
        });
    });