CodeSampleX

Ejemplo

three 0.185.1: Prove BufferGeometry.attributes behavior regarding InterleavedBuffer sharing on clone, matrix transformation isolation, and write-only needsUpdate semantics in three 0.185.1.

Muestra verificada para npm three 0.185.1: Prove BufferGeometry.attributes behavior regarding InterleavedBuffer sharing on clone, matrix transformation…

sha256:ccf77a5f7c1d7339622c21cac780775cb81b2a9d16de462b90eb25a4a88382df

Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido. Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas. MIT-0

Evidencia de ejecución

El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.

Base de evidencia
Contrato firmado aprobado
Recibos de verificación
3
Claves de firma que lo compilaron
3
Entorno declarado node linux x64 node node npm

Entornos de las ejecuciones de verificación

Entorno Contrato Etapas Ejecución
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18
node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5…
2026-09-07

Caso

HOW
Objetivo
Prove BufferGeometry.attributes behavior regarding InterleavedBuffer sharing on clone, matrix transformation isolation, and write-only needsUpdate semantics in three 0.185.1.
Paquetes
Símbolos
  • BufferGeometry.attributes
Entorno
node
Creado
2026-08-18T00:48:17Z

Contrato

  1. BufferGeometry.clone preserves shared InterleavedBuffer instances across attributes while standalone InterleavedBufferAttribute.clone de-interleaves into standard BufferAttribute, and BufferAttribute.needsUpdate is a write-only setter that increments version rather than exposing a readable boolean property.
  2. BufferGeometry.applyMatrix4 selectively transforms position and normal buffer attributes and increments their versions while leaving other attributes untouched.
  3. BufferGeometry.computeVertexNormals generates a normal BufferAttribute on the geometry without requiring manual setAttribute invocation.
  4. Direct dictionary assignment to BufferGeometry.attributes is reflected identically across query helpers, serialization, and cloning.

Archivos

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • test/contract.mjs

Descargar el artefacto de código fuente (tar.gz)

Código fuente

NOTES.md
# three BufferGeometry.attributes behavior

## Prior Solution and Pinned Release

An initial search of known solutions returned sample `sha256:7af2379b90650905a89e1d9f8bc695ab98b906c41fb16742d1f4e118f4e5bc97`, which verified basic `setAttribute` and `deleteAttribute` interactions along with unrelated `BufferAttribute.getX`, `Object3D.traverse`, and `Texture.source` semantics.

This contract pins `three@0.185.1` exactly and verifies deeper memory layout, transformation isolation, and lifecycle behaviors of `BufferGeometry.attributes`.

## Observed Behaviors and Traps

1. **InterleavedBuffer sharing on clone vs standalone de-interleaving**:
   Calling `.clone()` directly on an `InterleavedBufferAttribute` de-interleaves the data into a non-interleaved `BufferAttribute`. However, when multiple `InterleavedBufferAttribute`s sharing a single `InterleavedBuffer` are assigned to `BufferGeometry.attributes`, calling `geometry.clone()` retains the shared `InterleavedBuffer` across the cloned attributes.

2. **Write-only `needsUpdate` setter**:
   `BufferAttribute.prototype.needsUpdate` is implemented solely as a setter that increments the internal `version` integer (`this.version++`). Reading `attr.needsUpdate` evaluates to `undefined`. Code expecting a boolean flag check (`if (attr.needsUpdate) ...`) fails silently.

3. **Selective transformation via `applyMatrix4`**:
   Calling `geometry.applyMatrix4(matrix)` specifically transforms `attributes.position` and `attributes.normal` (incrementing their `version`), leaving all other attributes in `geometry.attributes` (such as `uv` or custom attributes) untouched.

4. **Dynamic normal generation**:
   `geometry.computeVertexNormals()` automatically allocates and assigns a new `Float32BufferAttribute` to `geometry.attributes.normal` (or resets an existing matching buffer in place) using `attributes.position`.

5. **Direct dictionary reflections**:
   `BufferGeometry.attributes` is a standard JavaScript dictionary. Direct property assignments and deletions (`geometry.attributes.custom = attr`, `delete geometry.attributes.custom`) reflect consistently across `getAttribute()`, `hasAttribute()`, `toJSON()`, and `clone()`.
