瀏覽代碼

LibWeb: Save WebGL context pointer in WebGLObject

This way we could be sure that context object won't be deallocated
before any of the objects that belong to it.

Having a context pointer is also going to be used in upcoming changes
to generate an INVALID_OPERATION error if an object does not belong to
the context it's being used in.
Aliaksandr Kalenik 7 月之前
父節點
當前提交
cf730870c5

+ 4 - 0
Libraries/LibWeb/WebGL/WebGL2RenderingContext.h

@@ -27,6 +27,10 @@ public:
 
     virtual ~WebGL2RenderingContext() override;
 
+    // FIXME: This is a hack required to visit context from WebGLObject.
+    //        It should be gone once WebGLRenderingContextBase inherits from PlatformObject.
+    GC::Cell const* gc_cell() const override { return this; }
+
     void present() override;
     void needs_to_present() override;
 

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLBuffer.cpp

@@ -15,13 +15,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLBuffer);
 
-GC::Ref<WebGLBuffer> WebGLBuffer::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLBuffer> WebGLBuffer::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLBuffer>(realm, handle);
+    return realm.create<WebGLBuffer>(realm, context, handle);
 }
 
-WebGLBuffer::WebGLBuffer(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLBuffer::WebGLBuffer(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLBuffer.h

@@ -18,12 +18,12 @@ class WebGLBuffer final : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLBuffer);
 
 public:
-    static GC::Ref<WebGLBuffer> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLBuffer> create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle);
 
     virtual ~WebGLBuffer();
 
 protected:
-    explicit WebGLBuffer(JS::Realm&, GLuint handle);
+    explicit WebGLBuffer(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLFramebuffer.cpp

@@ -14,13 +14,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLFramebuffer);
 
-GC::Ref<WebGLFramebuffer> WebGLFramebuffer::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLFramebuffer> WebGLFramebuffer::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLFramebuffer>(realm, handle);
+    return realm.create<WebGLFramebuffer>(realm, context, handle);
 }
 
-WebGLFramebuffer::WebGLFramebuffer(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLFramebuffer::WebGLFramebuffer(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLFramebuffer.h

@@ -16,12 +16,12 @@ class WebGLFramebuffer final : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLFramebuffer);
 
 public:
-    static GC::Ref<WebGLFramebuffer> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLFramebuffer> create(JS::Realm& realm, WebGLRenderingContextBase&, GLuint handle);
 
     virtual ~WebGLFramebuffer();
 
 protected:
-    explicit WebGLFramebuffer(JS::Realm&, GLuint handle);
+    explicit WebGLFramebuffer(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 8 - 1
Libraries/LibWeb/WebGL/WebGLObject.cpp

@@ -12,8 +12,9 @@
 
 namespace Web::WebGL {
 
-WebGLObject::WebGLObject(JS::Realm& realm, GLuint handle)
+WebGLObject::WebGLObject(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
     : Bindings::PlatformObject(realm)
+    , m_context(&context)
     , m_handle(handle)
 {
 }
@@ -26,4 +27,10 @@ void WebGLObject::initialize(JS::Realm& realm)
     WEB_SET_PROTOTYPE_FOR_INTERFACE(WebGLObject);
 }
 
+void WebGLObject::visit_edges(Visitor& visitor)
+{
+    Base::visit_edges(visitor);
+    visitor.visit(m_context->gc_cell());
+}
+
 }

+ 8 - 3
Libraries/LibWeb/WebGL/WebGLObject.h

@@ -10,6 +10,7 @@
 
 #include <LibWeb/Bindings/PlatformObject.h>
 #include <LibWeb/WebGL/Types.h>
+#include <LibWeb/WebGL/WebGLRenderingContextBase.h>
 
 namespace Web::WebGL {
 
@@ -25,16 +26,20 @@ public:
     GLuint handle() const { return m_handle; }
 
 protected:
-    explicit WebGLObject(JS::Realm&, GLuint handle);
+    explicit WebGLObject(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
-    virtual void initialize(JS::Realm&) override;
+    void initialize(JS::Realm&) override;
+    void visit_edges(Visitor&) override;
 
     bool invalidated() const { return m_invalidated; }
 
 private:
+    // FIXME: It should be GC::Ptr instead of raw pointer, but we need to make WebGLRenderingContextBase inherit from PlatformObject first.
+    WebGLRenderingContextBase* m_context;
+    GLuint m_handle { 0 };
+
     bool m_invalidated { false };
     String m_label;
-    GLuint m_handle { 0 };
 };
 
 }

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLProgram.cpp

@@ -15,13 +15,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLProgram);
 
-GC::Ref<WebGLProgram> WebGLProgram::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLProgram> WebGLProgram::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLProgram>(realm, handle);
+    return realm.create<WebGLProgram>(realm, context, handle);
 }
 
