Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@agoric/marshal

Package Overview
Dependencies
Maintainers
5
Versions
156
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@agoric/marshal - npm Package Compare versions

Comparing version 0.5.1-dev-cdf58e6.0 to 0.5.1-dev-d49cd68.0

src/deeplyFulfilled.js

38

index.js

@@ -1,4 +0,12 @@

export { PASS_STYLE, isObject } from './src/helpers/passStyleHelpers.js';
export { getErrorConstructor } from './src/helpers/error.js';
export { mapIterable, filterIterable } from './src/helpers/iter-helpers.js';
export {
PASS_STYLE,
isObject,
assertChecker,
getTag,
hasOwnPropertyOf,
} from './src/helpers/passStyle-helpers.js';
export { getErrorConstructor, toPassableError } from './src/helpers/error.js';
export {
getInterfaceOf,

@@ -8,15 +16,21 @@ ALLOW_IMPLICIT_REMOTABLES,

export { passStyleOf, everyPassableChild } from './src/passStyleOf.js';
export {
nameForPassableSymbol,
passableSymbolForName,
} from './src/helpers/symbol.js';
export { passStyleOf, assertPassable } from './src/passStyleOf.js';
export { pureCopy, sameValueZero } from './src/pureCopy.js';
export { deeplyFulfilled } from './src/deeplyFulfilled.js';
export { makeTagged } from './src/makeTagged.js';
export { Remotable, Far, ToFarFunction } from './src/make-far.js';
export { QCLASS, makeMarshal } from './src/marshal.js';
export { stringify, parse } from './src/marshal-stringify.js';
// Works, but not yet used
// export { decodeToJustin } from './src/marshal-justin.js';
export { pureCopy, Remotable, Far, ToFarFunction } from './src/make-far.js';
export { stringify, parse } from './src/marshal-stringify.js';
export {
isStructure,
assertStructure,
sameStructure,
fulfillToStructure,
} from './src/structure.js';
export {
assertRecord,

@@ -28,2 +42,2 @@ assertCopyArray,

isCopyArray,
} from './src/assertPassStyleOf.js';
} from './src/typeGuards.js';
{
"name": "@agoric/marshal",
"version": "0.5.1-dev-cdf58e6.0+cdf58e6",
"version": "0.5.1-dev-d49cd68.0+d49cd68",
"description": "marshal",

@@ -15,4 +15,2 @@ "type": "module",

"test:xs": "exit 0",
"pretty-fix": "prettier --write '**/*.js'",
"pretty-check": "prettier --check '**/*.js'",
"lint-fix": "yarn lint:eslint --fix && yarn lint:types",

@@ -38,10 +36,9 @@ "lint-check": "yarn lint",

"dependencies": {
"@agoric/assert": "0.3.16-dev-cdf58e6.0+cdf58e6",
"@agoric/eventual-send": "0.14.1-dev-cdf58e6.0+cdf58e6",
"@agoric/eventual-send": "0.14.1-dev-d49cd68.0+d49cd68",
"@agoric/nat": "^4.1.0",
"@agoric/promise-kit": "0.2.30-dev-cdf58e6.0+cdf58e6"
"@agoric/promise-kit": "0.2.30-dev-d49cd68.0+d49cd68"
},
"devDependencies": {
"@agoric/lockdown": "0.1.2-dev-cdf58e6.0+cdf58e6",
"@endo/ses-ava": "^0.2.8",
"@endo/lockdown": "^0.1.2",
"@endo/ses-ava": "^0.2.14",
"ava": "^3.12.1",

@@ -60,6 +57,2 @@ "c8": "^7.7.2"

},
"prettier": {
"trailingComma": "all",
"singleQuote": true
},
"publishConfig": {

@@ -74,3 +67,3 @@ "access": "public"

},
"gitHead": "cdf58e696bca3e662d876212d86bad68b3e47c10"
"gitHead": "d49cd68cfa5b91437e1b6e912880842702bcb225"
}
/* eslint-disable no-use-before-define */
// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference types="ses"/>
import { assert, details as X } from '@agoric/assert';
import { E } from '@agoric/eventual-send';
import { isObject } from './helpers/passStyleHelpers.js';
import { isObject } from './helpers/passStyle-helpers.js';
import { getInterfaceOf } from './helpers/remotable.js';