csx.json
{"case":{"believed":"Cloning an InterleavedBufferAttribute preserves its interleaved layout and BufferAttribute.needsUpdate is a readable boolean flag.","caseId":"case:sha256:432a86b9f80253955e369aa128b9b84e6e91b35d07ba35359405c3375ed96aec","contract":["BufferGeometry.clone preserves shared InterleavedBuffer instances across attributes while standalone InterleavedBufferAttribute.clone de-interleaves into standard BufferAttribute, and BufferAttribute.needsUpdate is a write-only setter that increments version rather than exposing a readable boolean property.","BufferGeometry.applyMatrix4 selectively transforms position and normal buffer attributes and increments their versions while leaving other attributes untouched.","BufferGeometry.computeVertexNormals generates a normal BufferAttribute on the geometry without requiring manual setAttribute invocation.","Direct dictionary assignment to BufferGeometry.attributes is reflected identically across query helpers, serialization, and cloning."],"goal":"Prove BufferGeometry.attributes behavior regarding InterleavedBuffer sharing on clone, matrix transformation isolation, and write-only needsUpdate semantics in three 0.185.1.","kind":"HOW","packages":["pkg:npm/three@0.185.1"],"schemaVersion":1,"symbols":["BufferGeometry.attributes"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/three@0.185.1"],"schemaVersion":1,"symbols":["BufferGeometry.attributes"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "npm-three-buffergeometry-attributes",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "npm-three-buffergeometry-attributes",
      "version": "1.0.0",
      "dependencies": {
        "three": "0.185.1"
      }
    },
    "node_modules/three": {
      "version": "0.185.1",
      "resolved": "https://registry.npmjs.org/three/-/three-0.185.1.tgz",
      "integrity": "sha512-5aojFCXKwnjBRZvUnt3WFfEcvUJgkN5LlijRFN95hMy8WVkG4I0QNcJE+OuWvuJ0bOdStrbfXn0pkd6/QyiAlg==",
      "license": "MIT"
    }
  }
}
package.json
{
  "name": "npm-three-buffergeometry-attributes",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node test/contract.mjs"
  },
  "dependencies": {
    "three": "0.185.1"
  }
}
test/contract.mjs
import assert from 'node:assert/strict';
import {
  BufferAttribute,
  BufferGeometry,
  InterleavedBuffer,
  InterleavedBufferAttribute,
  Matrix4,
} from 'three';

// 1. BufferGeometry.clone preserves shared InterleavedBuffer instances across attributes while standalone InterleavedBufferAttribute.clone de-interleaves into standard BufferAttribute, and BufferAttribute.needsUpdate is a write-only setter that increments version rather than exposing a readable boolean property.
{
  const bufferData = new Float32Array([
    // pos (xyz), uv (uv)
    0, 0, 0, 0.0, 0.0,
    1, 0, 0, 1.0, 0.0,
    0, 1, 0, 0.0, 1.0,
  ]);
  const interleaved = new InterleavedBuffer(bufferData, 5);
  const positionAttr = new InterleavedBufferAttribute(interleaved, 3, 0);
  const uvAttr = new InterleavedBufferAttribute(interleaved, 2, 3);

  // Standalone attr clone de-interleaves into a regular BufferAttribute
  const standaloneClone = positionAttr.clone();
  assert.equal(standaloneClone instanceof InterleavedBufferAttribute, false);
  assert.equal(standaloneClone instanceof BufferAttribute, true);
  assert.equal(standaloneClone.itemSize, 3);
  assert.equal(standaloneClone.count, 3);
  assert.equal(standaloneClone.array.length, 9);

  // When attached to BufferGeometry.attributes, geometry.clone() retains InterleavedBuffer sharing
  const geometry = new BufferGeometry();
  geometry.setAttribute('position', positionAttr);
  geometry.setAttribute('uv', uvAttr);

  assert.strictEqual(geometry.attributes.position, positionAttr);
  assert.strictEqual(geometry.attributes.uv, uvAttr);
  assert.strictEqual(geometry.attributes.position.data, geometry.attributes.uv.data);

  const clonedGeometry = geometry.clone();
  assert.ok(clonedGeometry.attributes.position instanceof InterleavedBufferAttribute);
  assert.ok(clonedGeometry.attributes.uv instanceof InterleavedBufferAttribute);
  assert.notStrictEqual(clonedGeometry.attributes.position.data, geometry.attributes.position.data);
  assert.strictEqual(clonedGeometry.attributes.position.data, clonedGeometry.attributes.uv.data);

  // needsUpdate is write-only: it increments version but yields undefined on read
  const regularAttr = new BufferAttribute(new Float32Array([1, 2, 3]), 3);
  assert.equal(regularAttr.version, 0);
  assert.equal(regularAttr.needsUpdate, undefined);
  regularAttr.needsUpdate = true;
  assert.equal(regularAttr.version, 1);
  assert.equal(regularAttr.needsUpdate, undefined);
}