-WebGLProgram::WebGLProgram(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLProgram::WebGLProgram(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLProgram.h

@@ -18,12 +18,12 @@ class WebGLProgram final : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLProgram);
 
 public:
-    static GC::Ref<WebGLProgram> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLProgram> create(JS::Realm& realm, WebGLRenderingContextBase&, GLuint handle);
 
     virtual ~WebGLProgram();
 
 protected:
-    explicit WebGLProgram(JS::Realm&, GLuint handle);
+    explicit WebGLProgram(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLQuery.cpp

@@ -13,13 +13,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLQuery);
 
-GC::Ref<WebGLQuery> WebGLQuery::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLQuery> WebGLQuery::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLQuery>(realm, handle);
+    return realm.create<WebGLQuery>(realm, context, handle);
 }
 
-WebGLQuery::WebGLQuery(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLQuery::WebGLQuery(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLQuery.h

@@ -16,12 +16,12 @@ class WebGLQuery : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLQuery);
 
 public:
-    static GC::Ref<WebGLQuery> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLQuery> create(JS::Realm& realm, WebGLRenderingContextBase&, GLuint handle);
 
     virtual ~WebGLQuery() override;
 
 protected:
-    explicit WebGLQuery(JS::Realm&, GLuint handle);
+    explicit WebGLQuery(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLRenderbuffer.cpp

@@ -14,13 +14,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLRenderbuffer);
 
-GC::Ref<WebGLRenderbuffer> WebGLRenderbuffer::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLRenderbuffer> WebGLRenderbuffer::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLRenderbuffer>(realm, handle);
+    return realm.create<WebGLRenderbuffer>(realm, context, handle);
 }
 
-WebGLRenderbuffer::WebGLRenderbuffer(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLRenderbuffer::WebGLRenderbuffer(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLRenderbuffer.h

@@ -16,12 +16,12 @@ class WebGLRenderbuffer final : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLRenderbuffer);
 
 public:
-    static GC::Ref<WebGLRenderbuffer> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLRenderbuffer> create(JS::Realm& realm, WebGLRenderingContextBase&, GLuint handle);
 
     virtual ~WebGLRenderbuffer();
 
 protected:
-    explicit WebGLRenderbuffer(JS::Realm&, GLuint handle);
+    explicit WebGLRenderbuffer(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 4 - 0
Libraries/LibWeb/WebGL/WebGLRenderingContext.h

@@ -26,6 +26,10 @@ public:
 
     virtual ~WebGLRenderingContext() override;
 
+    // FIXME: This is a hack required to visit context from WebGLObject.
+    //        It should be gone once WebGLRenderingContextBase inherits from PlatformObject.
+    GC::Cell const* gc_cell() const override { return this; }
+
     void present() override;
     void needs_to_present() override;
 

+ 18 - 0
Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+namespace Web::WebGL {
+
+// FIXME: This object should inherit from Bindings::PlatformObject and implement the WebGLRenderingContextBase IDL interface.
+//        We should make WebGL code generator to produce implementation for this interface.
+class WebGLRenderingContextBase {
+public:
+    virtual GC::Cell const* gc_cell() const = 0;
+};
+
+}

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLSampler.cpp

@@ -13,13 +13,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLSampler);
 
-GC::Ref<WebGLSampler> WebGLSampler::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLSampler> WebGLSampler::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLSampler>(realm, handle);
+    return realm.create<WebGLSampler>(realm, context, handle);
 }
 
-WebGLSampler::WebGLSampler(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLSampler::WebGLSampler(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLSampler.h

@@ -16,12 +16,12 @@ class WebGLSampler : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLSampler);
 
 public:
-    static GC::Ref<WebGLSampler> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLSampler> create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle);
 
     virtual ~WebGLSampler() override;
 
 protected:
-    explicit WebGLSampler(JS::Realm&, GLuint handle);
+    explicit WebGLSampler(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLShader.cpp

@@ -15,13 +15,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLShader);
 
-GC::Ref<WebGLShader> WebGLShader::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLShader> WebGLShader::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLShader>(realm, handle);
+    return realm.create<WebGLShader>(realm, context, handle);
 }
 
-WebGLShader::WebGLShader(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLShader::WebGLShader(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLShader.h

@@ -18,12 +18,12 @@ class WebGLShader final : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLShader);
 
 public:
-    static GC::Ref<WebGLShader> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLShader> create(JS::Realm& realm, WebGLRenderingContextBase&, GLuint handle);
 
     virtual ~WebGLShader();
 
 protected:
-    explicit WebGLShader(JS::Realm&, GLuint handle);
+    explicit WebGLShader(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLSync.cpp

@@ -13,13 +13,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLSync);
 
-GC::Ref<WebGLSync> WebGLSync::create(JS::Realm& realm, GLsyncInternal handle)
+GC::Ref<WebGLSync> WebGLSync::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLsyncInternal handle)
 {
-    return realm.create<WebGLSync>(realm, handle);
+    return realm.create<WebGLSync>(realm, context, handle);
 }
 
