| Leo Repp | 58b9f11 | 2021-11-22 11:57:47 +0100 | [diff] [blame^] | 1 | /*! |
| 2 | * static-extend <https://github.com/jonschlinkert/static-extend> |
| 3 | * |
| 4 | * Copyright (c) 2016, Jon Schlinkert. |
| 5 | * Licensed under the MIT License. |
| 6 | */ |
| 7 | |
| 8 | 'use strict'; |
| 9 | |
| 10 | var copy = require('object-copy'); |
| 11 | var define = require('define-property'); |
| 12 | var util = require('util'); |
| 13 | |
| 14 | /** |
| 15 | * Returns a function for extending the static properties, |
| 16 | * prototype properties, and descriptors from the `Parent` |
| 17 | * constructor onto `Child` constructors. |
| 18 | * |
| 19 | * ```js |
| 20 | * var extend = require('static-extend'); |
| 21 | * Parent.extend = extend(Parent); |
| 22 | * |
| 23 | * // optionally pass a custom merge function as the second arg |
| 24 | * Parent.extend = extend(Parent, function(Child) { |
| 25 | * Child.prototype.mixin = function(key, val) { |
| 26 | * Child.prototype[key] = val; |
| 27 | * }; |
| 28 | * }); |
| 29 | * |
| 30 | * // extend "child" constructors |
| 31 | * Parent.extend(Child); |
| 32 | * |
| 33 | * // optionally define prototype methods as the second arg |
| 34 | * Parent.extend(Child, { |
| 35 | * foo: function() {}, |
| 36 | * bar: function() {} |
| 37 | * }); |
| 38 | * ``` |
| 39 | * @param {Function} `Parent` Parent ctor |
| 40 | * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype. |
| 41 | * @param {Function} `Child` Child ctor |
| 42 | * @param {Object} `proto` Optionally pass additional prototype properties to inherit. |
| 43 | * @return {Object} |
| 44 | * @api public |
| 45 | */ |
| 46 | |
| 47 | function extend(Parent, extendFn) { |
| 48 | if (typeof Parent !== 'function') { |
| 49 | throw new TypeError('expected Parent to be a function.'); |
| 50 | } |
| 51 | |
| 52 | return function(Ctor, proto) { |
| 53 | if (typeof Ctor !== 'function') { |
| 54 | throw new TypeError('expected Ctor to be a function.'); |
| 55 | } |
| 56 | |
| 57 | util.inherits(Ctor, Parent); |
| 58 | copy(Ctor, Parent); |
| 59 | |
| 60 | // proto can be null or a plain object |
| 61 | if (typeof proto === 'object') { |
| 62 | var obj = Object.create(proto); |
| 63 | |
| 64 | for (var k in obj) { |
| 65 | Ctor.prototype[k] = obj[k]; |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | // keep a reference to the parent prototype |
| 70 | define(Ctor.prototype, '_parent_', { |
| 71 | configurable: true, |
| 72 | set: function() {}, |
| 73 | get: function() { |
| 74 | return Parent.prototype; |
| 75 | } |
| 76 | }); |
| 77 | |
| 78 | if (typeof extendFn === 'function') { |
| 79 | extendFn(Ctor, Parent); |
| 80 | } |
| 81 | |
| 82 | Ctor.extend = extend(Ctor, extendFn); |
| 83 | }; |
| 84 | }; |
| 85 | |
| 86 | /** |
| 87 | * Expose `extend` |
| 88 | */ |
| 89 | |
| 90 | module.exports = extend; |