diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 1e6cc12f116..60dbcc95559 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -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 .= "

$module

"; + foreach ($backtraces as $backtrace) { + $details .= "
$backtrace
"; + } + $details .= '
'; + } + $info['html'] .= "Included YUI modules: $yuicount "; + $info['txt'] .= "includedyuimodules: $yuicount "; + $info['html'] .= "Other JavaScript modules: $othercount "; + $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'] .= '
'.$details.'
'; + } + if (!empty($PERF->logwrites)) { $info['logwrites'] = $PERF->logwrites; $info['html'] .= 'Log DB writes '.$info['logwrites'].' '; diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 39857aa8bd8..54cb95927d5 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -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; } /** diff --git a/mod/quiz/locallib.php b/mod/quiz/locallib.php index f83a364625f..27ee96e60d1 100644 --- a/mod/quiz/locallib.php +++ b/mod/quiz/locallib.php @@ -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', diff --git a/theme/base/style/core.css b/theme/base/style/core.css index bdd3a19ee06..3ec94986a2d 100644 --- a/theme/base/style/core.css +++ b/theme/base/style/core.css @@ -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 */