-WebGLSync::WebGLSync(JS::Realm& realm, GLsyncInternal handle)
-    : WebGLObject(realm, 0)
+WebGLSync::WebGLSync(JS::Realm& realm, WebGLRenderingContextBase& context, GLsyncInternal handle)
+    : WebGLObject(realm, context, 0)
     , m_sync_handle(handle)
 {
 }

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLSync.h

@@ -16,14 +16,14 @@ class WebGLSync : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLSync);
 
 public:
-    static GC::Ref<WebGLSync> create(JS::Realm& realm, GLsyncInternal handle);
+    static GC::Ref<WebGLSync> create(JS::Realm& realm, WebGLRenderingContextBase&, GLsyncInternal handle);
 
     virtual ~WebGLSync() override;
 
     GLsyncInternal sync_handle() const { return m_sync_handle; }
 
 protected:
-    explicit WebGLSync(JS::Realm&, GLsyncInternal handle);
+    explicit WebGLSync(JS::Realm&, WebGLRenderingContextBase&, GLsyncInternal handle);
 
     virtual void initialize(JS::Realm&) override;
 

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLTexture.cpp

@@ -15,13 +15,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLTexture);
 
-GC::Ref<WebGLTexture> WebGLTexture::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLTexture> WebGLTexture::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLTexture>(realm, handle);
+    return realm.create<WebGLTexture>(realm, context, handle);
 }
 
-WebGLTexture::WebGLTexture(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLTexture::WebGLTexture(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLTexture.h

@@ -18,12 +18,12 @@ class WebGLTexture final : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLTexture);
 
 public:
-    static GC::Ref<WebGLTexture> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLTexture> create(JS::Realm& realm, WebGLRenderingContextBase&, GLuint handle);
 
     virtual ~WebGLTexture();
 
 protected:
-    explicit WebGLTexture(JS::Realm&, GLuint handle);
+    explicit WebGLTexture(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLTransformFeedback.cpp

@@ -13,13 +13,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLTransformFeedback);
 
-GC::Ref<WebGLTransformFeedback> WebGLTransformFeedback::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLTransformFeedback> WebGLTransformFeedback::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLTransformFeedback>(realm, handle);
+    return realm.create<WebGLTransformFeedback>(realm, context, handle);
 }
 
