Skip to content

Commit b53ea48

Browse files
committedDec 13, 2023
Fix fallback handling, better tests, remove process.env reference
1 parent 31dde5f commit b53ea48

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1479
-2390
lines changed
 

‎Reflect.ts

+72-31
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ namespace Reflect {
3030
declare const globalThis: any;
3131
declare const crypto: Crypto;
3232
declare const msCrypto: Crypto;
33-
declare const process: any;
3433

3534
/**
3635
* Applies a set of decorators to a target object.
@@ -563,20 +562,19 @@ namespace Reflect {
563562
sloppyModeThis();
564563

565564
let exporter = makeExporter(Reflect);
566-
if (typeof root.Reflect === "undefined") {
567-
root.Reflect = Reflect;
568-
}
569-
else {
565+
if (typeof root.Reflect !== "undefined") {
570566
exporter = makeExporter(root.Reflect, exporter);
571567
}
572568

573569
factory(exporter, root);
574570

571+
if (typeof root.Reflect === "undefined") {
572+
root.Reflect = Reflect;
573+
}
574+
575575
function makeExporter(target: typeof Reflect, previous?: <K extends keyof typeof Reflect>(key: K, value: typeof Reflect[K]) => void) {
576576
return <K extends keyof typeof Reflect>(key: K, value: typeof Reflect[K]) => {
577-
if (typeof target[key] !== "function") {
578-
Object.defineProperty(target, key, { configurable: true, writable: true, value });
579-
}
577+
Object.defineProperty(target, key, { configurable: true, writable: true, value });
580578
if (previous) previous(key, value);
581579
};
582580
}
@@ -623,10 +621,12 @@ namespace Reflect {
623621

624622
// Load global or shim versions of Map, Set, and WeakMap
625623
const functionPrototype = Object.getPrototypeOf(Function);
626-
const usePolyfill = typeof process === "object" && process["env" + ""] && process["env" + ""]["REFLECT_METADATA_USE_MAP_POLYFILL"] === "true";
627-
const _Map: typeof Map = !usePolyfill && typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : CreateMapPolyfill();
628-
const _Set: typeof Set = !usePolyfill && typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : CreateSetPolyfill();
629-
const _WeakMap: typeof WeakMap = !usePolyfill && typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill();
624+
const _Map: typeof Map = typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : CreateMapPolyfill();
625+
const _Set: typeof Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : CreateSetPolyfill();
626+
const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill();
627+
const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined;
628+
const metadataRegistry = GetOrCreateMetadataRegistry();
629+
const metadataProvider = CreateMetadataProvider(metadataRegistry);
630630

631631
function decorate(decorators: ClassDecorator[], target: Function): Function;
632632
function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined;
@@ -1489,14 +1489,19 @@ namespace Reflect {
14891489
// - Allows `import "reflect-metadata"` and `import "reflect-metadata/no-conflict"` to interoperate.
14901490
// - Uses isolated metadata if `Reflect` is frozen before the registry can be installed.
14911491

1492-
const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined;
1493-
const metadataRegistry = GetOrCreateMetadataRegistry();
1494-
const metadataProvider = CreateMetadataProvider(metadataRegistry);
1495-
14961492
/**
14971493
* Creates a registry used to allow multiple `reflect-metadata` providers.
14981494
*/
14991495
function CreateMetadataRegistry(): MetadataRegistry {
1496+
let fallback: MetadataProvider | undefined;
1497+
if (!IsUndefined(registrySymbol) &&
1498+
typeof root.Reflect !== "undefined" &&
1499+
!(registrySymbol in root.Reflect) &&
1500+
typeof root.Reflect.defineMetadata === "function") {
1501+
// interoperate with older version of `reflect-metadata` that did not support a registry.
1502+
fallback = CreateFallbackProvider(root.Reflect);
1503+
}
1504+
15001505
let first: MetadataProvider | undefined;
15011506
let second: MetadataProvider | undefined;
15021507
let rest: Set<MetadataProvider> | undefined;
@@ -1513,6 +1518,7 @@ namespace Reflect {
15131518
throw new Error("Cannot add provider to a frozen registry.");
15141519
}
15151520
switch (true) {
1521+
case fallback === provider: break;
15161522
case IsUndefined(first): first = provider; break;
15171523
case first === provider: break;
15181524
case IsUndefined(second): second = provider; break;
@@ -1525,23 +1531,30 @@ namespace Reflect {
15251531
}
15261532

15271533
function getProviderNoCache(O: object, P: string | symbol | undefined) {
1528-
if (IsUndefined(first)) return undefined;
1529-
if (first.isProviderFor(O, P)) return first;
1530-
if (IsUndefined(second)) return undefined;
1531-
if (second.isProviderFor(O, P)) return first;
1532-
if (IsUndefined(rest)) return undefined;
1533-
const iterator = GetIterator(rest);
1534-
while (true) {
1535-
const next = IteratorStep(iterator);
1536-
if (!next) {
1537-
return undefined;
1538-
}
1539-
const provider = IteratorValue(next);
1540-
if (provider.isProviderFor(O, P)) {
1541-
IteratorClose(iterator);
1542-
return provider;
1534+
if (!IsUndefined(first)) {
1535+
if (first.isProviderFor(O, P)) return first;
1536+
if (!IsUndefined(second)) {
1537+
if (second.isProviderFor(O, P)) return first;
1538+
if (!IsUndefined(rest)) {
1539+
const iterator = GetIterator(rest);
1540+
while (true) {
1541+
const next = IteratorStep(iterator);
1542+
if (!next) {
1543+
return undefined;
1544+
}
1545+
const provider = IteratorValue(next);
1546+
if (provider.isProviderFor(O, P)) {
1547+
IteratorClose(iterator);
1548+
return provider;
1549+
}
1550+
}
1551+
}
15431552
}
15441553
}
1554+
if (!IsUndefined(fallback) && fallback.isProviderFor(O, P)) {
1555+
return fallback;
1556+
}
1557+
return undefined;
15451558
}
15461559

15471560
function getProvider(O: object, P: string | symbol | undefined) {
@@ -1566,6 +1579,7 @@ namespace Reflect {
15661579
}
15671580

15681581
function hasProvider(provider: MetadataProvider) {
1582+
if (IsUndefined(provider)) throw new TypeError();
15691583
return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider);
15701584
}
15711585

@@ -1730,6 +1744,33 @@ namespace Reflect {
17301744
}
17311745
}
17321746

1747+
function CreateFallbackProvider(reflect: typeof Reflect): MetadataProvider {
1748+
const metadataOwner = new _WeakMap<object, Set<string | symbol | undefined>>();
1749+
const provider: MetadataProvider = {
1750+
isProviderFor(O, P) {
1751+
let metadataPropertySet = metadataOwner.get(O);
1752+
if (!IsUndefined(metadataPropertySet)) {
1753+
return metadataPropertySet.has(P);
1754+
}
1755+
if (reflect.getOwnMetadataKeys(O, P!).length) {
1756+
if (IsUndefined(metadataPropertySet)) {
1757+
metadataPropertySet = new _Set();
1758+
metadataOwner.set(O, metadataPropertySet);
1759+
}
1760+
metadataPropertySet.add(P);
1761+
return true;
1762+
}
1763+
return false;
1764+
},
1765+
OrdinaryDefineOwnMetadata: reflect.defineMetadata,
1766+
OrdinaryHasOwnMetadata: reflect.hasOwnMetadata,
1767+
OrdinaryGetOwnMetadata: reflect.getOwnMetadata,
1768+
OrdinaryOwnMetadataKeys: reflect.getOwnMetadataKeys,
1769+
OrdinaryDeleteMetadata: reflect.deleteMetadata,
1770+
};
1771+
return provider;
1772+
}
1773+
17331774
function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: true): MetadataProvider;
17341775
function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: false): MetadataProvider | undefined;
17351776
/**

‎ReflectLite.ts

+74-31
Original file line numberDiff line numberDiff line change
@@ -554,20 +554,19 @@ namespace Reflect {
554554
sloppyModeThis();
555555

556556
let exporter = makeExporter(Reflect);
557-
if (typeof root.Reflect === "undefined") {
558-
root.Reflect = Reflect;
559-
}
560-
else {
557+
if (typeof root.Reflect !== "undefined") {
561558
exporter = makeExporter(root.Reflect, exporter);
562559
}
563560

564561
factory(exporter, root);
565562

563+
if (typeof root.Reflect === "undefined") {
564+
root.Reflect = Reflect;
565+
}
566+
566567
function makeExporter(target: typeof Reflect, previous?: <K extends keyof typeof Reflect>(key: K, value: typeof Reflect[K]) => void) {
567568
return <K extends keyof typeof Reflect>(key: K, value: typeof Reflect[K]) => {
568-
if (typeof target[key] !== "function") {
569-
Object.defineProperty(target, key, { configurable: true, writable: true, value });
570-
}
569+
Object.defineProperty(target, key, { configurable: true, writable: true, value });
571570
if (previous) previous(key, value);
572571
};
573572
}
@@ -595,6 +594,9 @@ namespace Reflect {
595594
const _Map: typeof Map = typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : fail("A valid Map constructor could not be found.");
596595
const _Set: typeof Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : fail("A valid Set constructor could not be found.");
597596
const _WeakMap: typeof WeakMap = typeof WeakMap === "function" ? WeakMap : fail("A valid WeakMap constructor could not be found.");
597+
const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined;
598+
const metadataRegistry = GetOrCreateMetadataRegistry();
599+
const metadataProvider = CreateMetadataProvider(metadataRegistry);
598600

599601
function decorate(decorators: ClassDecorator[], target: Function): Function;
600602
function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined;
@@ -1455,14 +1457,19 @@ namespace Reflect {
14551457
// - Allows `import "reflect-metadata"` and `import "reflect-metadata/no-conflict"` to interoperate.
14561458
// - Uses isolated metadata if `Reflect` is frozen before the registry can be installed.
14571459

1458-
const registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined;
1459-
const metadataRegistry = GetOrCreateMetadataRegistry();
1460-
const metadataProvider = CreateMetadataProvider(metadataRegistry);
1461-
14621460
/**
14631461
* Creates a registry used to allow multiple `reflect-metadata` providers.
14641462
*/
14651463
function CreateMetadataRegistry(): MetadataRegistry {
1464+
let fallback: MetadataProvider | undefined;
1465+
if (!IsUndefined(registrySymbol) &&
1466+
typeof root.Reflect !== "undefined" &&
1467+
!(registrySymbol in root.Reflect) &&
1468+
typeof root.Reflect.defineMetadata === "function") {
1469+
// interoperate with older version of `reflect-metadata` that did not support a registry.
1470+
fallback = CreateFallbackProvider(root.Reflect);
1471+
}
1472+
14661473
let first: MetadataProvider | undefined;
14671474
let second: MetadataProvider | undefined;
14681475
let rest: Set<MetadataProvider> | undefined;
@@ -1479,6 +1486,7 @@ namespace Reflect {
14791486
throw new Error("Cannot add provider to a frozen registry.");
14801487
}
14811488
switch (true) {
1489+
case fallback === provider: break;
14821490
case IsUndefined(first): first = provider; break;
14831491
case first === provider: break;
14841492
case IsUndefined(second): second = provider; break;
@@ -1489,27 +1497,34 @@ namespace Reflect {
14891497
break;
14901498
}
14911499
}
1492-
1500+
14931501
function getProviderNoCache(O: object, P: string | symbol | undefined) {
1494-
if (IsUndefined(first)) return undefined;
1495-
if (first.isProviderFor(O, P)) return first;
1496-
if (IsUndefined(second)) return undefined;
1497-
if (second.isProviderFor(O, P)) return first;
1498-
if (IsUndefined(rest)) return undefined;
1499-
const iterator = GetIterator(rest);
1500-
while (true) {
1501-
const next = IteratorStep(iterator);
1502-
if (!next) {
1503-
return undefined;
1504-
}
1505-
const provider = IteratorValue(next);
1506-
if (provider.isProviderFor(O, P)) {
1507-
IteratorClose(iterator);
1508-
return provider;
1502+
if (!IsUndefined(first)) {
1503+
if (first.isProviderFor(O, P)) return first;
1504+
if (!IsUndefined(second)) {
1505+
if (second.isProviderFor(O, P)) return first;
1506+
if (!IsUndefined(rest)) {
1507+
const iterator = GetIterator(rest);
1508+
while (true) {
1509+
const next = IteratorStep(iterator);
1510+
if (!next) {
1511+
return undefined;
1512+
}
1513+
const provider = IteratorValue(next);
1514+
if (provider.isProviderFor(O, P)) {
1515+
IteratorClose(iterator);
1516+
return provider;
1517+
}
1518+
}
1519+
}
15091520
}
15101521
}
1522+
if (!IsUndefined(fallback) && fallback.isProviderFor(O, P)) {
1523+
return fallback;
1524+
}
1525+
return undefined;
15111526
}
1512-
1527+
15131528
function getProvider(O: object, P: string | symbol | undefined) {
15141529
let providerMap = targetProviderMap.get(O);
15151530
let provider: MetadataProvider | undefined;
@@ -1519,7 +1534,7 @@ namespace Reflect {
15191534
if (!IsUndefined(provider)) {
15201535
return provider;
15211536
}
1522-
1537+
15231538
provider = getProviderNoCache(O, P);
15241539
if (!IsUndefined(provider)) {
15251540
if (IsUndefined(providerMap)) {
@@ -1530,11 +1545,12 @@ namespace Reflect {
15301545
}
15311546
return provider;
15321547
}
1533-
1548+
15341549
function hasProvider(provider: MetadataProvider) {
1550+
if (IsUndefined(provider)) throw new TypeError();
15351551
return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider);
15361552
}
1537-
1553+
15381554
function setProvider(O: object, P: string | symbol | undefined, provider: MetadataProvider) {
15391555
if (!hasProvider(provider)) {
15401556
throw new Error("Metadata provider not registered.");
@@ -1696,6 +1712,33 @@ namespace Reflect {
16961712
}
16971713
}
16981714

1715+
function CreateFallbackProvider(reflect: typeof Reflect): MetadataProvider {
1716+
const metadataOwner = new _WeakMap<object, Set<string | symbol | undefined>>();
1717+
const provider: MetadataProvider = {
1718+
isProviderFor(O, P) {
1719+
let metadataPropertySet = metadataOwner.get(O);
1720+
if (!IsUndefined(metadataPropertySet)) {
1721+
return metadataPropertySet.has(P);
1722+
}
1723+
if (reflect.getOwnMetadataKeys(O, P!).length) {
1724+
if (IsUndefined(metadataPropertySet)) {
1725+
metadataPropertySet = new _Set();
1726+
metadataOwner.set(O, metadataPropertySet);
1727+
}
1728+
metadataPropertySet.add(P);
1729+
return true;
1730+
}
1731+
return false;
1732+
},
1733+
OrdinaryDefineOwnMetadata: reflect.defineMetadata,
1734+
OrdinaryHasOwnMetadata: reflect.hasOwnMetadata,
1735+
OrdinaryGetOwnMetadata: reflect.getOwnMetadata,
1736+
OrdinaryOwnMetadataKeys: reflect.getOwnMetadataKeys,
1737+
OrdinaryDeleteMetadata: reflect.deleteMetadata,
1738+
};
1739+
return provider;
1740+
}
1741+
16991742
function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: true): MetadataProvider;
17001743
function GetMetadataProvider(O: object, P: string | symbol | undefined, Create: false): MetadataProvider | undefined;
17011744
/**

0 commit comments

Comments
 (0)
Please sign in to comment.