Move HTML canvas and tracks from ExceptionCode to Exception
[WebKit-https.git] / Source / WebCore / bindings / js / JSWebGLRenderingContextBaseCustom.cpp
1 /*
2  * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "JSWebGLRenderingContextBase.h"
28
29 #if ENABLE(WEBGL)
30
31 #include "ANGLEInstancedArrays.h"
32 #include "EXTBlendMinMax.h"
33 #include "EXTFragDepth.h"
34 #include "EXTShaderTextureLOD.h"
35 #include "EXTTextureFilterAnisotropic.h"
36 #include "EXTsRGB.h"
37 #include "ExceptionCode.h"
38 #include "HTMLCanvasElement.h"
39 #include "HTMLImageElement.h"
40 #include "JSANGLEInstancedArrays.h"
41 #include "JSEXTBlendMinMax.h"
42 #include "JSEXTFragDepth.h"
43 #include "JSEXTShaderTextureLOD.h"
44 #include "JSEXTTextureFilterAnisotropic.h"
45 #include "JSEXTsRGB.h"
46 #include "JSHTMLCanvasElement.h"
47 #include "JSHTMLImageElement.h"
48 #include "JSImageData.h"
49 #include "JSOESElementIndexUint.h"
50 #include "JSOESStandardDerivatives.h"
51 #include "JSOESTextureFloat.h"
52 #include "JSOESTextureFloatLinear.h"
53 #include "JSOESTextureHalfFloat.h"
54 #include "JSOESTextureHalfFloatLinear.h"
55 #include "JSOESVertexArrayObject.h"
56 #include "JSWebGLBuffer.h"
57 #include "JSWebGLCompressedTextureATC.h"
58 #include "JSWebGLCompressedTexturePVRTC.h"
59 #include "JSWebGLCompressedTextureS3TC.h"
60 #include "JSWebGLDebugRendererInfo.h"
61 #include "JSWebGLDebugShaders.h"
62 #include "JSWebGLDepthTexture.h"
63 #include "JSWebGLDrawBuffers.h"
64 #include "JSWebGLFramebuffer.h"
65 #include "JSWebGLLoseContext.h"
66 #include "JSWebGLProgram.h"
67 #include "JSWebGLRenderbuffer.h"
68 #include "JSWebGLRenderingContext.h"
69 #include "JSWebGLShader.h"
70 #include "JSWebGLTexture.h"
71 #include "JSWebGLUniformLocation.h"
72 #include "JSWebGLVertexArrayObject.h"
73 #include "JSWebGLVertexArrayObjectOES.h"
74 #include "JSWebKitCSSMatrix.h"
75 #include "NotImplemented.h"
76 #include "OESElementIndexUint.h"
77 #include "OESStandardDerivatives.h"
78 #include "OESTextureFloat.h"
79 #include "OESTextureFloatLinear.h"
80 #include "OESTextureHalfFloat.h"
81 #include "OESTextureHalfFloatLinear.h"
82 #include "OESVertexArrayObject.h"
83 #include "WebGLBuffer.h"
84 #include "WebGLCompressedTextureATC.h"
85 #include "WebGLCompressedTexturePVRTC.h"
86 #include "WebGLCompressedTextureS3TC.h"
87 #include "WebGLDebugRendererInfo.h"
88 #include "WebGLDebugShaders.h"
89 #include "WebGLDepthTexture.h"
90 #include "WebGLDrawBuffers.h"
91 #include "WebGLExtension.h"
92 #include "WebGLFramebuffer.h"
93 #include "WebGLGetInfo.h"
94 #include "WebGLLoseContext.h"
95 #include "WebGLProgram.h"
96 #include "WebGLRenderingContextBase.h"
97 #include "WebGLVertexArrayObject.h"
98 #include "WebGLVertexArrayObjectOES.h"
99 #include <runtime/Error.h>
100 #include <runtime/JSObjectInlines.h>
101 #include <runtime/JSTypedArrays.h>
102 #include <runtime/TypedArrayInlines.h>
103 #include <runtime/TypedArrays.h>
104 #include <wtf/FastMalloc.h>
105
106 #if ENABLE(VIDEO)
107 #include "HTMLVideoElement.h"
108 #include "JSHTMLVideoElement.h"
109 #endif
110
111 #if ENABLE(WEBGL2)
112 #include "JSWebGL2RenderingContext.h"
113 #endif
114
115 using namespace JSC;
116
117 namespace WebCore {
118
119 JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<WebGLRenderingContextBase>&& object)
120 {
121 #if ENABLE(WEBGL2)
122     if (is<WebGL2RenderingContext>(object))
123         return createWrapper<WebGL2RenderingContext>(globalObject, WTFMove(object));
124 #endif
125     return createWrapper<WebGLRenderingContext>(globalObject, WTFMove(object));
126 }
127
128 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, WebGLRenderingContextBase& object)
129 {
130     return wrap(state, globalObject, object);
131 }
132     
133 // FIXME: There is a duplicate version of this function in JSWebGL2RenderingContextCustom.cpp,
134 // but it is not exactly the same! We should merge these.
135 static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const WebGLGetInfo& info)
136 {
137     switch (info.getType()) {
138     case WebGLGetInfo::kTypeBool:
139         return jsBoolean(info.getBool());
140     case WebGLGetInfo::kTypeBoolArray: {
141         MarkedArgumentBuffer list;
142         for (auto& value : info.getBoolArray())
143             list.append(jsBoolean(value));
144         return constructArray(exec, 0, globalObject, list);
145     }
146     case WebGLGetInfo::kTypeFloat:
147         return jsNumber(info.getFloat());
148     case WebGLGetInfo::kTypeInt:
149         return jsNumber(info.getInt());
150     case WebGLGetInfo::kTypeNull:
151         return jsNull();
152     case WebGLGetInfo::kTypeString:
153         return jsStringWithCache(exec, info.getString());
154     case WebGLGetInfo::kTypeUnsignedInt:
155         return jsNumber(info.getUnsignedInt());
156     case WebGLGetInfo::kTypeWebGLBuffer:
157         return toJS(exec, globalObject, info.getWebGLBuffer());
158     case WebGLGetInfo::kTypeWebGLFloatArray:
159         return toJS(exec, globalObject, info.getWebGLFloatArray());
160     case WebGLGetInfo::kTypeWebGLFramebuffer:
161         return toJS(exec, globalObject, info.getWebGLFramebuffer());
162     case WebGLGetInfo::kTypeWebGLIntArray:
163         return toJS(exec, globalObject, info.getWebGLIntArray());
164         // FIXME: implement WebGLObjectArray
165         // case WebGLGetInfo::kTypeWebGLObjectArray:
166     case WebGLGetInfo::kTypeWebGLProgram:
167         return toJS(exec, globalObject, info.getWebGLProgram());
168     case WebGLGetInfo::kTypeWebGLRenderbuffer:
169         return toJS(exec, globalObject, info.getWebGLRenderbuffer());
170     case WebGLGetInfo::kTypeWebGLTexture:
171         return toJS(exec, globalObject, info.getWebGLTexture());
172     case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
173         return toJS(exec, globalObject, info.getWebGLUnsignedByteArray());
174     case WebGLGetInfo::kTypeWebGLUnsignedIntArray:
175         return toJS(exec, globalObject, info.getWebGLUnsignedIntArray());
176 #if ENABLE(WEBGL2)
177     case WebGLGetInfo::kTypeWebGLVertexArrayObject:
178         return toJS(exec, globalObject, info.getWebGLVertexArrayObject());
179 #endif
180     case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
181         return toJS(exec, globalObject, info.getWebGLVertexArrayObjectOES());
182     default:
183         notImplemented();
184         return jsUndefined();
185     }
186 }
187
188 enum ObjectType { kBuffer, kRenderbuffer, kTexture, kVertexAttrib };
189
190 static JSValue getObjectParameter(JSWebGLRenderingContextBase* obj, ExecState& state, ObjectType objectType)
191 {
192     VM& vm = state.vm();
193     auto scope = DECLARE_THROW_SCOPE(vm);
194
195     if (state.argumentCount() != 2)
196         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
197     
198     ExceptionCode ec = 0;
199     WebGLRenderingContextBase& context = obj->wrapped();
200     unsigned target = state.uncheckedArgument(0).toInt32(&state);
201     RETURN_IF_EXCEPTION(scope, JSValue());
202     unsigned pname = state.uncheckedArgument(1).toInt32(&state);
203     RETURN_IF_EXCEPTION(scope, JSValue());
204     WebGLGetInfo info;
205     switch (objectType) {
206     case kBuffer:
207         info = context.getBufferParameter(target, pname);
208         break;
209     case kRenderbuffer:
210         info = context.getRenderbufferParameter(target, pname);
211         break;
212     case kTexture:
213         info = context.getTexParameter(target, pname);
214         break;
215     case kVertexAttrib:
216         // target => index
217         info = context.getVertexAttrib(target, pname);
218         break;
219     default:
220         notImplemented();
221         break;
222     }
223     if (ec) {
224         setDOMException(&state, ec);
225         return jsUndefined();
226     }
227     return toJS(&state, obj->globalObject(), info);
228 }
229
230 enum WhichProgramCall {
231     kProgramParameter, kUniform
232 };
233
234 static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, WebGLExtension* extension)
235 {
236     if (!extension)
237         return jsNull();
238     switch (extension->getName()) {
239     case WebGLExtension::WebGLLoseContextName:
240         return toJS(exec, globalObject, static_cast<WebGLLoseContext*>(extension));
241     case WebGLExtension::EXTShaderTextureLODName:
242         return toJS(exec, globalObject, static_cast<EXTShaderTextureLOD*>(extension));
243     case WebGLExtension::EXTTextureFilterAnisotropicName:
244         return toJS(exec, globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension));
245     case WebGLExtension::EXTsRGBName:
246         return toJS(exec, globalObject, static_cast<EXTsRGB*>(extension));
247     case WebGLExtension::EXTFragDepthName:
248         return toJS(exec, globalObject, static_cast<EXTFragDepth*>(extension));
249     case WebGLExtension::EXTBlendMinMaxName:
250         return toJS(exec, globalObject, static_cast<EXTBlendMinMax*>(extension));
251     case WebGLExtension::OESStandardDerivativesName:
252         return toJS(exec, globalObject, static_cast<OESStandardDerivatives*>(extension));
253     case WebGLExtension::OESTextureFloatName:
254         return toJS(exec, globalObject, static_cast<OESTextureFloat*>(extension));
255     case WebGLExtension::OESTextureFloatLinearName:
256         return toJS(exec, globalObject, static_cast<OESTextureFloatLinear*>(extension));
257     case WebGLExtension::OESTextureHalfFloatName:
258         return toJS(exec, globalObject, static_cast<OESTextureHalfFloat*>(extension));
259     case WebGLExtension::OESTextureHalfFloatLinearName:
260         return toJS(exec, globalObject, static_cast<OESTextureHalfFloatLinear*>(extension));
261     case WebGLExtension::OESVertexArrayObjectName:
262         return toJS(exec, globalObject, static_cast<OESVertexArrayObject*>(extension));
263     case WebGLExtension::OESElementIndexUintName:
264         return toJS(exec, globalObject, static_cast<OESElementIndexUint*>(extension));
265     case WebGLExtension::WebGLDebugRendererInfoName:
266         return toJS(exec, globalObject, static_cast<WebGLDebugRendererInfo*>(extension));
267     case WebGLExtension::WebGLDebugShadersName:
268         return toJS(exec, globalObject, static_cast<WebGLDebugShaders*>(extension));
269     case WebGLExtension::WebGLCompressedTextureATCName:
270         return toJS(exec, globalObject, static_cast<WebGLCompressedTextureATC*>(extension));
271     case WebGLExtension::WebGLCompressedTexturePVRTCName:
272         return toJS(exec, globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension));
273     case WebGLExtension::WebGLCompressedTextureS3TCName:
274         return toJS(exec, globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension));
275     case WebGLExtension::WebGLDepthTextureName:
276         return toJS(exec, globalObject, static_cast<WebGLDepthTexture*>(extension));
277     case WebGLExtension::WebGLDrawBuffersName:
278         return toJS(exec, globalObject, static_cast<WebGLDrawBuffers*>(extension));
279     case WebGLExtension::ANGLEInstancedArraysName:
280         return toJS(exec, globalObject, static_cast<ANGLEInstancedArrays*>(extension));
281     }
282     ASSERT_NOT_REACHED();
283     return jsNull();
284 }
285
286 bool JSWebGLRenderingContextBaseOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
287 {
288     JSWebGLRenderingContextBase* jsWebGLRenderingContext = jsCast<JSWebGLRenderingContextBase*>(handle.slot()->asCell());
289     void* root = WebCore::root(jsWebGLRenderingContext->wrapped().canvas());
290     return visitor.containsOpaqueRoot(root);
291 }
292
293 void JSWebGLRenderingContextBase::visitAdditionalChildren(SlotVisitor& visitor)
294 {
295     visitor.addOpaqueRoot(&wrapped());
296     visitor.addOpaqueRoot(root(wrapped().canvas()));
297 }
298
299 JSValue JSWebGLRenderingContextBase::getAttachedShaders(ExecState& state)
300 {
301     VM& vm = state.vm();
302     auto scope = DECLARE_THROW_SCOPE(vm);
303
304     if (state.argumentCount() < 1)
305         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
306     ExceptionCode ec = 0;
307     WebGLRenderingContextBase& context = wrapped();
308     WebGLProgram* program = JSWebGLProgram::toWrapped(state.uncheckedArgument(0));
309     if (!program && !state.uncheckedArgument(0).isUndefinedOrNull())
310         return throwTypeError(&state, scope);
311     Vector<RefPtr<WebGLShader>> shaders;
312     bool succeed = context.getAttachedShaders(program, shaders);
313     if (ec) {
314         setDOMException(&state, ec);
315         return jsNull();
316     }
317     if (!succeed)
318         return jsNull();
319     JSC::MarkedArgumentBuffer list;
320     for (size_t ii = 0; ii < shaders.size(); ++ii)
321         list.append(toJS(&state, globalObject(), shaders[ii].get()));
322     return constructArray(&state, 0, globalObject(), list);
323 }
324
325 JSValue JSWebGLRenderingContextBase::getExtension(ExecState& state)
326 {
327     VM& vm = state.vm();
328     auto scope = DECLARE_THROW_SCOPE(vm);
329
330     if (state.argumentCount() < 1)
331         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
332     
333     String name = state.uncheckedArgument(0).toWTFString(&state);
334     RETURN_IF_EXCEPTION(scope, JSValue());
335     return toJS(&state, globalObject(), wrapped().getExtension(name));
336 }
337
338 JSValue JSWebGLRenderingContextBase::getBufferParameter(ExecState& state)
339 {
340     return getObjectParameter(this, state, kBuffer);
341 }
342
343 JSValue JSWebGLRenderingContextBase::getFramebufferAttachmentParameter(ExecState& state)
344 {
345     VM& vm = state.vm();
346     auto scope = DECLARE_THROW_SCOPE(vm);
347
348     if (state.argumentCount() != 3)
349         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
350     
351     unsigned target = state.uncheckedArgument(0).toInt32(&state);
352     RETURN_IF_EXCEPTION(scope, JSValue());
353     unsigned attachment = state.uncheckedArgument(1).toInt32(&state);
354     RETURN_IF_EXCEPTION(scope, JSValue());
355     unsigned pname = state.uncheckedArgument(2).toInt32(&state);
356     RETURN_IF_EXCEPTION(scope, JSValue());
357     return toJS(&state, globalObject(), wrapped().getFramebufferAttachmentParameter(target, attachment, pname));
358 }
359
360 JSValue JSWebGLRenderingContextBase::getParameter(ExecState& state)
361 {
362     VM& vm = state.vm();
363     auto scope = DECLARE_THROW_SCOPE(vm);
364
365     if (state.argumentCount() != 1)
366         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
367     
368     unsigned pname = state.uncheckedArgument(0).toInt32(&state);
369     RETURN_IF_EXCEPTION(scope, JSValue());
370     return toJS(&state, globalObject(), wrapped().getParameter(pname));
371 }
372
373 JSValue JSWebGLRenderingContextBase::getProgramParameter(ExecState& state)
374 {
375     VM& vm = state.vm();
376     auto scope = DECLARE_THROW_SCOPE(vm);
377
378     if (state.argumentCount() != 2)
379         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
380     
381     WebGLProgram* program = JSWebGLProgram::toWrapped(state.uncheckedArgument(0));
382     if (!program && !state.uncheckedArgument(0).isUndefinedOrNull())
383         return throwTypeError(&state, scope);
384     unsigned pname = state.uncheckedArgument(1).toInt32(&state);
385     RETURN_IF_EXCEPTION(scope, JSValue());
386     return toJS(&state, globalObject(), wrapped().getProgramParameter(program, pname));
387 }
388
389 JSValue JSWebGLRenderingContextBase::getRenderbufferParameter(ExecState& state)
390 {
391     return getObjectParameter(this, state, kRenderbuffer);
392 }
393
394 JSValue JSWebGLRenderingContextBase::getShaderParameter(ExecState& state)
395 {
396     VM& vm = state.vm();
397     auto scope = DECLARE_THROW_SCOPE(vm);
398
399     if (state.argumentCount() != 2)
400         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
401     
402     if (!state.uncheckedArgument(0).isUndefinedOrNull() && !state.uncheckedArgument(0).inherits(JSWebGLShader::info()))
403         return throwTypeError(&state, scope);
404     WebGLShader* shader = JSWebGLShader::toWrapped(state.uncheckedArgument(0));
405     unsigned pname = state.uncheckedArgument(1).toInt32(&state);
406     RETURN_IF_EXCEPTION(scope, JSValue());
407     return toJS(&state, globalObject(), wrapped().getShaderParameter(shader, pname));
408 }
409
410 JSValue JSWebGLRenderingContextBase::getSupportedExtensions(ExecState& state)
411 {
412     WebGLRenderingContextBase& context = wrapped();
413     if (context.isContextLost())
414         return jsNull();
415     MarkedArgumentBuffer list;
416     for (auto& extension : context.getSupportedExtensions())
417         list.append(jsStringWithCache(&state, extension));
418     return constructArray(&state, 0, globalObject(), list);
419 }
420
421 JSValue JSWebGLRenderingContextBase::getTexParameter(ExecState& state)
422 {
423     return getObjectParameter(this, state, kTexture);
424 }
425
426 JSValue JSWebGLRenderingContextBase::getUniform(ExecState& state)
427 {
428     VM& vm = state.vm();
429     auto scope = DECLARE_THROW_SCOPE(vm);
430
431     if (state.argumentCount() != 2)
432         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
433     
434     WebGLProgram* program = JSWebGLProgram::toWrapped(state.uncheckedArgument(0));
435     if (!program && !state.uncheckedArgument(0).isUndefinedOrNull())
436         return throwTypeError(&state, scope);
437     WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(state.uncheckedArgument(1));
438     if (!location && !state.uncheckedArgument(1).isUndefinedOrNull())
439         return throwTypeError(&state, scope);
440     return toJS(&state, globalObject(), wrapped().getUniform(program, location));
441 }
442
443 JSValue JSWebGLRenderingContextBase::getVertexAttrib(ExecState& state)
444 {
445     return getObjectParameter(this, state, kVertexAttrib);
446 }
447
448 template<typename T, size_t inlineCapacity>
449 bool toVector(JSC::ExecState& state, JSC::JSValue value, Vector<T, inlineCapacity>& vector)
450 {
451     VM& vm = state.vm();
452     auto scope = DECLARE_THROW_SCOPE(vm);
453
454     if (!value.isObject())
455         return false;
456     
457     JSC::JSObject* object = asObject(value);
458     int32_t length = object->get(&state, state.vm().propertyNames->length).toInt32(&state);
459     
460     if (!vector.tryReserveCapacity(length))
461         return false;
462     vector.resize(length);
463     
464     for (int32_t i = 0; i < length; ++i) {
465         JSC::JSValue v = object->get(&state, i);
466         RETURN_IF_EXCEPTION(scope, false);
467         vector[i] = static_cast<T>(v.toNumber(&state));
468     }
469     
470     return true;
471 }
472
473 enum DataFunctionToCall {
474     f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
475     f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
476 };
477
478 enum DataFunctionMatrixToCall {
479     f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
480 };
481
482 static bool functionForUniform(DataFunctionToCall f)
483 {
484     switch (f) {
485     case f_uniform1v:
486     case f_uniform2v:
487     case f_uniform3v:
488     case f_uniform4v:
489         return true;
490     default: break;
491     }
492     return false;
493 }
494
495 static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState& state, WebGLRenderingContextBase& context)
496 {
497     VM& vm = state.vm();
498     auto scope = DECLARE_THROW_SCOPE(vm);
499
500     if (state.argumentCount() != 2)
501         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
502     
503     WebGLUniformLocation* location = 0;
504     long index = -1;
505     
506     if (functionForUniform(f)) {
507         location = JSWebGLUniformLocation::toWrapped(state.uncheckedArgument(0));
508         if (!location && !state.uncheckedArgument(0).isUndefinedOrNull())
509             return throwTypeError(&state, scope);
510     } else
511         index = state.uncheckedArgument(0).toInt32(&state);
512     
513     RETURN_IF_EXCEPTION(scope, JSValue());
514     
515     RefPtr<Float32Array> webGLArray = toFloat32Array(state.uncheckedArgument(1));
516     RETURN_IF_EXCEPTION(scope, JSValue());
517     
518     ExceptionCode ec = 0;
519     if (webGLArray) {
520         switch (f) {
521         case f_uniform1v:
522             context.uniform1fv(location, *webGLArray);
523             break;
524         case f_uniform2v:
525             context.uniform2fv(location, *webGLArray);
526             break;
527         case f_uniform3v:
528             context.uniform3fv(location, *webGLArray);
529             break;
530         case f_uniform4v:
531             context.uniform4fv(location, *webGLArray);
532             break;
533         case f_vertexAttrib1v:
534             context.vertexAttrib1fv(index, *webGLArray);
535             break;
536         case f_vertexAttrib2v:
537             context.vertexAttrib2fv(index, *webGLArray);
538             break;
539         case f_vertexAttrib3v:
540             context.vertexAttrib3fv(index, *webGLArray);
541             break;
542         case f_vertexAttrib4v:
543             context.vertexAttrib4fv(index, *webGLArray);
544             break;
545         }
546         
547         setDOMException(&state, ec);
548         return jsUndefined();
549     }
550     
551     Vector<float, 64> array;
552     if (!toVector(state, state.uncheckedArgument(1), array))
553         return throwTypeError(&state, scope);
554     
555     switch (f) {
556     case f_uniform1v:
557         context.uniform1fv(location, array.data(), array.size());
558         break;
559     case f_uniform2v:
560         context.uniform2fv(location, array.data(), array.size());
561         break;
562     case f_uniform3v:
563         context.uniform3fv(location, array.data(), array.size());
564         break;
565     case f_uniform4v:
566         context.uniform4fv(location, array.data(), array.size());
567         break;
568     case f_vertexAttrib1v:
569         context.vertexAttrib1fv(index, array.data(), array.size());
570         break;
571     case f_vertexAttrib2v:
572         context.vertexAttrib2fv(index, array.data(), array.size());
573         break;
574     case f_vertexAttrib3v:
575         context.vertexAttrib3fv(index, array.data(), array.size());
576         break;
577     case f_vertexAttrib4v:
578         context.vertexAttrib4fv(index, array.data(), array.size());
579         break;
580     }
581     
582     setDOMException(&state, ec);
583     return jsUndefined();
584 }
585
586 static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState& state, WebGLRenderingContextBase& context)
587 {
588     VM& vm = state.vm();
589     auto scope = DECLARE_THROW_SCOPE(vm);
590
591     if (state.argumentCount() != 2)
592         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
593     
594     WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(state.uncheckedArgument(0));
595     if (!location && !state.uncheckedArgument(0).isUndefinedOrNull())
596         return throwTypeError(&state, scope);
597     
598     RefPtr<Int32Array> webGLArray = toInt32Array(state.uncheckedArgument(1));
599     
600     ExceptionCode ec = 0;
601     if (webGLArray) {
602         switch (f) {
603         case f_uniform1v:
604             context.uniform1iv(location, *webGLArray);
605             break;
606         case f_uniform2v:
607             context.uniform2iv(location, *webGLArray);
608             break;
609         case f_uniform3v:
610             context.uniform3iv(location, *webGLArray);
611             break;
612         case f_uniform4v:
613             context.uniform4iv(location, *webGLArray);
614             break;
615         default:
616             break;
617         }
618         
619         setDOMException(&state, ec);
620         return jsUndefined();
621     }
622     
623     
624     Vector<int, 64> array;
625     if (!toVector(state, state.uncheckedArgument(1), array))
626         return throwTypeError(&state, scope);
627     
628     switch (f) {
629     case f_uniform1v:
630         context.uniform1iv(location, array.data(), array.size());
631         break;
632     case f_uniform2v:
633         context.uniform2iv(location, array.data(), array.size());
634         break;
635     case f_uniform3v:
636         context.uniform3iv(location, array.data(), array.size());
637         break;
638     case f_uniform4v:
639         context.uniform4iv(location, array.data(), array.size());
640         break;
641     default:
642         break;
643     }
644     
645     setDOMException(&state, ec);
646     return jsUndefined();
647 }
648
649 static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState& state, WebGLRenderingContextBase& context)
650 {
651     VM& vm = state.vm();
652     auto scope = DECLARE_THROW_SCOPE(vm);
653
654     if (state.argumentCount() != 3)
655         return throwException(&state, scope, createNotEnoughArgumentsError(&state));
656     
657     WebGLUniformLocation* location = JSWebGLUniformLocation::toWrapped(state.uncheckedArgument(0));
658     if (!location && !state.uncheckedArgument(0).isUndefinedOrNull())
659         return throwTypeError(&state, scope);
660     
661     bool transpose = state.uncheckedArgument(1).toBoolean(&state);
662     RETURN_IF_EXCEPTION(scope, JSValue());
663     
664     RefPtr<Float32Array> webGLArray = toFloat32Array(state.uncheckedArgument(2));
665
666     if (webGLArray) {
667         switch (f) {
668         case f_uniformMatrix2fv:
669             context.uniformMatrix2fv(location, transpose, *webGLArray);
670             break;
671         case f_uniformMatrix3fv:
672             context.uniformMatrix3fv(location, transpose, *webGLArray);
673             break;
674         case f_uniformMatrix4fv:
675             context.uniformMatrix4fv(location, transpose, *webGLArray);
676             break;
677         }
678
679         ExceptionCode ec = 0;
680         setDOMException(&state, ec);
681         return jsUndefined();
682     }
683     
684     Vector<float, 64> array;
685     if (!toVector(state, state.uncheckedArgument(2), array))
686         return throwTypeError(&state, scope);
687     
688     switch (f) {
689     case f_uniformMatrix2fv:
690         context.uniformMatrix2fv(location, transpose, array.data(), array.size());
691         break;
692     case f_uniformMatrix3fv:
693         context.uniformMatrix3fv(location, transpose, array.data(), array.size());
694         break;
695     case f_uniformMatrix4fv:
696         context.uniformMatrix4fv(location, transpose, array.data(), array.size());
697         break;
698     }
699
700     ExceptionCode ec = 0;
701     setDOMException(&state, ec);
702     return jsUndefined();
703 }
704
705 JSC::JSValue JSWebGLRenderingContextBase::uniform1fv(JSC::ExecState& state)
706 {
707     return dataFunctionf(f_uniform1v, state, wrapped());
708 }
709
710 JSC::JSValue JSWebGLRenderingContextBase::uniform1iv(JSC::ExecState& state)
711 {
712     return dataFunctioni(f_uniform1v, state, wrapped());
713 }
714
715 JSC::JSValue JSWebGLRenderingContextBase::uniform2fv(JSC::ExecState& state)
716 {
717     return dataFunctionf(f_uniform2v, state, wrapped());
718 }
719
720 JSC::JSValue JSWebGLRenderingContextBase::uniform2iv(JSC::ExecState& state)
721 {
722     return dataFunctioni(f_uniform2v, state, wrapped());
723 }
724
725 JSC::JSValue JSWebGLRenderingContextBase::uniform3fv(JSC::ExecState& state)
726 {
727     return dataFunctionf(f_uniform3v, state, wrapped());
728 }
729
730 JSC::JSValue JSWebGLRenderingContextBase::uniform3iv(JSC::ExecState& state)
731 {
732     return dataFunctioni(f_uniform3v, state, wrapped());
733 }
734
735 JSC::JSValue JSWebGLRenderingContextBase::uniform4fv(JSC::ExecState& state)
736 {
737     return dataFunctionf(f_uniform4v, state, wrapped());
738 }
739
740 JSC::JSValue JSWebGLRenderingContextBase::uniform4iv(JSC::ExecState& state)
741 {
742     return dataFunctioni(f_uniform4v, state, wrapped());
743 }
744
745 JSC::JSValue JSWebGLRenderingContextBase::uniformMatrix2fv(JSC::ExecState& state)
746 {
747     return dataFunctionMatrix(f_uniformMatrix2fv, state, wrapped());
748 }
749
750 JSC::JSValue JSWebGLRenderingContextBase::uniformMatrix3fv(JSC::ExecState& state)
751 {
752     return dataFunctionMatrix(f_uniformMatrix3fv, state, wrapped());
753 }
754
755 JSC::JSValue JSWebGLRenderingContextBase::uniformMatrix4fv(JSC::ExecState& state)
756 {
757     return dataFunctionMatrix(f_uniformMatrix4fv, state, wrapped());
758 }
759
760 JSC::JSValue JSWebGLRenderingContextBase::vertexAttrib1fv(JSC::ExecState& state)
761 {
762     return dataFunctionf(f_vertexAttrib1v, state, wrapped());
763 }
764
765 JSC::JSValue JSWebGLRenderingContextBase::vertexAttrib2fv(JSC::ExecState& state)
766 {
767     return dataFunctionf(f_vertexAttrib2v, state, wrapped());
768 }
769
770 JSC::JSValue JSWebGLRenderingContextBase::vertexAttrib3fv(JSC::ExecState& state)
771 {
772     return dataFunctionf(f_vertexAttrib3v, state, wrapped());
773 }
774
775 JSC::JSValue JSWebGLRenderingContextBase::vertexAttrib4fv(JSC::ExecState& state)
776 {
777     return dataFunctionf(f_vertexAttrib4v, state, wrapped());
778 }
779
780 } // namespace WebCore
781
782 #endif // ENABLE(WEBGL)