isPrototypeOf({}) in devtools console will throw TypeError

Open devtools, paste isPrototypeOf({}); into console, run the code and you will get:

Uncaught TypeError: Cannot convert undefined or null to object

I think the error message tells us: this in isPrototypeOf is undefined. But why? why doesn’t this substitution take place in this situation? Why is this not window?

Why isn’t my recorded audio being sent to OpenAI’s Whisper API for transcription in my Wix Velo integration?

Context / What I’m trying to do

I’m building a chat interface on Wix using a custom web component and an iframe for the chat UI. The idea is:

  1. User clicks “Record” in the iframe → message sent to parent page (since Wix doesnot allow iframe to do the recording)

  2. Parent page tells to start/stop recording via an action attribute

  3. Recorder captures WebM audio

  4. converts it to MP3 with lamejs, and exposes a Base64 data-URL

  5. User clicks “Upload” in the recorder → Base64 audio is postMessage-ed back to parent

(I upload the MP3 to CMS only to get a public URL; this isn’t actually needed for storage, it’s just to generate a URL. This attempt also did not work)

  1. Parent page calls my backend transcribeAudioFromUrl(publicUrl) (which hits OpenAI’s Whisper API)

  2. Transcript is injected back into the chat iframe input and sent off to the Chat API

Steps 1–3 seem to work (I see a public MP3 URL and can play it back), but the transcription never happens.

Relevant code

  1. Frontend listener in Wix page code
// in $w.onReady(...)
globalThis.addEventListener("message", async (event) => {
  const { type, audio } = event.data || {};

  if (type === "audioMessage" && audio) {
    try {
      // 1) Upload Base64 → Wix Media (only to get a public URL)
      const fileUrl   = await uploadAudioFromBase64(audio);
      const publicUrl = await getDownloadUrl(fileUrl);

      // 2) Show user audio in chat
      $w("#chatFrame").postMessage({ name: "User", audio: publicUrl });

      // 3) Transcribe via Whisper
      const transcript = await transcribeAudioFromUrl(publicUrl);

      // 4) Inject transcript and ask AI
      $w("#chatFrame").postMessage({ type: "setInputField", text: transcript });
      const reply = await getAnswerFromAI(transcript);
      $w("#chatFrame").postMessage({ name: "OpenAI", text: reply });
    } catch (err) {
      console.error("Upload or transcription error:", err);
      $w("#chatFrame").postMessage({
        name: "OpenAI",
        text: "❌"
      });
    }
  }
});
  1. Wix backend
import { webMethod, Permissions } from 'wix-web-module';
import { getSecret } from 'wix-secrets-backend';
import axios from 'axios';
const FormData = require('form-data');

// Helper: convert wix:document URL → public HTTPS URL
async function ensurePublicUrl(url) {
  if (/^wix:document:///.test(url)) {
    return await mediaManager.getDownloadUrl(url);
  }
  return url;
}

// Send binary buffer → Whisper API
async function whisperTranscription(buffer, mimeType) {
  const apiKey = await getSecret('OPENAI-API-KEY');
  const form = new FormData();
  form.append('file', buffer, { filename: 'recording', contentType: mimeType });
  form.append('model', 'whisper-1');
  form.append('response_format', 'text');
  const { data } = await axios.post(
    'https://api.openai.com/v1/audio/transcriptions',
    form,
    { headers: { ...form.getHeaders(), Authorization: `Bearer ${apiKey}` } }
  );
  return data;
}

export const transcribeAudioFromUrl = webMethod(Permissions.Anyone, async (url) => {
  const publicUrl = await ensurePublicUrl(url);
  const res = await axios.get(publicUrl, { responseType: 'arraybuffer' });
  return whisperTranscription(Buffer.from(res.data), 'audio/mp3');
});
</details>
  1. Recorder Costum Element
async handleStop() {
    const blob = new Blob(this.audioChunks, { type: 'audio/webm' });
    const arrayBuffer = await blob.arrayBuffer();
    const mp3Blob = await this.convertToMp3(arrayBuffer);
    this.lastMp3Blob = mp3Blob;

    // show preview + enable upload…
    this.uploadBtn.disabled = false;
  }

  uploadRecording() {
    if (!this.lastMp3Blob) return;
    const reader = new FileReader();
    reader.onloadend = () => {
      const base64 = reader.result;
      window.parent.postMessage({ type: 'audioMessage', audio: base64 }, '*');
      this.uploadBtn.textContent = '✅ Uploaded!';
      this.uploadBtn.disabled = true;
    };
    reader.readAsDataURL(this.lastMp3Blob);
  }

  // … convertToMp3() & floatTo16BitPCM() using lamejs …
}

If more details needed just let me know.

Error regarding Expo go on my Android Device linked to a react native project in visual studio

