javascript MDL-25013 YUI modules are now recursively loaded and a stacktrace stored...
authorSam Hemelryk <sam@moodle.com>
Fri, 12 Nov 2010 05:26:47 +0000 (05:26 +0000)
committerSam Hemelryk <sam@moodle.com>
Fri, 12 Nov 2010 05:26:47 +0000 (05:26 +0000)
lib/moodlelib.php
lib/outputrequirementslib.php
mod/quiz/locallib.php
theme/base/style/core.css

index 1e6cc12..60dbcc9 100644 (file)
@@ -9242,7 +9242,7 @@ function array_is_nested($array) {
  * @return array
  */
 function get_performance_info() {
-    global $CFG, $PERF, $DB;
+    global $CFG, $PERF, $DB, $PAGE;
 
     $info = array();
     $info['html'] = '';         // holds userfriendly HTML representation
@@ -9292,6 +9292,33 @@ function get_performance_info() {
         }
     }
 
+     $jsmodules = $PAGE->requires->get_loaded_modules();
+     if ($jsmodules) {
+         $yuicount = 0;
+         $othercount = 0;
+         $details = '';
+         foreach ($jsmodules as $module => $backtraces) {
+             if (strpos($module, 'yui') === 0) {
+                 $yuicount += 1;
+             } else {
+                 $othercount += 1;
+             }
+             $details .= "<div class='yui-module'><p>$module</p>";
+             foreach ($backtraces as $backtrace) {
+                 $details .= "<div class='backtrace'>$backtrace</div>";
+             }
+             $details .= '</div>';
+         }
+         $info['html'] .= "<span class='includedyuimodules'>Included YUI modules: $yuicount</span> ";
+         $info['txt'] .= "includedyuimodules: $yuicount ";
+         $info['html'] .= "<span class='includedjsmodules'>Other JavaScript modules: $othercount</span> ";
+         $info['txt'] .= "includedjsmodules: $othercount ";
+         // Slightly odd to output the details in a display: none div. The point
+         // Is that it takes a lot of space, and if you care you can reveal it
+         // using firebug.
+         $info['html'] .= '<div id="yui-module-debug" class="notifytiny">'.$details.'</div>';
+     }
+
     if (!empty($PERF->logwrites)) {
         $info['logwrites'] = $PERF->logwrites;
         $info['html'] .= '<span class="logwrites">Log DB writes '.$info['logwrites'].'</span> ';
index 39857aa..54cb959 100644 (file)
@@ -109,6 +109,8 @@ class page_requirements_manager {
     protected $M_yui_loader;
     /** some config vars exposed in JS, please no secret stuff there */
     protected $M_cfg;
+    /** stores debug backtraces from when JS modules were included in the page */
+    protected $debug_moduleloadstacktraces = array();
 
     /**
      * Page requirements constructor.
@@ -257,6 +259,12 @@ class page_requirements_manager {
                 }
             }
             $this->M_yui_loader->modules[$name] = $module;
+            if (debugging('', DEBUG_DEVELOPER)) {
+                if (!array_key_exists($name, $this->debug_moduleloadstacktraces)) {
+                    $this->debug_moduleloadstacktraces[$name] = array();
+                }
+                $this->debug_moduleloadstacktraces[$name][] = format_backtrace(debug_backtrace());
+            }
         }
     }
 
@@ -497,6 +505,14 @@ class page_requirements_manager {
             throw new coding_exception('Missing YUI3 module details.');
         }
 
+        // Don't load this module if we already have, no need to!
+        if ($this->js_module_loaded($module['name'])) {
+            if (debugging('', DEBUG_DEVELOPER)) {
+                $this->debug_moduleloadstacktraces[$module['name']][] = format_backtrace(debug_backtrace());
+            }
+            return;
+        }
+
         $module['fullpath'] = $this->js_fix_url($module['fullpath'])->out(false);
         // add all needed strings
         if (!empty($module['strings'])) {
@@ -509,11 +525,52 @@ class page_requirements_manager {
         }
         unset($module['strings']);
 
+        // Process module requirements and attempt to load each. This allows
+        // moodle modules to require each other.
+        if (!empty($module['requires'])){
+            foreach ($module['requires'] as $requirement) {
+                $rmodule = $this->find_module($requirement);
+                if (is_array($rmodule)) {
+                    $this->js_module($rmodule);
+                }
+            }
+        }
+        
         if ($this->headdone) {
             $this->extramodules[$module['name']] = $module;
         } else {
             $this->M_yui_loader->modules[$module['name']] = $module;
         }
+        if (debugging('', DEBUG_DEVELOPER)) {
+            if (!array_key_exists($module['name'], $this->debug_moduleloadstacktraces)) {
+                $this->debug_moduleloadstacktraces[$module['name']] = array();
+            }
+            $this->debug_moduleloadstacktraces[$module['name']][] = format_backtrace(debug_backtrace());
+        }
+    }
+
+    /**
+     * Returns true if the module has already been loaded.
+     *
+     * @param string|array $modulename
+     * @return bool True if the module has already been loaded
+     */
+    protected function js_module_loaded($module) {
+        if (is_string($module)) {
+            $modulename = $module;
+        } else {
+            $modulename = $module['name'];
+        }
+        return array_key_exists($modulename, $this->M_yui_loader->modules) ||
+               array_key_exists($modulename, $this->extramodules);
+    }
+
+    /**
+     * Returns the stacktraces from loading js modules.
+     * @return array
+     */
+    public function get_loaded_modules() {
+        return $this->debug_moduleloadstacktraces;
     }
 
     /**
index f83a364..27ee96e 100644 (file)
@@ -1247,7 +1247,6 @@ function quiz_check_safe_browser() {
 
 function quiz_get_js_module() {
     global $PAGE;
-    $PAGE->requires->js_module('core_question_engine');
     return array(
         'name' => 'mod_quiz',
         'fullpath' => '/mod/quiz/module.js',
index bdd3a19..3ec9498 100644 (file)
@@ -128,6 +128,8 @@ a.skip:active {position: static;display: block;}
 .arrow,
 .arrow_button input {font-family: Arial,Helvetica,Courier,sans-serif;}
 
+#yui-module-debug {display:none;}
+
 /**
  * Header
  */