@@ -17,2 +15,3 @@ import { Far } from './make-far.js';

const { ownKeys } = Reflect;
const { details: X } = assert;

@@ -19,0 +18,0 @@ const makeConverter = (mirrorConverter = undefined) => {

// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference types="ses"/>

@@ -8,4 +7,3 @@

import './internal-types.js';
import '@agoric/assert/exported.js';
import { assertChecker, checkNormalProperty } from './passStyleHelpers.js';
import { assertChecker, checkNormalProperty } from './passStyle-helpers.js';

@@ -48,9 +46,4 @@ const { details: X } = assert;

// Recursively validate that each member is passable.
CopyArrayHelper.every(candidate, v => !!passStyleOfRecur(v));
candidate.every(v => !!passStyleOfRecur(v));
},
every: (passable, fn) =>
// Note that we explicitly call `fn` with only the arguments we want
// to provide.
passable.every((v, i) => fn(v, i)),
});
// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference types="ses"/>

@@ -10,7 +9,6 @@

checkNormalProperty,
} from './passStyleHelpers.js';
} from './passStyle-helpers.js';
import '../types.js';
import './internal-types.js';
import '@agoric/assert/exported.js';

@@ -22,3 +20,2 @@ const { details: X } = assert;

getOwnPropertyDescriptors,
entries,
prototype: objectPrototype,

@@ -67,9 +64,4 @@ } = Object;

// Recursively validate that each member is passable.
CopyRecordHelper.every(candidate, v => !!passStyleOfRecur(v));
Object.values(candidate).every(v => !!passStyleOfRecur(v));
},
every: (passable, fn) =>
// Note that we explicitly call `fn` with only the arguments we want
// to provide.
entries(passable).every(([k, v]) => fn(v, k)),
});
// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference types="ses"/>

@@ -8,4 +7,3 @@

import './internal-types.js';
import '@agoric/assert/exported.js';
import { assertChecker } from './passStyleHelpers.js';
import { assertChecker } from './passStyle-helpers.js';

@@ -58,3 +56,3 @@ const { details: X } = assert;

const proto = getPrototypeOf(candidate);
const { name } = candidate;
const { name } = proto;
const EC = getErrorConstructor(name);

@@ -69,2 +67,3 @@ if (!EC || EC.prototype !== proto) {

const {
// Must allow `cause`, `errors`
message: mDesc,

@@ -101,4 +100,2 @@ // Allow but ignore only extraneous own `stack` property.

},
every: (_passable, _fn) => true,
});

@@ -105,0 +102,0 @@

// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference path="../extra-types.d.ts" />

@@ -30,8 +29,2 @@

* ) => void} assertValid
*
* @property {(passable: Passable,
* fn: (passable: Passable, index: any) => boolean
* ) => boolean} every
* For recuring through the nested passable structure. Like
* `Array.prototype.every`, return `false` to stop early.
*/
// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference types="ses"/>

@@ -8,3 +7,2 @@

import './internal-types.js';
import '@agoric/assert/exported.js';
import {

@@ -18,3 +16,3 @@ assertChecker,

getTag,
} from './passStyleHelpers.js';
} from './passStyle-helpers.js';
import { getEnvironmentOption } from './environment-options.js';

@@ -21,0 +19,0 @@

// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference types="ses"/>
import { assert, details as X, q } from '@agoric/assert';
import { assertChecker, PASS_STYLE } from './helpers/passStyleHelpers.js';
import { assertChecker, PASS_STYLE } from './helpers/passStyle-helpers.js';
import {

@@ -13,4 +11,6 @@ assertIface,

} from './helpers/remotable.js';
import { passStyleOf } from './passStyleOf.js';
import { pureCopy } from './pureCopy.js';
const { quote: q, details: X } = assert;
const { prototype: functionPrototype } = Function;

