UNPKG

aurelia-metadata

Version:

Utilities for reading and writing the metadata of JavaScript functions.

251 lines (205 loc) 6.81 kB
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; import { PLATFORM } from 'aurelia-pal'; function isObject(val) { return val && (typeof val === 'function' || typeof val === 'object'); } export const metadata = { resource: 'aurelia:resource', paramTypes: 'design:paramtypes', propertyType: 'design:type', properties: 'design:properties', get(metadataKey, target, targetKey) { if (!isObject(target)) { return undefined; } let result = metadata.getOwn(metadataKey, target, targetKey); return result === undefined ? metadata.get(metadataKey, Object.getPrototypeOf(target), targetKey) : result; }, getOwn(metadataKey, target, targetKey) { if (!isObject(target)) { return undefined; } return Reflect.getOwnMetadata(metadataKey, target, targetKey); }, define(metadataKey, metadataValue, target, targetKey) { Reflect.defineMetadata(metadataKey, metadataValue, target, targetKey); }, getOrCreateOwn(metadataKey, Type, target, targetKey) { let result = metadata.getOwn(metadataKey, target, targetKey); if (result === undefined) { result = new Type(); Reflect.defineMetadata(metadataKey, result, target, targetKey); } return result; } }; const originStorage = new Map(); const unknownOrigin = Object.freeze({ moduleId: undefined, moduleMember: undefined }); export let Origin = class Origin { constructor(moduleId, moduleMember) { this.moduleId = moduleId; this.moduleMember = moduleMember; } static get(fn) { let origin = originStorage.get(fn); if (origin === undefined) { PLATFORM.eachModule((key, value) => { if (typeof value === 'object') { let isBrowserWindow = typeof window !== 'undefined' && value === window; for (let name in value) { if (isBrowserWindow && name === 'webkitStorageInfo') { continue; } try { let exp = value[name]; if (exp === fn) { originStorage.set(fn, origin = new Origin(key, name)); return true; } } catch (e) {} } } if (value === fn) { originStorage.set(fn, origin = new Origin(key, 'default')); return true; } return false; }); } return origin || unknownOrigin; } static set(fn, origin) { originStorage.set(fn, origin); } }; export function decorators(...rest) { let applicator = function (target, key, descriptor) { let i = rest.length; if (key) { descriptor = descriptor || { value: target[key], writable: true, configurable: true, enumerable: true }; while (i--) { descriptor = rest[i](target, key, descriptor) || descriptor; } Object.defineProperty(target, key, descriptor); } else { while (i--) { target = rest[i](target) || target; } } return target; }; applicator.on = applicator; return applicator; } export function deprecated(optionsOrTarget, maybeKey, maybeDescriptor) { function decorator(target, key, descriptor) { const methodSignature = `${target.constructor.name}#${key}`; let options = maybeKey ? {} : optionsOrTarget || {}; let message = `DEPRECATION - ${methodSignature}`; if (typeof descriptor.value !== 'function') { throw new SyntaxError('Only methods can be marked as deprecated.'); } if (options.message) { message += ` - ${options.message}`; } return _extends({}, descriptor, { value: function deprecationWrapper() { if (options.error) { throw new Error(message); } else { console.warn(message); } return descriptor.value.apply(this, arguments); } }); } return maybeKey ? decorator(optionsOrTarget, maybeKey, maybeDescriptor) : decorator; } export function mixin(behavior) { const instanceKeys = Object.keys(behavior); function _mixin(possible) { let decorator = function (target) { let resolvedTarget = typeof target === 'function' ? target.prototype : target; let i = instanceKeys.length; while (i--) { let property = instanceKeys[i]; Object.defineProperty(resolvedTarget, property, { value: behavior[property], writable: true }); } }; return possible ? decorator(possible) : decorator; } return _mixin; } function alwaysValid() { return true; } function noCompose() {} function ensureProtocolOptions(options) { if (options === undefined) { options = {}; } else if (typeof options === 'function') { options = { validate: options }; } if (!options.validate) { options.validate = alwaysValid; } if (!options.compose) { options.compose = noCompose; } return options; } function createProtocolValidator(validate) { return function (target) { let result = validate(target); return result === true; }; } function createProtocolAsserter(name, validate) { return function (target) { let result = validate(target); if (result !== true) { throw new Error(result || `${name} was not correctly implemented.`); } }; } export function protocol(name, options) { options = ensureProtocolOptions(options); let result = function (target) { let resolvedTarget = typeof target === 'function' ? target.prototype : target; options.compose(resolvedTarget); result.assert(resolvedTarget); Object.defineProperty(resolvedTarget, 'protocol:' + name, { enumerable: false, configurable: false, writable: false, value: true }); }; result.validate = createProtocolValidator(options.validate); result.assert = createProtocolAsserter(name, options.validate); return result; } protocol.create = function (name, options) { options = ensureProtocolOptions(options); let hidden = 'protocol:' + name; let result = function (target) { let decorator = protocol(name, options); return target ? decorator(target) : decorator; }; result.decorates = function (obj) { return obj[hidden] === true; }; result.validate = createProtocolValidator(options.validate); result.assert = createProtocolAsserter(name, options.validate); return result; };