all files / montage/core/meta/ module-object-descriptor.js

48.33% Statements 29/60
40% Branches 12/30
50% Functions 6/12
48.33% Lines 29/60
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201                                                                                           18× 18× 18×   18×     18×                                                                         31×     31×       31×   31× 31× 13×     18×       18× 18×       18×       18×   18×     16×   16× 16×                                                                                                             18× 18×   18×                   18×      
var Montage = require("../core").Montage,
    Promise = require("../promise").Promise,
    ObjectDescriptor = require("./object-descriptor").ObjectDescriptor,
    Deserializer = require("../serialization/deserializer/montage-deserializer").MontageDeserializer,
    ModuleReference = require("../module-reference").ModuleReference,
    deprecate = require("../deprecate");
 
// Cache all loaded object descriptors
var OBJECT_DESCRIPTOR_CACHE = Object.create(null);
 
/**
 * @class ModuleObjectDescriptor
 * @extends ObjectDescriptor
 */
var ModuleObjectDescriptor = exports.ModuleObjectDescriptor = ObjectDescriptor.specialize(/** @lends ModuleObjectDescriptor# */ {
 
    /**
     * @function
     * @param {ModuleReference} module
     * @param {string} name
     * @returns this
     */
    initWithModuleAndExportName: {
        value: function (module, exportName) {
            var self = ObjectDescriptor.prototype.initWithName.call(this, exportName);
            self.module = module;
            self.exportName = exportName;
            return self;
        }
    },
 
    serializeSelf: {
        value: function (serializer) {
            if (!this.module) {
                throw new Error("Cannot serialize object descriptor without a module reference");
            }
            if (!this.exportName) {
                throw new Error("Cannot serialize object descriptor without an exportName");
            }
 
            this.super(serializer);
            this._setPropertyWithDefaults(serializer, "module", this.module);
            this._setPropertyWithDefaults(serializer, "exportName", this.exportName);
        }
    },
 
    deserializeSelf: {
        value: function (deserializer) {
            this.super(deserializer);
            this.module = deserializer.getProperty("module");
            this.exportName = deserializer.getProperty("exportName");
 
            Iif (!this.module) {
                throw new Error("Cannot deserialize object descriptor without a module reference");
            }
            Iif (!this.exportName) {
                throw new Error("Cannot deserialize object descriptor without an exportName");
            }
        }
    },
 
    /**
     * A reference to the module that this object descriptor is for.
     * @type {ModuleReference}
     */
    module: {
        value: null
    },
 
    /**
     * The name of the export this object descriptor is for.
     * @type {string}
     */
    exportName: {
        value: null
    },
 
    objectDescriptorInstanceModule: {
        serializable: false,
        value: null
    }
 
}, /** @lends ModuleObjectDescriptor. */ {
 
    /**
     * Gets an object descriptor from a serialized file at the given module id.
     * @function
     * @param {string} object descriptor module id
     * @param {function} require function
     */
    getObjectDescriptorWithModuleId: {
        value: function (moduleId, _require) {
            Iif (moduleId.search(/\.meta$/) === -1 && moduleId.search(/\.mjson$/) === -1) {
                throw new Error(moduleId + " object descriptor module id does not end in '.meta' or '.mjson'");
            }
            Iif (!_require) {
                throw new Error("Require needed to get object descriptor " + moduleId);
            }
 
            var targetRequire;
 
            var key = _require.location + "#" + moduleId;
            if (key in OBJECT_DESCRIPTOR_CACHE) {
                return OBJECT_DESCRIPTOR_CACHE[key];
            }
 
            return OBJECT_DESCRIPTOR_CACHE[key] = _require.async(moduleId)
                .then(function (object) {
                    // Need to get the require from the module, because thats
                    // what all the moduleId references are relative to.
                    targetRequire = getModuleRequire(_require, moduleId);
                    return new Deserializer().init(JSON.stringify(object), targetRequire).deserializeObject();
                }).then(function (objectDescriptor) {
                    
                    // TODO: May want to relax this to being just an Object Descriptor
                    Iif (!ModuleObjectDescriptor.prototype.isPrototypeOf(objectDescriptor)) {
                        throw new Error("Object in " + moduleId + " is not a module-object-descriptor");
                    }
 
                    objectDescriptor.objectDescriptorInstanceModule = new ModuleReference().initWithIdAndRequire(moduleId, _require);
 
                    if (objectDescriptor._parentReference) {
                        // Load parent "synchronously" so that all the properties
                        // through the object descriptor chain are available
                        return objectDescriptor._parentReference.promise(targetRequire) // MARK
                            .then(function (parentObjectDescriptor) {
                                objectDescriptor._parent = parentObjectDescriptor;
                                return objectDescriptor;
                            });
                    }
 
                    return objectDescriptor;
                });
        }
    },
 
    createDefaultObjectDescriptorForObject: {
        value: function (object) {
            var target = Montage.getInfoForObject(object).isInstance ? Object.getPrototypeOf(object) : object;
            var info = Montage.getInfoForObject(target);
            if (!info.objectName || !info.moduleId) {
                return Promise.reject("Cannot create module-object-descriptor for an object that has no been loaded from a module");
            }
 
            return this.super(object)
                .then(function (objectDescriptor) {
                    objectDescriptor.module = new ModuleReference().initWithIdAndRequire(info.moduleId, info.require);
                    objectDescriptor.exportName = info.objectName;
                    return objectDescriptor;
                });
        }
    },
 
    /***************************************************************
     * Deprecated methods.
     */
 
    /**
     * Gets an object descriptor from a serialized file at the given module id.
     * @deprecated
     * @function
     * @param {string} object descriptor module id
     * @param {function} require function
     */
    getBlueprintWithModuleId: {
        value: deprecate.deprecateMethod(void 0, function (moduleId, _require) {
            return ModuleObjectDescriptor.getObjectDescriptorWithModuleId(moduleId, _require);
        }, "ModuleBlueprint.getBlueprintWithModuleId", "ModuleObjectDescriptor.getObjectDescriptorWithModuleId")
    },
 
    /**
     * @deprecated
     */
    createDefaultBlueprintForObject: {
        value: deprecate.deprecateMethod(void 0, function (object) {
            return ModuleObjectDescriptor.createDefaultObjectDescriptorForObject(object);
        }, "ModuleBlueprint.createDefaultBlueprintForObject", "ModuleObjectDescriptor.createDefaultObjectDescriptorForObject")
    }
 
 
});
 
// Adapted from mr/sandbox
function getModuleRequire(parentRequire, moduleId) {
    var topId = parentRequire.resolve(moduleId);
    var module = parentRequire.getModuleDescriptor(topId);
 
    while (module.redirect || module.mappingRedirect) {
        if (module.redirect) {
            topId = module.redirect;
        } else {
            parentRequire = module.mappingRequire;
            topId = module.mappingRedirect;
        }
        module = parentRequire.getModuleDescriptor(topId);
    }
 
    return module.require;
}