@@ -26,69 +26,2 @@ const {

/**
* Do a deep copy of the object, handling Proxies and recursion.
* The resulting copy is guaranteed to be pure data, as well as hardened.
* Such a hardened, pure copy cannot be used as a communications path.
*
* @template {OnlyData} T
* @param {T} val input value. NOTE: Must be hardened!
* @returns {T} pure, hardened copy
*/
export const pureCopy = val => {
// passStyleOf now asserts that val has no pass-by-copy cycles.
const passStyle = passStyleOf(val);
switch (passStyle) {
case 'bigint':
case 'boolean':
case 'null':
case 'number':
case 'string':
case 'undefined':
case 'symbol':
return val;
case 'copyArray':
case 'copyRecord': {
const obj = /** @type {Object} */ (val);
// Create a new identity.
const copy = /** @type {T} */ (passStyle === 'copyArray' ? [] : {});
// Make a deep copy on the new identity.
// Object.entries(obj) takes a snapshot (even if a Proxy).
// Since we already know it is a copyRecord or copyArray, we
// know that Object.entries is safe enough. On a copyRecord it
// will represent all the own properties. On a copyArray it
// will represent all the own properties except for the length.
Object.entries(obj).forEach(([prop, value]) => {
copy[prop] = pureCopy(value);
});
return harden(copy);
}
case 'error': {
assert.fail(X`Errors cannot be copied: ${val}`, TypeError);
}
case 'remotable': {
assert.fail(
X`Input value ${q(
passStyle,
)} cannot be copied as it must be passed by reference`,
TypeError,
);
}
case 'promise': {
assert.fail(X`Promises cannot be copied`, TypeError);
}
default:
assert.fail(
X`Input value ${q(passStyle)} is not recognized as data`,
TypeError,
);
}
};
harden(pureCopy);
/**
* Now that the remotableProto does not provide its own `toString` method,

@@ -95,0 +28,0 @@ * ensure it always inherits from something. The original prototype of

// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference types="ses"/>
import { Nat } from '@agoric/nat';
import { assert, details as X, q } from '@agoric/assert';
import { QCLASS } from './marshal.js';

@@ -12,3 +10,4 @@

import { getErrorConstructor } from './helpers/error.js';
import { isObject } from './helpers/passStyleHelpers.js';
import { isObject } from './helpers/passStyle-helpers.js';
import { AtAtPrefixPattern, passableSymbolForName } from './helpers/symbol.js';

@@ -18,2 +17,3 @@ const { ownKeys } = Reflect;

const { stringify: quote } = JSON;
const { quote: q, details: X } = assert;

@@ -170,20 +170,14 @@ /**

}
case 'error': {
const { name, message } = rawTree;
assert.typeof(
name,
'string',
X`invalid error name typeof ${q(typeof name)}`,
);
assert(
getErrorConstructor(name) !== undefined,
X`Must be the name of an Error constructor ${name}`,
);
assert.typeof(
message,
'string',
X`invalid error message typeof ${q(typeof message)}`,
);
case 'symbol': {
const { name } = rawTree;
const sym = passableSymbolForName(name);
assert.typeof(sym, 'symbol');
return;
}
case 'tagged': {
const { tag, payload } = rawTree;
assert.typeof(tag, 'string');
prepare(payload);
return;
}
case 'slot': {

@@ -230,2 +224,20 @@ const { index, iface } = rawTree;

}
case 'error': {
const { name, message } = rawTree;
assert.typeof(
name,
'string',
X`invalid error name typeof ${q(typeof name)}`,
);
assert(
getErrorConstructor(name) !== undefined,
X`Must be the name of an Error constructor ${name}`,
);
assert.typeof(
message,
'string',
X`invalid error message typeof ${q(typeof message)}`,
);
return;
}

@@ -322,9 +334,25 @@ default: {

case '@@asyncIterator': {
// TODO deprecated. Eventually remove.
return out.next('Symbol.asyncIterator');
}
case 'error': {
const { name, message } = rawTree;
return out.next(`${name}(${quote(message)})`);
case 'symbol': {
const { name } = rawTree;
const sym = passableSymbolForName(name);
assert.typeof(sym, 'symbol');
const registeredName = Symbol.keyFor(sym);
if (registeredName === undefined) {
const match = AtAtPrefixPattern.exec(name);
assert(match !== null);
const suffix = match[1];
assert(Symbol[suffix] === sym);
return out.next(`Symbol[${quote(suffix)}]`);
}
return out.next(`Symbol.for(${quote(registeredName)})`);
}
case 'tagged': {
const { tag, payload } = rawTree;
out.next(`makeTagged(${quote(tag)},`);
decode(payload);
return out.next(')');
}

@@ -353,2 +381,7 @@ case 'slot': {

case 'error': {
const { name, message } = rawTree;
return out.next(`${name}(${quote(message)})`);
}
default: {

@@ -355,0 +388,0 @@ assert.fail(X`unrecognized ${q(QCLASS)} ${q(qclass)}`, TypeError);

// @ts-check
/// <reference types="ses"/>
import { assert, details as X } from '@agoric/assert';
import { makeMarshal } from './marshal.js';

@@ -8,2 +8,4 @@

const { details: X } = assert;
/** @type {ConvertValToSlot<any>} */

@@ -10,0 +12,0 @@ const doNotConvertValToSlot = val =>

// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference types="ses"/>
import { Nat } from '@agoric/nat';
import { assert, details as X, q } from '@agoric/assert';
import { passStyleOf } from './passStyleOf.js';

@@ -13,3 +11,9 @@

import { ErrorHelper, getErrorConstructor } from './helpers/error.js';
import { isObject } from './helpers/passStyleHelpers.js';
import { makeTagged } from './makeTagged.js';
import { isObject, getTag } from './helpers/passStyle-helpers.js';
import {
assertPassableSymbol,
nameForPassableSymbol,
passableSymbolForName,
} from './helpers/symbol.js';

@@ -19,2 +23,3 @@ const { ownKeys } = Reflect;

const { getOwnPropertyDescriptors, defineProperties, is, fromEntries } = Object;
const { details: X, quote: q } = assert;

@@ -77,2 +82,3 @@ /**

if (slotMap.has(val)) {
// TODO assert that it's the same iface as before
slotIndex = slotMap.get(val);

@@ -89,2 +95,3 @@ assert.typeof(slotIndex, 'number');

// TODO explore removing this special case
if (iface === undefined) {

@@ -124,2 +131,4 @@ return harden({

marshalSaveError(err);
// Must encode `cause`, `errors`.
// nested non-passable errors must be ok from here.
return harden({

@@ -142,6 +151,5 @@ [QCLASS]: 'error',

* Must encode `val` into plain JSON data *canonically*, such that
* `sameStructure(v1, v2)` implies
* `JSON.stringify(encode(v1)) === JSON.stringify(encode(v2))`
* For each record, we only accept sortable property names
* (no anonymous symbols). On the encoded form the sort
* `JSON.stringify(encode(v1)) === JSON.stringify(encode(v1))`
* For each copyRecord, we only accept string property names,
* not symbols. The encoded form the sort
* order of these names must be the same as their enumeration

@@ -194,12 +202,17 @@ * order, so a `JSON.stringify` of the encoded form agrees with

case 'symbol': {
switch (val) {
case Symbol.asyncIterator: {
return harden({
[QCLASS]: '@@asyncIterator',
});
}
default: {
assert.fail(X`Unsupported symbol ${q(String(val))}`);
}
assertPassableSymbol(val);
const name = /** @type {string} */ (nameForPassableSymbol(val));
if (name === '@@asyncIterator') {
// Deprectated qclass. TODO make conditional
// on environment variable. Eventually remove, but only after
// confident that all supported receivers understand
// `[QCLASS]: 'symbol'`.
return harden({
[QCLASS]: '@@asyncIterator',
});
}
return harden({
[QCLASS]: 'symbol',
name,
});
}

