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
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
// SPDX-FileCopyrightText: 2020 Philip Chimento <philip.chimento@gmail.com>
/* exported _checkAccessors, _registerType, definePublicProperties, definePrivateProperties */
// This is a helper module in which to put code that is common between the
// legacy GObject.Class system and the new GObject.registerClass system.
var _registerType = Symbol('GObject register type hook');
function _generateAccessors(pspec, propdesc, GObject) {
const {name, flags} = pspec;
const readable = flags & GObject.ParamFlags.READABLE;
const writable = flags & GObject.ParamFlags.WRITABLE;
if (!propdesc) {
propdesc = {
configurable: true,
enumerable: true,
};
}
if (readable && writable) {
if (!propdesc.get && !propdesc.set) {
const privateName = Symbol(`__autogeneratedAccessor__${name}`);
const defaultValue = pspec.get_default_value();
propdesc.get = function () {
if (!(privateName in this))
this[privateName] = defaultValue;
return this[privateName];
};
propdesc.set = function (value) {
if (value !== this[privateName]) {
this[privateName] = value;
this.notify(name);
}
};
} else if (!propdesc.get) {
propdesc.get = function () {
throw new Error(`setter defined without getter for property ${name}`);
};
} else if (!propdesc.set) {
propdesc.set = function () {
throw new Error(`getter defined without setter for property ${name}`);
};
}
} else if (readable && !propdesc.get) {
propdesc.get = function () {
throw new Error(`missing getter for read-only property ${name}`);
};
} else if (writable && !propdesc.set) {
propdesc.set = function () {
throw new Error(`missing setter for write-only property ${name}`);
};
}
return propdesc;
}
function _checkAccessors(proto, pspec, GObject, {generateAccessors = true, accessorMappingSymbol = null} = {}) {
const {name, flags} = pspec;
if (flags & GObject.ParamFlags.CONSTRUCT_ONLY)
return;
const underscoreName = name.replace(/-/g, '_');
const camelName = name.replace(/-([a-z])/g, match => match[1].toUpperCase());
let propdesc = Object.getOwnPropertyDescriptor(proto, name);
let dashPropdesc = propdesc, underscorePropdesc, camelPropdesc;
const nameIsCompound = name.includes('-');
if (nameIsCompound) {
underscorePropdesc = Object.getOwnPropertyDescriptor(proto, underscoreName);
camelPropdesc = Object.getOwnPropertyDescriptor(proto, camelName);
if (!propdesc)
propdesc = underscorePropdesc;
if (!propdesc)
propdesc = camelPropdesc;
}
const readable = flags & GObject.ParamFlags.READABLE;
const writable = flags & GObject.ParamFlags.WRITABLE;
if (!propdesc || (readable && !propdesc.get) || (writable && !propdesc.set))
propdesc = _generateAccessors(pspec, propdesc, GObject);
if (generateAccessors) {
if (!dashPropdesc)
Object.defineProperty(proto, name, propdesc);
if (nameIsCompound) {
if (!underscorePropdesc)
Object.defineProperty(proto, underscoreName, propdesc);
if (!camelPropdesc)
Object.defineProperty(proto, camelName, propdesc);
}
}
if (accessorMappingSymbol) {
proto[accessorMappingSymbol] = proto[accessorMappingSymbol] ?? {};
if (nameIsCompound) {
proto[accessorMappingSymbol][underscoreName] = propdesc;
proto[accessorMappingSymbol][camelName] = propdesc;
} else {
proto[accessorMappingSymbol][name] = propdesc;
}
}
}
function definePublicProperties(object, values) {
Object.defineProperties(object, Object.getOwnPropertyDescriptors(values));
}
function definePrivateProperties(object, values) {
const propertyKeys = [...Object.getOwnPropertyNames(values), ...Object.getOwnPropertySymbols(values)];
const privateDescriptors = Object.fromEntries(propertyKeys.map(key => {
const descriptor = Object.getOwnPropertyDescriptor(values, key);
return [key, {
...descriptor,
...'value' in descriptor ? {writable: false} : {},
configurable: false,
enumerable: false,
}];
}));
Object.defineProperties(object, privateDescriptors);
}
|