-WebGLTransformFeedback::WebGLTransformFeedback(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLTransformFeedback::WebGLTransformFeedback(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLTransformFeedback.h

@@ -16,12 +16,12 @@ class WebGLTransformFeedback : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLTransformFeedback);
 
 public:
-    static GC::Ref<WebGLTransformFeedback> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLTransformFeedback> create(JS::Realm& realm, WebGLRenderingContextBase&, GLuint handle);
 
     virtual ~WebGLTransformFeedback() override;
 
 protected:
-    explicit WebGLTransformFeedback(JS::Realm&, GLuint handle);
+    explicit WebGLTransformFeedback(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 4 - 4
Libraries/LibWeb/WebGL/WebGLVertexArrayObject.cpp

@@ -13,13 +13,13 @@ namespace Web::WebGL {
 
 GC_DEFINE_ALLOCATOR(WebGLVertexArrayObject);
 
-GC::Ref<WebGLVertexArrayObject> WebGLVertexArrayObject::create(JS::Realm& realm, GLuint handle)
+GC::Ref<WebGLVertexArrayObject> WebGLVertexArrayObject::create(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
 {
-    return realm.create<WebGLVertexArrayObject>(realm, handle);
+    return realm.create<WebGLVertexArrayObject>(realm, context, handle);
 }
 
-WebGLVertexArrayObject::WebGLVertexArrayObject(JS::Realm& realm, GLuint handle)
-    : WebGLObject(realm, handle)
+WebGLVertexArrayObject::WebGLVertexArrayObject(JS::Realm& realm, WebGLRenderingContextBase& context, GLuint handle)
+    : WebGLObject(realm, context, handle)
 {
 }
 

+ 2 - 2
Libraries/LibWeb/WebGL/WebGLVertexArrayObject.h

@@ -16,12 +16,12 @@ class WebGLVertexArrayObject : public WebGLObject {
     GC_DECLARE_ALLOCATOR(WebGLVertexArrayObject);
 
 public:
-    static GC::Ref<WebGLVertexArrayObject> create(JS::Realm& realm, GLuint handle);
+    static GC::Ref<WebGLVertexArrayObject> create(JS::Realm& realm, WebGLRenderingContextBase&, GLuint handle);
 
     virtual ~WebGLVertexArrayObject() override;
 
 protected:
-    explicit WebGLVertexArrayObject(JS::Realm&, GLuint handle);
+    explicit WebGLVertexArrayObject(JS::Realm&, WebGLRenderingContextBase&, GLuint handle);
 
     virtual void initialize(JS::Realm&) override;
 };

+ 19 - 10
Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp

@@ -242,7 +242,7 @@ static void generate_get_parameter(SourceGenerator& generator, int webgl_version
         glGetIntegerv(GL_@parameter_name@, &result);
         if (!result)
             return JS::js_null();
-        return @type_name@::create(m_realm, result);
+        return @type_name@::create(m_realm, *this, result);
 )~~~");
         } else {
             VERIFY_NOT_REACHED();
@@ -435,13 +435,14 @@ static Vector<GLchar> null_terminated_string(StringView string)
 #include <LibGfx/Bitmap.h>
 #include <LibWeb/Bindings/PlatformObject.h>
 #include <LibWeb/Forward.h>
+#include <LibWeb/WebGL/WebGLRenderingContextBase.h>
 #include <LibWeb/WebIDL/Types.h>
 
 namespace Web::WebGL {
 
 using namespace Web::HTML;
 
-class @class_name@ {
+class @class_name@ : public WebGLRenderingContextBase {
 public:
     @class_name@(JS::Realm&, NonnullOwnPtr<OpenGLContext>);
 
@@ -510,11 +511,19 @@ public:
             function_impl_generator.append("    m_context->notify_content_will_change();\n"sv);
         }
 
+        if (function.name == "getUniformLocation"sv) {
+            function_impl_generator.append(R"~~~(
+    auto name_null_terminated = null_terminated_string(name);
+    return WebGLUniformLocation::create(m_realm, glGetUniformLocation(program ? program->handle() : 0, name_null_terminated.data()));
+)~~~");
+            continue;
+        }
+
         if (function.name == "createBuffer"sv) {
             function_impl_generator.append(R"~~~(
     GLuint handle = 0;
     glGenBuffers(1, &handle);
-    return WebGLBuffer::create(m_realm, handle);
+    return WebGLBuffer::create(m_realm, *this, handle);
 )~~~");
             continue;
         }
@@ -523,7 +532,7 @@ public:
             function_impl_generator.append(R"~~~(
     GLuint handle = 0;
     glGenTextures(1, &handle);
-    return WebGLTexture::create(m_realm, handle);
+    return WebGLTexture::create(m_realm, *this, handle);
 )~~~");
             continue;
         }
@@ -532,7 +541,7 @@ public:
             function_impl_generator.append(R"~~~(
     GLuint handle = 0;
     glGenFramebuffers(1, &handle);
-    return WebGLFramebuffer::create(m_realm, handle);
+    return WebGLFramebuffer::create(m_realm, *this, handle);
 )~~~");
             continue;
         }
@@ -541,7 +550,7 @@ public:
             function_impl_generator.append(R"~~~(
     GLuint handle = 0;
     glGenRenderbuffers(1, &handle);
-    return WebGLRenderbuffer::create(m_realm, handle);
+    return WebGLRenderbuffer::create(m_realm, *this, handle);
 )~~~");
             continue;
         }
@@ -550,7 +559,7 @@ public:
             function_impl_generator.append(R"~~~(
     GLuint handle = 0;
     glGenVertexArrays(1, &handle);
-    return WebGLVertexArrayObject::create(m_realm, handle);
+    return WebGLVertexArrayObject::create(m_realm, *this, handle);
 )~~~");
             continue;
         }
@@ -559,7 +568,7 @@ public:
             function_impl_generator.append(R"~~~(
     GLuint handle = 0;
     glGenSamplers(1, &handle);
-    return WebGLSampler::create(m_realm, handle);
+    return WebGLSampler::create(m_realm, *this, handle);
 )~~~");
             continue;
         }
@@ -567,7 +576,7 @@ public:
         if (function.name == "fenceSync"sv) {
             function_impl_generator.append(R"~~~(
     GLsync handle = glFenceSync(condition, flags);
-    return WebGLSync::create(m_realm, handle);
+    return WebGLSync::create(m_realm, *this, handle);
 )~~~");
             continue;
         }
@@ -1104,7 +1113,7 @@ public:
             function_impl_generator.append("    return @call_string@;"sv);
         } else if (is_webgl_object_type(function.return_type->name())) {
             function_impl_generator.set("return_type_name", function.return_type->name());
-            function_impl_generator.append("    return @return_type_name@::create(m_realm, @call_string@);"sv);
+            function_impl_generator.append("    return @return_type_name@::create(m_realm, *this, @call_string@);"sv);
         } else {
             VERIFY_NOT_REACHED();
         }