heyujie
2021-06-07 8f8155aa4c83f7c2577ac123add550766b6a7ce3
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
"use strict";
 
var isPlainFunction = require("type/plain-function/is")
  , ensureValue     = require("type/value/ensure")
  , isValue         = require("type/value/is")
  , map             = require("es5-ext/object/map")
  , contains        = require("es5-ext/string/#/contains");
 
var call = Function.prototype.call
  , defineProperty = Object.defineProperty
  , getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
  , getPrototypeOf = Object.getPrototypeOf
  , hasOwnProperty = Object.prototype.hasOwnProperty
  , cacheDesc = { configurable: false, enumerable: false, writable: false, value: null }
  , define;
 
define = function (name, options) {
    var value, dgs, cacheName, desc, writable = false, resolvable, flat;
    options = Object(ensureValue(options));
    cacheName = options.cacheName;
    flat = options.flat;
    if (!isValue(cacheName)) cacheName = name;
    delete options.cacheName;
    value = options.value;
    resolvable = isPlainFunction(value);
    delete options.value;
    dgs = { configurable: Boolean(options.configurable), enumerable: Boolean(options.enumerable) };
    if (name !== cacheName) {
        dgs.get = function () {
            if (hasOwnProperty.call(this, cacheName)) return this[cacheName];
            cacheDesc.value = resolvable ? call.call(value, this, options) : value;
            cacheDesc.writable = writable;
            defineProperty(this, cacheName, cacheDesc);
            cacheDesc.value = null;
            if (desc) defineProperty(this, name, desc);
            return this[cacheName];
        };
    } else if (!flat) {
        dgs.get = function self() {
            var ownDesc;
            if (hasOwnProperty.call(this, name)) {
                ownDesc = getOwnPropertyDescriptor(this, name);
                // It happens in Safari, that getter is still called after property
                // was defined with a value, following workarounds that
                // While in IE11 it may happen that here ownDesc is undefined (go figure)
                if (ownDesc) {
                    if (ownDesc.hasOwnProperty("value")) return ownDesc.value;
                    if (typeof ownDesc.get === "function" && ownDesc.get !== self) {
                        return ownDesc.get.call(this);
                    }
                    return value;
                }
            }
            desc.value = resolvable ? call.call(value, this, options) : value;
            defineProperty(this, name, desc);
            desc.value = null;
            return this[name];
        };
    } else {
        dgs.get = function self() {
            var base = this, ownDesc;
            if (hasOwnProperty.call(this, name)) {
                // It happens in Safari, that getter is still called after property
                // was defined with a value, following workarounds that
                ownDesc = getOwnPropertyDescriptor(this, name);
                if (ownDesc.hasOwnProperty("value")) return ownDesc.value;
                if (typeof ownDesc.get === "function" && ownDesc.get !== self) {
                    return ownDesc.get.call(this);
                }
            }
            while (!hasOwnProperty.call(base, name)) base = getPrototypeOf(base);
            desc.value = resolvable ? call.call(value, base, options) : value;
            defineProperty(base, name, desc);
            desc.value = null;
            return base[name];
        };
    }
    dgs.set = function (value) {
        if (hasOwnProperty.call(this, name)) {
            throw new TypeError("Cannot assign to lazy defined '" + name + "' property of " + this);
        }
        dgs.get.call(this);
        this[cacheName] = value;
    };
    if (options.desc) {
        desc = {
            configurable: contains.call(options.desc, "c"),
            enumerable: contains.call(options.desc, "e")
        };
        if (cacheName === name) {
            desc.writable = contains.call(options.desc, "w");
            desc.value = null;
        } else {
            writable = contains.call(options.desc, "w");
            desc.get = dgs.get;
            desc.set = dgs.set;
        }
        delete options.desc;
    } else if (cacheName === name) {
        desc = {
            configurable: Boolean(options.configurable),
            enumerable: Boolean(options.enumerable),
            writable: Boolean(options.writable),
            value: null
        };
    }
    delete options.configurable;
    delete options.enumerable;
    delete options.writable;
    return dgs;
};
 
module.exports = function (props) {
    return map(props, function (desc, name) { return define(name, desc); });
};