{"record":{"id":"7fc042b796381bef","repo":"oven-sh/bun","slug":"typename-name-this-true-accessors-requir","errorCode":null,"errorMessage":"${typeName}.${name}: `this: true` accessors require `sharedThis: true`","messagePattern":"(.+?)\\.(.+?): `this: true` accessors require `sharedThis: true`","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/codegen/generate-classes.ts","lineNumber":2000,"sourceCode":"    thunk(\n      classSymbolName(typeName, \"call\"),\n      `(global: &JSGlobalObject, callframe: &CallFrame) -> JSValue`,\n      `    host_fn::host_fn_static(global, callframe, ${T}::call)`,\n    );\n  }\n\n  // ── proto getters / setters / fns ────────────────────────────────────────\n  // Closure form (`|t, g, c| T::method(t, g, c)`) rather than bare `T::method`\n  // so `&mut T → &T` autoref/coercion applies — many user impls take `&self`.\n  {\n    const seen = new Map<string, string>();\n    const exportNames = name => zigExportName(seen, n => protoSymbolName(typeName, n), proto[name]);\n    for (const name in proto) {\n      const { getter, setter, fn, this: thisValue = false, passThis, DOMJIT } = proto[name];\n      const names = exportNames(name);\n\n      if (thisValue && !sharedThis && (names.getter || names.setter)) {\n        throw new Error(`${typeName}.${name}: \\`this: true\\` accessors require \\`sharedThis: true\\``);\n      }\n\n      if (names.getter) {\n        const id = rustSnakeIdent(getter);\n        thunk(\n          names.getter,\n          `(this: ${recv}, ${thisValue ? \"this_value: JSValue, \" : \"\"}global: &JSGlobalObject) -> JSValue`,\n          thisValue\n            ? `    host_fn::host_fn_getter_this_shared(this, this_value, global, |t, v, g| ${T}::${id}(t, v, g))`\n            : `    ${helper(\"host_fn_getter\")}(this, global, |t, g| ${T}::${id}(t, g))`,\n        );\n      }\n\n      if (names.setter) {\n        const id = rustSnakeIdent(setter);\n        thunk(\n          names.setter,\n          `(this: ${recv}, ${thisValue ? \"this_value: JSValue, \" : \"\"}global: &JSGlobalObject, value: JSValue) -> bool`,","sourceCodeStart":1982,"sourceCodeEnd":2018,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/codegen/generate-classes.ts#L1982-L2018","documentation":"generate-classes.ts supports `this: true` on proto accessors so a getter/setter receives the JS `this` value as an extra argument — but the generated thunk that forwards this_value only exists on the sharedThis code path (host_fn::host_fn_getter_this_shared). If a class definition opts out with `sharedThis: false` while a proto getter/setter uses `this: true`, the required thunk cannot be generated, so the generator rejects the combination. Note the generator default is sharedThis: true; this fires only on an explicit opt-out.","triggerScenarios":"Writing `const config = { sharedThis: false, proto: { get foo() { ... } } }` style definitions in a .classes.ts file — i.e. any proto getter/setter entry with `this: true` on a class whose definition explicitly sets `sharedThis: false`.","commonSituations":"Adding `this: true` to an accessor of an older class that predates the sharedThis default and carries an explicit `sharedThis: false`; migrating a mutable-self class to shared accessors without removing the opt-out.","solutions":["Remove the explicit `sharedThis: false` from the class definition so it uses the default shared this-handling the accessor requires","Or drop `this: true` from the getter/setter if the accessor does not actually need the JS receiver","Re-run codegen and confirm the generated host_fn_getter_this_shared thunk compiles"],"exampleFix":"// before (Foo.classes.ts)\nexport default {\n  sharedThis: false,\n  proto: { get owner() { /* this: true */ } },\n} as ClassDefinition<Foo>;\n\n// after\nexport default {\n  proto: { get owner() { /* this: true */ } },\n} as ClassDefinition<Foo>;","handlingStrategy":"validation","validationCode":"// check the combo before codegen: this:true accessors need sharedThis\nconst sharedThis = obj.sharedThis !== false; // generator default is true\nfor (const [name, prop] of Object.entries(obj.proto ?? {})) {\n  const p = prop as { this?: boolean; getter?: unknown; setter?: unknown };\n  if (p.this === true && !sharedThis && (p.getter || p.setter)) {\n    throw new Error(`${obj.name}.${name}: this:true accessor requires sharedThis`);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid explicit `sharedThis: false` on new classes — it exists only as an opt-out for un-migrated types","Any accessor that inspects the JS receiver needs `this: true`, which presupposes shared this-handling"],"tags":["codegen","classes","bindings","accessors"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}