i started a new react native project on visual studio and downloaded Expo go in my android device
When i initialized the app through npx expo start it bundled perfectly for the first time on
the expo go
but then when i deleted the default index.js and App.js file and installed expo router and created an app folder with an index.jsx file in the project directory changed the entry point in package.json to
“main”: “expo-router/entry” and added scheme in app.json
the app is getting bundled in terminal
Android Bundled 1662ms node_modulesexpo-routerentry.js (1029 modules)
but it is giving an error on expo go
which is:
exception thrown when executing UIframeGuarded

attempt to invoke interface method ‘void com.facebook.react.uimanager.ViewManagerDelegate.setProperty(android.view.View,java.lang.String,java.lang.object) on a null object reference

i have made a simple todo app through same method just a week before it worked fine but now
this is giving an error at beginning only
please if anyone can help

I am having collision problems with a map glb file in three.js

I have a map glb file. I’ve taken the skeld map from Among Us for walking around in and for some reason I can’t collide with it properly. For example I can’t walk on the floor, only on the ceiling plane.

My best guess is that the floor collision mesh is offset vertically but even after fixing it it doesn’t work. I’d love some help.

I’m new to three.js and javascript in general so a lot of it is vibe coding so please forgive me if the answer is obvious. Here’s my main.js file:

import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls.js';
import * as CANNON from 'cannon-es';

const PLAYER_RADIUS = 1;
const MOVE_SPEED = 10;
const SCALE_FACTOR = 20;
const JUMP_FORCE = 10;

let canJump = true;

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x222222);

const camera = new THREE.PerspectiveCamera(
  75, window.innerWidth / window.innerHeight, 0.1, 1000
);
camera.position.set(0, PLAYER_RADIUS, 0);

const renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);

scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 0.6));
const dir = new THREE.DirectionalLight(0xffffff, 0.8);
dir.position.set(5, 10, 7.5);
dir.castShadow = true;
scene.add(dir);

const world = new CANNON.World({
  gravity: new CANNON.Vec3(0, -9.82, 0)
});
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 20;
world.solver.tolerance = 0.001;

const playerBody = new CANNON.Body({
  mass: 1,
  fixedRotation: true,
  linearDamping: 0.9
});
playerBody.addShape(new CANNON.Sphere(PLAYER_RADIUS));
world.addBody(playerBody);

const controls = new PointerLockControls(camera, renderer.domElement);
scene.add(controls.getObject());
const blocker = document.getElementById('blocker');
blocker.addEventListener('click', () => controls.lock());
controls.addEventListener('lock', () => blocker.style.display = 'none');
controls.addEventListener('unlock', () => blocker.style.display = '');

const move = {
  forward: 0,
  back: 0,
  left: 0,
  right: 0
};
window.addEventListener('keydown', e => {
  if (e.code === 'KeyW') move.forward = 1;
  if (e.code === 'KeyS') move.back = 1;
  if (e.code === 'KeyA') move.left = 1;
  if (e.code === 'KeyD') move.right = 1;
  if (e.code === 'Space' && canJump) {
    playerBody.velocity.y = JUMP_FORCE;
    canJump = false;
  }
});
window.addEventListener('keyup', e => {
  if (e.code === 'KeyW') move.forward = 0;
  if (e.code === 'KeyS') move.back = 0;
  if (e.code === 'KeyA') move.left = 0;
  if (e.code === 'KeyD') move.right = 0;
});

const groundRay = new CANNON.Ray(
  new CANNON.Vec3(),
  new CANNON.Vec3(0, -1, 0)
);
groundRay.mode = CANNON.Ray.CLOSEST;
groundRay.skipBackfaces = true;

