@gtkx/runtime 2.0.0-beta.1 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/internal.d.ts +16 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +12 -0
- package/dist/internal.js.map +1 -1
- package/dist/listeners.d.ts +3 -13
- package/dist/listeners.d.ts.map +1 -1
- package/dist/listeners.js +12 -12
- package/dist/listeners.js.map +1 -1
- package/dist/mixin.d.ts +5 -3
- package/dist/mixin.d.ts.map +1 -1
- package/dist/mixin.js +36 -9
- package/dist/mixin.js.map +1 -1
- package/dist/object.d.ts +11 -0
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +18 -25
- package/dist/object.js.map +1 -1
- package/dist/properties.d.ts +4 -2
- package/dist/properties.d.ts.map +1 -1
- package/dist/properties.js +69 -16
- package/dist/properties.js.map +1 -1
- package/dist/property-brand.d.ts +5 -0
- package/dist/property-brand.d.ts.map +1 -0
- package/dist/property-brand.js +5 -0
- package/dist/property-brand.js.map +1 -0
- package/dist/register-class.d.ts +102 -20
- package/dist/register-class.d.ts.map +1 -1
- package/dist/register-class.js +19 -37
- package/dist/register-class.js.map +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -4
- package/dist/registry.js.map +1 -1
- package/dist/signal-brand.d.ts +12 -0
- package/dist/signal-brand.d.ts.map +1 -0
- package/dist/signal-brand.js +6 -0
- package/dist/signal-brand.js.map +1 -0
- package/dist/signal.d.ts +39 -2
- package/dist/signal.d.ts.map +1 -1
- package/dist/signal.js +75 -5
- package/dist/signal.js.map +1 -1
- package/dist/type.d.ts.map +1 -1
- package/dist/type.js +1 -1
- package/dist/type.js.map +1 -1
- package/package.json +4 -4
- package/src/internal.ts +41 -0
- package/src/listeners.ts +21 -26
- package/src/mixin.ts +55 -9
- package/src/object.ts +55 -5
- package/src/properties.ts +94 -17
- package/src/property-brand.ts +5 -0
- package/src/register-class.ts +296 -95
- package/src/registry.ts +4 -4
- package/src/signal-brand.ts +29 -0
- package/src/signal.ts +177 -6
- package/src/type.ts +1 -1
package/src/properties.ts
CHANGED
|
@@ -55,7 +55,7 @@ type AccessorBase = PropertyCheck & {
|
|
|
55
55
|
type DeclaredAccessor = AccessorBase & {
|
|
56
56
|
isInterfaceProperty?: false;
|
|
57
57
|
memberName: string;
|
|
58
|
-
|
|
58
|
+
hasMemberAccessor: boolean;
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
type InterfaceAccessor = AccessorBase & { isInterfaceProperty: true };
|
|
@@ -100,7 +100,7 @@ const paramSpecDefaultValue = bind(LIB, "g_param_spec_get_default_value", [PARAM
|
|
|
100
100
|
const paramSpecName = bind(LIB, "g_param_spec_get_name", [PARAM_T], stringT("borrowed"));
|
|
101
101
|
const typeClassRef = bind(LIB, "g_type_class_ref", [biguint64T], CLASS_T);
|
|
102
102
|
const typeClassUnref = bind(LIB, "g_type_class_unref", [CLASS_T], voidT);
|
|
103
|
-
const
|
|
103
|
+
const propertyChecks: Map<bigint, Map<string, PropertyCheck | null>> = new Map();
|
|
104
104
|
const classFindProperty = bind(LIB, "g_object_class_find_property", [CLASS_T, stringT("borrowed")], PARAM_T);
|
|
105
105
|
|
|
106
106
|
const classListProperties = bind(
|
|
@@ -214,8 +214,11 @@ const findSourceSpec = (source: bigint | AnyClass, name: string): ExternalObject
|
|
|
214
214
|
* @param source The GType, wrapper class or interface declaring the property.
|
|
215
215
|
* @returns Handle of the override spec.
|
|
216
216
|
*/
|
|
217
|
-
const newParamSpecOverride = (name: string, source: bigint | AnyClass): ExternalObject<Handle> =>
|
|
218
|
-
|
|
217
|
+
const newParamSpecOverride = (name: string, source: bigint | AnyClass): ExternalObject<Handle> => {
|
|
218
|
+
const canonicalName = canonicalCase(name);
|
|
219
|
+
|
|
220
|
+
return paramSpecOverrideNew(canonicalName, findSourceSpec(source, canonicalName)) as ExternalObject<Handle>;
|
|
221
|
+
};
|
|
219
222
|
|
|
220
223
|
function describeValue(value: unknown): string {
|
|
221
224
|
if (typeof value === "string") {
|
|
@@ -283,6 +286,24 @@ function assertWritable(instance: object, check: PropertyCheck, value: unknown):
|
|
|
283
286
|
throw new TypeError(propertyMessage(instance, check, refusalTail(check, value, READ_ONLY_REASON)));
|
|
284
287
|
}
|
|
285
288
|
|
|
289
|
+
function assertReadable(instance: object, check: PropertyCheck): void {
|
|
290
|
+
if (isParamReadable(check.flags)) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
throw new TypeError(
|
|
295
|
+
propertyMessage(instance, check, `cannot read property '${check.propertyName}'; the property is write-only`),
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function assertMutable(instance: object, check: PropertyCheck, value: unknown): void {
|
|
300
|
+
assertWritable(instance, check, value);
|
|
301
|
+
|
|
302
|
+
if (isParamConstructOnly(check.flags)) {
|
|
303
|
+
throw new TypeError(propertyMessage(instance, check, refusalTail(check, value, CONSTRUCT_ONLY_REASON)));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
286
307
|
function writeHeld(check: PropertyCheck, gValue: ExternalObject<Handle>, value: unknown): void {
|
|
287
308
|
check.write ??= valueWriterFor(check.valueType);
|
|
288
309
|
check.write(gValue, check.narrowValue(value));
|
|
@@ -333,7 +354,7 @@ function isReadableProperty(gtype: bigint, propertyName: string): boolean {
|
|
|
333
354
|
}
|
|
334
355
|
}
|
|
335
356
|
|
|
336
|
-
function
|
|
357
|
+
function lookupPropertyCheck(gtype: bigint, name: string): PropertyCheck | null {
|
|
337
358
|
const klass = typeClassRef(gtype) as ExternalObject<Handle>;
|
|
338
359
|
|
|
339
360
|
try {
|
|
@@ -345,10 +366,35 @@ function lookupCoercionCheck(gtype: bigint, name: string): PropertyCheck | null
|
|
|
345
366
|
}
|
|
346
367
|
}
|
|
347
368
|
|
|
348
|
-
function
|
|
349
|
-
const checks =
|
|
369
|
+
function propertyCheckFor(gtype: bigint, name: string): PropertyCheck | null {
|
|
370
|
+
const checks = propertyChecks.getOrInsertComputed(gtype, () => new Map<string, PropertyCheck | null>());
|
|
371
|
+
|
|
372
|
+
return checks.getOrInsertComputed(name, () => lookupPropertyCheck(gtype, name));
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function objectPropertyCheckFor(instance: object, name: string): PropertyCheck {
|
|
376
|
+
const gtype = getInstanceType(instance);
|
|
377
|
+
const check = typeIsA(gtype, TYPE_OBJECT) ? propertyCheckFor(gtype, name) : null;
|
|
378
|
+
|
|
379
|
+
if (check === null) {
|
|
380
|
+
throw new TypeError(`${instanceClassName(instance)} has no GObject property named '${name}'`);
|
|
381
|
+
}
|
|
350
382
|
|
|
351
|
-
return
|
|
383
|
+
return check;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function readableObjectPropertyFor(instance: object, name: string): ConstructProperty {
|
|
387
|
+
const check = objectPropertyCheckFor(instance, name);
|
|
388
|
+
assertReadable(instance, check);
|
|
389
|
+
|
|
390
|
+
return { name: check.propertyName, value: newValueForType(check.valueType) };
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function writableObjectPropertyFor(instance: object, name: string, value: unknown): ConstructProperty {
|
|
394
|
+
const check = objectPropertyCheckFor(instance, name);
|
|
395
|
+
assertMutable(instance, check, value);
|
|
396
|
+
|
|
397
|
+
return { name: check.propertyName, value: checkedValueFor(instance, check, value) };
|
|
352
398
|
}
|
|
353
399
|
|
|
354
400
|
function truncateToWhole(check: PropertyCheck, value: number): number {
|
|
@@ -384,7 +430,7 @@ function coercePropertyValue(gtype: bigint, propertyName: string, value: unknown
|
|
|
384
430
|
return value;
|
|
385
431
|
}
|
|
386
432
|
|
|
387
|
-
const check =
|
|
433
|
+
const check = propertyCheckFor(gtype, propertyName);
|
|
388
434
|
|
|
389
435
|
return check === null ? value : coerceNumber(check, value);
|
|
390
436
|
}
|
|
@@ -499,12 +545,35 @@ function checkedSetter(accessor: DeclaredAccessor): (this: object, value: unknow
|
|
|
499
545
|
};
|
|
500
546
|
}
|
|
501
547
|
|
|
502
|
-
function
|
|
503
|
-
|
|
548
|
+
function memberDescriptorFor(prototype: object, name: string): PropertyDescriptor | undefined {
|
|
549
|
+
let current: object | null = prototype;
|
|
550
|
+
|
|
551
|
+
while (current !== null) {
|
|
552
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, name);
|
|
553
|
+
|
|
554
|
+
if (descriptor !== undefined) {
|
|
555
|
+
return descriptor;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
current = Reflect.getPrototypeOf(current);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return undefined;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
function isMemberAccessor(descriptor: PropertyDescriptor | undefined): boolean {
|
|
565
|
+
return descriptor !== undefined && ("get" in descriptor || "set" in descriptor);
|
|
504
566
|
}
|
|
505
567
|
|
|
506
568
|
function defineAccessor(prototype: object, descriptor: PropertyDescriptor, alias: string): void {
|
|
507
|
-
if (
|
|
569
|
+
if (Object.getOwnPropertyDescriptor(prototype, alias) !== undefined) {
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const parent = Reflect.getPrototypeOf(prototype);
|
|
574
|
+
const inherited = parent === null ? undefined : memberDescriptorFor(parent, alias);
|
|
575
|
+
|
|
576
|
+
if (inherited !== undefined && !isMemberAccessor(inherited)) {
|
|
508
577
|
return;
|
|
509
578
|
}
|
|
510
579
|
|
|
@@ -513,13 +582,13 @@ function defineAccessor(prototype: object, descriptor: PropertyDescriptor, alias
|
|
|
513
582
|
|
|
514
583
|
function installAccessors(klass: AnyClass, accessor: DeclaredAccessor): void {
|
|
515
584
|
const prototype = (klass as { prototype: object }).prototype;
|
|
516
|
-
accessor.
|
|
585
|
+
accessor.hasMemberAccessor = isMemberAccessor(Object.getOwnPropertyDescriptor(prototype, accessor.memberName));
|
|
517
586
|
|
|
518
587
|
const descriptor: PropertyDescriptor = {
|
|
519
588
|
configurable: true,
|
|
520
589
|
enumerable: true,
|
|
521
|
-
get: accessor.
|
|
522
|
-
set: accessor.
|
|
590
|
+
get: accessor.hasMemberAccessor ? memberGetter(accessor) : storedGetter(accessor),
|
|
591
|
+
set: accessor.hasMemberAccessor ? memberSetter(accessor) : checkedSetter(accessor),
|
|
523
592
|
};
|
|
524
593
|
|
|
525
594
|
for (const alias of accessorNames(accessor.name)) {
|
|
@@ -586,7 +655,13 @@ function callMember(instance: object, member: string, args: unknown[]): unknown
|
|
|
586
655
|
}
|
|
587
656
|
|
|
588
657
|
function backingMemberFor(instance: object, accessor: DeclaredAccessor): string | undefined {
|
|
589
|
-
if (accessor.
|
|
658
|
+
if (accessor.hasMemberAccessor) {
|
|
659
|
+
return accessor.memberName;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const descriptor = Object.getOwnPropertyDescriptor(instance, accessor.memberName);
|
|
663
|
+
|
|
664
|
+
if (descriptor === undefined || ("value" in descriptor && typeof descriptor.value === "function")) {
|
|
590
665
|
return undefined;
|
|
591
666
|
}
|
|
592
667
|
|
|
@@ -686,7 +761,7 @@ function buildAccessor(klass: AnyClass, name: string, pspec: PropertySpec): Decl
|
|
|
686
761
|
...checkFor(getHandle(pspec), name),
|
|
687
762
|
memberName: camelCase(name),
|
|
688
763
|
storage: Symbol(`gtkx:property:${name}`),
|
|
689
|
-
|
|
764
|
+
hasMemberAccessor: false,
|
|
690
765
|
};
|
|
691
766
|
|
|
692
767
|
installAccessors(klass, accessor);
|
|
@@ -770,8 +845,10 @@ export {
|
|
|
770
845
|
makeGetProperty,
|
|
771
846
|
makeSetProperty,
|
|
772
847
|
newParamSpecOverride,
|
|
848
|
+
readableObjectPropertyFor,
|
|
773
849
|
SET_PROPERTY_VFUNC,
|
|
774
850
|
toNativeProperties,
|
|
851
|
+
writableObjectPropertyFor,
|
|
775
852
|
type ConstructProperty,
|
|
776
853
|
type PropertyDispatch,
|
|
777
854
|
type PropertySpec,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const propertyMapOverride: unique symbol = Symbol("gtkx.propertyMapOverride");
|
|
2
|
+
const writablePropertyMapOverride: unique symbol = Symbol("gtkx.writablePropertyMapOverride");
|
|
3
|
+
const descriptorFreePropertySpec: unique symbol = Symbol("gtkx.descriptorFreePropertySpec");
|
|
4
|
+
|
|
5
|
+
export { descriptorFreePropertySpec, propertyMapOverride, writablePropertyMapOverride };
|