Наверное многие из тех, кто работает с WebGL и при этом использует Chrome, знают о таком полезнейшем расширении как WebGL Inspector. Данный инструмент позволяет пролить немного света на black box магию которая происходит в недрах вашего WebGLRenderingContext.
Если какое-то время вы счастливо работали со связкой Javascript + Inspector, но в какой-то момент перешли на Dart (было ли это решение продиктовано необходимостью, голосами в вашей голове либо злыми духами — неважно, то наверное заметили, что Inspector ваших взглядов не разделяет и работать со сгенерированными js файлами отказывается.
О том, почему так происходит, и как эту проблему решить — под катом.

Для начала уточню еще раз, что речь пойдет только о сгенерированном dart2js коде, для связки DartVM + Inspector скорее всего потребуется написание специального interop кода для взаимодействия со сторонним javascript-ом.

Немного теории

Сначала разберемся с dart'ом и dart2js. В библиотеке Dart есть специальный класс для работы с WebGL — RenderingContext, который соответствует WebGLRenderingContext из спецификации WebGL. Для связки этих двух типов во время исполнения, стартовый код определяет тип созданного WebGL контекста с помощью свойства context.constructor.name которое возвращает имя функции, которая породила объект. Далее для полученного типа ищется соответствующий ему Dart класс. Классы ставятся в соответствие вызовами функции:

$.defineNativeMethods("JSType", $.DartClass);


Например, для контекста WebGL свойство context.constructor.name вернет "WebGLRenderingContext", соответствующий Dart класс — RenderingContext.
Inspector, в свою очередь, проксирует обычный WebGLRenderingContext своим CaptureContext'ом, что позволяет ему отлавливать все вызовы функций контекста.

Кто виноват и что делать

«Виноваты» обе стороны.
Во-первых, constructor.name для CaptureContext'а возвращает пустую строку. Во-вторых, dart2js, понятное дело, ничего не знает о CaptureContext, и никакого соответствия для него нет.
Сначала исправляем Inspector'а:
  • находим файлы расширения, в убунте лежат в ~/.config/google-chrome/Default/Extensions/ogkcjmbhnfmlnielkjhedpcjomeaghda/1.13_0
  • в файле gli.all.js заменяем
    var CaptureContext = function(canvas, rawgl, options) {
    ...
    }
    

    на
    function CaptureContext(canvas, rawgl, options) {
    ...
    }
    


    Теперь constructor.name вернет то, что нам нужно.

Исправляем *.dart.js файл:
  • находим секцию с вызовами $.defineNativeMethods
  • добавляем
    $.defineNativeMethods("CaptureContext", $.RenderingContext);
    



Заключение

Минусы такого решения очевидны: js файл нужно менять каждый раз после генерации, хак для расширения более постоянен, но все-таки убьется при его обновлении. Надеюсь все же, решение окажется кому-нибудь полезным и спасет пару жизней или хотя бы нервных клеток.

Если вы хотите следить за развитием событий или у вас есть решение получше, то кроме коментариев есть соответствующий багрепорт для Dart и change request для Inspector'а.