@metamask-previews/json-rpc-engine 10.2.0-preview-fd4aea5a → 10.2.0-preview-fdf20ce5

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 CHANGED
@@ -11,10 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  - Upgrade `@metamask/utils` from `^11.8.1` to `^11.9.0` ([#7511](https://github.com/MetaMask/core/pull/7511))
13
13
 
14
- ### Fixed
15
-
16
- - Ensure non-object data in RPC errors is deserialized correctly when using JsonRpcEngine compatibility tools ([#7638](https://github.com/MetaMask/core/pull/7638))
17
-
18
14
  ## [10.2.0]
19
15
 
20
16
  ### Added
@@ -98,25 +98,6 @@ 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
- }
120
101
  /**
121
102
  * Unserialize an error from a thrown value. Creates a {@link JsonRpcError} if
122
103
  * the thrown value is an object with a `code` property. Otherwise, creates a
@@ -157,7 +138,10 @@ function deserializeError(thrown) {
157
138
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
158
139
  // @ts-ignore - Our error type is outdated.
159
140
  new Error(message, { cause })
160
- : new rpc_errors_1.JsonRpcError(code, message, deserializeData(data, cause));
141
+ : new rpc_errors_1.JsonRpcError(code, message, {
142
+ ...((0, utils_1.isObject)(data) ? data : undefined),
143
+ cause,
144
+ });
161
145
  if (typeof stack === 'string') {
162
146
  error.stack = stack;
163
147
  }
@@ -1 +1 @@
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
+ {"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 +1 @@
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
+ {"version":3,"file":"compatibility-utils.d.cts","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"AAAA,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;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CA+C5E"}
@@ -1 +1 @@
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
+ {"version":3,"file":"compatibility-utils.d.mts","sourceRoot":"","sources":["../../src/v2/compatibility-utils.ts"],"names":[],"mappings":"AAAA,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;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CA+C5E"}
@@ -1,5 +1,5 @@
1
1
  import { getMessageFromCode, JsonRpcError } from "@metamask/rpc-errors";
2
- import { hasProperty, isObject, isValidJson } from "@metamask/utils";
2
+ import { hasProperty, isObject } 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,25 +90,6 @@ 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
- }
112
93
  /**
113
94
  * Unserialize an error from a thrown value. Creates a {@link JsonRpcError} if
114
95
  * the thrown value is an object with a `code` property. Otherwise, creates a
@@ -149,7 +130,10 @@ export function deserializeError(thrown) {
149
130
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
150
131
  // @ts-ignore - Our error type is outdated.
151
132
  new Error(message, { cause })
152
- : new JsonRpcError(code, message, deserializeData(data, cause));
133
+ : new JsonRpcError(code, message, {
134
+ ...(isObject(data) ? data : undefined),
135
+ cause,
136
+ });
153
137
  if (typeof stack === 'string') {
154
138
  error.stack = stack;
155
139
  }
@@ -1 +1 @@
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"]}
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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/json-rpc-engine",
3
- "version": "10.2.0-preview-fd4aea5a",
3
+ "version": "10.2.0-preview-fdf20ce5",
4
4
  "description": "A tool for processing JSON-RPC messages",
5
5
  "keywords": [
6
6
  "MetaMask",