Главная > AJAX, ExtJS Framework, Open Source, Разное > Ext.UpdateManager — глубинное иследование на тему выполнения скриптов.

Ext.UpdateManager — глубинное иследование на тему выполнения скриптов.

24 октября 2007

Приветствую, сегодня наше исследование будет кратким и коснется интересного вопроса - как Ext.UpdateManager знает, что когда он подгружает HTML-код, нужно выполнить скрипты и, что самое интересное, как он их выполняет. Для этого нужно произвести исследования структуры исходного кода и проследить цепочку вызовов функций. Не бойтесь, в исходном дистрибутиве есть прекрасно документированая и хорошо форматированная справка, которая, кроме описания, включает и просмотр исходного кода.

И так, свойство UpdateManager.loadScripts, которое имеет логический тип и указывает менеджеру, что делать со скриптами. Что же происходит, когда оно установлено в true (то есть, разрешено исполнение скриптов в загружаемом коде).

1. Сам процесс получения кода от сервера к процессу выполнения не имеет никакого отношения. То есть, искать этот код в Ext.AJAX не имеет смысла.

2. После получения ответа сервера, UpdateManager передает управление в свой дочерний класс, который отвечает за корректную обработку данных. Это Ext.UpdateManager.BasicRenderer. Он реализует один обязательный метод - render(). Это определено в файле UpdateManager.js (в самом конце).

3. Исследуем реализацию метода Ext.UpdateManager.BasicRenderer.render. Оказывается, он также ничего не делает! Он вызывает дальше метод update елемента DOM-узла (объект Ext.Element), которому и передается ответ сервера, а также значение параметра UpdateManager.loadScripts. На этом примере мы можем видеть, что для реализации своего варианта обновления для не DOM-элементов возможно, не нужно переопределять рендер, можно создать свой класс, который будет передаваться как элемент, подлежащий обновлению, а в нем переопределять метод update.

4. Теперь следует перейти к описанию класса Ext.Element и найти там метод update. Он находится в файле Element.js.

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

  • получаем елемент HEAD страницы (туда добавляются скрипты);
  • выделяем тело скрипта, заключенное в теги <script></script>;
  • если присутствует аттрибут src, то есть скрипт загружается из внешнего файла, то получаем его значение (не файла, а содержимое аттрибута, то есть имя и путь к файлу скрипта на сервере);
  • выделяется аттрибут type, если присутствует.

Все это происходит в цикле, который обрабатывает содержимое  ответа сервера. Если мы выделили src, то скрипт создает пустой элемент <script>, добавляет к нему путь к скрипту, а потом присоединяет как дочерний к элемнту HEAD. Это означает, что скрипт будет обработан браузером самостоятельно, он загружается и исполняется как обычно.

Если же у нас тело скрипта прямо в документе, и оно имеет не нулевую длину, то мы исполняем его через вызов функции eval. Последним штрихом будет замена участков кода <script></script> на пустую строку перед присоединением к обновляемому узлу.

Вот часть кода, которая реализует вышеописанный метод:

  1. span style="color: #3366CC;">"head"'\"])(.*?)\1/i;
  2.  
  3.   var typeRe = /\stype=([\'\"])(.*?)\1/i; var match;
  4.  
  5.   while(match = re.exec(html)){
  6.  
  7.   var attrs = match[1];
  8.  
  9.   var srcMatch = attrs ? attrs.match(srcRe) : false;
  10.  
  11.   if(srcMatch && srcMatch[2]){
  12.  
  13.   var s = document.createElement("script");
  14.  
  15.   s.src = srcMatch[2];
  16.  
  17.   var typeMatch = attrs.match(typeRe);
  18.  
  19.   if(typeMatch && typeMatch[2]){
  20.  
  21.   s.type = typeMatch[2];
  22.  
  23.   }
  24.  
  25.   hd.appendChild(s);
  26.  
  27.   }else if(match[2] && match[2].length > 0){
  28.  
  29.   eval(match[2]);
  30.  
  31.   }
  32.  
  33.   }
  34.  
  35.   var el = document.getElementById(id);
  36.  
  37.   if(el){el.parentNode.removeChild(el);}
  38.  
  39.   if(typeof callback == "function"){
  40.  
  41.   callback();
  42.  
  43.   }

Вот таким образом происходит выполнение подгружаемых скриптов в ExtJS. В таком и других случаях, когда вы не понимаете логики работы какого-либо элемента - просто исследуйте исходники, попытайтесь восстановить работу скрипта, посмотрте, какие функции и как, в какой последовательности вызываются, и изучайте исходный код. Ведь именно в этом прелесть open-source.

Ccылки по теме:

  1. 24 октября 2007 в 16:14 | #1

    Спасибо автору, очень интересно…

    Уверен, если дать более менее сложные скрипты в теле подгружаемого документа — хана данному выполнению скриптов…

    я просто долго уже занимаюсь данным вопросом … и столько уже камней нарыл …
    вот один из них:
    что к примеру будет если в подгружаемом скрипте всретится document.write

    хана всему!

Комментирование отключено.