%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /proc/985914/root/data/old/home/stash/stash/atlassian-stash/static/util/
Upload File :
Create Path :
Current File : //proc/985914/root/data/old/home/stash/stash/atlassian-stash/static/util/deprecation.js

define('util/deprecation', [
    'underscore',
    'util/events',
    'util/text'
], function(
    _,
    events,
    textUtil
    ) {

    'use strict';

    var has = Object.prototype.hasOwnProperty;
    var toString = Object.prototype.toString;

    /**
     * Return a function that logs a deprecation warning to the console the first time it is called.
     *
     * @param {string|Function} displayNameOrShowMessageFn the name of the thing being deprecated. Alternatively, a function to be returned
     * @param {string?} alternativeName the name of the alternative thing to use
     * @param {string?} sinceVersion the version this has been deprecated since
     * @param {string?} removeInVersion the version this will be removed in
     * @return {Function} that logs the warning
     */
    function getShowDeprecationMessage(displayNameOrShowMessageFn, alternativeName, sinceVersion, removeInVersion) {
        if (typeof displayNameOrShowMessageFn === 'function') {
            return displayNameOrShowMessageFn;
        }
        var called = false;
        return function deprecated() {
            if (!called) {
                called = true;
                var message = textUtil.toSentenceCase(displayNameOrShowMessageFn) + " has been deprecated" + (sinceVersion ? " since " + sinceVersion : '') +
                              " and will be removed in " + (removeInVersion || "a future release") + ".";
                if (alternativeName) {
                    message += " Use " + alternativeName + " instead.";
                }

                var err = new Error();
                var stack = err.stack || err.stacktrace;
                var stackMessage = (stack && stack.replace(/^Error\n/, "")) || 'No stack trace of the deprecated usage is available in your current browser.';
                console.log(message + "\n" + stackMessage);
            }
        };
    }

    /**
     * Returns a wrapped version of the function that logs a deprecation warning when the function is used.
     * @param {Function} fn the fn to wrap
     * @param {string|Function} displayNameOrShowMessageFn the name of the fn to be displayed in the message. Alternatively, a function to log deprecation warnings
     * @param {string} alternativeName the name of an alternative function to use
     * @param {string} sinceVersion the version this has been deprecated since
     * @param {string} removeInVersion the version this will be removed in
     * @return {Function} wrapping the original function
     */
    function deprecateFunctionExpression(fn, displayNameOrShowMessageFn, alternativeName, sinceVersion, removeInVersion) {
        if (fn.__deprecated) {
            return fn; // don't double deprecate
        }

        var showDeprecationMessage = getShowDeprecationMessage(displayNameOrShowMessageFn || fn.name || 'this function', alternativeName, sinceVersion, removeInVersion);
        var deprecatedFn = function deprecated() {
            showDeprecationMessage();
            return fn.apply(this, arguments);
        };

        Object.defineProperty(deprecatedFn, '__deprecated', {
            enumerable : false,
            configurable : false,
            writable : false,
            value : true
        });

        return deprecatedFn;
    }

    /**
     * Returns a wrapped version of the constructor that logs a deprecation warning when the constructor is instantiated.
     * @param {Function} constructorFn the constructor function to wrap
     * @param {string|Function} displayNameOrShowMessageFn the name of the fn to be displayed in the message. Alternatively, a function to log deprecation warnings
     * @param {string} alternativeName the name of an alternative function to use
     * @param {string} sinceVersion the version this has been deprecated since
     * @param {string} removeInVersion the version this will be removed in
     * @return {Function} wrapping the original function
     */
    function deprecateConstructor(constructorFn, displayNameOrShowMessageFn, alternativeName, sinceVersion, removeInVersion) {
        if (constructorFn.__deprecated) { // don't double deprecate
            return constructorFn;
        }
        var deprecatedConstructor = deprecateFunctionExpression(constructorFn, displayNameOrShowMessageFn, alternativeName, sinceVersion, removeInVersion);
        deprecatedConstructor.prototype = constructorFn.prototype;
        _.extend(deprecatedConstructor, constructorFn); //copy static methods across;

        return deprecatedConstructor;
    }

    /**
     * Wraps a "value" object property in a deprecation warning in browsers supporting Object.defineProperty
     * @param {Object} obj the object containing the property
     * @param {string} prop the name of the property to deprecate
     * @param {string|Function} displayNameOrShowMessageFn the display name of the property to deprecate (optional, will fall back to the property name). Alternatively, a function to log deprecation warnings
     * @param {string} alternativeName the name of an alternative to use
     * @param {string} sinceVersion the version this has been deprecated since
     * @param {string} removeInVersion the version this will be removed in
     */
    function deprecateValueProperty(obj, prop, displayNameOrShowMessageFn, alternativeName, sinceVersion, removeInVersion) {
        var oldVal = obj[prop];
        var showDeprecationMessage = getShowDeprecationMessage(displayNameOrShowMessageFn || prop, alternativeName, sinceVersion, removeInVersion);
        Object.defineProperty(obj, prop, {
            get : function () {
                showDeprecationMessage();
                return oldVal;
            },
            set : function(val) {
                oldVal = val;
                showDeprecationMessage();
                return val;
            }
        });
    }

    /**
     * Wraps an object property in a deprecation warning, if possible. functions will always log warnings, but other
     * types of properties will only log in browsers supporting Object.defineProperty
     * @param {Object} obj the object containing the property
     * @param {string} prop the name of the property to deprecate
     * @param {string|Function} displayNameOrShowMessageFn the display name of the property to deprecate (optional, will fall back to the property name). Alternatively, a function to log deprecation warnings
     * @param {string} alternativeName the name of an alternative to use
     * @param {string} sinceVersion the version this has been deprecated since
     * @param {string} removeInVersion the version this will be removed in
     */
    function deprecateObjectProperty(obj, prop, displayNameOrShowMessageFn, alternativeName, sinceVersion, removeInVersion) {
        if (typeof obj[prop] === 'function') {
            // assume all functions are constructors.
            obj[prop] = deprecateConstructor(obj[prop], displayNameOrShowMessageFn || prop, alternativeName, sinceVersion, removeInVersion);
        } else {
            deprecateValueProperty(obj, prop, displayNameOrShowMessageFn, alternativeName, sinceVersion, removeInVersion);
        }
    }

    function deprecateAllProperties(obj, objDisplayPrefix, alternativeNamePrefix, sinceVersion, removeInVersion) {
        for(var attr in obj) {
            if (has.call(obj, attr)) {
                deprecateObjectProperty(obj, attr, objDisplayPrefix + attr, alternativeNamePrefix && (alternativeNamePrefix + attr),
                    sinceVersion, removeInVersion);
            }
        }
    }

    // These properties will not be touched since Backbone uses them on the model itself.
    // But the deprecation should "just work" because they are synonymous with the attributes.
    var whitelistedProperty = "id";
    // These properties cannot be deprecated well since Backbone uses them on the model itself.
    // We throw early when they are deprecated.
    var blacklistedProperties = /^(attributes|url|isNew|hasChanged|changed(Attributes)|previous(Attributes)|clone)$/;

    /**
     * This function will deprecate a json property on an object that has been converted to a Brace.Model
     * @param {Brace.Model} BraceModel the Brace.Model class that contains the attribute.
     * @param {string} className the name of the Brace.Model class
     * @param {string} attr the name of the attribute to deprecate
     * @param {string} sinceVersion the version this has been deprecated since
     * @param {string} removeInVersion the version this will be removed in
     */
    function deprecateJsonModelProp(BraceModel, className, attr, sinceVersion, removeInVersion) {
        if (whitelistedProperty === attr) {
            return;
        }
        if (blacklistedProperties.test(attr)) {
            throw new Error("The property " + attr + " cannot be deprecated when converting to a Brace model.");
        }
        var showDeprecationMessage = getShowDeprecationMessage(
            className + '::' + attr,
            className + "::get|set('" + attr + "')",
            sinceVersion, removeInVersion);

        Object.defineProperty(BraceModel.prototype, attr, {
            get : function () {
                showDeprecationMessage();
                return this.get(attr);
            },
            set : function(val) {
                showDeprecationMessage();
                this.set(attr, val);
            }
        });
    }

    /**
     * This function will deprecate a JSON model in favor of a Brace.Model
     * @param {Brace.Model} BraceModel the Brace.Model class that has replaced a JSON model
     * @param {string} className the name of the Brace.Model class
     * @param {string} sinceVersion the version in which the JSON became a Brace model
     * @param {string} removeInVersion the version in which the JSON attributes will be removed.
     */
    function deprecateJsonModel(BraceModel, className, sinceVersion, removeInVersion) {
        var namedAttrs = BraceModel.prototype.namedAttributes;
        var attr;
        if (toString.call(namedAttrs) === '[object Array]') {
            var i = namedAttrs.length;
            while(i--) {
                deprecateJsonModelProp(BraceModel, className, namedAttrs[i], sinceVersion, removeInVersion);
            }
        } else {
            for(attr in namedAttrs) {
                if (has.call(namedAttrs, attr)) {
                    deprecateJsonModelProp(BraceModel, className, attr, sinceVersion, removeInVersion);
                }
            }
        }
    }

    /**
     * Deprecate an attribute of a brace model by deprecating the getFoo and setFoo convenience methods.
     * @param {function} BraceModel the Brace.Model with the attribute to deprecate
     * @param {string} attributeName the name of the attribute to deprecate
     * @param {string} alternativeName the name or instructions for the alternative
     * @param {string} sinceVersion the version that the attribute was deprecated
     * @param {string} removeInVersion the version that the attribute will be removed
     */
    function deprecateBraceAttribute(BraceModel, attributeName, alternativeName, sinceVersion, removeInVersion) {
        if (has.call(BraceModel.prototype.namedAttributes, attributeName)) {
            var SentenceCaseAttribute = textUtil.toSentenceCase(attributeName);

            BraceModel.prototype['get' + SentenceCaseAttribute] = deprecateFunctionExpression(BraceModel.prototype['get' + SentenceCaseAttribute],
                attributeName, alternativeName, sinceVersion, removeInVersion);

            BraceModel.prototype['set' + SentenceCaseAttribute] = deprecateFunctionExpression(BraceModel.prototype['set' + SentenceCaseAttribute],
                attributeName, alternativeName, sinceVersion, removeInVersion);
        }
    }

    /**
     * Deprecates the Brace methods on a model that should now be referenced as read-only JSON.
     *
     * NOTE: This should rarely be used. It is currently used for a bug that leaked into our API.
     *
     * @param {Brace.Model} braceModel the model to deprecate and replace with raw JSON
     * @param {string} sinceVersion the version that the model was deprecated
     * @param {string} removeInVersion the version that the model will be removed
     */
    function deprecateJsonAsBraceModel(braceModel, sinceVersion, removeInVersion) {
        var proto = braceModel.constructor.prototype;
        braceModel = braceModel.clone();
        var json = braceModel.toJSON();
        var attr;

        // a backdoor reference we can use without triggering any deprecation warnings.
        Object.defineProperty(braceModel, '__json', {
            enumerable : false,
            configurable : false,
            writable : false,
            value : json
        });

        // Use a single deprecation message for all properties
        // This avoids calls that cause 4-6 warnings to pop up at once E.g.,
        //      if you call .getMyProp(), which internally calls .get('myProp'), which accesses .attributes, etc...
        var deprecationMessageFn = getShowDeprecationMessage(
            "use of this object's Backbone properties",
            "raw JSON properties on this object", sinceVersion, removeInVersion);


        for(attr in braceModel) {
            // No hasOwnProperty check - we want to handle everything accessible from this model
            // that won't already be handled as raw json later
            if (!has.call(json, attr)) {
                deprecateObjectProperty(braceModel, attr, deprecationMessageFn);
            }
        }

        // add the raw json properties onto the object
        for (attr in json) {
            if (has.call(json, attr) && !has.call(braceModel, attr) && !has.call(proto, attr)) {
                braceModel[attr] = json[attr];
            }
        }

        return braceModel;
    }


    var eventDeprecations = {};

    /**
     * @param {string} eventName
     * @param {*} context
     * @param {*} args excess arguments are passed to the handlers as
     * @param {string?} alternativeName the name of the alternative thing to use
     * @param {string?} sinceVersion the version this has been deprecated since
     * @param {string?} removeInVersion the version this will be removed in
     */
    function triggerDeprecated(eventName, context/*, ...args, alternativeName, sinceVersion, removeInVersion*/) {
        if (events.listeners(eventName).length) {
            if (arguments.length < 5) {
                throw new Error("eventName, context, alternativeName, sinceVersion, and removeInVersion must all be provided (but can be null).");
            }
            var triggerArgs = Array.prototype.slice.call(arguments, 0, arguments.length - 3);
            var alternativeName = arguments[arguments.length - 3];
            var sinceVersion = arguments[arguments.length - 2];
            var removeInVersion = arguments[arguments.length - 1];
            var showMessage = eventDeprecations[eventName] ||
                              (eventDeprecations[eventName] =
                                getShowDeprecationMessage("Event '" + eventName + "'", "'" + alternativeName + "'", sinceVersion, removeInVersion));
            showMessage();
            events.trigger.apply(events, triggerArgs);
        }
    }

    return {
        fn : deprecateFunctionExpression,
        construct : deprecateConstructor,
        prop : deprecateObjectProperty,
        obj : deprecateAllProperties,
        braceAsJson : deprecateJsonModel,
        braceAttribute: deprecateBraceAttribute,
        jsonAsBrace : deprecateJsonAsBraceModel,
        triggerDeprecated : triggerDeprecated,
        getMessageLogger : getShowDeprecationMessage
    };
});

Zerion Mini Shell 1.0