@agoric/transform-eventual-send
Advanced tools
Comparing version 1.0.3 to 1.1.0
'use strict'; | ||
var eventualSendBundle = {"source":"function getExport() { 'use strict'; let exports = {}; const module = { exports }; 'use strict';\n\n'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nfunction _interopDefault$1 (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\nvar harden = _interopDefault$1(require('@agoric/harden'));\n\n/* global */\n\nconst readOnlyProxy = {\n set(_target, _prop, _value) {\n return false;\n },\n isExtensible(_target) {\n return false;\n },\n setPrototypeOf(_target, _value) {\n return false;\n },\n deleteProperty(_target, _prop) {\n return false;\n },\n};\n\n/**\n * A Proxy handler for E(x).\n *\n * @param {*} x Any value passed to E(x)\n * @returns {ProxyHandler} the Proxy handler\n */\nfunction EProxyHandler(x, HandledPromise) {\n return harden({\n ...readOnlyProxy,\n get(_target, p, _receiver) {\n if (`${p}` !== p) {\n return undefined;\n }\n // Harden this Promise because it's our only opportunity to ensure\n // p1=E(x).foo() is hardened. The Handled Promise API does not (yet)\n // allow the handler to synchronously influence the promise returned\n // by the handled methods, so we must freeze it from the outside. See\n // #95 for details.\n return (...args) => harden(HandledPromise.applyMethod(x, p, args));\n },\n apply(_target, _thisArg, argArray = []) {\n return harden(HandledPromise.applyFunction(x, argArray));\n },\n has(_target, _p) {\n // We just pretend everything exists.\n return true;\n },\n });\n}\n\nfunction makeE(HandledPromise) {\n function E(x) {\n const handler = EProxyHandler(x, HandledPromise);\n return harden(new Proxy(() => {}, handler));\n }\n\n const makeEGetterProxy = x =>\n new Proxy(Object.create(null), {\n ...readOnlyProxy,\n has(_target, _prop) {\n return true;\n },\n get(_target, prop) {\n return HandledPromise.get(x, prop);\n },\n });\n\n E.G = makeEGetterProxy;\n E.resolve = HandledPromise.resolve;\n\n return harden(E);\n}\n\n/* global HandledPromise */\n\nconst { defineProperties, getOwnPropertyDescriptors } = Object;\n\n// 'E' and 'HandledPromise' are exports of the module\n\n// For now:\n// import { HandledPromise, E } from '@agoric/eventual-send';\n// ...\n\nconst hp =\n typeof HandledPromise === 'undefined'\n ? // eslint-disable-next-line no-use-before-define\n makeHandledPromise(Promise)\n : harden(HandledPromise);\nconst E = makeE(hp);\n\n// the following method (makeHandledPromise) is part\n// of the shim, and will not be exported by the module once the feature\n// becomes a part of standard javascript\n\n/**\n * Create a HandledPromise class to have it support eventual send\n * (wavy-dot) operations.\n *\n * Based heavily on nanoq\n * https://github.com/drses/nanoq/blob/master/src/nanoq.js\n *\n * Original spec for the infix-bang (predecessor to wavy-dot) desugaring:\n * https://web.archive.org/web/20161026162206/http://wiki.ecmascript.org/doku.php?id=strawman:concurrency\n *\n * @return {typeof HandledPromise} Handled promise\n */\nfunction makeHandledPromise(Promise) {\n // xs doesn't support WeakMap in pre-loaded closures\n // aka \"vetted customization code\"\n let presenceToHandler;\n let presenceToPromise;\n let promiseToHandler;\n function ensureMaps() {\n if (!presenceToHandler) {\n presenceToHandler = new WeakMap();\n presenceToPromise = new WeakMap();\n promiseToHandler = new WeakMap();\n }\n }\n\n // This special handler accepts Promises, and forwards\n // handled Promises to their corresponding fulfilledHandler.\n let forwardingHandler;\n let handle;\n let handledPromiseResolve;\n\n function HandledPromise(executor, unfulfilledHandler = undefined) {\n if (new.target === undefined) {\n throw new Error('must be invoked with \"new\"');\n }\n let handledResolve;\n let handledReject;\n let fulfilled = false;\n const superExecutor = (resolve, reject) => {\n handledResolve = value => {\n fulfilled = true;\n resolve(value);\n };\n handledReject = err => {\n fulfilled = true;\n reject(err);\n };\n };\n const handledP = harden(\n Reflect.construct(Promise, [superExecutor], new.target),\n );\n\n ensureMaps();\n let continueForwarding = () => {};\n\n if (!unfulfilledHandler) {\n // Create a simple unfulfilledHandler that just postpones until the\n // fulfilledHandler is set.\n //\n // This is insufficient for actual remote handled Promises\n // (too many round-trips), but is an easy way to create a\n // local handled Promise.\n const interlockP = new Promise((resolve, reject) => {\n continueForwarding = (err = null, targetP = undefined) => {\n if (err !== null) {\n reject(err);\n return;\n }\n // Box the target promise so that it isn't further resolved.\n resolve([targetP]);\n // Return undefined.\n };\n });\n\n const makePostponed = postponedOperation => {\n // Just wait until the handler is resolved/rejected.\n return function postpone(x, ...args) {\n // console.log(`forwarding ${postponedOperation} ${args[0]}`);\n return new HandledPromise((resolve, reject) => {\n interlockP\n .then(([targetP]) => {\n // If targetP is a handled promise, use it, otherwise x.\n const nextPromise = targetP || x;\n resolve(\n HandledPromise[postponedOperation](nextPromise, ...args),\n );\n })\n .catch(reject);\n });\n };\n };\n\n unfulfilledHandler = {\n get: makePostponed('get'),\n applyMethod: makePostponed('applyMethod'),\n };\n }\n\n const validateHandler = h => {\n if (Object(h) !== h) {\n throw TypeError(`Handler ${h} cannot be a primitive`);\n }\n };\n validateHandler(unfulfilledHandler);\n\n // Until the handled promise is resolved, we use the unfulfilledHandler.\n promiseToHandler.set(handledP, unfulfilledHandler);\n\n const rejectHandled = reason => {\n if (fulfilled) {\n return;\n }\n handledReject(reason);\n continueForwarding(reason);\n };\n\n let resolvedPresence = null;\n const resolveWithPresence = presenceHandler => {\n if (fulfilled) {\n return resolvedPresence;\n }\n try {\n // Sanity checks.\n validateHandler(presenceHandler);\n\n // Validate and install our mapped target (i.e. presence).\n resolvedPresence = Object.create(null);\n\n // Create table entries for the presence mapped to the\n // fulfilledHandler.\n presenceToPromise.set(resolvedPresence, handledP);\n presenceToHandler.set(resolvedPresence, presenceHandler);\n\n // Remove the mapping, as our presenceHandler should be\n // used instead.\n promiseToHandler.delete(handledP);\n\n // We committed to this presence, so resolve.\n handledResolve(resolvedPresence);\n continueForwarding();\n return resolvedPresence;\n } catch (e) {\n handledReject(e);\n continueForwarding();\n throw e;\n }\n };\n\n const resolveHandled = async (target, deprecatedPresenceHandler) => {\n if (fulfilled) {\n return undefined;\n }\n try {\n if (deprecatedPresenceHandler) {\n throw TypeError(\n `resolveHandled no longer accepts a handler; use resolveWithPresence`,\n );\n }\n\n // Resolve with the target when it's ready.\n handledResolve(target);\n\n const existingUnfulfilledHandler = promiseToHandler.get(target);\n if (existingUnfulfilledHandler) {\n // Reuse the unfulfilled handler.\n promiseToHandler.set(handledP, existingUnfulfilledHandler);\n return continueForwarding(null, target);\n }\n\n // See if the target is a presence we already know of.\n const presence = await target;\n const existingPresenceHandler = presenceToHandler.get(presence);\n if (existingPresenceHandler) {\n promiseToHandler.set(handledP, existingPresenceHandler);\n return continueForwarding(null, handledP);\n }\n\n // Remove the mapping, as we don't need a handler.\n promiseToHandler.delete(handledP);\n return continueForwarding();\n } catch (e) {\n handledReject(e);\n }\n return continueForwarding();\n };\n\n // Invoke the callback to let the user resolve/reject.\n executor(\n (...args) => {\n resolveHandled(...args);\n },\n rejectHandled,\n resolveWithPresence,\n );\n return handledP;\n }\n\n HandledPromise.prototype = Promise.prototype;\n\n // Uncomment this line if needed for conformance to the proposal.\n // Currently the proposal does not specify this, but we might change\n // our mind.\n // Object.setPrototypeOf(HandledPromise, Promise);\n\n const staticMethods = harden({\n get(target, key) {\n return handle(target, 'get', key);\n },\n getSendOnly(target, key) {\n handle(target, 'get', key);\n },\n applyFunction(target, args) {\n return handle(target, 'applyMethod', undefined, args);\n },\n applyFunctionSendOnly(target, args) {\n handle(target, 'applyMethod', undefined, args);\n },\n applyMethod(target, key, args) {\n return handle(target, 'applyMethod', key, args);\n },\n applyMethodSendOnly(target, key, args) {\n handle(target, 'applyMethod', key, args);\n },\n resolve(value) {\n ensureMaps();\n // Resolving a Presence returns the pre-registered handled promise.\n const handledPromise = presenceToPromise.get(value);\n if (handledPromise) {\n return handledPromise;\n }\n const basePromise = Promise.resolve(value);\n if (basePromise === value) {\n return value;\n }\n return handledPromiseResolve(value);\n },\n });\n\n defineProperties(HandledPromise, getOwnPropertyDescriptors(staticMethods));\n\n function makeForwarder(operation, localImpl) {\n return (o, ...args) => {\n // We are in another turn already, and have the naked object.\n const fulfilledHandler = presenceToHandler.get(o);\n if (\n fulfilledHandler &&\n typeof fulfilledHandler[operation] === 'function'\n ) {\n // The handler was resolved, so use it.\n return fulfilledHandler[operation](o, ...args);\n }\n\n // Not handled, so use the local implementation.\n return localImpl(o, ...args);\n };\n }\n\n // eslint-disable-next-line prefer-const\n forwardingHandler = {\n get: makeForwarder('get', (o, key) => o[key]),\n applyMethod: makeForwarder('applyMethod', (o, optKey, args) => {\n if (optKey === undefined || optKey === null) {\n return o(...args);\n }\n // console.log(`sending`, optKey, o[optKey], o);\n if (typeof o[optKey] !== 'function') {\n throw TypeError(`o[${JSON.stringify(optKey)}] is not a function`);\n }\n return o[optKey](...args);\n }),\n };\n\n handle = (p, operation, ...args) => {\n ensureMaps();\n const unfulfilledHandler = promiseToHandler.get(p);\n let executor;\n if (\n unfulfilledHandler &&\n typeof unfulfilledHandler[operation] === 'function'\n ) {\n executor = (resolve, reject) => {\n // We run in a future turn to prevent synchronous attacks,\n HandledPromise.resolve()\n .then(() =>\n // and resolve to the answer from the specific unfulfilled handler,\n resolve(unfulfilledHandler[operation](p, ...args)),\n )\n .catch(reject);\n };\n } else {\n executor = (resolve, reject) => {\n // We run in a future turn to prevent synchronous attacks,\n HandledPromise.resolve(p)\n .then(o => {\n // We now have the naked object,\n if (typeof forwardingHandler[operation] !== 'function') {\n throw TypeError(\n `forwardingHandler.${operation} is not a function`,\n );\n }\n // and resolve to the forwardingHandler's operation.\n resolve(forwardingHandler[operation](o, ...args));\n })\n .catch(reject);\n };\n }\n\n // We return a handled promise with the default unfulfilled handler.\n // This prevents a race between the above Promise.resolves and\n // pipelining.\n return new HandledPromise(executor);\n };\n\n handledPromiseResolve = Promise.resolve.bind(HandledPromise);\n return harden(HandledPromise);\n}\n\nexports.E = E;\nexports.HandledPromise = hp;\nexports.makeHandledPromise = makeHandledPromise;\n\n\nreturn module.exports;\n}\n","sourceMap":"//# sourceURL=/home/ubuntu/agoric-sdk/packages/eventual-send/dist/eventual-send.cjs.js\n","moduleFormat":"getExport"}; | ||
function makeEventualSendTransformer(parser, generate) { | ||
let HandledPromise; | ||
let evaluateProgram; | ||
let myRequire; | ||
let recursive = false; | ||
const transform = { | ||
closeOverSES(s) { | ||
// FIXME: This will go away when we can bundle an @agoric/harden that understands SES. | ||
myRequire = name => { | ||
if (name === '@agoric/harden') { | ||
return s.global.SES.harden; | ||
} | ||
throw Error(`Unrecognized require ${name}`); | ||
}; | ||
// FIXME: This should be replaced with ss.evaluateProgram support in SES. | ||
evaluateProgram = (src, endowments = {}) => s.evaluate(src, endowments); | ||
}, | ||
rewrite(ss) { | ||
const source = ss.src; | ||
const endowments = ss.endowments || {}; | ||
if (!recursive && !('HandledPromise' in endowments)) { | ||
// Use a getter to postpone initialization. | ||
Object.defineProperty(endowments, 'HandledPromise', { | ||
get() { | ||
if (!HandledPromise) { | ||
// Get a HandledPromise endowment for the evaluator. | ||
// It will be hardened in the evaluator's context. | ||
const { source: evSendSrc, moduleFormat } = eventualSendBundle; | ||
if (moduleFormat === 'getExport') { | ||
recursive = true; | ||
try { | ||
const ns = (evaluateProgram || ss.evaluateProgram)( | ||
`(${evSendSrc})()`, | ||
{ require: myRequire || require }, | ||
); | ||
HandledPromise = ns.HandledPromise; | ||
} finally { | ||
recursive = false; | ||
} | ||
} else { | ||
throw Error(`Unrecognized moduleFormat ${moduleFormat}`); | ||
} | ||
} | ||
return HandledPromise; | ||
}, | ||
}); | ||
} | ||
// Parse with eventualSend enabled, rewriting to | ||
// HandledPromise.got/set/apply/applyMethod/delete(...) | ||
const source = ss.src; | ||
// HandledPromise.get/applyFunction/applyMethod(...) | ||
const parseFunc = parser.parse; | ||
@@ -28,2 +74,3 @@ const ast = (parseFunc || parser)(source, { | ||
ast, | ||
endowments, | ||
src: actualSource, | ||
@@ -30,0 +77,0 @@ }; |
@@ -0,7 +1,53 @@ | ||
var eventualSendBundle = {"source":"function getExport() { 'use strict'; let exports = {}; const module = { exports }; 'use strict';\n\n'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nfunction _interopDefault$1 (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\nvar harden = _interopDefault$1(require('@agoric/harden'));\n\n/* global */\n\nconst readOnlyProxy = {\n set(_target, _prop, _value) {\n return false;\n },\n isExtensible(_target) {\n return false;\n },\n setPrototypeOf(_target, _value) {\n return false;\n },\n deleteProperty(_target, _prop) {\n return false;\n },\n};\n\n/**\n * A Proxy handler for E(x).\n *\n * @param {*} x Any value passed to E(x)\n * @returns {ProxyHandler} the Proxy handler\n */\nfunction EProxyHandler(x, HandledPromise) {\n return harden({\n ...readOnlyProxy,\n get(_target, p, _receiver) {\n if (`${p}` !== p) {\n return undefined;\n }\n // Harden this Promise because it's our only opportunity to ensure\n // p1=E(x).foo() is hardened. The Handled Promise API does not (yet)\n // allow the handler to synchronously influence the promise returned\n // by the handled methods, so we must freeze it from the outside. See\n // #95 for details.\n return (...args) => harden(HandledPromise.applyMethod(x, p, args));\n },\n apply(_target, _thisArg, argArray = []) {\n return harden(HandledPromise.applyFunction(x, argArray));\n },\n has(_target, _p) {\n // We just pretend everything exists.\n return true;\n },\n });\n}\n\nfunction makeE(HandledPromise) {\n function E(x) {\n const handler = EProxyHandler(x, HandledPromise);\n return harden(new Proxy(() => {}, handler));\n }\n\n const makeEGetterProxy = x =>\n new Proxy(Object.create(null), {\n ...readOnlyProxy,\n has(_target, _prop) {\n return true;\n },\n get(_target, prop) {\n return HandledPromise.get(x, prop);\n },\n });\n\n E.G = makeEGetterProxy;\n E.resolve = HandledPromise.resolve;\n\n return harden(E);\n}\n\n/* global HandledPromise */\n\nconst { defineProperties, getOwnPropertyDescriptors } = Object;\n\n// 'E' and 'HandledPromise' are exports of the module\n\n// For now:\n// import { HandledPromise, E } from '@agoric/eventual-send';\n// ...\n\nconst hp =\n typeof HandledPromise === 'undefined'\n ? // eslint-disable-next-line no-use-before-define\n makeHandledPromise(Promise)\n : harden(HandledPromise);\nconst E = makeE(hp);\n\n// the following method (makeHandledPromise) is part\n// of the shim, and will not be exported by the module once the feature\n// becomes a part of standard javascript\n\n/**\n * Create a HandledPromise class to have it support eventual send\n * (wavy-dot) operations.\n *\n * Based heavily on nanoq\n * https://github.com/drses/nanoq/blob/master/src/nanoq.js\n *\n * Original spec for the infix-bang (predecessor to wavy-dot) desugaring:\n * https://web.archive.org/web/20161026162206/http://wiki.ecmascript.org/doku.php?id=strawman:concurrency\n *\n * @return {typeof HandledPromise} Handled promise\n */\nfunction makeHandledPromise(Promise) {\n // xs doesn't support WeakMap in pre-loaded closures\n // aka \"vetted customization code\"\n let presenceToHandler;\n let presenceToPromise;\n let promiseToHandler;\n function ensureMaps() {\n if (!presenceToHandler) {\n presenceToHandler = new WeakMap();\n presenceToPromise = new WeakMap();\n promiseToHandler = new WeakMap();\n }\n }\n\n // This special handler accepts Promises, and forwards\n // handled Promises to their corresponding fulfilledHandler.\n let forwardingHandler;\n let handle;\n let handledPromiseResolve;\n\n function HandledPromise(executor, unfulfilledHandler = undefined) {\n if (new.target === undefined) {\n throw new Error('must be invoked with \"new\"');\n }\n let handledResolve;\n let handledReject;\n let fulfilled = false;\n const superExecutor = (resolve, reject) => {\n handledResolve = value => {\n fulfilled = true;\n resolve(value);\n };\n handledReject = err => {\n fulfilled = true;\n reject(err);\n };\n };\n const handledP = harden(\n Reflect.construct(Promise, [superExecutor], new.target),\n );\n\n ensureMaps();\n let continueForwarding = () => {};\n\n if (!unfulfilledHandler) {\n // Create a simple unfulfilledHandler that just postpones until the\n // fulfilledHandler is set.\n //\n // This is insufficient for actual remote handled Promises\n // (too many round-trips), but is an easy way to create a\n // local handled Promise.\n const interlockP = new Promise((resolve, reject) => {\n continueForwarding = (err = null, targetP = undefined) => {\n if (err !== null) {\n reject(err);\n return;\n }\n // Box the target promise so that it isn't further resolved.\n resolve([targetP]);\n // Return undefined.\n };\n });\n\n const makePostponed = postponedOperation => {\n // Just wait until the handler is resolved/rejected.\n return function postpone(x, ...args) {\n // console.log(`forwarding ${postponedOperation} ${args[0]}`);\n return new HandledPromise((resolve, reject) => {\n interlockP\n .then(([targetP]) => {\n // If targetP is a handled promise, use it, otherwise x.\n const nextPromise = targetP || x;\n resolve(\n HandledPromise[postponedOperation](nextPromise, ...args),\n );\n })\n .catch(reject);\n });\n };\n };\n\n unfulfilledHandler = {\n get: makePostponed('get'),\n applyMethod: makePostponed('applyMethod'),\n };\n }\n\n const validateHandler = h => {\n if (Object(h) !== h) {\n throw TypeError(`Handler ${h} cannot be a primitive`);\n }\n };\n validateHandler(unfulfilledHandler);\n\n // Until the handled promise is resolved, we use the unfulfilledHandler.\n promiseToHandler.set(handledP, unfulfilledHandler);\n\n const rejectHandled = reason => {\n if (fulfilled) {\n return;\n }\n handledReject(reason);\n continueForwarding(reason);\n };\n\n let resolvedPresence = null;\n const resolveWithPresence = presenceHandler => {\n if (fulfilled) {\n return resolvedPresence;\n }\n try {\n // Sanity checks.\n validateHandler(presenceHandler);\n\n // Validate and install our mapped target (i.e. presence).\n resolvedPresence = Object.create(null);\n\n // Create table entries for the presence mapped to the\n // fulfilledHandler.\n presenceToPromise.set(resolvedPresence, handledP);\n presenceToHandler.set(resolvedPresence, presenceHandler);\n\n // Remove the mapping, as our presenceHandler should be\n // used instead.\n promiseToHandler.delete(handledP);\n\n // We committed to this presence, so resolve.\n handledResolve(resolvedPresence);\n continueForwarding();\n return resolvedPresence;\n } catch (e) {\n handledReject(e);\n continueForwarding();\n throw e;\n }\n };\n\n const resolveHandled = async (target, deprecatedPresenceHandler) => {\n if (fulfilled) {\n return undefined;\n }\n try {\n if (deprecatedPresenceHandler) {\n throw TypeError(\n `resolveHandled no longer accepts a handler; use resolveWithPresence`,\n );\n }\n\n // Resolve with the target when it's ready.\n handledResolve(target);\n\n const existingUnfulfilledHandler = promiseToHandler.get(target);\n if (existingUnfulfilledHandler) {\n // Reuse the unfulfilled handler.\n promiseToHandler.set(handledP, existingUnfulfilledHandler);\n return continueForwarding(null, target);\n }\n\n // See if the target is a presence we already know of.\n const presence = await target;\n const existingPresenceHandler = presenceToHandler.get(presence);\n if (existingPresenceHandler) {\n promiseToHandler.set(handledP, existingPresenceHandler);\n return continueForwarding(null, handledP);\n }\n\n // Remove the mapping, as we don't need a handler.\n promiseToHandler.delete(handledP);\n return continueForwarding();\n } catch (e) {\n handledReject(e);\n }\n return continueForwarding();\n };\n\n // Invoke the callback to let the user resolve/reject.\n executor(\n (...args) => {\n resolveHandled(...args);\n },\n rejectHandled,\n resolveWithPresence,\n );\n return handledP;\n }\n\n HandledPromise.prototype = Promise.prototype;\n\n // Uncomment this line if needed for conformance to the proposal.\n // Currently the proposal does not specify this, but we might change\n // our mind.\n // Object.setPrototypeOf(HandledPromise, Promise);\n\n const staticMethods = harden({\n get(target, key) {\n return handle(target, 'get', key);\n },\n getSendOnly(target, key) {\n handle(target, 'get', key);\n },\n applyFunction(target, args) {\n return handle(target, 'applyMethod', undefined, args);\n },\n applyFunctionSendOnly(target, args) {\n handle(target, 'applyMethod', undefined, args);\n },\n applyMethod(target, key, args) {\n return handle(target, 'applyMethod', key, args);\n },\n applyMethodSendOnly(target, key, args) {\n handle(target, 'applyMethod', key, args);\n },\n resolve(value) {\n ensureMaps();\n // Resolving a Presence returns the pre-registered handled promise.\n const handledPromise = presenceToPromise.get(value);\n if (handledPromise) {\n return handledPromise;\n }\n const basePromise = Promise.resolve(value);\n if (basePromise === value) {\n return value;\n }\n return handledPromiseResolve(value);\n },\n });\n\n defineProperties(HandledPromise, getOwnPropertyDescriptors(staticMethods));\n\n function makeForwarder(operation, localImpl) {\n return (o, ...args) => {\n // We are in another turn already, and have the naked object.\n const fulfilledHandler = presenceToHandler.get(o);\n if (\n fulfilledHandler &&\n typeof fulfilledHandler[operation] === 'function'\n ) {\n // The handler was resolved, so use it.\n return fulfilledHandler[operation](o, ...args);\n }\n\n // Not handled, so use the local implementation.\n return localImpl(o, ...args);\n };\n }\n\n // eslint-disable-next-line prefer-const\n forwardingHandler = {\n get: makeForwarder('get', (o, key) => o[key]),\n applyMethod: makeForwarder('applyMethod', (o, optKey, args) => {\n if (optKey === undefined || optKey === null) {\n return o(...args);\n }\n // console.log(`sending`, optKey, o[optKey], o);\n if (typeof o[optKey] !== 'function') {\n throw TypeError(`o[${JSON.stringify(optKey)}] is not a function`);\n }\n return o[optKey](...args);\n }),\n };\n\n handle = (p, operation, ...args) => {\n ensureMaps();\n const unfulfilledHandler = promiseToHandler.get(p);\n let executor;\n if (\n unfulfilledHandler &&\n typeof unfulfilledHandler[operation] === 'function'\n ) {\n executor = (resolve, reject) => {\n // We run in a future turn to prevent synchronous attacks,\n HandledPromise.resolve()\n .then(() =>\n // and resolve to the answer from the specific unfulfilled handler,\n resolve(unfulfilledHandler[operation](p, ...args)),\n )\n .catch(reject);\n };\n } else {\n executor = (resolve, reject) => {\n // We run in a future turn to prevent synchronous attacks,\n HandledPromise.resolve(p)\n .then(o => {\n // We now have the naked object,\n if (typeof forwardingHandler[operation] !== 'function') {\n throw TypeError(\n `forwardingHandler.${operation} is not a function`,\n );\n }\n // and resolve to the forwardingHandler's operation.\n resolve(forwardingHandler[operation](o, ...args));\n })\n .catch(reject);\n };\n }\n\n // We return a handled promise with the default unfulfilled handler.\n // This prevents a race between the above Promise.resolves and\n // pipelining.\n return new HandledPromise(executor);\n };\n\n handledPromiseResolve = Promise.resolve.bind(HandledPromise);\n return harden(HandledPromise);\n}\n\nexports.E = E;\nexports.HandledPromise = hp;\nexports.makeHandledPromise = makeHandledPromise;\n\n\nreturn module.exports;\n}\n","sourceMap":"//# sourceURL=/home/ubuntu/agoric-sdk/packages/eventual-send/dist/eventual-send.cjs.js\n","moduleFormat":"getExport"}; | ||
function makeEventualSendTransformer(parser, generate) { | ||
let HandledPromise; | ||
let evaluateProgram; | ||
let myRequire; | ||
let recursive = false; | ||
const transform = { | ||
closeOverSES(s) { | ||
// FIXME: This will go away when we can bundle an @agoric/harden that understands SES. | ||
myRequire = name => { | ||
if (name === '@agoric/harden') { | ||
return s.global.SES.harden; | ||
} | ||
throw Error(`Unrecognized require ${name}`); | ||
}; | ||
// FIXME: This should be replaced with ss.evaluateProgram support in SES. | ||
evaluateProgram = (src, endowments = {}) => s.evaluate(src, endowments); | ||
}, | ||
rewrite(ss) { | ||
const source = ss.src; | ||
const endowments = ss.endowments || {}; | ||
if (!recursive && !('HandledPromise' in endowments)) { | ||
// Use a getter to postpone initialization. | ||
Object.defineProperty(endowments, 'HandledPromise', { | ||
get() { | ||
if (!HandledPromise) { | ||
// Get a HandledPromise endowment for the evaluator. | ||
// It will be hardened in the evaluator's context. | ||
const { source: evSendSrc, moduleFormat } = eventualSendBundle; | ||
if (moduleFormat === 'getExport') { | ||
recursive = true; | ||
try { | ||
const ns = (evaluateProgram || ss.evaluateProgram)( | ||
`(${evSendSrc})()`, | ||
{ require: myRequire || require }, | ||
); | ||
HandledPromise = ns.HandledPromise; | ||
} finally { | ||
recursive = false; | ||
} | ||
} else { | ||
throw Error(`Unrecognized moduleFormat ${moduleFormat}`); | ||
} | ||
} | ||
return HandledPromise; | ||
}, | ||
}); | ||
} | ||
// Parse with eventualSend enabled, rewriting to | ||
// HandledPromise.got/set/apply/applyMethod/delete(...) | ||
const source = ss.src; | ||
// HandledPromise.get/applyFunction/applyMethod(...) | ||
const parseFunc = parser.parse; | ||
@@ -26,2 +72,3 @@ const ast = (parseFunc || parser)(source, { | ||
ast, | ||
endowments, | ||
src: actualSource, | ||
@@ -28,0 +75,0 @@ }; |
@@ -5,10 +5,56 @@ (function (global, factory) { | ||
(global = global || self, global.makeEventalSendTransformer = factory()); | ||
}(this, function () { 'use strict'; | ||
}(this, (function () { 'use strict'; | ||
var eventualSendBundle = {"source":"function getExport() { 'use strict'; let exports = {}; const module = { exports }; 'use strict';\n\n'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nfunction _interopDefault$1 (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\nvar harden = _interopDefault$1(require('@agoric/harden'));\n\n/* global */\n\nconst readOnlyProxy = {\n set(_target, _prop, _value) {\n return false;\n },\n isExtensible(_target) {\n return false;\n },\n setPrototypeOf(_target, _value) {\n return false;\n },\n deleteProperty(_target, _prop) {\n return false;\n },\n};\n\n/**\n * A Proxy handler for E(x).\n *\n * @param {*} x Any value passed to E(x)\n * @returns {ProxyHandler} the Proxy handler\n */\nfunction EProxyHandler(x, HandledPromise) {\n return harden({\n ...readOnlyProxy,\n get(_target, p, _receiver) {\n if (`${p}` !== p) {\n return undefined;\n }\n // Harden this Promise because it's our only opportunity to ensure\n // p1=E(x).foo() is hardened. The Handled Promise API does not (yet)\n // allow the handler to synchronously influence the promise returned\n // by the handled methods, so we must freeze it from the outside. See\n // #95 for details.\n return (...args) => harden(HandledPromise.applyMethod(x, p, args));\n },\n apply(_target, _thisArg, argArray = []) {\n return harden(HandledPromise.applyFunction(x, argArray));\n },\n has(_target, _p) {\n // We just pretend everything exists.\n return true;\n },\n });\n}\n\nfunction makeE(HandledPromise) {\n function E(x) {\n const handler = EProxyHandler(x, HandledPromise);\n return harden(new Proxy(() => {}, handler));\n }\n\n const makeEGetterProxy = x =>\n new Proxy(Object.create(null), {\n ...readOnlyProxy,\n has(_target, _prop) {\n return true;\n },\n get(_target, prop) {\n return HandledPromise.get(x, prop);\n },\n });\n\n E.G = makeEGetterProxy;\n E.resolve = HandledPromise.resolve;\n\n return harden(E);\n}\n\n/* global HandledPromise */\n\nconst { defineProperties, getOwnPropertyDescriptors } = Object;\n\n// 'E' and 'HandledPromise' are exports of the module\n\n// For now:\n// import { HandledPromise, E } from '@agoric/eventual-send';\n// ...\n\nconst hp =\n typeof HandledPromise === 'undefined'\n ? // eslint-disable-next-line no-use-before-define\n makeHandledPromise(Promise)\n : harden(HandledPromise);\nconst E = makeE(hp);\n\n// the following method (makeHandledPromise) is part\n// of the shim, and will not be exported by the module once the feature\n// becomes a part of standard javascript\n\n/**\n * Create a HandledPromise class to have it support eventual send\n * (wavy-dot) operations.\n *\n * Based heavily on nanoq\n * https://github.com/drses/nanoq/blob/master/src/nanoq.js\n *\n * Original spec for the infix-bang (predecessor to wavy-dot) desugaring:\n * https://web.archive.org/web/20161026162206/http://wiki.ecmascript.org/doku.php?id=strawman:concurrency\n *\n * @return {typeof HandledPromise} Handled promise\n */\nfunction makeHandledPromise(Promise) {\n // xs doesn't support WeakMap in pre-loaded closures\n // aka \"vetted customization code\"\n let presenceToHandler;\n let presenceToPromise;\n let promiseToHandler;\n function ensureMaps() {\n if (!presenceToHandler) {\n presenceToHandler = new WeakMap();\n presenceToPromise = new WeakMap();\n promiseToHandler = new WeakMap();\n }\n }\n\n // This special handler accepts Promises, and forwards\n // handled Promises to their corresponding fulfilledHandler.\n let forwardingHandler;\n let handle;\n let handledPromiseResolve;\n\n function HandledPromise(executor, unfulfilledHandler = undefined) {\n if (new.target === undefined) {\n throw new Error('must be invoked with \"new\"');\n }\n let handledResolve;\n let handledReject;\n let fulfilled = false;\n const superExecutor = (resolve, reject) => {\n handledResolve = value => {\n fulfilled = true;\n resolve(value);\n };\n handledReject = err => {\n fulfilled = true;\n reject(err);\n };\n };\n const handledP = harden(\n Reflect.construct(Promise, [superExecutor], new.target),\n );\n\n ensureMaps();\n let continueForwarding = () => {};\n\n if (!unfulfilledHandler) {\n // Create a simple unfulfilledHandler that just postpones until the\n // fulfilledHandler is set.\n //\n // This is insufficient for actual remote handled Promises\n // (too many round-trips), but is an easy way to create a\n // local handled Promise.\n const interlockP = new Promise((resolve, reject) => {\n continueForwarding = (err = null, targetP = undefined) => {\n if (err !== null) {\n reject(err);\n return;\n }\n // Box the target promise so that it isn't further resolved.\n resolve([targetP]);\n // Return undefined.\n };\n });\n\n const makePostponed = postponedOperation => {\n // Just wait until the handler is resolved/rejected.\n return function postpone(x, ...args) {\n // console.log(`forwarding ${postponedOperation} ${args[0]}`);\n return new HandledPromise((resolve, reject) => {\n interlockP\n .then(([targetP]) => {\n // If targetP is a handled promise, use it, otherwise x.\n const nextPromise = targetP || x;\n resolve(\n HandledPromise[postponedOperation](nextPromise, ...args),\n );\n })\n .catch(reject);\n });\n };\n };\n\n unfulfilledHandler = {\n get: makePostponed('get'),\n applyMethod: makePostponed('applyMethod'),\n };\n }\n\n const validateHandler = h => {\n if (Object(h) !== h) {\n throw TypeError(`Handler ${h} cannot be a primitive`);\n }\n };\n validateHandler(unfulfilledHandler);\n\n // Until the handled promise is resolved, we use the unfulfilledHandler.\n promiseToHandler.set(handledP, unfulfilledHandler);\n\n const rejectHandled = reason => {\n if (fulfilled) {\n return;\n }\n handledReject(reason);\n continueForwarding(reason);\n };\n\n let resolvedPresence = null;\n const resolveWithPresence = presenceHandler => {\n if (fulfilled) {\n return resolvedPresence;\n }\n try {\n // Sanity checks.\n validateHandler(presenceHandler);\n\n // Validate and install our mapped target (i.e. presence).\n resolvedPresence = Object.create(null);\n\n // Create table entries for the presence mapped to the\n // fulfilledHandler.\n presenceToPromise.set(resolvedPresence, handledP);\n presenceToHandler.set(resolvedPresence, presenceHandler);\n\n // Remove the mapping, as our presenceHandler should be\n // used instead.\n promiseToHandler.delete(handledP);\n\n // We committed to this presence, so resolve.\n handledResolve(resolvedPresence);\n continueForwarding();\n return resolvedPresence;\n } catch (e) {\n handledReject(e);\n continueForwarding();\n throw e;\n }\n };\n\n const resolveHandled = async (target, deprecatedPresenceHandler) => {\n if (fulfilled) {\n return undefined;\n }\n try {\n if (deprecatedPresenceHandler) {\n throw TypeError(\n `resolveHandled no longer accepts a handler; use resolveWithPresence`,\n );\n }\n\n // Resolve with the target when it's ready.\n handledResolve(target);\n\n const existingUnfulfilledHandler = promiseToHandler.get(target);\n if (existingUnfulfilledHandler) {\n // Reuse the unfulfilled handler.\n promiseToHandler.set(handledP, existingUnfulfilledHandler);\n return continueForwarding(null, target);\n }\n\n // See if the target is a presence we already know of.\n const presence = await target;\n const existingPresenceHandler = presenceToHandler.get(presence);\n if (existingPresenceHandler) {\n promiseToHandler.set(handledP, existingPresenceHandler);\n return continueForwarding(null, handledP);\n }\n\n // Remove the mapping, as we don't need a handler.\n promiseToHandler.delete(handledP);\n return continueForwarding();\n } catch (e) {\n handledReject(e);\n }\n return continueForwarding();\n };\n\n // Invoke the callback to let the user resolve/reject.\n executor(\n (...args) => {\n resolveHandled(...args);\n },\n rejectHandled,\n resolveWithPresence,\n );\n return handledP;\n }\n\n HandledPromise.prototype = Promise.prototype;\n\n // Uncomment this line if needed for conformance to the proposal.\n // Currently the proposal does not specify this, but we might change\n // our mind.\n // Object.setPrototypeOf(HandledPromise, Promise);\n\n const staticMethods = harden({\n get(target, key) {\n return handle(target, 'get', key);\n },\n getSendOnly(target, key) {\n handle(target, 'get', key);\n },\n applyFunction(target, args) {\n return handle(target, 'applyMethod', undefined, args);\n },\n applyFunctionSendOnly(target, args) {\n handle(target, 'applyMethod', undefined, args);\n },\n applyMethod(target, key, args) {\n return handle(target, 'applyMethod', key, args);\n },\n applyMethodSendOnly(target, key, args) {\n handle(target, 'applyMethod', key, args);\n },\n resolve(value) {\n ensureMaps();\n // Resolving a Presence returns the pre-registered handled promise.\n const handledPromise = presenceToPromise.get(value);\n if (handledPromise) {\n return handledPromise;\n }\n const basePromise = Promise.resolve(value);\n if (basePromise === value) {\n return value;\n }\n return handledPromiseResolve(value);\n },\n });\n\n defineProperties(HandledPromise, getOwnPropertyDescriptors(staticMethods));\n\n function makeForwarder(operation, localImpl) {\n return (o, ...args) => {\n // We are in another turn already, and have the naked object.\n const fulfilledHandler = presenceToHandler.get(o);\n if (\n fulfilledHandler &&\n typeof fulfilledHandler[operation] === 'function'\n ) {\n // The handler was resolved, so use it.\n return fulfilledHandler[operation](o, ...args);\n }\n\n // Not handled, so use the local implementation.\n return localImpl(o, ...args);\n };\n }\n\n // eslint-disable-next-line prefer-const\n forwardingHandler = {\n get: makeForwarder('get', (o, key) => o[key]),\n applyMethod: makeForwarder('applyMethod', (o, optKey, args) => {\n if (optKey === undefined || optKey === null) {\n return o(...args);\n }\n // console.log(`sending`, optKey, o[optKey], o);\n if (typeof o[optKey] !== 'function') {\n throw TypeError(`o[${JSON.stringify(optKey)}] is not a function`);\n }\n return o[optKey](...args);\n }),\n };\n\n handle = (p, operation, ...args) => {\n ensureMaps();\n const unfulfilledHandler = promiseToHandler.get(p);\n let executor;\n if (\n unfulfilledHandler &&\n typeof unfulfilledHandler[operation] === 'function'\n ) {\n executor = (resolve, reject) => {\n // We run in a future turn to prevent synchronous attacks,\n HandledPromise.resolve()\n .then(() =>\n // and resolve to the answer from the specific unfulfilled handler,\n resolve(unfulfilledHandler[operation](p, ...args)),\n )\n .catch(reject);\n };\n } else {\n executor = (resolve, reject) => {\n // We run in a future turn to prevent synchronous attacks,\n HandledPromise.resolve(p)\n .then(o => {\n // We now have the naked object,\n if (typeof forwardingHandler[operation] !== 'function') {\n throw TypeError(\n `forwardingHandler.${operation} is not a function`,\n );\n }\n // and resolve to the forwardingHandler's operation.\n resolve(forwardingHandler[operation](o, ...args));\n })\n .catch(reject);\n };\n }\n\n // We return a handled promise with the default unfulfilled handler.\n // This prevents a race between the above Promise.resolves and\n // pipelining.\n return new HandledPromise(executor);\n };\n\n handledPromiseResolve = Promise.resolve.bind(HandledPromise);\n return harden(HandledPromise);\n}\n\nexports.E = E;\nexports.HandledPromise = hp;\nexports.makeHandledPromise = makeHandledPromise;\n\n\nreturn module.exports;\n}\n","sourceMap":"//# sourceURL=/home/ubuntu/agoric-sdk/packages/eventual-send/dist/eventual-send.cjs.js\n","moduleFormat":"getExport"}; | ||
function makeEventualSendTransformer(parser, generate) { | ||
let HandledPromise; | ||
let evaluateProgram; | ||
let myRequire; | ||
let recursive = false; | ||
const transform = { | ||
closeOverSES(s) { | ||
// FIXME: This will go away when we can bundle an @agoric/harden that understands SES. | ||
myRequire = name => { | ||
if (name === '@agoric/harden') { | ||
return s.global.SES.harden; | ||
} | ||
throw Error(`Unrecognized require ${name}`); | ||
}; | ||
// FIXME: This should be replaced with ss.evaluateProgram support in SES. | ||
evaluateProgram = (src, endowments = {}) => s.evaluate(src, endowments); | ||
}, | ||
rewrite(ss) { | ||
const source = ss.src; | ||
const endowments = ss.endowments || {}; | ||
if (!recursive && !('HandledPromise' in endowments)) { | ||
// Use a getter to postpone initialization. | ||
Object.defineProperty(endowments, 'HandledPromise', { | ||
get() { | ||
if (!HandledPromise) { | ||
// Get a HandledPromise endowment for the evaluator. | ||
// It will be hardened in the evaluator's context. | ||
const { source: evSendSrc, moduleFormat } = eventualSendBundle; | ||
if (moduleFormat === 'getExport') { | ||
recursive = true; | ||
try { | ||
const ns = (evaluateProgram || ss.evaluateProgram)( | ||
`(${evSendSrc})()`, | ||
{ require: myRequire || require }, | ||
); | ||
HandledPromise = ns.HandledPromise; | ||
} finally { | ||
recursive = false; | ||
} | ||
} else { | ||
throw Error(`Unrecognized moduleFormat ${moduleFormat}`); | ||
} | ||
} | ||
return HandledPromise; | ||
}, | ||
}); | ||
} | ||
// Parse with eventualSend enabled, rewriting to | ||
// HandledPromise.got/set/apply/applyMethod/delete(...) | ||
const source = ss.src; | ||
// HandledPromise.get/applyFunction/applyMethod(...) | ||
const parseFunc = parser.parse; | ||
@@ -33,2 +79,3 @@ const ast = (parseFunc || parser)(source, { | ||
ast, | ||
endowments, | ||
src: actualSource, | ||
@@ -44,2 +91,2 @@ }; | ||
})); | ||
}))); |
{ | ||
"name": "@agoric/transform-eventual-send", | ||
"version": "1.0.3", | ||
"version": "1.1.0", | ||
"description": "transform-eventual-send", | ||
@@ -12,18 +12,13 @@ "main": "dist/transform-eventual-send.cjs.js", | ||
"lint-check": "eslint '**/*.{js,jsx}'", | ||
"build": "rollup -c rollup.config.js" | ||
"build": "node -r esm ./scripts/build-esend.js && rollup -c rollup.config.js" | ||
}, | ||
"devDependencies": { | ||
"@agoric/acorn-eventual-send": "^1.0.2", | ||
"@agoric/acorn-eventual-send": "^2.0.0", | ||
"@agoric/babel-parser": "^7.6.4", | ||
"@agoric/eventual-send": "^0.4.4", | ||
"@agoric/bundle-source": "^1.0.4", | ||
"@agoric/eventual-send": "^0.5.0", | ||
"@agoric/harden": "^0.0.4", | ||
"@babel/generator": "^7.5.0", | ||
"astring": "^1.4.0", | ||
"eslint": "^5.11.1", | ||
"eslint-config-airbnb": "^17.1.0", | ||
"eslint-config-prettier": "^3.3.0", | ||
"eslint-plugin-import": "^2.14.0", | ||
"eslint-plugin-jsx-a11y": "^6.1.2", | ||
"eslint-plugin-prettier": "^3.0.1", | ||
"eslint-plugin-react": "^7.12.0", | ||
"prettier": "^1.16.4", | ||
"esm": "^3.2.5", | ||
"rollup": "^1.16.6", | ||
@@ -36,6 +31,3 @@ "rollup-plugin-node-resolve": "^5.2.0", | ||
}, | ||
"dependencies": { | ||
"@agoric/harden": "0.0.4", | ||
"esm": "^3.2.5" | ||
}, | ||
"dependencies": {}, | ||
"keywords": [], | ||
@@ -42,0 +34,0 @@ "files": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
61001
0
14
352
6
2
- Removed@agoric/harden@0.0.4
- Removedesm@^3.2.5
- Removed@agoric/harden@0.0.4(transitive)
- Removed@agoric/make-hardener@0.0.4(transitive)
- Removedesm@3.2.25(transitive)