-
Notifications
You must be signed in to change notification settings - Fork 206
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: move allValues, zip to internal (#7075)
* refactor(internal): split utils between Jessie and extra-Jessie * refactor: move allValues, zip to internal - prune collect.js * docs: clarify not Jessie Co-authored-by: Turadg Aleahmad <[email protected]> --------- Co-authored-by: Turadg Aleahmad <[email protected]> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
- Loading branch information
1 parent
67b9128
commit b71d61c
Showing
11 changed files
with
144 additions
and
142 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// @ts-check | ||
import { isObject } from '@endo/marshal'; | ||
|
||
/** | ||
* @file method-tools use dynamic property lookup, which is not Jessie-compatible | ||
*/ | ||
|
||
const { getPrototypeOf, create, fromEntries, getOwnPropertyDescriptors } = | ||
Object; | ||
const { ownKeys, apply } = Reflect; | ||
|
||
/** @typedef {import('@endo/marshal/src/types').Remotable} Remotable */ | ||
|
||
/** | ||
* Prioritize symbols as earlier than strings. | ||
* | ||
* @param {string|symbol} a | ||
* @param {string|symbol} b | ||
* @returns {-1 | 0 | 1} | ||
*/ | ||
const compareStringified = (a, b) => { | ||
if (typeof a === typeof b) { | ||
const left = String(a); | ||
const right = String(b); | ||
// eslint-disable-next-line no-nested-ternary | ||
return left < right ? -1 : left > right ? 1 : 0; | ||
} | ||
if (typeof a === 'symbol') { | ||
assert(typeof b === 'string'); | ||
return -1; | ||
} | ||
assert(typeof a === 'string'); | ||
assert(typeof b === 'symbol'); | ||
return 1; | ||
}; | ||
|
||
/** | ||
* TODO Consolidate with the `getMethodNames` in `@endo/eventual-send` | ||
* | ||
* @param {any} val | ||
* @returns {(string|symbol)[]} | ||
*/ | ||
export const getMethodNames = val => { | ||
let layer = val; | ||
const names = new Set(); // Set to deduplicate | ||
while (layer !== null && layer !== Object.prototype) { | ||
// be tolerant of non-objects | ||
const descs = getOwnPropertyDescriptors(layer); | ||
for (const name of ownKeys(descs)) { | ||
// In case a method is overridden by a non-method, | ||
// test `val[name]` rather than `layer[name]` | ||
if (typeof val[name] === 'function') { | ||
names.add(name); | ||
} | ||
} | ||
if (!isObject(val)) { | ||
break; | ||
} | ||
layer = getPrototypeOf(layer); | ||
} | ||
return harden([...names].sort(compareStringified)); | ||
}; | ||
harden(getMethodNames); | ||
|
||
/** | ||
* TODO This function exists only to ease the | ||
* https://github.com/Agoric/agoric-sdk/pull/5970 transition, from all methods | ||
* being own properties to methods being inherited from a common prototype. | ||
* This transition breaks two patterns used in prior code: autobinding, | ||
* and enumerating methods by enumerating own properties. For both, the | ||
* preferred repairs are | ||
* * autobinding: Replace, for example, | ||
* `foo(obj.method)` with `foo(arg => `obj.method(arg))`. IOW, stop relying | ||
* on expressions like `obj.method` to extract a method still bound to the | ||
* state of `obj` because, for virtual and durable objects, | ||
* they no longer will after #5970. | ||
* * method enumeration: Replace, for example | ||
* `Reflect.ownKeys(obj)` with `getMethodNames(obj)`. | ||
* | ||
* Once all problematic cases have been converted in this manner, this | ||
* `bindAllMethods` hack can and TODO should be deleted. However, we currently | ||
* have no reliable static way to track down and fix all autobinding sites. | ||
* For those objects that have not yet been fully repaired by the above two | ||
* techniques, `bindAllMethods` creates an object that acts much like the | ||
* pre-#5970 objects, with all their methods as instance-bound own properties. | ||
* It does this by making a new object inheriting from `obj` where the new | ||
* object has bound own methods overridding all the methods it would have | ||
* inherited from `obj`. | ||
* | ||
* @param {Remotable} obj | ||
* @returns {Remotable} | ||
*/ | ||
export const bindAllMethods = obj => | ||
harden( | ||
create( | ||
obj, | ||
fromEntries( | ||
getMethodNames(obj).map(name => [ | ||
name, | ||
{ | ||
value: (/** @type {unknown[]} */ ...args) => | ||
apply(obj[name], obj, args), | ||
enumerable: true, | ||
}, | ||
]), | ||
), | ||
), | ||
); | ||
harden(bindAllMethods); |
Oops, something went wrong.