// 2. BufferGeometry.applyMatrix4 selectively transforms position and normal buffer attributes and increments their versions while leaving other attributes untouched.
{
  const geometry = new BufferGeometry();
  const positions = new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
  const normals = new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1]);
  const uvs = new Float32Array([0.5, 0.25, 0.5, 0.75, 0.25, 0.5]);
  const custom = new Float32Array([10, 20, 30]);

  geometry.setAttribute('position', new BufferAttribute(positions, 3));
  geometry.setAttribute('normal', new BufferAttribute(normals, 3));
  geometry.setAttribute('uv', new BufferAttribute(uvs, 2));
  geometry.attributes.custom = new BufferAttribute(custom, 1);

  const mat = new Matrix4().makeScale(2, 2, 2).setPosition(0, 5, 0);
  geometry.applyMatrix4(mat);

  // Position is scaled and translated, version is incremented
  assert.equal(geometry.attributes.position.getX(0), 2);
  assert.equal(geometry.attributes.position.getY(0), 5);
  assert.equal(geometry.attributes.position.getZ(0), 0);
  assert.equal(geometry.attributes.position.version, 1);

  // UV and custom attributes in geometry.attributes are not touched (version remains 0)
  assert.equal(geometry.attributes.uv.getX(0), 0.5);
  assert.equal(geometry.attributes.uv.getY(0), 0.25);
  assert.equal(geometry.attributes.uv.version, 0);
  assert.equal(geometry.attributes.custom.getX(0), 10);
  assert.equal(geometry.attributes.custom.version, 0);
}

// 3. BufferGeometry.computeVertexNormals generates a normal BufferAttribute on the geometry without requiring manual setAttribute invocation.
{
  const geometry = new BufferGeometry();
  geometry.setAttribute('position', new BufferAttribute(new Float32Array([
    0, 0, 0,
    1, 0, 0,
    0, 1, 0,
  ]), 3));

  assert.equal(geometry.attributes.normal, undefined);
  geometry.computeVertexNormals();

  assert.ok(geometry.attributes.normal instanceof BufferAttribute);
  assert.equal(geometry.attributes.normal.count, 3);
  assert.equal(geometry.attributes.normal.itemSize, 3);
  assert.equal(geometry.attributes.normal.getX(0), 0);
  assert.equal(geometry.attributes.normal.getY(0), 0);
  assert.equal(geometry.attributes.normal.getZ(0), 1);
}

// 4. Direct dictionary assignment to BufferGeometry.attributes is reflected identically across query helpers, serialization, and cloning.
{
  const geometry = new BufferGeometry();
  const attr = new BufferAttribute(new Float32Array([1, 2, 3]), 3);
  geometry.attributes.velocity = attr;

  assert.strictEqual(geometry.getAttribute('velocity'), attr);
  assert.equal(geometry.hasAttribute('velocity'), true);

  const json = geometry.toJSON();
  assert.ok(json.data.attributes.velocity !== undefined);
  assert.deepEqual(json.data.attributes.velocity.array, [1, 2, 3]);

  delete geometry.attributes.velocity;
  assert.equal(geometry.hasAttribute('velocity'), false);
  assert.strictEqual(geometry.getAttribute('velocity'), undefined);
}

Seeder de origen

csx-seed