new GLTFLoader().load(
  'amongusSkeld.glb',
  ({
    scene: map
  }) => {
    map.scale.set(SCALE_FACTOR, SCALE_FACTOR, SCALE_FACTOR);
    map.updateMatrixWorld(true);
    scene.add(map);

    const vertices = [];
    const indices = [];
    let vOff = 0;

    map.traverse(node => {
      if (!node.isMesh) return;
      const geom = node.geometry.clone();
      geom.applyMatrix4(node.matrixWorld);
      const pa = geom.attributes.position;
      for (let i = 0; i < pa.count; i++) {
        vertices.push(pa.getX(i), pa.getY(i), pa.getZ(i));
      }
      if (geom.index) {
        const ix = geom.index;
        for (let i = 0; i < ix.count; i += 3) {
          indices.push(
            ix.getX(i) + vOff,
            ix.getX(i + 1) + vOff,
            ix.getX(i + 2) + vOff
          );
        }
      } else {
        for (let i = 0; i < pa.count; i += 3) {
          indices.push(vOff + i, vOff + i + 1, vOff + i + 2);
        }
      }
      vOff += pa.count;
    });
    console.log(`Merged collision mesh: ${vertices.length/3} verts, ${indices.length/3} tris`);

    const triShape = new CANNON.Trimesh(vertices, indices);
    const mapBody = new CANNON.Body({
      mass: 0
    });
    mapBody.addShape(triShape);
    world.addBody(mapBody);

    const colGeom = new THREE.BufferGeometry();
    colGeom.setAttribute('position',
      new THREE.BufferAttribute(new Float32Array(vertices), 3)
    );
    colGeom.setIndex(indices);
    const colMat = new THREE.MeshBasicMaterial({
      color: 0xff0000,
      wireframe: true,
      transparent: true,
      opacity: 0.5
    });
    const colMesh = new THREE.Mesh(colGeom, colMat);
    scene.add(colMesh);

    const bbox = new THREE.Box3().setFromObject(map);
    const {
      min,
      max
    } = bbox;
    const center = bbox.getCenter(new THREE.Vector3());

    const rayFrom = new CANNON.Vec3(center.x, max.y + SCALE_FACTOR, center.z);
    const rayTo = new CANNON.Vec3(center.x, min.y - SCALE_FACTOR, center.z);
    const ray = new CANNON.Ray(rayFrom, rayTo);
    const result = new CANNON.RaycastResult();

    ray.intersectWorld(
      world, {
        mode: CANNON.Ray.CLOSEST,
        skipBackfaces: true
      },
      result
    );

    const spawnY = result.hasHit ?
      result.hitPointWorld.y + PLAYER_RADIUS + 0.1 :
      max.y + PLAYER_RADIUS + 0.1;

    playerBody.position.set(center.x, spawnY, center.z);
    controls.getObject().position.set(center.x, spawnY, center.z);
    console.log(`Spawn at Y=${spawnY.toFixed(2)}, hit at Y=${result.hasHit ? result.hitPointWorld.y.toFixed(2) : 'none'}`);
  },
  xhr => console.log(`Loading map: ${(xhr.loaded/xhr.total*100).toFixed(1)}%`),
  err => console.error('Map load error:', err)
);

const clock = new THREE.Clock();
const FIXED_DT = 1 / 60;
const euler = new THREE.Euler(0, 0, 0, 'YXZ');
const quat = new THREE.Quaternion();

function animate() {
  requestAnimationFrame(animate);
  const dt = clock.getDelta();

  groundRay.from.copy(playerBody.position);
  groundRay.to.copy(playerBody.position);
  groundRay.to.y -= PLAYER_RADIUS + 0.1;
  const result = new CANNON.RaycastResult();
  groundRay.intersectWorld(world, {}, result);
  canJump = result.hasHit && result.distance < PLAYER_RADIUS + 0.1;

  if (controls.isLocked) {
    const forward = new THREE.Vector3();
    camera.getWorldDirection(forward);
    forward.y = 0;
    forward.normalize();

    const rightDir = new THREE.Vector3();
    rightDir.crossVectors(forward, new THREE.Vector3(0, 1, 0)).normalize();

    const moveDir = new THREE.Vector3();
    moveDir.addScaledVector(forward, move.forward - move.back);
    moveDir.addScaledVector(rightDir, move.right - move.left);

    if (moveDir.lengthSq() > 0) {
      moveDir.normalize().multiplyScalar(MOVE_SPEED);
      playerBody.velocity.x = moveDir.x;
      playerBody.velocity.z = moveDir.z;
    }

    controls.getObject().position.copy(playerBody.position);
  }

  world.step(FIXED_DT, dt, 10);
  renderer.render(scene, camera);
}
animate();

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

[vite]: Rollup failed to resolve import “cloudflare:sockets” from “/home/runner/work/texhub-web/texhub-web/node_modules/pg-cloudflare/dist/index.js”

Today when I want to build the project, shows error:

