aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-05-16 23:25:12 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-05-16 23:25:12 -0700
commit154e049638753abc10ed0eca2012685fe3b831be (patch)
treebdeb6b0bf8137ee36df0aab436ac50713ddeb5ef /src/test
parente80f865974df7aae5e2f6abb966b36497da693c6 (diff)
downloadbun-154e049638753abc10ed0eca2012685fe3b831be.tar.gz
bun-154e049638753abc10ed0eca2012685fe3b831be.tar.zst
bun-154e049638753abc10ed0eca2012685fe3b831be.zip
lots
Former-commit-id: 9ccb4dd082afbc4f94982bf092360487232d8b60
Diffstat (limited to 'src/test')
-rw-r--r--src/test/fixtures/exports-bug.js2342
-rw-r--r--src/test/fixtures/label-continue-break-bug.js125
-rw-r--r--src/test/fixtures/symbols-bug.js16
-rw-r--r--src/test/tester.zig4
4 files changed, 2487 insertions, 0 deletions
diff --git a/src/test/fixtures/exports-bug.js b/src/test/fixtures/exports-bug.js
new file mode 100644
index 000000000..081b8cfa0
--- /dev/null
+++ b/src/test/fixtures/exports-bug.js
@@ -0,0 +1,2342 @@
+import {
+ RGBAFormat,
+ HalfFloatType,
+ FloatType,
+ UnsignedByteType,
+ TriangleFanDrawMode,
+ TriangleStripDrawMode,
+ TrianglesDrawMode,
+ LinearToneMapping,
+ BackSide,
+} from "../constants.js";
+import { _Math } from "../math/Math.js";
+import { DataTexture } from "../textures/DataTexture.js";
+import { Frustum } from "../math/Frustum.js";
+import { Matrix4 } from "../math/Matrix4.js";
+import { ShaderLib } from "./shaders/ShaderLib.js";
+import { UniformsLib } from "./shaders/UniformsLib.js";
+import { cloneUniforms } from "./shaders/UniformsUtils.js";
+import { Vector2 } from "../math/Vector2.js";
+import { Vector3 } from "../math/Vector3.js";
+import { Vector4 } from "../math/Vector4.js";
+import { WebGLAnimation } from "./webgl/WebGLAnimation.js";
+import { WebGLAttributes } from "./webgl/WebGLAttributes.js";
+import { WebGLBackground } from "./webgl/WebGLBackground.js";
+import { WebGLBufferRenderer } from "./webgl/WebGLBufferRenderer.js";
+import { WebGLCapabilities } from "./webgl/WebGLCapabilities.js";
+import { WebGLClipping } from "./webgl/WebGLClipping.js";
+import { WebGLExtensions } from "./webgl/WebGLExtensions.js";
+import { WebGLGeometries } from "./webgl/WebGLGeometries.js";
+import { WebGLIndexedBufferRenderer } from "./webgl/WebGLIndexedBufferRenderer.js";
+import { WebGLInfo } from "./webgl/WebGLInfo.js";
+import { WebGLMorphtargets } from "./webgl/WebGLMorphtargets.js";
+import { WebGLObjects } from "./webgl/WebGLObjects.js";
+import { WebGLPrograms } from "./webgl/WebGLPrograms.js";
+import { WebGLProperties } from "./webgl/WebGLProperties.js";
+import { WebGLRenderLists } from "./webgl/WebGLRenderLists.js";
+import { WebGLRenderStates } from "./webgl/WebGLRenderStates.js";
+import { WebGLShadowMap } from "./webgl/WebGLShadowMap.js";
+import { WebGLState } from "./webgl/WebGLState.js";
+import { WebGLTextures } from "./webgl/WebGLTextures.js";
+import { WebGLUniforms } from "./webgl/WebGLUniforms.js";
+import { WebGLUtils } from "./webgl/WebGLUtils.js";
+import { WebVRManager } from "./webvr/WebVRManager.js";
+import { WebXRManager } from "./webvr/WebXRManager.js";
+
+/**
+ * @author supereggbert / http://www.paulbrunt.co.uk/
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ * @author szimek / https://github.com/szimek/
+ * @author tschw
+ */
+
+function WebGLRenderer(parameters) {
+ parameters = parameters || {};
+
+ var _canvas =
+ parameters.canvas !== undefined
+ ? parameters.canvas
+ : document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"),
+ _context = parameters.context !== undefined ? parameters.context : null,
+ _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
+ _depth = parameters.depth !== undefined ? parameters.depth : true,
+ _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
+ _antialias =
+ parameters.antialias !== undefined ? parameters.antialias : false,
+ _premultipliedAlpha =
+ parameters.premultipliedAlpha !== undefined
+ ? parameters.premultipliedAlpha
+ : true,
+ _preserveDrawingBuffer =
+ parameters.preserveDrawingBuffer !== undefined
+ ? parameters.preserveDrawingBuffer
+ : false,
+ _powerPreference =
+ parameters.powerPreference !== undefined
+ ? parameters.powerPreference
+ : "default",
+ _failIfMajorPerformanceCaveat =
+ parameters.failIfMajorPerformanceCaveat !== undefined
+ ? parameters.failIfMajorPerformanceCaveat
+ : false;
+
+ var currentRenderList = null;
+ var currentRenderState = null;
+
+ // public properties
+
+ this.domElement = _canvas;
+
+ // Debug configuration container
+ this.debug = {
+ /**
+ * Enables error checking and reporting when shader programs are being compiled
+ * @type {boolean}
+ */
+ checkShaderErrors: true,
+ };
+
+ // clearing
+
+ this.autoClear = true;
+ this.autoClearColor = true;
+ this.autoClearDepth = true;
+ this.autoClearStencil = true;
+
+ // scene graph
+
+ this.sortObjects = true;
+
+ // user-defined clipping
+
+ this.clippingPlanes = [];
+ this.localClippingEnabled = false;
+
+ // physically based shading
+
+ this.gammaFactor = 2.0; // for backwards compatibility
+ this.gammaInput = false;
+ this.gammaOutput = false;
+
+ // physical lights
+
+ this.physicallyCorrectLights = false;
+
+ // tone mapping
+
+ this.toneMapping = LinearToneMapping;
+ this.toneMappingExposure = 1.0;
+ this.toneMappingWhitePoint = 1.0;
+
+ // morphs
+
+ this.maxMorphTargets = 8;
+ this.maxMorphNormals = 4;
+
+ // internal properties
+
+ var _this = this,
+ _isContextLost = false,
+ // internal state cache
+
+ _framebuffer = null,
+ _currentActiveCubeFace = 0,
+ _currentActiveMipmapLevel = 0,
+ _currentRenderTarget = null,
+ _currentFramebuffer = null,
+ _currentMaterialId = -1,
+ // geometry and program caching
+
+ _currentGeometryProgram = {
+ geometry: null,
+ program: null,
+ wireframe: false,
+ },
+ _currentCamera = null,
+ _currentArrayCamera = null,
+ _currentViewport = new Vector4(),
+ _currentScissor = new Vector4(),
+ _currentScissorTest = null,
+ //
+
+ _width = _canvas.width,
+ _height = _canvas.height,
+ _pixelRatio = 1,
+ _viewport = new Vector4(0, 0, _width, _height),
+ _scissor = new Vector4(0, 0, _width, _height),
+ _scissorTest = false,
+ // frustum
+
+ _frustum = new Frustum(),
+ // clipping
+
+ _clipping = new WebGLClipping(),
+ _clippingEnabled = false,
+ _localClippingEnabled = false,
+ // camera matrices cache
+
+ _projScreenMatrix = new Matrix4(),
+ _vector3 = new Vector3();
+
+ function getTargetPixelRatio() {
+ return _currentRenderTarget === null ? _pixelRatio : 1;
+ }
+
+ // initialize
+
+ var _gl;
+
+ try {
+ var contextAttributes = {
+ alpha: _alpha,
+ depth: _depth,
+ stencil: _stencil,
+ antialias: _antialias,
+ premultipliedAlpha: _premultipliedAlpha,
+ preserveDrawingBuffer: _preserveDrawingBuffer,
+ powerPreference: _powerPreference,
+ failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat,
+ xrCompatible: true,
+ };
+
+ // event listeners must be registered before WebGL context is created, see #12753
+
+ _canvas.addEventListener("webglcontextlost", onContextLost, false);
+ _canvas.addEventListener("webglcontextrestored", onContextRestore, false);
+
+ _gl =
+ _context ||
+ _canvas.getContext("webgl", contextAttributes) ||
+ _canvas.getContext("experimental-webgl", contextAttributes);
+
+ if (_gl === null) {
+ if (_canvas.getContext("webgl") !== null) {
+ throw new Error(
+ "Error creating WebGL context with your selected attributes."
+ );
+ } else {
+ throw new Error("Error creating WebGL context.");
+ }
+ }
+
+ // Some experimental-webgl implementations do not have getShaderPrecisionFormat
+
+ if (_gl.getShaderPrecisionFormat === undefined) {
+ _gl.getShaderPrecisionFormat = function () {
+ return { rangeMin: 1, rangeMax: 1, precision: 1 };
+ };
+ }
+ } catch (error) {
+ console.error("THREE.WebGLRenderer: " + error.message);
+ throw error;
+ }
+
+ var extensions, capabilities, state, info;
+ var properties, textures, attributes, geometries, objects;
+ var programCache, renderLists, renderStates;
+
+ var background, morphtargets, bufferRenderer, indexedBufferRenderer;
+
+ var utils;
+
+ function initGLContext() {
+ extensions = new WebGLExtensions(_gl);
+
+ capabilities = new WebGLCapabilities(_gl, extensions, parameters);
+
+ if (!capabilities.isWebGL2) {
+ extensions.get("WEBGL_depth_texture");
+ extensions.get("OES_texture_float");
+ extensions.get("OES_texture_half_float");
+ extensions.get("OES_texture_half_float_linear");
+ extensions.get("OES_standard_derivatives");
+ extensions.get("OES_element_index_uint");
+ extensions.get("ANGLE_instanced_arrays");
+ }
+
+ extensions.get("OES_texture_float_linear");
+
+ utils = new WebGLUtils(_gl, extensions, capabilities);
+
+ state = new WebGLState(_gl, extensions, utils, capabilities);
+ state.scissor(
+ _currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor()
+ );
+ state.viewport(
+ _currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor()
+ );
+
+ info = new WebGLInfo(_gl);
+ properties = new WebGLProperties();
+ textures = new WebGLTextures(
+ _gl,
+ extensions,
+ state,
+ properties,
+ capabilities,
+ utils,
+ info
+ );
+ attributes = new WebGLAttributes(_gl);
+ geometries = new WebGLGeometries(_gl, attributes, info);
+ objects = new WebGLObjects(geometries, info);
+ morphtargets = new WebGLMorphtargets(_gl);
+ programCache = new WebGLPrograms(_this, extensions, capabilities);
+ renderLists = new WebGLRenderLists();
+ renderStates = new WebGLRenderStates();
+
+ background = new WebGLBackground(
+ _this,
+ state,
+ objects,
+ _premultipliedAlpha
+ );
+
+ bufferRenderer = new WebGLBufferRenderer(
+ _gl,
+ extensions,
+ info,
+ capabilities
+ );
+ indexedBufferRenderer = new WebGLIndexedBufferRenderer(
+ _gl,
+ extensions,
+ info,
+ capabilities
+ );
+
+ info.programs = programCache.programs;
+
+ _this.capabilities = capabilities;
+ _this.extensions = extensions;
+ _this.properties = properties;
+ _this.renderLists = renderLists;
+ _this.state = state;
+ _this.info = info;
+ }
+
+ initGLContext();
+
+ // vr
+
+ var vr =
+ typeof navigator !== "undefined" &&
+ "xr" in navigator &&
+ "supportsSession" in navigator.xr
+ ? new WebXRManager(_this, _gl)
+ : new WebVRManager(_this);
+
+ this.vr = vr;
+
+ // shadow map
+
+ var shadowMap = new WebGLShadowMap(
+ _this,
+ objects,
+ capabilities.maxTextureSize
+ );
+
+ this.shadowMap = shadowMap;
+
+ // API
+
+ this.getContext = function () {
+ return _gl;
+ };
+
+ this.getContextAttributes = function () {
+ return _gl.getContextAttributes();
+ };
+
+ this.forceContextLoss = function () {
+ var extension = extensions.get("WEBGL_lose_context");
+ if (extension) extension.loseContext();
+ };
+
+ this.forceContextRestore = function () {
+ var extension = extensions.get("WEBGL_lose_context");
+ if (extension) extension.restoreContext();
+ };
+
+ this.getPixelRatio = function () {
+ return _pixelRatio;
+ };
+
+ this.setPixelRatio = function (value) {
+ if (value === undefined) return;
+
+ _pixelRatio = value;
+
+ this.setSize(_width, _height, false);
+ };
+
+ this.getSize = function (target) {
+ if (target === undefined) {
+ console.warn(
+ "WebGLRenderer: .getsize() now requires a Vector2 as an argument"
+ );
+
+ target = new Vector2();
+ }
+
+ return target.set(_width, _height);
+ };
+
+ this.setSize = function (width, height, updateStyle) {
+ if (vr.isPresenting()) {
+ console.warn(
+ "THREE.WebGLRenderer: Can't change size while VR device is presenting."
+ );
+ return;
+ }
+
+ _width = width;
+ _height = height;
+
+ _canvas.width = Math.floor(width * _pixelRatio);
+ _canvas.height = Math.floor(height * _pixelRatio);
+
+ if (updateStyle !== false) {
+ _canvas.style.width = width + "px";
+ _canvas.style.height = height + "px";
+ }
+
+ this.setViewport(0, 0, width, height);
+ };
+
+ this.getDrawingBufferSize = function (target) {
+ if (target === undefined) {
+ console.warn(
+ "WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument"
+ );
+
+ target = new Vector2();
+ }
+
+ return target.set(_width * _pixelRatio, _height * _pixelRatio).floor();
+ };
+
+ this.setDrawingBufferSize = function (width, height, pixelRatio) {
+ _width = width;
+ _height = height;
+
+ _pixelRatio = pixelRatio;
+
+ _canvas.width = Math.floor(width * pixelRatio);
+ _canvas.height = Math.floor(height * pixelRatio);
+
+ this.setViewport(0, 0, width, height);
+ };
+
+ this.getCurrentViewport = function (target) {
+ if (target === undefined) {
+ console.warn(
+ "WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument"
+ );
+
+ target = new Vector4();
+ }
+
+ return target.copy(_currentViewport);
+ };
+
+ this.getViewport = function (target) {
+ return target.copy(_viewport);
+ };
+
+ this.setViewport = function (x, y, width, height) {
+ if (x.isVector4) {
+ _viewport.set(x.x, x.y, x.z, x.w);
+ } else {
+ _viewport.set(x, y, width, height);
+ }
+
+ state.viewport(
+ _currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor()
+ );
+ };
+
+ this.getScissor = function (target) {
+ return target.copy(_scissor);
+ };
+
+ this.setScissor = function (x, y, width, height) {
+ if (x.isVector4) {
+ _scissor.set(x.x, x.y, x.z, x.w);
+ } else {
+ _scissor.set(x, y, width, height);
+ }
+
+ state.scissor(
+ _currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor()
+ );
+ };
+
+ this.getScissorTest = function () {
+ return _scissorTest;
+ };
+
+ this.setScissorTest = function (boolean) {
+ state.setScissorTest((_scissorTest = boolean));
+ };
+
+ // Clearing
+
+ this.getClearColor = function () {
+ return background.getClearColor();
+ };
+
+ this.setClearColor = function () {
+ background.setClearColor.apply(background, arguments);
+ };
+
+ this.getClearAlpha = function () {
+ return background.getClearAlpha();
+ };
+
+ this.setClearAlpha = function () {
+ background.setClearAlpha.apply(background, arguments);
+ };
+
+ this.clear = function (color, depth, stencil) {
+ var bits = 0;
+
+ if (color === undefined || color) bits |= _gl.COLOR_BUFFER_BIT;
+ if (depth === undefined || depth) bits |= _gl.DEPTH_BUFFER_BIT;
+ if (stencil === undefined || stencil) bits |= _gl.STENCIL_BUFFER_BIT;
+
+ _gl.clear(bits);
+ };
+
+ this.clearColor = function () {
+ this.clear(true, false, false);
+ };
+
+ this.clearDepth = function () {
+ this.clear(false, true, false);
+ };
+
+ this.clearStencil = function () {
+ this.clear(false, false, true);
+ };
+
+ //
+
+ this.dispose = function () {
+ _canvas.removeEventListener("webglcontextlost", onContextLost, false);
+ _canvas.removeEventListener(
+ "webglcontextrestored",
+ onContextRestore,
+ false
+ );
+
+ renderLists.dispose();
+ renderStates.dispose();
+ properties.dispose();
+ objects.dispose();
+
+ vr.dispose();
+
+ animation.stop();
+ };
+
+ // Events
+
+ function onContextLost(event) {
+ event.preventDefault();
+
+ console.log("THREE.WebGLRenderer: Context Lost.");
+
+ _isContextLost = true;
+ }
+
+ function onContextRestore(/* event */) {
+ console.log("THREE.WebGLRenderer: Context Restored.");
+
+ _isContextLost = false;
+
+ initGLContext();
+ }
+
+ function onMaterialDispose(event) {
+ var material = event.target;
+
+ material.removeEventListener("dispose", onMaterialDispose);
+
+ deallocateMaterial(material);
+ }
+
+ // Buffer deallocation
+
+ function deallocateMaterial(material) {
+ releaseMaterialProgramReference(material);
+
+ properties.remove(material);
+ }
+
+ function releaseMaterialProgramReference(material) {
+ var programInfo = properties.get(material).program;
+
+ material.program = undefined;
+
+ if (programInfo !== undefined) {
+ programCache.releaseProgram(programInfo);
+ }
+ }
+
+ // Buffer rendering
+
+ function renderObjectImmediate(object, program) {
+ object.render(function (object) {
+ _this.renderBufferImmediate(object, program);
+ });
+ }
+
+ this.renderBufferImmediate = function (object, program) {
+ state.initAttributes();
+
+ var buffers = properties.get(object);
+
+ if (object.hasPositions && !buffers.position)
+ buffers.position = _gl.createBuffer();
+ if (object.hasNormals && !buffers.normal)
+ buffers.normal = _gl.createBuffer();
+ if (object.hasUvs && !buffers.uv) buffers.uv = _gl.createBuffer();
+ if (object.hasColors && !buffers.color) buffers.color = _gl.createBuffer();
+
+ var programAttributes = program.getAttributes();
+
+ if (object.hasPositions) {
+ _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.position);
+ _gl.bufferData(_gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW);
+
+ state.enableAttribute(programAttributes.position);
+ _gl.vertexAttribPointer(
+ programAttributes.position,
+ 3,
+ _gl.FLOAT,
+ false,
+ 0,
+ 0
+ );
+ }
+
+ if (object.hasNormals) {
+ _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.normal);
+ _gl.bufferData(_gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW);
+
+ state.enableAttribute(programAttributes.normal);
+ _gl.vertexAttribPointer(
+ programAttributes.normal,
+ 3,
+ _gl.FLOAT,
+ false,
+ 0,
+ 0
+ );
+ }
+
+ if (object.hasUvs) {
+ _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.uv);
+ _gl.bufferData(_gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW);
+
+ state.enableAttribute(programAttributes.uv);
+ _gl.vertexAttribPointer(programAttributes.uv, 2, _gl.FLOAT, false, 0, 0);
+ }
+
+ if (object.hasColors) {
+ _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.color);
+ _gl.bufferData(_gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW);
+
+ state.enableAttribute(programAttributes.color);
+ _gl.vertexAttribPointer(
+ programAttributes.color,
+ 3,
+ _gl.FLOAT,
+ false,
+ 0,
+ 0
+ );
+ }
+
+ state.disableUnusedAttributes();
+
+ _gl.drawArrays(_gl.TRIANGLES, 0, object.count);
+
+ object.count = 0;
+ };
+
+ this.renderBufferDirect = function (
+ camera,
+ fog,
+ geometry,
+ material,
+ object,
+ group
+ ) {
+ var frontFaceCW = object.isMesh && object.matrixWorld.determinant() < 0;
+
+ state.setMaterial(material, frontFaceCW);
+
+ var program = setProgram(camera, fog, material, object);
+
+ var updateBuffers = false;
+
+ if (
+ _currentGeometryProgram.geometry !== geometry.id ||
+ _currentGeometryProgram.program !== program.id ||
+ _currentGeometryProgram.wireframe !== (material.wireframe === true)
+ ) {
+ _currentGeometryProgram.geometry = geometry.id;
+ _currentGeometryProgram.program = program.id;
+ _currentGeometryProgram.wireframe = material.wireframe === true;
+ updateBuffers = true;
+ }
+
+ if (object.morphTargetInfluences) {
+ morphtargets.update(object, geometry, material, program);
+
+ updateBuffers = true;
+ }
+
+ //
+
+ var index = geometry.index;
+ var position = geometry.attributes.position;
+ var rangeFactor = 1;
+
+ if (material.wireframe === true) {
+ index = geometries.getWireframeAttribute(geometry);
+ rangeFactor = 2;
+ }
+
+ var attribute;
+ var renderer = bufferRenderer;
+
+ if (index !== null) {
+ attribute = attributes.get(index);
+
+ renderer = indexedBufferRenderer;
+ renderer.setIndex(attribute);
+ }
+
+ if (updateBuffers) {
+ setupVertexAttributes(material, program, geometry);
+
+ if (index !== null) {
+ _gl.bindBuffer(_gl.ELEMENT_ARRAY_BUFFER, attribute.buffer);
+ }
+ }
+
+ //
+
+ var dataCount = Infinity;
+
+ if (index !== null) {
+ dataCount = index.count;
+ } else if (position !== undefined) {
+ dataCount = position.count;
+ }
+
+ var rangeStart = geometry.drawRange.start * rangeFactor;
+ var rangeCount = geometry.drawRange.count * rangeFactor;
+
+ var groupStart = group !== null ? group.start * rangeFactor : 0;
+ var groupCount = group !== null ? group.count * rangeFactor : Infinity;
+
+ var drawStart = Math.max(rangeStart, groupStart);
+ var drawEnd =
+ Math.min(dataCount, rangeStart + rangeCount, groupStart + groupCount) - 1;
+
+ var drawCount = Math.max(0, drawEnd - drawStart + 1);
+
+ if (drawCount === 0) return;
+
+ //
+
+ if (object.isMesh) {
+ if (material.wireframe === true) {
+ state.setLineWidth(material.wireframeLinewidth * getTargetPixelRatio());
+ renderer.setMode(_gl.LINES);
+ } else {
+ switch (object.drawMode) {
+ case TrianglesDrawMode:
+ renderer.setMode(_gl.TRIANGLES);
+ break;
+
+ case TriangleStripDrawMode:
+ renderer.setMode(_gl.TRIANGLE_STRIP);
+ break;
+
+ case TriangleFanDrawMode:
+ renderer.setMode(_gl.TRIANGLE_FAN);
+ break;
+ }
+ }
+ } else if (object.isLine) {
+ var lineWidth = material.linewidth;
+
+ if (lineWidth === undefined) lineWidth = 1; // Not using Line*Material
+
+ state.setLineWidth(lineWidth * getTargetPixelRatio());
+
+ if (object.isLineSegments) {
+ renderer.setMode(_gl.LINES);
+ } else if (object.isLineLoop) {
+ renderer.setMode(_gl.LINE_LOOP);
+ } else {
+ renderer.setMode(_gl.LINE_STRIP);
+ }
+ } else if (object.isPoints) {
+ renderer.setMode(_gl.POINTS);
+ } else if (object.isSprite) {
+ renderer.setMode(_gl.TRIANGLES);
+ }
+
+ if (geometry && geometry.isInstancedBufferGeometry) {
+ if (geometry.maxInstancedCount > 0) {
+ renderer.renderInstances(geometry, drawStart, drawCount);
+ }
+ } else {
+ renderer.render(drawStart, drawCount);
+ }
+ };
+
+ function setupVertexAttributes(material, program, geometry) {
+ if (
+ geometry &&
+ geometry.isInstancedBufferGeometry &&
+ !capabilities.isWebGL2
+ ) {
+ if (extensions.get("ANGLE_instanced_arrays") === null) {
+ console.error(
+ "THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays."
+ );
+ return;
+ }
+ }
+
+ state.initAttributes();
+
+ var geometryAttributes = geometry.attributes;
+
+ var programAttributes = program.getAttributes();
+
+ var materialDefaultAttributeValues = material.defaultAttributeValues;
+
+ for (var name in programAttributes) {
+ var programAttribute = programAttributes[name];
+
+ if (programAttribute >= 0) {
+ var geometryAttribute = geometryAttributes[name];
+
+ if (geometryAttribute !== undefined) {
+ var normalized = geometryAttribute.normalized;
+ var size = geometryAttribute.itemSize;
+
+ var attribute = attributes.get(geometryAttribute);
+
+ // TODO Attribute may not be available on context restore
+
+ if (attribute === undefined) continue;
+
+ var buffer = attribute.buffer;
+ var type = attribute.type;
+ var bytesPerElement = attribute.bytesPerElement;
+
+ if (geometryAttribute.isInterleavedBufferAttribute) {
+ var data = geometryAttribute.data;
+ var stride = data.stride;
+ var offset = geometryAttribute.offset;
+
+ if (data && data.isInstancedInterleavedBuffer) {
+ state.enableAttributeAndDivisor(
+ programAttribute,
+ data.meshPerAttribute
+ );
+
+ if (geometry.maxInstancedCount === undefined) {
+ geometry.maxInstancedCount = data.meshPerAttribute * data.count;
+ }
+ } else {
+ state.enableAttribute(programAttribute);
+ }
+
+ _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer);
+ _gl.vertexAttribPointer(
+ programAttribute,
+ size,
+ type,
+ normalized,
+ stride * bytesPerElement,
+ offset * bytesPerElement
+ );
+ } else {
+ if (geometryAttribute.isInstancedBufferAttribute) {
+ state.enableAttributeAndDivisor(
+ programAttribute,
+ geometryAttribute.meshPerAttribute
+ );
+
+ if (geometry.maxInstancedCount === undefined) {
+ geometry.maxInstancedCount =
+ geometryAttribute.meshPerAttribute * geometryAttribute.count;
+ }
+ } else {
+ state.enableAttribute(programAttribute);
+ }
+
+ _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer);
+ _gl.vertexAttribPointer(
+ programAttribute,
+ size,
+ type,
+ normalized,
+ 0,
+ 0
+ );
+ }
+ } else if (materialDefaultAttributeValues !== undefined) {
+ var value = materialDefaultAttributeValues[name];
+
+ if (value !== undefined) {
+ switch (value.length) {
+ case 2:
+ _gl.vertexAttrib2fv(programAttribute, value);
+ break;
+
+ case 3:
+ _gl.vertexAttrib3fv(programAttribute, value);
+ break;
+
+ case 4:
+ _gl.vertexAttrib4fv(programAttribute, value);
+ break;
+
+ default:
+ _gl.vertexAttrib1fv(programAttribute, value);
+ }
+ }
+ }
+ }
+ }
+
+ state.disableUnusedAttributes();
+ }
+
+ // Compile
+
+ this.compile = function (scene, camera) {
+ currentRenderState = renderStates.get(scene, camera);
+ currentRenderState.init();
+
+ scene.traverse(function (object) {
+ if (object.isLight) {
+ currentRenderState.pushLight(object);
+
+ if (object.castShadow) {
+ currentRenderState.pushShadow(object);
+ }
+ }
+ });
+
+ currentRenderState.setupLights(camera);
+
+ scene.traverse(function (object) {
+ if (object.material) {
+ if (Array.isArray(object.material)) {
+ for (var i = 0; i < object.material.length; i++) {
+ initMaterial(object.material[i], scene.fog, object);
+ }
+ } else {
+ initMaterial(object.material, scene.fog, object);
+ }
+ }
+ });
+ };
+
+ // Animation Loop
+
+ var onAnimationFrameCallback = null;
+
+ function onAnimationFrame(time) {
+ if (vr.isPresenting()) return;
+ if (onAnimationFrameCallback) onAnimationFrameCallback(time);
+ }
+
+ var animation = new WebGLAnimation();
+ animation.setAnimationLoop(onAnimationFrame);
+
+ if (typeof window !== "undefined") animation.setContext(window);
+
+ this.setAnimationLoop = function (callback) {
+ onAnimationFrameCallback = callback;
+ vr.setAnimationLoop(callback);
+
+ animation.start();
+ };
+
+ // Rendering
+
+ this.render = function (scene, camera) {
+ var renderTarget, forceClear;
+
+ if (arguments[2] !== undefined) {
+ console.warn(
+ "THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead."
+ );
+ renderTarget = arguments[2];
+ }
+
+ if (arguments[3] !== undefined) {
+ console.warn(
+ "THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead."
+ );
+ forceClear = arguments[3];
+ }
+
+ if (!(camera && camera.isCamera)) {
+ console.error(
+ "THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera."
+ );
+ return;
+ }
+
+ if (_isContextLost) return;
+
+ // reset caching for this frame
+
+ _currentGeometryProgram.geometry = null;
+ _currentGeometryProgram.program = null;
+ _currentGeometryProgram.wireframe = false;
+ _currentMaterialId = -1;
+ _currentCamera = null;
+
+ // update scene graph
+
+ if (scene.autoUpdate === true) scene.updateMatrixWorld();
+
+ // update camera matrices and frustum
+
+ if (camera.parent === null) camera.updateMatrixWorld();
+
+ if (vr.enabled) {
+ camera = vr.getCamera(camera);
+ }
+
+ //
+
+ currentRenderState = renderStates.get(scene, camera);
+ currentRenderState.init();
+
+ scene.onBeforeRender(
+ _this,
+ scene,
+ camera,
+ renderTarget || _currentRenderTarget
+ );
+
+ _projScreenMatrix.multiplyMatrices(
+ camera.projectionMatrix,
+ camera.matrixWorldInverse
+ );
+ _frustum.setFromMatrix(_projScreenMatrix);
+
+ _localClippingEnabled = this.localClippingEnabled;
+ _clippingEnabled = _clipping.init(
+ this.clippingPlanes,
+ _localClippingEnabled,
+ camera
+ );
+
+ currentRenderList = renderLists.get(scene, camera);
+ currentRenderList.init();
+
+ projectObject(scene, camera, 0, _this.sortObjects);
+
+ if (_this.sortObjects === true) {
+ currentRenderList.sort();
+ }
+
+ //
+
+ if (_clippingEnabled) _clipping.beginShadows();
+
+ var shadowsArray = currentRenderState.state.shadowsArray;
+
+ shadowMap.render(shadowsArray, scene, camera);
+
+ currentRenderState.setupLights(camera);
+
+ if (_clippingEnabled) _clipping.endShadows();
+
+ //
+
+ if (this.info.autoReset) this.info.reset();
+
+ if (renderTarget !== undefined) {
+ this.setRenderTarget(renderTarget);
+ }
+
+ //
+
+ background.render(currentRenderList, scene, camera, forceClear);
+
+ // render scene
+
+ var opaqueObjects = currentRenderList.opaque;
+ var transparentObjects = currentRenderList.transparent;
+
+ if (scene.overrideMaterial) {
+ var overrideMaterial = scene.overrideMaterial;
+
+ if (opaqueObjects.length)
+ renderObjects(opaqueObjects, scene, camera, overrideMaterial);
+ if (transparentObjects.length)
+ renderObjects(transparentObjects, scene, camera, overrideMaterial);
+ } else {
+ // opaque pass (front-to-back order)
+
+ if (opaqueObjects.length) renderObjects(opaqueObjects, scene, camera);
+
+ // transparent pass (back-to-front order)
+
+ if (transparentObjects.length)
+ renderObjects(transparentObjects, scene, camera);
+ }
+
+ //
+
+ scene.onAfterRender(_this, scene, camera);
+
+ //
+
+ if (_currentRenderTarget !== null) {
+ // Generate mipmap if we're using any kind of mipmap filtering
+
+ textures.updateRenderTargetMipmap(_currentRenderTarget);
+
+ // resolve multisample renderbuffers to a single-sample texture if necessary
+
+ textures.updateMultisampleRenderTarget(_currentRenderTarget);
+ }
+
+ // Ensure depth buffer writing is enabled so it can be cleared on next render
+
+ state.buffers.depth.setTest(true);
+ state.buffers.depth.setMask(true);
+ state.buffers.color.setMask(true);
+
+ state.setPolygonOffset(false);
+
+ if (vr.enabled) {
+ vr.submitFrame();
+ }
+
+ // _gl.finish();
+
+ currentRenderList = null;
+ currentRenderState = null;
+ };
+
+ function projectObject(object, camera, groupOrder, sortObjects) {
+ if (object.visible === false) return;
+
+ var visible = object.layers.test(camera.layers);
+
+ if (visible) {
+ if (object.isGroup) {
+ groupOrder = object.renderOrder;
+ } else if (object.isLOD) {
+ if (object.autoUpdate === true) object.update(camera);
+ } else if (object.isLight) {
+ currentRenderState.pushLight(object);
+
+ if (object.castShadow) {
+ currentRenderState.pushShadow(object);
+ }
+ } else if (object.isSprite) {
+ if (!object.frustumCulled || _frustum.intersectsSprite(object)) {
+ if (sortObjects) {
+ _vector3
+ .setFromMatrixPosition(object.matrixWorld)
+ .applyMatrix4(_projScreenMatrix);
+ }
+
+ var geometry = objects.update(object);
+ var material = object.material;
+
+ if (material.visible) {
+ currentRenderList.push(
+ object,
+ geometry,
+ material,
+ groupOrder,
+ _vector3.z,
+ null
+ );
+ }
+ }
+ } else if (object.isImmediateRenderObject) {
+ if (sortObjects) {
+ _vector3
+ .setFromMatrixPosition(object.matrixWorld)
+ .applyMatrix4(_projScreenMatrix);
+ }
+
+ currentRenderList.push(
+ object,
+ null,
+ object.material,
+ groupOrder,
+ _vector3.z,
+ null
+ );
+ } else if (object.isMesh || object.isLine || object.isPoints) {
+ if (object.isSkinnedMesh) {
+ object.skeleton.update();
+ }
+
+ if (!object.frustumCulled || _frustum.intersectsObject(object)) {
+ if (sortObjects) {
+ _vector3
+ .setFromMatrixPosition(object.matrixWorld)
+ .applyMatrix4(_projScreenMatrix);
+ }
+
+ var geometry = objects.update(object);
+ var material = object.material;
+
+ if (Array.isArray(material)) {
+ var groups = geometry.groups;
+
+ for (var i = 0, l = groups.length; i < l; i++) {
+ var group = groups[i];
+ var groupMaterial = material[group.materialIndex];
+
+ if (groupMaterial && groupMaterial.visible) {
+ currentRenderList.push(
+ object,
+ geometry,
+ groupMaterial,
+ groupOrder,
+ _vector3.z,
+ group
+ );
+ }
+ }
+ } else if (material.visible) {
+ currentRenderList.push(
+ object,
+ geometry,
+ material,
+ groupOrder,
+ _vector3.z,
+ null
+ );
+ }
+ }
+ }
+ }
+
+ var children = object.children;
+
+ for (var i = 0, l = children.length; i < l; i++) {
+ projectObject(children[i], camera, groupOrder, sortObjects);
+ }
+ }
+
+ function renderObjects(renderList, scene, camera, overrideMaterial) {
+ for (var i = 0, l = renderList.length; i < l; i++) {
+ var renderItem = renderList[i];
+
+ var object = renderItem.object;
+ var geometry = renderItem.geometry;
+ var material =
+ overrideMaterial === undefined ? renderItem.material : overrideMaterial;
+ var group = renderItem.group;
+
+ if (camera.isArrayCamera) {
+ _currentArrayCamera = camera;
+
+ var cameras = camera.cameras;
+
+ for (var j = 0, jl = cameras.length; j < jl; j++) {
+ var camera2 = cameras[j];
+
+ if (object.layers.test(camera2.layers)) {
+ state.viewport(_currentViewport.copy(camera2.viewport));
+
+ currentRenderState.setupLights(camera2);
+
+ renderObject(object, scene, camera2, geometry, material, group);
+ }
+ }
+ } else {
+ _currentArrayCamera = null;
+
+ renderObject(object, scene, camera, geometry, material, group);
+ }
+ }
+ }
+
+ function renderObject(object, scene, camera, geometry, material, group) {
+ object.onBeforeRender(_this, scene, camera, geometry, material, group);
+ currentRenderState = renderStates.get(scene, _currentArrayCamera || camera);
+
+ object.modelViewMatrix.multiplyMatrices(
+ camera.matrixWorldInverse,
+ object.matrixWorld
+ );
+ object.normalMatrix.getNormalMatrix(object.modelViewMatrix);
+
+ if (object.isImmediateRenderObject) {
+ state.setMaterial(material);
+
+ var program = setProgram(camera, scene.fog, material, object);
+
+ _currentGeometryProgram.geometry = null;
+ _currentGeometryProgram.program = null;
+ _currentGeometryProgram.wireframe = false;
+
+ renderObjectImmediate(object, program);
+ } else {
+ _this.renderBufferDirect(
+ camera,
+ scene.fog,
+ geometry,
+ material,
+ object,
+ group
+ );
+ }
+
+ object.onAfterRender(_this, scene, camera, geometry, material, group);
+ currentRenderState = renderStates.get(scene, _currentArrayCamera || camera);
+ }
+
+ function initMaterial(material, fog, object) {
+ var materialProperties = properties.get(material);
+
+ var lights = currentRenderState.state.lights;
+ var shadowsArray = currentRenderState.state.shadowsArray;
+
+ var lightsStateVersion = lights.state.version;
+
+ var parameters = programCache.getParameters(
+ material,
+ lights.state,
+ shadowsArray,
+ fog,
+ _clipping.numPlanes,
+ _clipping.numIntersection,
+ object
+ );
+
+ var code = programCache.getProgramCode(material, parameters);
+
+ var program = materialProperties.program;
+ var programChange = true;
+
+ if (program === undefined) {
+ // new material
+ material.addEventListener("dispose", onMaterialDispose);
+ } else if (program.code !== code) {
+ // changed glsl or parameters
+ releaseMaterialProgramReference(material);
+ } else if (materialProperties.lightsStateVersion !== lightsStateVersion) {
+ materialProperties.lightsStateVersion = lightsStateVersion;
+
+ programChange = false;
+ } else if (parameters.shaderID !== undefined) {
+ // same glsl and uniform list
+ return;
+ } else {
+ // only rebuild uniform list
+ programChange = false;
+ }
+
+ if (programChange) {
+ if (parameters.shaderID) {
+ var shader = ShaderLib[parameters.shaderID];
+
+ materialProperties.shader = {
+ name: material.type,
+ uniforms: cloneUniforms(shader.uniforms),
+ vertexShader: shader.vertexShader,
+ fragmentShader: shader.fragmentShader,
+ };
+ } else {
+ materialProperties.shader = {
+ name: material.type,
+ uniforms: material.uniforms,
+ vertexShader: material.vertexShader,
+ fragmentShader: material.fragmentShader,
+ };
+ }
+
+ material.onBeforeCompile(materialProperties.shader, _this);
+
+ // Computing code again as onBeforeCompile may have changed the shaders
+ code = programCache.getProgramCode(material, parameters);
+
+ program = programCache.acquireProgram(
+ material,
+ materialProperties.shader,
+ parameters,
+ code
+ );
+
+ materialProperties.program = program;
+ material.program = program;
+ }
+
+ var programAttributes = program.getAttributes();
+
+ if (material.morphTargets) {
+ material.numSupportedMorphTargets = 0;
+
+ for (var i = 0; i < _this.maxMorphTargets; i++) {
+ if (programAttributes["morphTarget" + i] >= 0) {
+ material.numSupportedMorphTargets++;
+ }
+ }
+ }
+
+ if (material.morphNormals) {
+ material.numSupportedMorphNormals = 0;
+
+ for (var i = 0; i < _this.maxMorphNormals; i++) {
+ if (programAttributes["morphNormal" + i] >= 0) {
+ material.numSupportedMorphNormals++;
+ }
+ }
+ }
+
+ var uniforms = materialProperties.shader.uniforms;
+
+ if (
+ (!material.isShaderMaterial && !material.isRawShaderMaterial) ||
+ material.clipping === true
+ ) {
+ materialProperties.numClippingPlanes = _clipping.numPlanes;
+ materialProperties.numIntersection = _clipping.numIntersection;
+ uniforms.clippingPlanes = _clipping.uniform;
+ }
+
+ materialProperties.fog = fog;
+
+ // store the light setup it was created for
+
+ materialProperties.lightsStateVersion = lightsStateVersion;
+
+ if (material.lights) {
+ // wire up the material to this renderer's lighting state
+
+ uniforms.ambientLightColor.value = lights.state.ambient;
+ uniforms.lightProbe.value = lights.state.probe;
+ uniforms.directionalLights.value = lights.state.directional;
+ uniforms.spotLights.value = lights.state.spot;
+ uniforms.rectAreaLights.value = lights.state.rectArea;
+ uniforms.pointLights.value = lights.state.point;
+ uniforms.hemisphereLights.value = lights.state.hemi;
+
+ uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
+ uniforms.directionalShadowMatrix.value =
+ lights.state.directionalShadowMatrix;
+ uniforms.spotShadowMap.value = lights.state.spotShadowMap;
+ uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
+ uniforms.pointShadowMap.value = lights.state.pointShadowMap;
+ uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
+ // TODO (abelnation): add area lights shadow info to uniforms
+ }
+
+ var progUniforms = materialProperties.program.getUniforms(),
+ uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, uniforms);
+
+ materialProperties.uniformsList = uniformsList;
+ }
+
+ function setProgram(camera, fog, material, object) {
+ textures.resetTextureUnits();
+
+ var materialProperties = properties.get(material);
+ var lights = currentRenderState.state.lights;
+
+ if (_clippingEnabled) {
+ if (_localClippingEnabled || camera !== _currentCamera) {
+ var useCache =
+ camera === _currentCamera && material.id === _currentMaterialId;
+
+ // we might want to call this function with some ClippingGroup
+ // object instead of the material, once it becomes feasible
+ // (#8465, #8379)
+ _clipping.setState(
+ material.clippingPlanes,
+ material.clipIntersection,
+ material.clipShadows,
+ camera,
+ materialProperties,
+ useCache
+ );
+ }
+ }
+
+ if (material.needsUpdate === false) {
+ if (materialProperties.program === undefined) {
+ material.needsUpdate = true;
+ } else if (material.fog && materialProperties.fog !== fog) {
+ material.needsUpdate = true;
+ } else if (
+ material.lights &&
+ materialProperties.lightsStateVersion !== lights.state.version
+ ) {
+ material.needsUpdate = true;
+ } else if (
+ materialProperties.numClippingPlanes !== undefined &&
+ (materialProperties.numClippingPlanes !== _clipping.numPlanes ||
+ materialProperties.numIntersection !== _clipping.numIntersection)
+ ) {
+ material.needsUpdate = true;
+ }
+ }
+
+ if (material.needsUpdate) {
+ initMaterial(material, fog, object);
+ material.needsUpdate = false;
+ }
+
+ var refreshProgram = false;
+ var refreshMaterial = false;
+ var refreshLights = false;
+
+ var program = materialProperties.program,
+ p_uniforms = program.getUniforms(),
+ m_uniforms = materialProperties.shader.uniforms;
+
+ if (state.useProgram(program.program)) {
+ refreshProgram = true;
+ refreshMaterial = true;
+ refreshLights = true;
+ }
+
+ if (material.id !== _currentMaterialId) {
+ _currentMaterialId = material.id;
+
+ refreshMaterial = true;
+ }
+
+ if (refreshProgram || _currentCamera !== camera) {
+ p_uniforms.setValue(_gl, "projectionMatrix", camera.projectionMatrix);
+
+ if (capabilities.logarithmicDepthBuffer) {
+ p_uniforms.setValue(
+ _gl,
+ "logDepthBufFC",
+ 2.0 / (Math.log(camera.far + 1.0) / Math.LN2)
+ );
+ }
+
+ if (_currentCamera !== camera) {
+ _currentCamera = camera;
+
+ // lighting uniforms depend on the camera so enforce an update
+ // now, in case this material supports lights - or later, when
+ // the next material that does gets activated:
+
+ refreshMaterial = true; // set to true on material change
+ refreshLights = true; // remains set until update done
+ }
+
+ // load material specific uniforms
+ // (shader material also gets them for the sake of genericity)
+
+ if (
+ material.isShaderMaterial ||
+ material.isMeshPhongMaterial ||
+ material.isMeshStandardMaterial ||
+ material.envMap
+ ) {
+ var uCamPos = p_uniforms.map.cameraPosition;
+
+ if (uCamPos !== undefined) {
+ uCamPos.setValue(
+ _gl,
+ _vector3.setFromMatrixPosition(camera.matrixWorld)
+ );
+ }
+ }
+
+ if (
+ material.isMeshPhongMaterial ||
+ material.isMeshLambertMaterial ||
+ material.isMeshBasicMaterial ||
+ material.isMeshStandardMaterial ||
+ material.isShaderMaterial ||
+ material.skinning
+ ) {
+ p_uniforms.setValue(_gl, "viewMatrix", camera.matrixWorldInverse);
+ }
+ }
+
+ // skinning uniforms must be set even if material didn't change
+ // auto-setting of texture unit for bone texture must go before other textures
+ // not sure why, but otherwise weird things happen
+
+ if (material.skinning) {
+ p_uniforms.setOptional(_gl, object, "bindMatrix");
+ p_uniforms.setOptional(_gl, object, "bindMatrixInverse");
+
+ var skeleton = object.skeleton;
+
+ if (skeleton) {
+ var bones = skeleton.bones;
+
+ if (capabilities.floatVertexTextures) {
+ if (skeleton.boneTexture === undefined) {
+ // layout (1 matrix = 4 pixels)
+ // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
+ // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)
+ // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)
+ // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)
+ // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
+
+ var size = Math.sqrt(bones.length * 4); // 4 pixels needed for 1 matrix
+ size = _Math.ceilPowerOfTwo(size);
+ size = Math.max(size, 4);
+
+ var boneMatrices = new Float32Array(size * size * 4); // 4 floats per RGBA pixel
+ boneMatrices.set(skeleton.boneMatrices); // copy current values
+
+ var boneTexture = new DataTexture(
+ boneMatrices,
+ size,
+ size,
+ RGBAFormat,
+ FloatType
+ );
+ boneTexture.needsUpdate = true;
+
+ skeleton.boneMatrices = boneMatrices;
+ skeleton.boneTexture = boneTexture;
+ skeleton.boneTextureSize = size;
+ }
+
+ p_uniforms.setValue(
+ _gl,
+ "boneTexture",
+ skeleton.boneTexture,
+ textures
+ );
+ p_uniforms.setValue(_gl, "boneTextureSize", skeleton.boneTextureSize);
+ } else {
+ p_uniforms.setOptional(_gl, skeleton, "boneMatrices");
+ }
+ }
+ }
+
+ if (refreshMaterial) {
+ p_uniforms.setValue(
+ _gl,
+ "toneMappingExposure",
+ _this.toneMappingExposure
+ );
+ p_uniforms.setValue(
+ _gl,
+ "toneMappingWhitePoint",
+ _this.toneMappingWhitePoint
+ );
+
+ if (material.lights) {
+ // the current material requires lighting info
+
+ // note: all lighting uniforms are always set correctly
+ // they simply reference the renderer's state for their
+ // values
+ //
+ // use the current material's .needsUpdate flags to set
+ // the GL state when required
+
+ markUniformsLightsNeedsUpdate(m_uniforms, refreshLights);
+ }
+
+ // refresh uniforms common to several materials
+
+ if (fog && material.fog) {
+ refreshUniformsFog(m_uniforms, fog);
+ }
+
+ if (material.isMeshBasicMaterial) {
+ refreshUniformsCommon(m_uniforms, material);
+ } else if (material.isMeshLambertMaterial) {
+ refreshUniformsCommon(m_uniforms, material);
+ refreshUniformsLambert(m_uniforms, material);
+ } else if (material.isMeshPhongMaterial) {
+ refreshUniformsCommon(m_uniforms, material);
+
+ if (material.isMeshToonMaterial) {
+ refreshUniformsToon(m_uniforms, material);
+ } else {
+ refreshUniformsPhong(m_uniforms, material);
+ }
+ } else if (material.isMeshStandardMaterial) {
+ refreshUniformsCommon(m_uniforms, material);
+
+ if (material.isMeshPhysicalMaterial) {
+ refreshUniformsPhysical(m_uniforms, material);
+ } else {
+ refreshUniformsStandard(m_uniforms, material);
+ }
+ } else if (material.isMeshMatcapMaterial) {
+ refreshUniformsCommon(m_uniforms, material);
+
+ refreshUniformsMatcap(m_uniforms, material);
+ } else if (material.isMeshDepthMaterial) {
+ refreshUniformsCommon(m_uniforms, material);
+ refreshUniformsDepth(m_uniforms, material);
+ } else if (material.isMeshDistanceMaterial) {
+ refreshUniformsCommon(m_uniforms, material);
+ refreshUniformsDistance(m_uniforms, material);
+ } else if (material.isMeshNormalMaterial) {
+ refreshUniformsCommon(m_uniforms, material);
+ refreshUniformsNormal(m_uniforms, material);
+ } else if (material.isLineBasicMaterial) {
+ refreshUniformsLine(m_uniforms, material);
+
+ if (material.isLineDashedMaterial) {
+ refreshUniformsDash(m_uniforms, material);
+ }
+ } else if (material.isPointsMaterial) {
+ refreshUniformsPoints(m_uniforms, material);
+ } else if (material.isSpriteMaterial) {
+ refreshUniformsSprites(m_uniforms, material);
+ } else if (material.isShadowMaterial) {
+ m_uniforms.color.value.copy(material.color);
+ m_uniforms.opacity.value = material.opacity;
+ }
+
+ // RectAreaLight Texture
+ // TODO (mrdoob): Find a nicer implementation
+
+ if (m_uniforms.ltc_1 !== undefined)
+ m_uniforms.ltc_1.value = UniformsLib.LTC_1;
+ if (m_uniforms.ltc_2 !== undefined)
+ m_uniforms.ltc_2.value = UniformsLib.LTC_2;
+
+ WebGLUniforms.upload(
+ _gl,
+ materialProperties.uniformsList,
+ m_uniforms,
+ textures
+ );
+ }
+
+ if (material.isShaderMaterial && material.uniformsNeedUpdate === true) {
+ WebGLUniforms.upload(
+ _gl,
+ materialProperties.uniformsList,
+ m_uniforms,
+ textures
+ );
+ material.uniformsNeedUpdate = false;
+ }
+
+ if (material.isSpriteMaterial) {
+ p_uniforms.setValue(_gl, "center", object.center);
+ }
+
+ // common matrices
+
+ p_uniforms.setValue(_gl, "modelViewMatrix", object.modelViewMatrix);
+ p_uniforms.setValue(_gl, "normalMatrix", object.normalMatrix);
+ p_uniforms.setValue(_gl, "modelMatrix", object.matrixWorld);
+
+ return program;
+ }
+
+ // Uniforms (refresh uniforms objects)
+
+ function refreshUniformsCommon(uniforms, material) {
+ uniforms.opacity.value = material.opacity;
+
+ if (material.color) {
+ uniforms.diffuse.value.copy(material.color);
+ }
+
+ if (material.emissive) {
+ uniforms.emissive.value
+ .copy(material.emissive)
+ .multiplyScalar(material.emissiveIntensity);
+ }
+
+ if (material.map) {
+ uniforms.map.value = material.map;
+ }
+
+ if (material.alphaMap) {
+ uniforms.alphaMap.value = material.alphaMap;
+ }
+
+ if (material.specularMap) {
+ uniforms.specularMap.value = material.specularMap;
+ }
+
+ if (material.envMap) {
+ uniforms.envMap.value = material.envMap;
+
+ // don't flip CubeTexture envMaps, flip everything else:
+ // WebGLRenderTargetCube will be flipped for backwards compatibility
+ // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture
+ // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future
+ uniforms.flipEnvMap.value = material.envMap.isCubeTexture ? -1 : 1;
+
+ uniforms.reflectivity.value = material.reflectivity;
+ uniforms.refractionRatio.value = material.refractionRatio;
+
+ uniforms.maxMipLevel.value = properties.get(
+ material.envMap
+ ).__maxMipLevel;
+ }
+
+ if (material.lightMap) {
+ uniforms.lightMap.value = material.lightMap;
+ uniforms.lightMapIntensity.value = material.lightMapIntensity;
+ }
+
+ if (material.aoMap) {
+ uniforms.aoMap.value = material.aoMap;
+ uniforms.aoMapIntensity.value = material.aoMapIntensity;
+ }
+
+ // uv repeat and offset setting priorities
+ // 1. color map
+ // 2. specular map
+ // 3. normal map
+ // 4. bump map
+ // 5. alpha map
+ // 6. emissive map
+
+ var uvScaleMap;
+
+ if (material.map) {
+ uvScaleMap = material.map;
+ } else if (material.specularMap) {
+ uvScaleMap = material.specularMap;
+ } else if (material.displacementMap) {
+ uvScaleMap = material.displacementMap;
+ } else if (material.normalMap) {
+ uvScaleMap = material.normalMap;
+ } else if (material.bumpMap) {
+ uvScaleMap = material.bumpMap;
+ } else if (material.roughnessMap) {
+ uvScaleMap = material.roughnessMap;
+ } else if (material.metalnessMap) {
+ uvScaleMap = material.metalnessMap;
+ } else if (material.alphaMap) {
+ uvScaleMap = material.alphaMap;
+ } else if (material.emissiveMap) {
+ uvScaleMap = material.emissiveMap;
+ }
+
+ if (uvScaleMap !== undefined) {
+ // backwards compatibility
+ if (uvScaleMap.isWebGLRenderTarget) {
+ uvScaleMap = uvScaleMap.texture;
+ }
+
+ if (uvScaleMap.matrixAutoUpdate === true) {
+ uvScaleMap.updateMatrix();
+ }
+
+ uniforms.uvTransform.value.copy(uvScaleMap.matrix);
+ }
+ }
+
+ function refreshUniformsLine(uniforms, material) {
+ uniforms.diffuse.value.copy(material.color);
+ uniforms.opacity.value = material.opacity;
+ }
+
+ function refreshUniformsDash(uniforms, material) {
+ uniforms.dashSize.value = material.dashSize;
+ uniforms.totalSize.value = material.dashSize + material.gapSize;
+ uniforms.scale.value = material.scale;
+ }
+
+ function refreshUniformsPoints(uniforms, material) {
+ uniforms.diffuse.value.copy(material.color);
+ uniforms.opacity.value = material.opacity;
+ uniforms.size.value = material.size * _pixelRatio;
+ uniforms.scale.value = _height * 0.5;
+
+ uniforms.map.value = material.map;
+
+ if (material.map !== null) {
+ if (material.map.matrixAutoUpdate === true) {
+ material.map.updateMatrix();
+ }
+
+ uniforms.uvTransform.value.copy(material.map.matrix);
+ }
+ }
+
+ function refreshUniformsSprites(uniforms, material) {
+ uniforms.diffuse.value.copy(material.color);
+ uniforms.opacity.value = material.opacity;
+ uniforms.rotation.value = material.rotation;
+ uniforms.map.value = material.map;
+
+ if (material.map !== null) {
+ if (material.map.matrixAutoUpdate === true) {
+ material.map.updateMatrix();
+ }
+
+ uniforms.uvTransform.value.copy(material.map.matrix);
+ }
+ }
+
+ function refreshUniformsFog(uniforms, fog) {
+ uniforms.fogColor.value.copy(fog.color);
+
+ if (fog.isFog) {
+ uniforms.fogNear.value = fog.near;
+ uniforms.fogFar.value = fog.far;
+ } else if (fog.isFogExp2) {
+ uniforms.fogDensity.value = fog.density;
+ }
+ }
+
+ function refreshUniformsLambert(uniforms, material) {
+ if (material.emissiveMap) {
+ uniforms.emissiveMap.value = material.emissiveMap;
+ }
+ }
+
+ function refreshUniformsPhong(uniforms, material) {
+ uniforms.specular.value.copy(material.specular);
+ uniforms.shininess.value = Math.max(material.shininess, 1e-4); // to prevent pow( 0.0, 0.0 )
+
+ if (material.emissiveMap) {
+ uniforms.emissiveMap.value = material.emissiveMap;
+ }
+
+ if (material.bumpMap) {
+ uniforms.bumpMap.value = material.bumpMap;
+ uniforms.bumpScale.value = material.bumpScale;
+ if (material.side === BackSide) uniforms.bumpScale.value *= -1;
+ }
+
+ if (material.normalMap) {
+ uniforms.normalMap.value = material.normalMap;
+ uniforms.normalScale.value.copy(material.normalScale);
+ if (material.side === BackSide) uniforms.normalScale.value.negate();
+ }
+
+ if (material.displacementMap) {
+ uniforms.displacementMap.value = material.displacementMap;
+ uniforms.displacementScale.value = material.displacementScale;
+ uniforms.displacementBias.value = material.displacementBias;
+ }
+ }
+
+ function refreshUniformsToon(uniforms, material) {
+ refreshUniformsPhong(uniforms, material);
+
+ if (material.gradientMap) {
+ uniforms.gradientMap.value = material.gradientMap;
+ }
+ }
+
+ function refreshUniformsStandard(uniforms, material) {
+ uniforms.roughness.value = material.roughness;
+ uniforms.metalness.value = material.metalness;
+
+ if (material.roughnessMap) {
+ uniforms.roughnessMap.value = material.roughnessMap;
+ }
+
+ if (material.metalnessMap) {
+ uniforms.metalnessMap.value = material.metalnessMap;
+ }
+
+ if (material.emissiveMap) {
+ uniforms.emissiveMap.value = material.emissiveMap;
+ }
+
+ if (material.bumpMap) {
+ uniforms.bumpMap.value = material.bumpMap;
+ uniforms.bumpScale.value = material.bumpScale;
+ if (material.side === BackSide) uniforms.bumpScale.value *= -1;
+ }
+
+ if (material.normalMap) {
+ uniforms.normalMap.value = material.normalMap;
+ uniforms.normalScale.value.copy(material.normalScale);
+ if (material.side === BackSide) uniforms.normalScale.value.negate();
+ }
+
+ if (material.displacementMap) {
+ uniforms.displacementMap.value = material.displacementMap;
+ uniforms.displacementScale.value = material.displacementScale;
+ uniforms.displacementBias.value = material.displacementBias;
+ }
+
+ if (material.envMap) {
+ //uniforms.envMap.value = material.envMap; // part of uniforms common
+ uniforms.envMapIntensity.value = material.envMapIntensity;
+ }
+ }
+
+ function refreshUniformsPhysical(uniforms, material) {
+ refreshUniformsStandard(uniforms, material);
+
+ uniforms.reflectivity.value = material.reflectivity; // also part of uniforms common
+
+ uniforms.clearcoat.value = material.clearcoat;
+ uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
+ if (material.sheen) uniforms.sheen.value.copy(material.sheen);
+
+ if (material.clearcoatNormalMap) {
+ uniforms.clearcoatNormalScale.value.copy(material.clearcoatNormalScale);
+ uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
+
+ if (material.side === BackSide) {
+ uniforms.clearcoatNormalScale.value.negate();
+ }
+ }
+
+ uniforms.transparency.value = material.transparency;
+ }
+
+ function refreshUniformsMatcap(uniforms, material) {
+ if (material.matcap) {
+ uniforms.matcap.value = material.matcap;
+ }
+
+ if (material.bumpMap) {
+ uniforms.bumpMap.value = material.bumpMap;
+ uniforms.bumpScale.value = material.bumpScale;
+ if (material.side === BackSide) uniforms.bumpScale.value *= -1;
+ }
+
+ if (material.normalMap) {
+ uniforms.normalMap.value = material.normalMap;
+ uniforms.normalScale.value.copy(material.normalScale);
+ if (material.side === BackSide) uniforms.normalScale.value.negate();
+ }
+
+ if (material.displacementMap) {
+ uniforms.displacementMap.value = material.displacementMap;
+ uniforms.displacementScale.value = material.displacementScale;
+ uniforms.displacementBias.value = material.displacementBias;
+ }
+ }
+
+ function refreshUniformsDepth(uniforms, material) {
+ if (material.displacementMap) {
+ uniforms.displacementMap.value = material.displacementMap;
+ uniforms.displacementScale.value = material.displacementScale;
+ uniforms.displacementBias.value = material.displacementBias;
+ }
+ }
+
+ function refreshUniformsDistance(uniforms, material) {
+ if (material.displacementMap) {
+ uniforms.displacementMap.value = material.displacementMap;
+ uniforms.displacementScale.value = material.displacementScale;
+ uniforms.displacementBias.value = material.displacementBias;
+ }
+
+ uniforms.referencePosition.value.copy(material.referencePosition);
+ uniforms.nearDistance.value = material.nearDistance;
+ uniforms.farDistance.value = material.farDistance;
+ }
+
+ function refreshUniformsNormal(uniforms, material) {
+ if (material.bumpMap) {
+ uniforms.bumpMap.value = material.bumpMap;
+ uniforms.bumpScale.value = material.bumpScale;
+ if (material.side === BackSide) uniforms.bumpScale.value *= -1;
+ }
+
+ if (material.normalMap) {
+ uniforms.normalMap.value = material.normalMap;
+ uniforms.normalScale.value.copy(material.normalScale);
+ if (material.side === BackSide) uniforms.normalScale.value.negate();
+ }
+
+ if (material.displacementMap) {
+ uniforms.displacementMap.value = material.displacementMap;
+ uniforms.displacementScale.value = material.displacementScale;
+ uniforms.displacementBias.value = material.displacementBias;
+ }
+ }
+
+ // If uniforms are marked as clean, they don't need to be loaded to the GPU.
+
+ function markUniformsLightsNeedsUpdate(uniforms, value) {
+ uniforms.ambientLightColor.needsUpdate = value;
+ uniforms.lightProbe.needsUpdate = value;
+
+ uniforms.directionalLights.needsUpdate = value;
+ uniforms.pointLights.needsUpdate = value;
+ uniforms.spotLights.needsUpdate = value;
+ uniforms.rectAreaLights.needsUpdate = value;
+ uniforms.hemisphereLights.needsUpdate = value;
+ }
+
+ //
+ this.setFramebuffer = function (value) {
+ if (_framebuffer !== value) _gl.bindFramebuffer(_gl.FRAMEBUFFER, value);
+
+ _framebuffer = value;
+ };
+
+ this.getActiveCubeFace = function () {
+ return _currentActiveCubeFace;
+ };
+
+ this.getActiveMipmapLevel = function () {
+ return _currentActiveMipmapLevel;
+ };
+
+ this.getRenderTarget = function () {
+ return _currentRenderTarget;
+ };
+
+ this.setRenderTarget = function (
+ renderTarget,
+ activeCubeFace,
+ activeMipmapLevel
+ ) {
+ _currentRenderTarget = renderTarget;
+ _currentActiveCubeFace = activeCubeFace;
+ _currentActiveMipmapLevel = activeMipmapLevel;
+
+ if (
+ renderTarget &&
+ properties.get(renderTarget).__webglFramebuffer === undefined
+ ) {
+ textures.setupRenderTarget(renderTarget);
+ }
+
+ var framebuffer = _framebuffer;
+ var isCube = false;
+
+ if (renderTarget) {
+ var __webglFramebuffer = properties.get(renderTarget).__webglFramebuffer;
+
+ if (renderTarget.isWebGLRenderTargetCube) {
+ framebuffer = __webglFramebuffer[activeCubeFace || 0];
+ isCube = true;
+ } else if (renderTarget.isWebGLMultisampleRenderTarget) {
+ framebuffer =
+ properties.get(renderTarget).__webglMultisampledFramebuffer;
+ } else {
+ framebuffer = __webglFramebuffer;
+ }
+
+ _currentViewport.copy(renderTarget.viewport);
+ _currentScissor.copy(renderTarget.scissor);
+ _currentScissorTest = renderTarget.scissorTest;
+ } else {
+ _currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor();
+ _currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor();
+ _currentScissorTest = _scissorTest;
+ }
+
+ if (_currentFramebuffer !== framebuffer) {
+ _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
+ _currentFramebuffer = framebuffer;
+ }
+
+ state.viewport(_currentViewport);
+ state.scissor(_currentScissor);
+ state.setScissorTest(_currentScissorTest);
+
+ if (isCube) {
+ var textureProperties = properties.get(renderTarget.texture);
+ _gl.framebufferTexture2D(
+ _gl.FRAMEBUFFER,
+ _gl.COLOR_ATTACHMENT0,
+ _gl.TEXTURE_CUBE_MAP_POSITIVE_X + (activeCubeFace || 0),
+ textureProperties.__webglTexture,
+ activeMipmapLevel || 0
+ );
+ }
+ };
+
+ this.readRenderTargetPixels = function (
+ renderTarget,
+ x,
+ y,
+ width,
+ height,
+ buffer,
+ activeCubeFaceIndex
+ ) {
+ if (!(renderTarget && renderTarget.isWebGLRenderTarget)) {
+ console.error(
+ "THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget."
+ );
+ return;
+ }
+
+ var framebuffer = properties.get(renderTarget).__webglFramebuffer;
+
+ if (
+ renderTarget.isWebGLRenderTargetCube &&
+ activeCubeFaceIndex !== undefined
+ ) {
+ framebuffer = framebuffer[activeCubeFaceIndex];
+ }
+
+ if (framebuffer) {
+ var restore = false;
+
+ if (framebuffer !== _currentFramebuffer) {
+ _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
+
+ restore = true;
+ }
+
+ try {
+ var texture = renderTarget.texture;
+ var textureFormat = texture.format;
+ var textureType = texture.type;
+
+ if (
+ textureFormat !== RGBAFormat &&
+ utils.convert(textureFormat) !==
+ _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_FORMAT)
+ ) {
+ console.error(
+ "THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format."
+ );
+ return;
+ }
+
+ if (
+ textureType !== UnsignedByteType &&
+ utils.convert(textureType) !==
+ _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_TYPE) && // IE11, Edge and Chrome Mac < 52 (#9513)
+ !(
+ textureType === FloatType &&
+ (capabilities.isWebGL2 ||
+ extensions.get("OES_texture_float") ||
+ extensions.get("WEBGL_color_buffer_float"))
+ ) && // Chrome Mac >= 52 and Firefox
+ !(
+ textureType === HalfFloatType &&
+ (capabilities.isWebGL2
+ ? extensions.get("EXT_color_buffer_float")
+ : extensions.get("EXT_color_buffer_half_float"))
+ )
+ ) {
+ console.error(
+ "THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type."
+ );
+ return;
+ }
+
+ if (
+ _gl.checkFramebufferStatus(_gl.FRAMEBUFFER) ===
+ _gl.FRAMEBUFFER_COMPLETE
+ ) {
+ // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
+
+ if (
+ x >= 0 &&
+ x <= renderTarget.width - width &&
+ y >= 0 &&
+ y <= renderTarget.height - height
+ ) {
+ _gl.readPixels(
+ x,
+ y,
+ width,
+ height,
+ utils.convert(textureFormat),
+ utils.convert(textureType),
+ buffer
+ );
+ }
+ } else {
+ console.error(
+ "THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete."
+ );
+ }
+ } finally {
+ if (restore) {
+ _gl.bindFramebuffer(_gl.FRAMEBUFFER, _currentFramebuffer);
+ }
+ }
+ }
+ };
+
+ this.copyFramebufferToTexture = function (position, texture, level) {
+ var width = texture.image.width;
+ var height = texture.image.height;
+ var glFormat = utils.convert(texture.format);
+
+ textures.setTexture2D(texture, 0);
+
+ _gl.copyTexImage2D(
+ _gl.TEXTURE_2D,
+ level || 0,
+ glFormat,
+ position.x,
+ position.y,
+ width,
+ height,
+ 0
+ );
+ };
+
+ this.copyTextureToTexture = function (
+ position,
+ srcTexture,
+ dstTexture,
+ level
+ ) {
+ var width = srcTexture.image.width;
+ var height = srcTexture.image.height;
+ var glFormat = utils.convert(dstTexture.format);
+ var glType = utils.convert(dstTexture.type);
+
+ textures.setTexture2D(dstTexture, 0);
+
+ if (srcTexture.isDataTexture) {
+ _gl.texSubImage2D(
+ _gl.TEXTURE_2D,
+ level || 0,
+ position.x,
+ position.y,
+ width,
+ height,
+ glFormat,
+ glType,
+ srcTexture.image.data
+ );
+ } else {
+ _gl.texSubImage2D(
+ _gl.TEXTURE_2D,
+ level || 0,
+ position.x,
+ position.y,
+ glFormat,
+ glType,
+ srcTexture.image
+ );
+ }
+ };
+
+ if (typeof __THREE_DEVTOOLS__ !== "undefined") {
+ __THREE_DEVTOOLS__.dispatchEvent(
+ new CustomEvent("observe", { detail: this })
+ ); // eslint-disable-line no-undef
+ }
+}
+
+export { WebGLRenderer };
diff --git a/src/test/fixtures/label-continue-break-bug.js b/src/test/fixtures/label-continue-break-bug.js
new file mode 100644
index 000000000..12e46cca3
--- /dev/null
+++ b/src/test/fixtures/label-continue-break-bug.js
@@ -0,0 +1,125 @@
+Object.assign(Interpolant.prototype, {
+ evaluate: function (t) {
+ var pp = this.parameterPositions,
+ i1 = this._cachedIndex,
+ t1 = pp[i1],
+ t0 = pp[i1 - 1];
+
+ validate_interval: {
+ seek: {
+ var right;
+
+ linear_scan: {
+ //- See http://jsperf.com/comparison-to-undefined/3
+ //- slower code:
+ //-
+ //- if ( t >= t1 || t1 === undefined ) {
+ forward_scan: if (!(t < t1)) {
+ for (var giveUpAt = i1 + 2; ; ) {
+ if (t1 === undefined) {
+ if (t < t0) break forward_scan;
+
+ // after end
+
+ i1 = pp.length;
+ this._cachedIndex = i1;
+ return this.afterEnd_(i1 - 1, t, t0);
+ }
+
+ if (i1 === giveUpAt) break; // this loop
+
+ t0 = t1;
+ t1 = pp[++i1];
+
+ if (t < t1) {
+ // we have arrived at the sought interval
+ break seek;
+ }
+ }
+
+ // prepare binary search on the right side of the index
+ right = pp.length;
+ break linear_scan;
+ }
+
+ //- slower code:
+ //- if ( t < t0 || t0 === undefined ) {
+ if (!(t >= t0)) {
+ // looping?
+
+ var t1global = pp[1];
+
+ if (t < t1global) {
+ i1 = 2; // + 1, using the scan for the details
+ t0 = t1global;
+ }
+
+ // linear reverse scan
+
+ for (var giveUpAt = i1 - 2; ; ) {
+ if (t0 === undefined) {
+ // before start
+
+ this._cachedIndex = 0;
+ return this.beforeStart_(0, t, t1);
+ }
+
+ if (i1 === giveUpAt) break; // this loop
+
+ t1 = t0;
+ t0 = pp[--i1 - 1];
+
+ if (t >= t0) {
+ // we have arrived at the sought interval
+ break seek;
+ }
+ }
+
+ // prepare binary search on the left side of the index
+ right = i1;
+ i1 = 0;
+ break linear_scan;
+ }
+
+ // the interval is valid
+
+ break validate_interval;
+ } // linear scan
+
+ // binary search
+
+ while (i1 < right) {
+ var mid = (i1 + right) >>> 1;
+
+ if (t < pp[mid]) {
+ right = mid;
+ } else {
+ i1 = mid + 1;
+ }
+ }
+
+ t1 = pp[i1];
+ t0 = pp[i1 - 1];
+
+ // check boundary cases, again
+
+ if (t0 === undefined) {
+ this._cachedIndex = 0;
+ return this.beforeStart_(0, t, t1);
+ }
+
+ if (t1 === undefined) {
+ i1 = pp.length;
+ this._cachedIndex = i1;
+ return this.afterEnd_(i1 - 1, t0, t);
+ }
+ } // seek
+
+ this._cachedIndex = i1;
+
+ this.intervalChanged_(i1, t0, t1);
+ } // validate_interval
+
+ return this.interpolate_(i1, t0, t, t1);
+ },
+});
diff --git a/src/test/fixtures/symbols-bug.js b/src/test/fixtures/symbols-bug.js
new file mode 100644
index 000000000..f40ec8c50
--- /dev/null
+++ b/src/test/fixtures/symbols-bug.js
@@ -0,0 +1,16 @@
+var boom = {
+ a: 2,
+ b: "4",
+ c: "6",
+ d: "8",
+ e: "10",
+ f: 12,
+ g: 14,
+}["15"];
+
+const foo = "bacon";
+const james = "not-bacon";
+const lordy = "sammy";
+const boop = {
+ hey: { foo },
+};
diff --git a/src/test/tester.zig b/src/test/tester.zig
index 6b3174eac..81e1c8ea2 100644
--- a/src/test/tester.zig
+++ b/src/test/tester.zig
@@ -66,6 +66,10 @@ pub const Tester = struct {
}
pub fn evaluate_outcome(self: *const @This()) Outcome {
+ if (self.expected.len > self.result.len) {
+ return .fail;
+ }
+
for (self.expected) |char, i| {
if (char != self.result[i]) {
return Outcome.fail;