Triangle vertex data is uploaded to a WebGL buffer and connected to the shader before drawArrays paints pixels.

Program

WebGL shaders do not know where vertices live until JavaScript binds a buffer and describes the attribute layout.

vertex_buffer.html
<canvas id="stage" width="360" height="210"></canvas>
<script>
  const gl = stage.getContext("webgl");
  const vertices = new Float32Array([
    0.0,  0.62,  0.94, 0.35, 0.28,
   -0.62, -0.52,  0.22, 0.82, 0.55,
    0.62, -0.52,  0.29, 0.55, 0.96
  ]);
  const buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 20, 0);
  gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 20, 8);
  gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
typed array Float32Array stores compact numeric data in the shape WebGL expects.
buffer A WebGL buffer stores vertex data on the GPU side.
attribute pointer vertexAttribPointer tells WebGL how to read each vertex attribute out of the buffer.