[plugin:vite:resolve] [plugin vite:resolve] Module "fs" has been externalized for browser compatibility, imported by "/home/runner/work/texhub-web/texhub-web/node_modules/pg-connection-string/index.js". See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.
[plugin:vite:resolve] [plugin vite:resolve] Module "stream" has been externalized for browser compatibility, imported by "/home/runner/work/texhub-web/texhub-web/node_modules/split2/index.js". See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.
✓ 3117 modules transformed.
x Build failed in 10.41s
error during build:
[vite]: Rollup failed to resolve import "cloudflare:sockets" from "/home/runner/work/texhub-web/texhub-web/node_modules/pg-cloudflare/dist/index.js".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
    at viteWarn (file:///home/runner/work/texhub-web/texhub-web/node_modules/vite/dist/node/chunks/dep-C6uTJdX2.js:65839:17)
    at onwarn (file:///home/runner/work/texhub-web/texhub-web/node_modules/@vitejs/plugin-react/dist/index.mjs:102:9)
    at onRollupWarning (file:///home/runner/work/texhub-web/texhub-web/node_modules/vite/dist/node/chunks/dep-C6uTJdX2.js:65869:5)
    at onwarn (file:///home/runner/work/texhub-web/texhub-web/node_modules/vite/dist/node/chunks/dep-C6uTJdX2.js:65534:7)
    at file:///home/runner/work/texhub-web/texhub-web/node_modules/rollup/dist/es/shared/node-entry.js:20723:13
    at Object.logger [as onLog] (file:///home/runner/work/texhub-web/texhub-web/node_modules/rollup/dist/es/shared/node-entry.js:22588:9)
    at ModuleLoader.handleInvalidResolvedId (file:///home/runner/work/texhub-web/texhub-web/node_modules/rollup/dist/es/shared/node-entry.js:21335:26)
    at ModuleLoader.resolveDynamicImport (file:///home/runner/work/texhub-web/texhub-web/node_modules/rollup/dist/es/shared/node-entry.js:21393:58)
    at async file:///home/runner/work/texhub-web/texhub-web/node_modules/rollup/dist/es/shared/node-entry.js:21281:32
    at async Promise.all (index 4)
Error: Process completed with exit code 1.

then I use this command to check the dependencies:

➜  texhub-web git:(main) pnpm list pg-cloudflare --depth=Infinity

Legend: production dependency, optional only, dev only

[email protected] /Users/xiaoqiangjiang/source/reddwarf/frontend/texhub-web (PRIVATE)

dependencies:
texhub-broadcast 1.0.69
└─┬ pg 8.15.6
  └── pg-cloudflare 1.2.5

then I added the exclude config in vite.config.mts like this:

build: {
    outDir: "build",
    sourcemap: "hidden",
    rollupOptions: {
      output: {
        sourcemapExcludeSources: false,
        manualChunks: {
          react: ["react", "react-router-dom", "react-dom"],
          reddwarf: ["rd-component", "rdjs-wheel"],
        },
      },
      // https://github.com/brianc/node-postgres/issues/2987
      external: ["pg-cloudflare"],
    },
  }

shows error like this:

Uncaught TypeError: The specifier “pg-cloudflare” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”.

why did this happend? what should I do to fixed this problem?

When i use position “fixed” image disappears

hello everyone i have an issue. I`m working on tailwind when i use fixed img disappears can anyone explain why ?!

<div style="backdrop-filter: blur(10px);" class="p-3 w-full border-b fixed border-[#E4E4E7]">
  <div class="flex justify-between mx-3">
    <div class="p-2 rounded-xl bg-[#564DE6] transition-all duration-50">
      <button class="text-white">
        Add new 
      </button>
    </div>
    <div class="border z-50 border-[#bebec3] rounded-[50%] flex cursor-pointer">
      <img class="p-1" width="38" src="img/smart.png" alt="Logo" />
    </div>
  </div>
</div>

Twitter / X – upload media via v2 endpoints

twitter deprecated command parameter soon. Launching separate endpoints for each command rather. I am working on Javascript

Source: https://docs.x.com/x-api/media/media-upload-initialize

My code fails at Finalize step – stating total file size does not match.
Following is code for APPEND

        var media_id = result.data.id;    
        var url = 'https://api.x.com/2/media/upload/' + media_id + '/append';
        var chunkSize = 5*1000*1000  
        var chunkCount = Math.ceil(totalSize / chunkSize);  
        var boundary = '011000010111000001101001'
         
    
        for (var segmentIndex = 0; segmentIndex < chunkCount; segmentIndex++) {
            
            var startByte = segmentIndex * chunkSize;
            var endByte = Math.min(startByte + chunkSize, totalSize);
            var chunkBytes = videoBlob.getBytes().slice(startByte, endByte); 
    
            var part1 = "--" + boundary + 'rnContent-Disposition: form-data; name="segment_index"rnrn';
            var part2 = "--" + boundary + 'rnContent-Disposition: form-data; name="media"; filename="CHUNK.mp4"rnContent-Type: video/mp4rnrn';
            var part3 = "rn--" + boundary + "--";
    
            // Convert string parts to bytes
            var part1Bytes = Utilities.newBlob(part1).getBytes();
            var segmentIndexBytes = Utilities.newBlob(String(segmentIndex + 1) + "rn").getBytes();
            var part2Bytes = Utilities.newBlob(part2).getBytes();
            var part3Bytes = Utilities.newBlob(part3).getBytes();
    
            var totalLength = part1Bytes.length + segmentIndexBytes.length + part2Bytes.length + chunkBytes.length + part3Bytes.length;
            var fullBody = new Uint8Array(totalLength);
    
            fullBody.set(part1Bytes, 0);
            fullBody.set(segmentIndexBytes, part1Bytes.length);
            fullBody.set(part2Bytes, part1Bytes.length + segmentIndexBytes.length);
            fullBody.set(chunkBytes, part1Bytes.length + segmentIndexBytes.length + part2Bytes.length);
            fullBody.set(part3Bytes, part1Bytes.length + segmentIndexBytes.length + part2Bytes.length + chunkBytes.length);
            
            
            var parameters = {
              'headers': {
                'Authorization': 'Bearer ' + serviceTw.getAccessToken(),
                'Content-Type': 'multipart/form-data; boundary=' + boundary ,
              },
              'payload': fullBody,
              'method': 'POST',
            };
             
              var response = UrlFetchApp.fetch(url, parameters);
    }

Any idea why its failing? although logging the byte counts , everything matches exactly

Dynamically Populating Chrome Context Menu Items via Extension

I’m building a Chrome extension with the Plasmo and Supabase, where I fetch data from whenever the browser’s context menu is opened, using a broadcasted contextmenu event. I aim to dynamically update context menu items (child elements) with the fetched data.

The problem is that on the first right-click, the context menu shows the correct number of child items, but their titles reflect outdated data (e.g., from a previous fetch or initial state). Only on the second context menu open do the titles update correctly with the latest data.

How can I ensure that the context menu items are updated with fresh data immediately on the first open? I was trying different approaches without any luck so far.

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'refresh-context-menu') {
    chrome.contextMenus.removeAll(() => {
    fetchUserLinks().then(links => {
        chrome.contextMenus.create({
          id: "context-menu",
          title: "ExtensionName",
          contexts: ["editable"]
        }, () => {
          chrome.contextMenus.create({
            id: "my-links",
            parentId: "context-menu",
            title: "My Links",
            contexts: ["editable"]
          }, () => {
            links.forEach((link, index) => {
              chrome.contextMenus.create({
                id: `link-${index}`,
                parentId: "my-links",
                title: link.short_name,
                contexts: ["editable"]
              })
            })
          })
        })
      })
    })
  }
})

Dropdown copying same value in other dropdown due to unique key

I have two dropdowns. Each one is rendering dynamically based on number of rows. Lets say two rows here. The issue is when I select one dropdown then same value is getting copied to other dropdown. I think this is due to same key but how do I make this work as same key is used to fetch value from static.json file. Thanks in advance.

const IdTypes = [
{
    label: 'Identifications Type',
    key: 'typeCd',
    options: [] as string[],
    type: 'select',
},

]

const rows = ['0001', '0002']


    {rows.map((seq, index) => (
<Grid container spacing={1}>
{IdTypes.map((field) => {
      { field.options = [] }
   {
      getDropdownData(jsonData, 'typeCd').map(item => {
           field.options?.push(item.cd + ' - ' + item.desc)
     })
   }
   return (
   <Grid item key={index}>
     {renderField(field)}
   </Grid>
  )
 })}
</Grid>
)}

const renderField = (field: any) => {
   const { label, type, key, options } = field
    if (type === 'select') {
     return (
      <Controller
          name={key}
          control={control}
          render={({ field }) => (
          <FormControl size='small' fullWidth>
          <InputLabel>{label}</InputLabel>
          <Select {...field} label={label}>
          {(options || []).map((option: string, index: any) => (
          <MenuItem key={index} value={option.split('-')[0].trim()}>
             {option}
          </MenuItem>
          ))}
         </Select>
     </FormControl>
     )}
     />
     )
}

getDropdownData is a utility that gives description based on the key we pass.

How to encrypt form-data fields using node-forge before sending to API?

I’m working on a signup API where I’m using form-data to send user data (name, email, password, profile picture etc.).I am using NextJs on the client side. On the server side, I’m using node-forge for encryption and decryption.

I want to encrypt payload on the client-side using node-forge before sending them to the server.

I’m using Node.js on the backend and consuming the API from a frontend web app.

What is the proper way to implement support for N shadowmaps in webGPU renderer?

I`m making a basic forward renderer in webGPU, that supports multiple types of light sources and shadowmapping. When I was figuring out the shadowmapping part, I bound shadowmaps to shadowpass, wrote depth values to them and then read those values in the render pass. Everything worked fine, but I had a hardcoded amount of lights (1 of each type).

Now I want to be able to add and remove lights at runtime, but can not figure out how. The algorithm i am trying now is for each light type (point, directional, spot), take spotlights for example:

  1. Bind a texture_depth_2d_array as depth texture to the spotlights shadow pass.
        const depthTextureSpot = this._device.createTexture({
            dimension: '2d',
            size: [512, 512, scene.spotLights.length || 1],
            format: 'depth32float',
            usage:
                GPUTextureUsage.TEXTURE_BINDING |
                GPUTextureUsage.COPY_DST |
                GPUTextureUsage.RENDER_ATTACHMENT,
        })

        const depthTextureSpotView = depthTextureSpot.createView({
            dimension: '2d-array',
        })

        const spotLightShadowPass = commandEncoder.beginRenderPass({
            colorAttachments: [],
            depthStencilAttachment: {
                view: depthTextureSpotView,
                depthClearValue: 1.0,
                depthLoadOp: 'clear',
                depthStoreOp: 'store',
            },
        })
  1. Calculate depth values from each light’s pov and store them in the corresponding “texture” in texture_depth_2d_array, so i have shadowmaps for all lights of this type (this code doesn’t work).
@vertex
fn vertex_main(vert: VertexInput) -> @builtin(position) vec4f {

    for (var i = 0u; i < arrayLength(&pointLightsBuffer.lights); i++) {
        let light_view_projection_matrix = 
            pointLightsBuffer.lights[i].light_projection_matrix * pointLightsBuffer.lights[i].light_view_matrix;

        return light_view_projection_matrix * node_params.transform * float4(vert.position, 1.0);
    };
    return float4(vert.position, 1.0);
};
  1. Pass the resulting texture_depth_2d_array to render pass and read depth values to calculate final color.

I am facing a problem in step 2, because there seems to be no way to write depth values to an arbitrary place in texture_depth_2d_array. Or if there is, i can’t figure it out. As far as i understand, the only type of texture to allow it is texture_storage_2d_array, but then there`s a problem of where do i get depth values from.

All the tutorials and papers I’ve read online so far, deal with a predefined amount of lights and have a separate render pass for each individual light.

The actual question is: is my approach even viable? If it is, then how to overcome obstacles described above? And if it isn’t (which is the case, most likely), what is the standard approach to rendering N lights with shadowmaps in webGPU?

Can @typedef describe objects partially

I have a message object that can have all kinds of keys, some of which I know, some of them I can’t know.

// @ts-check
/**
 * @typedef {Object} Message
 * @property {String} sender
 * @property {String} receiver
*/

/** @type {Message} */
let msg = {
  sender: "preference-manager",
  receiver: "user-manager",
  deletePref: "refresh-rate"
}

I get an error message:

Object literal may only specify known properties, and ‘deletePref’ does not exist in type ‘Message’.ts(2353)

Is there a way to define an incomplete type so that TypeScript compiler won’t complain?

P.S. I use tsc to improve type safety of the JS code, but it still has to be valid JS.

Ambiguous information about WebGL clip space

I am reading about WebGL clip space, I think it basically should mean the same thing as coordinate system. The same site specifies ambiguous, information.
In WebGL basics is specified left hand system, where z aux goes from -1 to 1:
WebGL basics clip space
enter image description here.

But in WebGL game development basics the coordinate system is specified as right handed, like in OpenGL where z axis goes in opposite direction, from 1 to -1:
WegGL game development coordinate system.
enter image description here
Which variant is the correct one? What I’ve practically seen so far, it was consistent with left handed.

skip number +=2. why? [closed]

I want to go to next number of my page. When I select for example row 10 every thing is ok and 20 as well. But when I select 10 or 20 or 50, and then change to another number of row, my page number skip +=2.

My problem is occurred when I shift to another row number for showing numbers. this project is the page for numbers and has 189 rows and you can see the numbers by 10 rows or 20 rows or 50 rows. I create the right angle for next and left angle for previous. I want to go 1 by 1 when I click on “>”or “<“

// this code is related to bottom of mobile number page for showing the number of rows
const toggleVisibility = () => {
    let tfootTdInput = document.querySelector(".tfoot-td-input"); // the number between <>
    tfootTdInput.value = "1";
    let tfootRow = document.getElementById("tfoot-row");
    let selectedValue = tfootRow.value;
    let hidden1 = document.querySelectorAll(".hidden1-10");
    let hidden11 = document.querySelectorAll(".hidden11-20");
    let hidden111 = document.querySelectorAll(".hidden111-50");



    if (selectedValue == 10) {

        hidden1.forEach(tr => {
            tr.style.display = "table-row"; //  show rows
        });

        let currentStartRow = 1; // the number for starting row
        const rowsPerPage = 10; // count of roes' number in each page
        const totalRows = 388; // number of all rows
        const rightAngleClick = document.querySelector("#tfootangleRight");
        const leftAngleClick = document.querySelector("#tfootangleLeft");
        const skipFirstPageNumber = document.querySelector("#skipFirstPageNumber");
        const skipLastPageNumber = document.querySelector("#skipLastPageNumber");


        const updateRowVisibility = () => {
            // hide rows
            const allRows = document.querySelectorAll('tr.display-none');
            allRows.forEach(td => {
                td.style.display = 'none';
            });

            // counting new rows for showing
            const endRow = Math.min(currentStartRow + rowsPerPage - 1);
            for (let i = currentStartRow; i <= endRow; i++) {
                const rowToShow = document.querySelector(`.hidden${i}`);
                if (rowToShow) {
                    rowToShow.style.display = 'table-row'; // show row
                }

            }
            if (tfootTdInput.value == "1") {
                leftAngleClick.style.visibility = "hidden";
                skipFirstPageNumber.style.visibility = "hidden";
            }
            else if (tfootTdInput.value == "18") {
                rightAngleClick.style.visibility = "visible";
                skipLastPageNumber.style.visibility = "visible";
            }

            else {
                leftAngleClick.style.visibility = "visible";
                skipFirstPageNumber.style.visibility = "visible";

            }


        };

        // this function is for (>) button
            rightAngleClick.addEventListener("click", () => {
                // extend the number of row

                currentStartRow += rowsPerPage;
                currentStartRow > totalRows ? currentStartRow = totalRows : currentStartRow; // for avoiding of becomming row number bigger than number row(388)
                tfootTdInput.value ++;

                if (tfootTdInput.value == "19 ") {
                    rightAngleClick.style.visibility = "hidden";
                    skipLastPageNumber.style.visibility = "hidden";
                }

                updateRowVisibility(); // updating the view of number page
            });

        // this function is for (<) button
        leftAngleClick.addEventListener("click", () => {

            currentStartRow -= rowsPerPage;

            if (currentStartRow < 1) {
                currentStartRow = 1; // for avoiding of becomming row number smaller than 1

            }
            tfootTdInput.value--;


            updateRowVisibility(); // updating the view of number page

        });

        // at first updating the view of number page
        updateRowVisibility();

        skipFirstPageNumber.addEventListener('click', () => {    //skip to first page of numbers

            leftAngleClick.style.visibility = "hidden";
            skipFirstPageNumber.style.visibility = "hidden";
            const allRows = document.querySelectorAll('tr.display-none');
            allRows.forEach(td => {
                td.style.display = 'none';
            });
            tfootTdInput.value = 1;
            hidden1.forEach(tr => {

                tr.style.display = "table-row"
            });
            rightAngleClick.style.visibility = "visible";
            skipLastPageNumber.style.visibility = "visible";
        })

        skipLastPageNumber.addEventListener('click', () => {     //skip to last page of numbers

            rightAngleClick.style.visibility = "hidden";
            skipLastPageNumber.style.visibility = "hidden";
            const allRows = document.querySelectorAll('tr.display-none');
            allRows.forEach(td => {
                td.style.display = 'none';
            });
            tfootTdInput.value = 19;
            leftAngleClick.style.visibility = "visible";
            skipFirstPageNumber.style.visibility = "visible";
            const lastPageNum10 = document.querySelectorAll(".hidden181-189");
            lastPageNum10.forEach(tr => {
                tr.style.display = "table-row"
            })

        })
        










    }
    else if (selectedValue == 20) {
        hidden11.forEach(tr => {
            tr.style.display = "table-row"; // نمایش hidden11
        });





        let tfootTdInput = document.querySelector(".tfoot-td-input"); // the number between <>
        let currentStartRow = 1; // the number for starting row
        const rowsPerPage2 = 20; // count of roes' number in each page
        const totalRows = 388; // number of all rows
        const rightAngleClick = document.querySelector("#tfootangleRight");

        const updateRowVisibility = () => {
            // hide rows
            const allRows = document.querySelectorAll('tr.display-none');
            allRows.forEach(td => {
                td.style.display = 'none';
            });

            // counting new rows for showing
            const endRow = Math.min(currentStartRow + rowsPerPage2 - 1);
            for (let i = currentStartRow; i <= endRow; i++) {
                const rowToShow = document.querySelector(`.hidden${i}`);
                if (rowToShow) {
                    rowToShow.style.display = 'table-row'; // show row
                }

            }
            if (tfootTdInput.value == "1") {
                tfootangleLeft.style.visibility = "hidden";
                skipFirstPageNumber.style.visibility = "hidden";
            }
            else if (tfootTdInput.value == "10") {
                rightAngleClick.style.visibility = "hidden";
                skipLastPageNumber.style.visibility = "hidden";
            }

            else if (tfootTdInput.value == "9") {
                rightAngleClick.style.visibility = "visible";
                skipLastPageNumber.style.visibility = "visible";
            }

            else {
                tfootangleLeft.style.visibility = "visible";
                skipFirstPageNumber.style.visibility = "visible";

            }



        };

        // this function is for (>) button
        rightAngleClick.addEventListener("click", () => {
            // extend the number of row
            currentStartRow += rowsPerPage2;
            if (currentStartRow > totalRows) {
                currentStartRow = totalRows; // for avoiding of becomming row number bigger than number row(388)
            }
            tfootTdInput.value++;


            updateRowVisibility(); // updating the view of number page
        });

        // this function is for (<) button
        tfootangleLeft.addEventListener("click", () => {

            currentStartRow -= rowsPerPage2;

            if (currentStartRow < 1) {
                currentStartRow = 1; // for avoiding of becomming row number smaller than 1

            }
            tfootTdInput.value--;

            updateRowVisibility(); // updating the view of number page

        });

        // at first updating the view of number page
        updateRowVisibility();


        skipFirstPageNumber.addEventListener('click', () => {    //skip to first page of numbers

            leftAngleClick.style.visibility = "hidden";
            skipFirstPageNumber.style.visibility = "hidden";
            const allRows = document.querySelectorAll('tr.display-none');
            allRows.forEach(td => {
                td.style.display = 'none';
            });
            tfootTdInput.value = 1;
            hidden1.forEach(tr => {

                tr.style.display = "table-row"
            });
            rightAngleClick.style.visibility = "visible";
            skipLastPageNumber.style.visibility = "visible";
        })

        skipLastPageNumber.addEventListener('click', () => {     //skip to last page of numbers

            rightAngleClick.style.visibility = "hidden";
            skipLastPageNumber.style.visibility = "hidden";
            const allRows = document.querySelectorAll('tr.display-none');
            allRows.forEach(td => {
                td.style.display = 'none';
            });
            tfootTdInput.value = 10;
            leftAngleClick.style.visibility = "visible";
            skipFirstPageNumber.style.visibility = "visible";
            const lastPageNum20 = document.querySelectorAll(".hidden181-189");
            lastPageNum20.forEach(tr => {
                tr.style.display = "table-row"
            })

        })





    }
    else if (selectedValue == 50) {
        hidden111.forEach(tr => {
            tr.style.display = "table-row"; // نمایش hidden111
        });




        let tfootTdInput = document.querySelector(".tfoot-td-input"); // the number between <>
        let currentStartRow = 1; // the number for starting row
        const rowsPerPage3 = 50; // count of roes' number in each page
        const totalRows = 388; // number of all rows
        const rightAngleClick = document.querySelector("#tfootangleRight");

        const updateRowVisibility = () => {
            // hide rows
            const allRows = document.querySelectorAll('tr.display-none');
            allRows.forEach(td => {
                td.style.display = 'none';
            });

            // counting new rows for showing
            const endRow = Math.min(currentStartRow + rowsPerPage3 - 1);
            for (let i = currentStartRow; i <= endRow; i++) {
                const rowToShow = document.querySelector(`.hidden${i}`);
                if (rowToShow) {
                    rowToShow.style.display = 'table-row'; // show row
                }

            }
            if (tfootTdInput.value == "1") {
                tfootangleLeft.style.visibility = "hidden";
                skipFirstPageNumber.style.visibility = "hidden";
            }
            else if (tfootTdInput.value == "4") {
                rightAngleClick.style.visibility = "hidden";
                skipLastPageNumber.style.visibility = "hidden";
            }

            else if (tfootTdInput.value == "3") {
                rightAngleClick.style.visibility = "visible";
                skipLastPageNumber.style.visibility = "visible";
            }

            else {
                tfootangleLeft.style.visibility = "visible";
                skipFirstPageNumber.style.visibility = "visible";

            }


        };

        // this function is for (>) button
        rightAngleClick.addEventListener("click", () => {
            // extend the number of row
            currentStartRow += rowsPerPage3;
            if (currentStartRow > totalRows) {
                currentStartRow = totalRows; // for avoiding of becomming row number bigger than number row(388)
            }
            tfootTdInput.value++;


            updateRowVisibility(); // updating the view of number page
        });

        // this function is for (<) button
        tfootangleLeft.addEventListener("click", () => {

            currentStartRow -= rowsPerPage3;

            if (currentStartRow < 1) {
                currentStartRow = 1; // for avoiding of becomming row number smaller than 1

            }
            tfootTdInput.value--;

            updateRowVisibility(); // updating the view of number page

        });

        // at first updating the view of number page
        updateRowVisibility();

    }
    else {
        hidden1.forEach(tr => {
            tr.style.display = "none"; // نمایش hidden111
        });
        hidden11.forEach(tr => {
            tr.style.display = "none"; // نمایش hidden111
        });
        hidden111.forEach(tr => {
            tr.style.display = "none"; // نمایش hidden111
        });

        skipFirstPageNumber.addEventListener('click', () => {    //skip to first page of numbers

            leftAngleClick.style.visibility = "hidden";
            skipFirstPageNumber.style.visibility = "hidden";
            const allRows = document.querySelectorAll('tr.display-none');
            allRows.forEach(td => {
                td.style.display = 'none';
            });
            tfootTdInput.value = 1;
            hidden1.forEach(tr => {

                tr.style.display = "table-row"
            });
            rightAngleClick.style.visibility = "visible";
            skipLastPageNumber.style.visibility = "visible";
        })

        skipLastPageNumber.addEventListener('click', () => {     //skip to last page of numbers

            rightAngleClick.style.visibility = "hidden";
            skipLastPageNumber.style.visibility = "hidden";
            const allRows = document.querySelectorAll('tr.display-none');
            allRows.forEach(td => {
                td.style.display = 'none';
            });
            tfootTdInput.value = 4;
            leftAngleClick.style.visibility = "visible";
            skipFirstPageNumber.style.visibility = "visible";
            const lastPageNum50 = document.querySelectorAll(".hidden151-189");
            lastPageNum50.forEach(tr => {
                tr.style.display = "table-row"
            })

        })

    };

};

I’ve changed some variables and numbers but wasn’t enough.

How to show only children that are not overflow from their parent?

I have a parent div with a certain width with some children items, I want to show as many as possible of children in the parent that are not overflow from the parent ?

For example in the code here –

https://jsfiddle.net/vk9256sp/10/

.parent {
  width: 200px;
  border: 2px solid black;
  display: flex;
  overflow: hidden
}

.item {
  margin: 5px;
  padding: 2px;
  border: 1px solid black;
}
<div class="parent">
  <div class="item">
    Hello1
  </div>
  <div class="item">
    Hello2
  </div>
  <div class="item">
    Hello3
  </div>
  <div class="item">
    Hello4
  </div>
  <div class="item">
    Hello5
  </div>
  <div class="item">
    Hello6
  </div>
</div>

I want the show the first 3 items, and stop show the children from the 4th one because they started to overflow

(The answer should be for any width of the parent and any number of children, also I only care about the overflow in the width)