@metamask-previews/json-rpc-engine 10.2.0-preview-c72fc191 → 10.2.1-preview-a4747b2b
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/CHANGELOG.md +8 -1
- package/dist/v2/compatibility-utils.cjs +20 -4
- package/dist/v2/compatibility-utils.cjs.map +1 -1
- package/dist/v2/compatibility-utils.d.cts.map +1 -1
- package/dist/v2/compatibility-utils.d.mts.map +1 -1
- package/dist/v2/compatibility-utils.mjs +21 -5
- package/dist/v2/compatibility-utils.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [10.2.1]
|
|
11
|
+
|
|
10
12
|
### Changed
|
|
11
13
|
|
|
12
14
|
- Upgrade `@metamask/utils` from `^11.8.1` to `^11.9.0` ([#7511](https://github.com/MetaMask/core/pull/7511))
|
|
13
15
|
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Ensure non-object data in RPC errors is deserialized correctly when using JsonRpcEngine compatibility tools ([#7638](https://github.com/MetaMask/core/pull/7638))
|
|
19
|
+
|
|
14
20
|
## [10.2.0]
|
|
15
21
|
|
|
16
22
|
### Added
|
|
@@ -258,7 +264,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
258
264
|
This change may affect consumers that depend on the eager execution of middleware _during_ request processing, _outside of_ middleware functions and request handlers.
|
|
259
265
|
- In general, it is a bad practice to work with state that depends on middleware execution, while the middleware are executing.
|
|
260
266
|
|
|
261
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/json-rpc-engine@10.2.
|
|
267
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/json-rpc-engine@10.2.1...HEAD
|
|
268
|
+
[10.2.1]: https://github.com/MetaMask/core/compare/@metamask/json-rpc-engine@10.2.0...@metamask/json-rpc-engine@10.2.1
|
|
262
269
|
[10.2.0]: https://github.com/MetaMask/core/compare/@metamask/json-rpc-engine@10.1.1...@metamask/json-rpc-engine@10.2.0
|
|
263
270
|
[10.1.1]: https://github.com/MetaMask/core/compare/@metamask/json-rpc-engine@10.1.0...@metamask/json-rpc-engine@10.1.1
|
|
264
271
|
[10.1.0]: https://github.com/MetaMask/core/compare/@metamask/json-rpc-engine@10.0.3...@metamask/json-rpc-engine@10.1.0
|
|
@@ -98,6 +98,25 @@ function propagateToRequest(req, context) {
|
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
100
|
exports.propagateToRequest = propagateToRequest;
|
|
101
|
+
/**
|
|
102
|
+
* Deserialize the error property for a thrown error, merging in the cause where possible.
|
|
103
|
+
*
|
|
104
|
+
* @param data - The data from the thrown error.
|
|
105
|
+
* @param cause - The cause from the thrown error.
|
|
106
|
+
* @returns The deserialized data.
|
|
107
|
+
*/
|
|
108
|
+
function deserializeData(data, cause) {
|
|
109
|
+
// If data is an object, merge with cause.
|
|
110
|
+
if ((0, utils_1.isObject)(data)) {
|
|
111
|
+
return { ...data, cause };
|
|
112
|
+
}
|
|
113
|
+
// If data is a JSON value that's not mergeable.
|
|
114
|
+
if ((0, utils_1.isValidJson)(data)) {
|
|
115
|
+
return data;
|
|
116
|
+
}
|
|
117
|
+
// If data is undefined, only use cause.
|
|
118
|
+
return { cause };
|
|
119
|
+
}
|
|
101
120
|
/**
|
|
102
121
|
* Unserialize an error from a thrown value. Creates a {@link JsonRpcError} if
|
|
103
122
|
* the thrown value is an object with a `code` property. Otherwise, creates a
|
|
@@ -138,10 +157,7 @@ function deserializeError(thrown) {
|
|
|
138
157
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
139
158
|
// @ts-ignore - Our error type is outdated.
|
|
140
159
|
new Error(message, { cause })
|
|
141
|
-
: new rpc_errors_1.JsonRpcError(code, message,
|
|
142
|
-
...((0, utils_1.isObject)(data) ? data : undefined),
|
|
143
|
-
cause,
|
|
144
|
-
});
|
|
160
|
+
: new rpc_errors_1.JsonRpcError(code, message, deserializeData(data, cause));
|
|
145
161
|
if (typeof stack === 'string') {
|
|
146
162
|
error.stack = stack;
|
|
147
163
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compatibility-utils.cjs","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { getMessageFromCode, JsonRpcError } from '@metamask/rpc-errors';\nimport type { Json } from '@metamask/utils';\nimport { hasProperty, isObject } from '@metamask/utils';\n// ATTN: We must NOT use 'klona/full' here because it freezes properties on the clone.\nimport { klona } from 'klona';\n\nimport { MiddlewareContext } from './MiddlewareContext';\nimport { stringify } from './utils';\nimport type { JsonRpcRequest } from './utils';\n\n// Legacy engine compatibility utils\n\n/**\n * Create a deep clone of a value as follows:\n * - Assumes acyclical objects\n * - Does not copy property descriptors (i.e. uses mutable defaults)\n * - Ignores non-enumerable properties\n * - Ignores getters and setters\n *\n * @throws If the value is an object with a circular reference.\n * @param value - The value to clone.\n * @returns The cloned value.\n */\nexport const deepClone = <Type>(value: Type): DeepCloned<Type> =>\n klona(value) as DeepCloned<Type>;\n\n// Matching the default implementation of klona, this type:\n// - Removes readonly modifiers\n// - Excludes non-enumerable / symbol properties\ntype DeepCloned<Type> = Type extends readonly (infer ArrayType)[]\n ? DeepCloned<ArrayType>[]\n : Type extends object\n ? {\n -readonly [Key in keyof Type & (string | number)]: DeepCloned<\n Type[Key]\n >;\n }\n : Type;\n\n/**\n * Standard JSON-RPC request properties.\n */\nexport const requestProps = ['jsonrpc', 'method', 'params', 'id'];\n\n/**\n * Make a JSON-RPC request from a legacy request. Clones the params to avoid\n * freezing them, which could cause errors in an involved legacy engine.\n *\n * @param req - The legacy request to make a request from.\n * @returns The JSON-RPC request.\n */\nexport function fromLegacyRequest<Request extends JsonRpcRequest>(\n req: Request,\n): Request {\n const request = {\n jsonrpc: '2.0' as const,\n method: req.method,\n } as Partial<Request>;\n request.id = req.id;\n if (hasProperty(req, 'params') && req.params !== undefined) {\n request.params = deepClone(req.params);\n }\n return request as Request;\n}\n\n/**\n * Make a middleware context from a legacy request by copying over all non-JSON-RPC\n * properties from the request to the context object.\n *\n * @param req - The legacy request to make a context from.\n * @returns The middleware context.\n */\nexport function makeContext<Request extends Record<string | symbol, unknown>>(\n req: Request,\n): MiddlewareContext {\n const context = new MiddlewareContext();\n propagateToContext(req, context);\n return context;\n}\n\n/**\n * Copies non-JSON-RPC string properties from the request to the context.\n *\n * For compatibility with our problematic practice of appending non-standard\n * fields to requests for inter-middleware communication in the legacy engine.\n *\n * **ATTN:** Only string properties that do not already exist in the context\n * are copied.\n *\n * @param req - The request to propagate the context from.\n * @param context - The context to propagate to.\n */\nexport function propagateToContext(\n req: Record<string, unknown>,\n context: MiddlewareContext<Record<string, unknown>>,\n): void {\n Object.keys(req)\n .filter(\n (key) =>\n typeof key === 'string' &&\n !requestProps.includes(key) &&\n !context.has(key),\n )\n .forEach((key) => {\n context.set(key, req[key]);\n });\n}\n\n/**\n * Copies non-JSON-RPC string properties from the context to the request.\n *\n * For compatibility with our problematic practice of appending non-standard\n * fields to requests for inter-middleware communication in the legacy engine.\n *\n * **ATTN:** Only string properties are copied.\n *\n * @param req - The request to propagate the context to.\n * @param context - The context to propagate from.\n */\nexport function propagateToRequest(\n req: Record<string, unknown>,\n context: MiddlewareContext,\n): void {\n Array.from(context.keys())\n .filter(\n ((key) => typeof key === 'string' && !requestProps.includes(key)) as (\n value: unknown,\n ) => value is string,\n )\n .forEach((key) => {\n req[key] = context.get(key);\n });\n}\n\n/**\n * Unserialize an error from a thrown value. Creates a {@link JsonRpcError} if\n * the thrown value is an object with a `code` property. Otherwise, creates a\n * plain {@link Error}.\n *\n * @param thrown - The thrown value to unserialize.\n * @returns The unserialized error.\n */\nexport function deserializeError(thrown: unknown): Error | JsonRpcError<Json> {\n // @ts-expect-error - New, but preferred if available.\n // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/isError\n if (typeof Error.isError === 'function' && Error.isError(thrown)) {\n return thrown as Error;\n }\n // Unlike Error.isError, instanceof does not work for Errors from other realms.\n if (thrown instanceof Error) {\n return thrown;\n }\n if (typeof thrown === 'string') {\n return new Error(thrown);\n }\n if (!isObject(thrown)) {\n return new Error(`Unknown error: ${stringify(thrown)}`);\n }\n\n const code =\n typeof thrown.code === 'number' && Number.isInteger(thrown.code)\n ? thrown.code\n : undefined;\n\n let message = 'Unknown error';\n if (typeof thrown.message === 'string') {\n message = thrown.message;\n } else if (typeof code === 'number') {\n message = getMessageFromCode(code, message);\n }\n\n const { stack, cause, data } = thrown;\n\n const error =\n code === undefined\n ? // Jest complains if we use the `@ts-expect-error` directive here.\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - Our error type is outdated.\n new Error(message, { cause })\n : new JsonRpcError(code, message, {\n ...(isObject(data) ? data : undefined),\n cause,\n });\n\n if (typeof stack === 'string') {\n error.stack = stack;\n }\n\n return error;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"compatibility-utils.cjs","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { OptionalDataWithOptionalCause } from '@metamask/rpc-errors';\nimport { getMessageFromCode, JsonRpcError } from '@metamask/rpc-errors';\nimport type { Json } from '@metamask/utils';\nimport { hasProperty, isObject, isValidJson } from '@metamask/utils';\n// ATTN: We must NOT use 'klona/full' here because it freezes properties on the clone.\nimport { klona } from 'klona';\n\nimport { MiddlewareContext } from './MiddlewareContext';\nimport { stringify } from './utils';\nimport type { JsonRpcRequest } from './utils';\n\n// Legacy engine compatibility utils\n\n/**\n * Create a deep clone of a value as follows:\n * - Assumes acyclical objects\n * - Does not copy property descriptors (i.e. uses mutable defaults)\n * - Ignores non-enumerable properties\n * - Ignores getters and setters\n *\n * @throws If the value is an object with a circular reference.\n * @param value - The value to clone.\n * @returns The cloned value.\n */\nexport const deepClone = <Type>(value: Type): DeepCloned<Type> =>\n klona(value) as DeepCloned<Type>;\n\n// Matching the default implementation of klona, this type:\n// - Removes readonly modifiers\n// - Excludes non-enumerable / symbol properties\ntype DeepCloned<Type> = Type extends readonly (infer ArrayType)[]\n ? DeepCloned<ArrayType>[]\n : Type extends object\n ? {\n -readonly [Key in keyof Type & (string | number)]: DeepCloned<\n Type[Key]\n >;\n }\n : Type;\n\n/**\n * Standard JSON-RPC request properties.\n */\nexport const requestProps = ['jsonrpc', 'method', 'params', 'id'];\n\n/**\n * Make a JSON-RPC request from a legacy request. Clones the params to avoid\n * freezing them, which could cause errors in an involved legacy engine.\n *\n * @param req - The legacy request to make a request from.\n * @returns The JSON-RPC request.\n */\nexport function fromLegacyRequest<Request extends JsonRpcRequest>(\n req: Request,\n): Request {\n const request = {\n jsonrpc: '2.0' as const,\n method: req.method,\n } as Partial<Request>;\n request.id = req.id;\n if (hasProperty(req, 'params') && req.params !== undefined) {\n request.params = deepClone(req.params);\n }\n return request as Request;\n}\n\n/**\n * Make a middleware context from a legacy request by copying over all non-JSON-RPC\n * properties from the request to the context object.\n *\n * @param req - The legacy request to make a context from.\n * @returns The middleware context.\n */\nexport function makeContext<Request extends Record<string | symbol, unknown>>(\n req: Request,\n): MiddlewareContext {\n const context = new MiddlewareContext();\n propagateToContext(req, context);\n return context;\n}\n\n/**\n * Copies non-JSON-RPC string properties from the request to the context.\n *\n * For compatibility with our problematic practice of appending non-standard\n * fields to requests for inter-middleware communication in the legacy engine.\n *\n * **ATTN:** Only string properties that do not already exist in the context\n * are copied.\n *\n * @param req - The request to propagate the context from.\n * @param context - The context to propagate to.\n */\nexport function propagateToContext(\n req: Record<string, unknown>,\n context: MiddlewareContext<Record<string, unknown>>,\n): void {\n Object.keys(req)\n .filter(\n (key) =>\n typeof key === 'string' &&\n !requestProps.includes(key) &&\n !context.has(key),\n )\n .forEach((key) => {\n context.set(key, req[key]);\n });\n}\n\n/**\n * Copies non-JSON-RPC string properties from the context to the request.\n *\n * For compatibility with our problematic practice of appending non-standard\n * fields to requests for inter-middleware communication in the legacy engine.\n *\n * **ATTN:** Only string properties are copied.\n *\n * @param req - The request to propagate the context to.\n * @param context - The context to propagate from.\n */\nexport function propagateToRequest(\n req: Record<string, unknown>,\n context: MiddlewareContext,\n): void {\n Array.from(context.keys())\n .filter(\n ((key) => typeof key === 'string' && !requestProps.includes(key)) as (\n value: unknown,\n ) => value is string,\n )\n .forEach((key) => {\n req[key] = context.get(key);\n });\n}\n\n/**\n * Deserialize the error property for a thrown error, merging in the cause where possible.\n *\n * @param data - The data from the thrown error.\n * @param cause - The cause from the thrown error.\n * @returns The deserialized data.\n */\nfunction deserializeData(\n data: unknown,\n cause: unknown,\n): OptionalDataWithOptionalCause {\n // If data is an object, merge with cause.\n if (isObject(data)) {\n return { ...data, cause };\n }\n\n // If data is a JSON value that's not mergeable.\n if (isValidJson(data)) {\n return data;\n }\n\n // If data is undefined, only use cause.\n return { cause };\n}\n\n/**\n * Unserialize an error from a thrown value. Creates a {@link JsonRpcError} if\n * the thrown value is an object with a `code` property. Otherwise, creates a\n * plain {@link Error}.\n *\n * @param thrown - The thrown value to unserialize.\n * @returns The unserialized error.\n */\nexport function deserializeError(thrown: unknown): Error | JsonRpcError<Json> {\n // @ts-expect-error - New, but preferred if available.\n // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/isError\n if (typeof Error.isError === 'function' && Error.isError(thrown)) {\n return thrown as Error;\n }\n // Unlike Error.isError, instanceof does not work for Errors from other realms.\n if (thrown instanceof Error) {\n return thrown;\n }\n if (typeof thrown === 'string') {\n return new Error(thrown);\n }\n if (!isObject(thrown)) {\n return new Error(`Unknown error: ${stringify(thrown)}`);\n }\n\n const code =\n typeof thrown.code === 'number' && Number.isInteger(thrown.code)\n ? thrown.code\n : undefined;\n\n let message = 'Unknown error';\n if (typeof thrown.message === 'string') {\n message = thrown.message;\n } else if (typeof code === 'number') {\n message = getMessageFromCode(code, message);\n }\n\n const { stack, cause, data } = thrown;\n\n const error =\n code === undefined\n ? // Jest complains if we use the `@ts-expect-error` directive here.\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - Our error type is outdated.\n new Error(message, { cause })\n : new JsonRpcError(code, message, deserializeData(data, cause));\n\n if (typeof stack === 'string') {\n error.stack = stack;\n }\n\n return error;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compatibility-utils.d.cts","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compatibility-utils.d.cts","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,YAAY,EAAE,6BAA6B;AACxE,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAK5C,OAAO,EAAE,iBAAiB,EAAE,gCAA4B;AAExD,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAgB;AAI9C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,yCACY,CAAC;AAKnC,KAAK,UAAU,CAAC,IAAI,IAAI,IAAI,SAAS,SAAS,CAAC,MAAM,SAAS,CAAC,EAAE,GAC7D,UAAU,CAAC,SAAS,CAAC,EAAE,GACvB,IAAI,SAAS,MAAM,GACjB;IACE,CAAC,UAAU,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,UAAU,CAC3D,IAAI,CAAC,GAAG,CAAC,CACV;CACF,GACD,IAAI,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY,UAAwC,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,SAAS,cAAc,EAC9D,GAAG,EAAE,OAAO,GACX,OAAO,CAUT;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAC1E,GAAG,EAAE,OAAO,GACX,iBAAiB,CAInB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAClD,IAAI,CAWN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,iBAAiB,GACzB,IAAI,CAUN;AA2BD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CA4C5E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compatibility-utils.d.mts","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compatibility-utils.d.mts","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,YAAY,EAAE,6BAA6B;AACxE,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAK5C,OAAO,EAAE,iBAAiB,EAAE,gCAA4B;AAExD,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAgB;AAI9C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,yCACY,CAAC;AAKnC,KAAK,UAAU,CAAC,IAAI,IAAI,IAAI,SAAS,SAAS,CAAC,MAAM,SAAS,CAAC,EAAE,GAC7D,UAAU,CAAC,SAAS,CAAC,EAAE,GACvB,IAAI,SAAS,MAAM,GACjB;IACE,CAAC,UAAU,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,UAAU,CAC3D,IAAI,CAAC,GAAG,CAAC,CACV;CACF,GACD,IAAI,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY,UAAwC,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,SAAS,cAAc,EAC9D,GAAG,EAAE,OAAO,GACX,OAAO,CAUT;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAC1E,GAAG,EAAE,OAAO,GACX,iBAAiB,CAInB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAClD,IAAI,CAWN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,iBAAiB,GACzB,IAAI,CAUN;AA2BD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CA4C5E"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getMessageFromCode, JsonRpcError } from "@metamask/rpc-errors";
|
|
2
|
-
import { hasProperty, isObject } from "@metamask/utils";
|
|
2
|
+
import { hasProperty, isObject, isValidJson } from "@metamask/utils";
|
|
3
3
|
// ATTN: We must NOT use 'klona/full' here because it freezes properties on the clone.
|
|
4
4
|
import { klona } from "klona";
|
|
5
5
|
import { MiddlewareContext } from "./MiddlewareContext.mjs";
|
|
@@ -90,6 +90,25 @@ export function propagateToRequest(req, context) {
|
|
|
90
90
|
req[key] = context.get(key);
|
|
91
91
|
});
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Deserialize the error property for a thrown error, merging in the cause where possible.
|
|
95
|
+
*
|
|
96
|
+
* @param data - The data from the thrown error.
|
|
97
|
+
* @param cause - The cause from the thrown error.
|
|
98
|
+
* @returns The deserialized data.
|
|
99
|
+
*/
|
|
100
|
+
function deserializeData(data, cause) {
|
|
101
|
+
// If data is an object, merge with cause.
|
|
102
|
+
if (isObject(data)) {
|
|
103
|
+
return { ...data, cause };
|
|
104
|
+
}
|
|
105
|
+
// If data is a JSON value that's not mergeable.
|
|
106
|
+
if (isValidJson(data)) {
|
|
107
|
+
return data;
|
|
108
|
+
}
|
|
109
|
+
// If data is undefined, only use cause.
|
|
110
|
+
return { cause };
|
|
111
|
+
}
|
|
93
112
|
/**
|
|
94
113
|
* Unserialize an error from a thrown value. Creates a {@link JsonRpcError} if
|
|
95
114
|
* the thrown value is an object with a `code` property. Otherwise, creates a
|
|
@@ -130,10 +149,7 @@ export function deserializeError(thrown) {
|
|
|
130
149
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
131
150
|
// @ts-ignore - Our error type is outdated.
|
|
132
151
|
new Error(message, { cause })
|
|
133
|
-
: new JsonRpcError(code, message,
|
|
134
|
-
...(isObject(data) ? data : undefined),
|
|
135
|
-
cause,
|
|
136
|
-
});
|
|
152
|
+
: new JsonRpcError(code, message, deserializeData(data, cause));
|
|
137
153
|
if (typeof stack === 'string') {
|
|
138
154
|
error.stack = stack;
|
|
139
155
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compatibility-utils.mjs","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { getMessageFromCode, JsonRpcError } from '@metamask/rpc-errors';\nimport type { Json } from '@metamask/utils';\nimport { hasProperty, isObject } from '@metamask/utils';\n// ATTN: We must NOT use 'klona/full' here because it freezes properties on the clone.\nimport { klona } from 'klona';\n\nimport { MiddlewareContext } from './MiddlewareContext';\nimport { stringify } from './utils';\nimport type { JsonRpcRequest } from './utils';\n\n// Legacy engine compatibility utils\n\n/**\n * Create a deep clone of a value as follows:\n * - Assumes acyclical objects\n * - Does not copy property descriptors (i.e. uses mutable defaults)\n * - Ignores non-enumerable properties\n * - Ignores getters and setters\n *\n * @throws If the value is an object with a circular reference.\n * @param value - The value to clone.\n * @returns The cloned value.\n */\nexport const deepClone = <Type>(value: Type): DeepCloned<Type> =>\n klona(value) as DeepCloned<Type>;\n\n// Matching the default implementation of klona, this type:\n// - Removes readonly modifiers\n// - Excludes non-enumerable / symbol properties\ntype DeepCloned<Type> = Type extends readonly (infer ArrayType)[]\n ? DeepCloned<ArrayType>[]\n : Type extends object\n ? {\n -readonly [Key in keyof Type & (string | number)]: DeepCloned<\n Type[Key]\n >;\n }\n : Type;\n\n/**\n * Standard JSON-RPC request properties.\n */\nexport const requestProps = ['jsonrpc', 'method', 'params', 'id'];\n\n/**\n * Make a JSON-RPC request from a legacy request. Clones the params to avoid\n * freezing them, which could cause errors in an involved legacy engine.\n *\n * @param req - The legacy request to make a request from.\n * @returns The JSON-RPC request.\n */\nexport function fromLegacyRequest<Request extends JsonRpcRequest>(\n req: Request,\n): Request {\n const request = {\n jsonrpc: '2.0' as const,\n method: req.method,\n } as Partial<Request>;\n request.id = req.id;\n if (hasProperty(req, 'params') && req.params !== undefined) {\n request.params = deepClone(req.params);\n }\n return request as Request;\n}\n\n/**\n * Make a middleware context from a legacy request by copying over all non-JSON-RPC\n * properties from the request to the context object.\n *\n * @param req - The legacy request to make a context from.\n * @returns The middleware context.\n */\nexport function makeContext<Request extends Record<string | symbol, unknown>>(\n req: Request,\n): MiddlewareContext {\n const context = new MiddlewareContext();\n propagateToContext(req, context);\n return context;\n}\n\n/**\n * Copies non-JSON-RPC string properties from the request to the context.\n *\n * For compatibility with our problematic practice of appending non-standard\n * fields to requests for inter-middleware communication in the legacy engine.\n *\n * **ATTN:** Only string properties that do not already exist in the context\n * are copied.\n *\n * @param req - The request to propagate the context from.\n * @param context - The context to propagate to.\n */\nexport function propagateToContext(\n req: Record<string, unknown>,\n context: MiddlewareContext<Record<string, unknown>>,\n): void {\n Object.keys(req)\n .filter(\n (key) =>\n typeof key === 'string' &&\n !requestProps.includes(key) &&\n !context.has(key),\n )\n .forEach((key) => {\n context.set(key, req[key]);\n });\n}\n\n/**\n * Copies non-JSON-RPC string properties from the context to the request.\n *\n * For compatibility with our problematic practice of appending non-standard\n * fields to requests for inter-middleware communication in the legacy engine.\n *\n * **ATTN:** Only string properties are copied.\n *\n * @param req - The request to propagate the context to.\n * @param context - The context to propagate from.\n */\nexport function propagateToRequest(\n req: Record<string, unknown>,\n context: MiddlewareContext,\n): void {\n Array.from(context.keys())\n .filter(\n ((key) => typeof key === 'string' && !requestProps.includes(key)) as (\n value: unknown,\n ) => value is string,\n )\n .forEach((key) => {\n req[key] = context.get(key);\n });\n}\n\n/**\n * Unserialize an error from a thrown value. Creates a {@link JsonRpcError} if\n * the thrown value is an object with a `code` property. Otherwise, creates a\n * plain {@link Error}.\n *\n * @param thrown - The thrown value to unserialize.\n * @returns The unserialized error.\n */\nexport function deserializeError(thrown: unknown): Error | JsonRpcError<Json> {\n // @ts-expect-error - New, but preferred if available.\n // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/isError\n if (typeof Error.isError === 'function' && Error.isError(thrown)) {\n return thrown as Error;\n }\n // Unlike Error.isError, instanceof does not work for Errors from other realms.\n if (thrown instanceof Error) {\n return thrown;\n }\n if (typeof thrown === 'string') {\n return new Error(thrown);\n }\n if (!isObject(thrown)) {\n return new Error(`Unknown error: ${stringify(thrown)}`);\n }\n\n const code =\n typeof thrown.code === 'number' && Number.isInteger(thrown.code)\n ? thrown.code\n : undefined;\n\n let message = 'Unknown error';\n if (typeof thrown.message === 'string') {\n message = thrown.message;\n } else if (typeof code === 'number') {\n message = getMessageFromCode(code, message);\n }\n\n const { stack, cause, data } = thrown;\n\n const error =\n code === undefined\n ? // Jest complains if we use the `@ts-expect-error` directive here.\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - Our error type is outdated.\n new Error(message, { cause })\n : new JsonRpcError(code, message, {\n ...(isObject(data) ? data : undefined),\n cause,\n });\n\n if (typeof stack === 'string') {\n error.stack = stack;\n }\n\n return error;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"compatibility-utils.mjs","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { OptionalDataWithOptionalCause } from '@metamask/rpc-errors';\nimport { getMessageFromCode, JsonRpcError } from '@metamask/rpc-errors';\nimport type { Json } from '@metamask/utils';\nimport { hasProperty, isObject, isValidJson } from '@metamask/utils';\n// ATTN: We must NOT use 'klona/full' here because it freezes properties on the clone.\nimport { klona } from 'klona';\n\nimport { MiddlewareContext } from './MiddlewareContext';\nimport { stringify } from './utils';\nimport type { JsonRpcRequest } from './utils';\n\n// Legacy engine compatibility utils\n\n/**\n * Create a deep clone of a value as follows:\n * - Assumes acyclical objects\n * - Does not copy property descriptors (i.e. uses mutable defaults)\n * - Ignores non-enumerable properties\n * - Ignores getters and setters\n *\n * @throws If the value is an object with a circular reference.\n * @param value - The value to clone.\n * @returns The cloned value.\n */\nexport const deepClone = <Type>(value: Type): DeepCloned<Type> =>\n klona(value) as DeepCloned<Type>;\n\n// Matching the default implementation of klona, this type:\n// - Removes readonly modifiers\n// - Excludes non-enumerable / symbol properties\ntype DeepCloned<Type> = Type extends readonly (infer ArrayType)[]\n ? DeepCloned<ArrayType>[]\n : Type extends object\n ? {\n -readonly [Key in keyof Type & (string | number)]: DeepCloned<\n Type[Key]\n >;\n }\n : Type;\n\n/**\n * Standard JSON-RPC request properties.\n */\nexport const requestProps = ['jsonrpc', 'method', 'params', 'id'];\n\n/**\n * Make a JSON-RPC request from a legacy request. Clones the params to avoid\n * freezing them, which could cause errors in an involved legacy engine.\n *\n * @param req - The legacy request to make a request from.\n * @returns The JSON-RPC request.\n */\nexport function fromLegacyRequest<Request extends JsonRpcRequest>(\n req: Request,\n): Request {\n const request = {\n jsonrpc: '2.0' as const,\n method: req.method,\n } as Partial<Request>;\n request.id = req.id;\n if (hasProperty(req, 'params') && req.params !== undefined) {\n request.params = deepClone(req.params);\n }\n return request as Request;\n}\n\n/**\n * Make a middleware context from a legacy request by copying over all non-JSON-RPC\n * properties from the request to the context object.\n *\n * @param req - The legacy request to make a context from.\n * @returns The middleware context.\n */\nexport function makeContext<Request extends Record<string | symbol, unknown>>(\n req: Request,\n): MiddlewareContext {\n const context = new MiddlewareContext();\n propagateToContext(req, context);\n return context;\n}\n\n/**\n * Copies non-JSON-RPC string properties from the request to the context.\n *\n * For compatibility with our problematic practice of appending non-standard\n * fields to requests for inter-middleware communication in the legacy engine.\n *\n * **ATTN:** Only string properties that do not already exist in the context\n * are copied.\n *\n * @param req - The request to propagate the context from.\n * @param context - The context to propagate to.\n */\nexport function propagateToContext(\n req: Record<string, unknown>,\n context: MiddlewareContext<Record<string, unknown>>,\n): void {\n Object.keys(req)\n .filter(\n (key) =>\n typeof key === 'string' &&\n !requestProps.includes(key) &&\n !context.has(key),\n )\n .forEach((key) => {\n context.set(key, req[key]);\n });\n}\n\n/**\n * Copies non-JSON-RPC string properties from the context to the request.\n *\n * For compatibility with our problematic practice of appending non-standard\n * fields to requests for inter-middleware communication in the legacy engine.\n *\n * **ATTN:** Only string properties are copied.\n *\n * @param req - The request to propagate the context to.\n * @param context - The context to propagate from.\n */\nexport function propagateToRequest(\n req: Record<string, unknown>,\n context: MiddlewareContext,\n): void {\n Array.from(context.keys())\n .filter(\n ((key) => typeof key === 'string' && !requestProps.includes(key)) as (\n value: unknown,\n ) => value is string,\n )\n .forEach((key) => {\n req[key] = context.get(key);\n });\n}\n\n/**\n * Deserialize the error property for a thrown error, merging in the cause where possible.\n *\n * @param data - The data from the thrown error.\n * @param cause - The cause from the thrown error.\n * @returns The deserialized data.\n */\nfunction deserializeData(\n data: unknown,\n cause: unknown,\n): OptionalDataWithOptionalCause {\n // If data is an object, merge with cause.\n if (isObject(data)) {\n return { ...data, cause };\n }\n\n // If data is a JSON value that's not mergeable.\n if (isValidJson(data)) {\n return data;\n }\n\n // If data is undefined, only use cause.\n return { cause };\n}\n\n/**\n * Unserialize an error from a thrown value. Creates a {@link JsonRpcError} if\n * the thrown value is an object with a `code` property. Otherwise, creates a\n * plain {@link Error}.\n *\n * @param thrown - The thrown value to unserialize.\n * @returns The unserialized error.\n */\nexport function deserializeError(thrown: unknown): Error | JsonRpcError<Json> {\n // @ts-expect-error - New, but preferred if available.\n // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/isError\n if (typeof Error.isError === 'function' && Error.isError(thrown)) {\n return thrown as Error;\n }\n // Unlike Error.isError, instanceof does not work for Errors from other realms.\n if (thrown instanceof Error) {\n return thrown;\n }\n if (typeof thrown === 'string') {\n return new Error(thrown);\n }\n if (!isObject(thrown)) {\n return new Error(`Unknown error: ${stringify(thrown)}`);\n }\n\n const code =\n typeof thrown.code === 'number' && Number.isInteger(thrown.code)\n ? thrown.code\n : undefined;\n\n let message = 'Unknown error';\n if (typeof thrown.message === 'string') {\n message = thrown.message;\n } else if (typeof code === 'number') {\n message = getMessageFromCode(code, message);\n }\n\n const { stack, cause, data } = thrown;\n\n const error =\n code === undefined\n ? // Jest complains if we use the `@ts-expect-error` directive here.\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - Our error type is outdated.\n new Error(message, { cause })\n : new JsonRpcError(code, message, deserializeData(data, cause));\n\n if (typeof stack === 'string') {\n error.stack = stack;\n }\n\n return error;\n}\n"]}
|