@@ -236,4 +249,10 @@ case 'copyRecord': {

}
case 'error': {
return encodeError(val);
case 'tagged': {
/** @type {Encoding} */
const result = harden({
[QCLASS]: 'tagged',
tag: getTag(val),
payload: encode(val.payload),
});
return result;
}

@@ -245,2 +264,5 @@ case 'remotable': {

}
case 'error': {
return encodeError(val);
}
case 'promise': {

@@ -272,2 +294,4 @@ // console.log(`serializeSlot: ${val}`);

}
// TODO SECURITY HAZARD: must enfoce that remotable vs promise
// is according to the encoded string.
const slot = slots[Number(Nat(index))];

@@ -357,6 +381,19 @@ const val = convertSlotToVal(slot, iface);

case '@@asyncIterator': {
// Deprectated qclass. TODO make conditional
// on environment variable. Eventually remove, but after confident
// that there are no more supported senders.
return Symbol.asyncIterator;
}
case 'symbol': {
const { name } = rawTree;
return passableSymbolForName(name);
}
case 'tagged': {
const { tag, payload } = rawTree;
return makeTagged(tag, fullRevive(payload));
}
case 'error': {
// Must decode `cause` and `errors` properties
const { name, message, errorId } = rawTree;

@@ -379,2 +416,6 @@ assert.typeof(

: `Remote${EC.name}(${errorId})`;
// Due to a defect in the SES type definition, the next line is
// fails a type check.
// Pending https://github.com/endojs/endo/issues/977
// @ts-ignore-next-line
const error = assert.error(`${message}`, EC, { errorName });

@@ -381,0 +422,0 @@ return error;

// @ts-check
// eslint-disable-next-line spaced-comment
/// <reference types="ses"/>
import { isPromise } from '@agoric/promise-kit';
import { isObject, PASS_STYLE } from './helpers/passStyleHelpers.js';
import { isObject, PASS_STYLE } from './helpers/passStyle-helpers.js';
import { CopyArrayHelper } from './helpers/copyArray.js';
import { CopyRecordHelper } from './helpers/copyRecord.js';
import { TaggedHelper } from './helpers/tagged.js';
import { RemotableHelper } from './helpers/remotable.js';
import { ErrorHelper } from './helpers/error.js';
import { RemotableHelper } from './helpers/remotable.js';
import './types.js';
import './helpers/internal-types.js';
import { assertPassableSymbol } from './helpers/symbol.js';

@@ -29,5 +30,5 @@ const { details: X, quote: q } = assert;

* accidents.
* @returns {{passStyleOf: PassStyleOf, HelperTable: any}}
* @returns {PassStyleOf}
*/
const makePassStyleOfKit = passStyleHelpers => {
const makePassStyleOf = passStyleHelpers => {
const HelperTable = {

@@ -37,4 +38,5 @@ __proto__: null,

copyRecord: undefined,
tagged: undefined,
remotable: undefined,
error: undefined,
remotable: undefined,
};

@@ -119,6 +121,9 @@ for (const helper of passStyleHelpers) {

case 'number':
case 'bigint':
case 'symbol': {
case 'bigint': {
return typestr;
}
case 'symbol': {
assertPassableSymbol(inner);
return 'symbol';
}
case 'object': {

@@ -179,23 +184,16 @@ if (inner === null) {

};
return harden({ passStyleOf, HelperTable });
return harden(passStyleOf);
};
const { passStyleOf, HelperTable } = makePassStyleOfKit([
export const passStyleOf = makePassStyleOf([
CopyArrayHelper,
CopyRecordHelper,
TaggedHelper,
RemotableHelper,
ErrorHelper,
RemotableHelper,
]);
export { passStyleOf };
export const everyPassableChild = (passable, fn) => {
const passStyle = passStyleOf(passable);
const helper = HelperTable[passStyle];
if (helper) {
// everyPassable guards .every so that each helper only gets a
// genuine passable of its own flavor.
return helper.every(passable, fn);
}
return true;
export const assertPassable = val => {
passStyleOf(val); // throws if val is not a passable
};
harden(everyPassableChild);
harden(assertPassable);
// @ts-nocheck TODO Fix the recursive types to it checks. Will this
// require a .d.ts file? I don't know.
// eslint-disable-next-line spaced-comment
/// <reference path="extra-types.d.ts" />

@@ -9,4 +8,10 @@

* @typedef { "undefined" | "null" |
* "boolean" | "number" | "bigint" | "string" | "symbol" |
* "copyArray" | "copyRecord" | "remotable" |
* "boolean" | "number" | "bigint" | "string" | "symbol"
* } PrimitiveStyle
*/
/**
* @typedef { PrimitiveStyle |
* "copyRecord" | "copyArray" | "tagged" |
* "remotable" |
* "error" | "promise"

@@ -28,6 +33,6 @@ * } PassStyle

* "boolean" | "number" | "bigint" | "string" | "symbol"),
* * the pass-by-copy containers ("copyArray" | "copyRecord") that
* * the pass-by-copy containers
* ("copyRecord" | "copyArray" | "tagged") that
* contain other Passables,
* * and the special cases ("error" | "promise"), which
* also contain other Passables.
* * and the special cases ("error" | "promise").
*

@@ -48,14 +53,3 @@ * A Passable's pass-by-copy superstructure ends in

/**
* @typedef {Passable} Structure
*
* A Passable is a Structure when it contains only
* * pass-by-copy primitives,
* * pass-by-copy containers,
* * remotables.
*
* Two Structures may be compared by for equivalence according to
* `sameStructure`, which is the strongest equivalence class supported by
* marshal's distributed object semantics.
*
* Two Structures can also be compared for full ordering,
* Two Passables can also be compared for total rank ordering,
* * where their passStyles are ordered according to the

@@ -79,10 +73,5 @@ * PassStyle typedef above.

/**
* @deprecated Renamed to `Structure`
* @typedef {Structure} Comparable
*/
/**
* @typedef {Structure} OnlyData
* @typedef {Passable} OnlyData
*
* A Structure is OnlyData when its pass-by-copy superstructure has no
* A Passable is OnlyData when its pass-by-copy superstructure has no
* remotables, i.e., when all the leaves of the data structure tree are

@@ -115,11 +104,19 @@ * primitive data types or empty composites.

/**
* @typedef {Passable} CopySet
* @template T
* @typedef {T[]} CopyArray
*/
/**
* @typedef {Passable} CopyMap
* @template T
* @typedef {Record<string, T>} CopyRecord
*/
/**
* @typedef {Passable} PatternNode
* @typedef {{
* [PASS_STYLE]: 'tagged',
* [Symbol.toStringTag]: string,
* payload: Passable
* }} CopyTagged
*
* The tag is the value of the `[String.toStringTag]` property.
*/

@@ -156,2 +153,3 @@

* EncodingClass<'@@asyncIterator'> |
* EncodingClass<'symbol'> & { name: string } |
* EncodingClass<'error'> & { name: string,

@@ -163,10 +161,12 @@ * message: string,

* EncodingClass<'hilbert'> & { original: Encoding,
* rest?: Encoding }
* rest?: Encoding
* } |
* EncodingClass<'tagged'> & { tag: string,
* payload: Encoding
* }
* } EncodingUnion
*
* @typedef {{ [index: string]: Encoding,
* '@qclass'?: undefined }
* } EncodingRecord
* '@qclass'?: undefined
* }} EncodingRecord
* We exclude '@qclass' as a property in encoding records.
*
* @typedef {EncodingUnion | null | string |

@@ -256,3 +256,2 @@ * boolean | number | EncodingRecord

* Simple semantics, just tell what interface (or undefined) a remotable has.
*
* @param {*} maybeRemotable the value to check

@@ -279,3 +278,2 @@ * @returns {InterfaceSpec|undefined} the interface specification, or undefined

* See the various uses for good examples.
*
* @param {boolean} cond

@@ -282,0 +280,0 @@ * @param {Details=} details

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc