{"id":18285888,"url":"https://github.com/exodusmovement/patch-broken-hermes-typed-arrays","last_synced_at":"2025-04-05T07:32:36.611Z","repository":{"id":254312353,"uuid":"842777232","full_name":"ExodusMovement/patch-broken-hermes-typed-arrays","owner":"ExodusMovement","description":"Attempt to fix broken Hermes engine TypedArray implementation for React Native","archived":false,"fork":false,"pushed_at":"2024-08-27T13:41:05.000Z","size":111,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T14:26:01.055Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://npmjs.com/@exodus/patch-broken-hermes-typed-arrays","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ExodusMovement.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-15T03:59:50.000Z","updated_at":"2024-11-04T22:30:44.000Z","dependencies_parsed_at":"2024-08-27T15:03:20.217Z","dependency_job_id":null,"html_url":"https://github.com/ExodusMovement/patch-broken-hermes-typed-arrays","commit_stats":null,"previous_names":["exodusmovement/patch-broken-hermes-typed-arrays"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Fpatch-broken-hermes-typed-arrays","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Fpatch-broken-hermes-typed-arrays/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Fpatch-broken-hermes-typed-arrays/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Fpatch-broken-hermes-typed-arrays/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ExodusMovement","download_url":"https://codeload.github.com/ExodusMovement/patch-broken-hermes-typed-arrays/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247305879,"owners_count":20917201,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T13:18:04.668Z","updated_at":"2025-04-05T07:32:31.477Z","avatar_url":"https://github.com/ExodusMovement.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `@exodus/patch-broken-hermes-typed-arrays`\n\nFix broken Hermes engine TypedArray implementation for React Native\n\nSimply:\n```js\nimport '@exodus/patch-broken-hermes-typed-arrays'\n```\n\n## What is this about?\n\nThe problem behind this issue:\n```js\n\u003e Buffer.alloc(10).subarray(0).toString('hex')\n'0,0,0,0,0,0,0,0,0,0'\n// What?\n```\n\nYou might be inclined to fix the specific location where this is throwing (e.g. with a\n`Buffer.from`), but that is a mistake.\n\nMost important: **it is very hard to track all those**.\n\n_Also, `Buffer.from(arg)` is a copy and inefficiency,\n`Buffer.from(x.buffer, x.byteOffset, x.byteLength)` is awkward, prone to human errors and can\ntrigger security checks for doing something on `buffer.buffer` manually (which is an unsafe\npractice, e.g. a mistype like `x.byteLegnth` can leak passwords/secrets to other users by exposing\nunrelated application memory). You don't want a ton of copies of that pattern in your codebase._\n\nFixing this on `Buffer` (e.g. by monkey-patching it) is also insufficient — your codebase could\ninclude multiple dependencies which bundled [buffer](https://www.npmjs.com/package/buffer), and all\nthose instances won't be fixed that way!\n\nAlso, this affects more than `Buffer` and more than `subarray` — Hermes engine doesn't implement\n[TypedArray](https://tc39.es/ecma262/#sec-%typedarray%-intrinsic-object) correctly.\n\ni.e. Hermes implementation of `TypedArray` doesn't follow these sections of the specification:\n * [ECMAScript® Language Specification, `%TypedArray%.prototype.subarray`](https://tc39.es/ecma262/#sec-%typedarray%.prototype.subarray)\n * [ECMAScript® Language Specification, `%TypedArray%.prototype.map`](https://tc39.es/ecma262/#sec-%typedarray%.prototype.map)\n * [ECMAScript® Language Specification, `%TypedArray%.prototype.filter`](https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter)\n * [ECMAScript® Language Specification, `%TypedArray%.prototype.slice`](https://tc39.es/ecma262/#sec-%typedarray%.prototype.slice)\n\n## The fix\n\nOverall, this module is just a glorified version of the following snippet (but with `.map`/`.filter`\nsupport and safeguards against Hermes updates, to detect if things change).\n\n```js\nTypedArray.prototype.subarray = function (...args) {\n  var arr = subarray.apply(this, args)\n  if (!this.constructor || arr.constructor === this.constructor) return arr\n  return new this.constructor(arr.buffer, arr.byteOffset, arr.length)\n}\n```\n\nNote: the above version might be not spec-compliant if Hermes implements resizable `TypedArray`s\nfrom ECMAScript 2024, or e.g. starts supporting `Symbol.Species`\n\nAlso the snippet above doesn't have a Hermes check, so it will also blindly patch arrays if you\nswitch to JavaScriptCore\n\n_This is why this module exists — it handles all that_\n\n## The problem, in more details\n\nE.g. with [buffer](https://www.npmjs.com/package/buffer):\n\n```js\n// ... import Buffer polyfill from https://npmjs.com/package/buffer\n// ... and a console.log polyfill\nconsole.log(Buffer.alloc(2).subarray(0, 1).constructor.name)\nconsole.log(Buffer.alloc(2).map(() =\u003e 1).constructor.name)\nconsole.log(Buffer.alloc(2).filter(() =\u003e true).constructor.name)\n```\n\n```console\n% node buftest.0.js                                         \nBuffer\nBuffer\nBuffer\n% jsc buftest.0.js \nBuffer\nBuffer\nBuffer\n% hermes buftest.0.js\nUint8Array\nUint8Array\nUint8Array\n```\n\n### This is not limited to `buffer`\n\n```js\n// Let's assume this will get transpiled for a demo, Hermes has no `class` support\n\nclass TestArray extends Uint16Array {\n  static instances = 0\n  constructor(...args) {\n    super(...args)\n    // console.log('We can do something here!')\n    TestArray.instances++ // count constructor calls\n    return this\n  }\n\n  hello() {\n    return 'hi there'\n  }\n}\n\nvar arr = new TestArray(10)\n// TestArray.instances: 1\n\nvar mapped = arr.map((_, i) =\u003e i * 10)\n// TestArray.instances: 2\n\nconsole.log(TestArray.instances) // 2 everywhere, but 1 in Hermes\nconsole.log(mapped.constructor.name) // 'TestArray' everywhere, but 'Uint16Array' in Hermes\nconsole.log(mapped.hello()) // throws in Hermes\n```\n\n## How do Jest-style tests work on Hermes here?\n\nSee [`@exodus/test`](https://github.com/ExodusMovement/test)\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexodusmovement%2Fpatch-broken-hermes-typed-arrays","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexodusmovement%2Fpatch-broken-hermes-typed-arrays","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexodusmovement%2Fpatch-broken-hermes-typed-arrays/lists"}