Skip to content

Commit

Permalink
Fix synchronously loading/applying stylesheets on page load.
Browse files Browse the repository at this point in the history
Starting in 2.0, stylesheet loading became asynchronous, through the
usage of promises for both calculating the list of stylesheets and the
initial call to less.refresh(). This resulted in visual issues while
loading on some browsers (noticed in Firefox and Safari), along with
breakages of any custom JavaScript that depended on the computed style
of elements on the page, due to race conditions.

This change preserves the promise for initial page loading, in order to
retain support for less.pageLoadFinished, but immediately executes the
stylesheet scan (through a new less.registerStylesheetsImmediately
function) and the less.refresh() call. That resulting behavior matches
versions of less prior to 2.0.

This unveiled a regression in registering functions, both in the browser
and in unit tests, that was not previously noticed due to the
asynchronous load. Registered functions would have a 'less' variable set
to the less options, and not less itself, when not going through the
asynchronous loading mode. This meant that both unit tests and
real-world function registration would break when the sync page loading
was fixed. Overriding window.less to point to the actual less module and
not less.options during bootstrap fixes this.

This fixes #2317.
  • Loading branch information
chipx86 committed Apr 28, 2015
1 parent 5ad6fb3 commit f667575
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 17 deletions.
11 changes: 5 additions & 6 deletions lib/less-browser/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ require("./add-default-options")(window, options);

var less = module.exports = require("./index")(window, options);

window.less = less;

if (options.onReady) {
if (/!watch/.test(window.location.hash)) {
less.watch();
}

less.pageLoadFinished = less.registerStylesheets().then(
function () {
return less.refresh(less.env === 'development');
}
);
}
less.registerStylesheetsImmediately();
less.pageLoadFinished = less.refresh(less.env === 'development');
}
30 changes: 19 additions & 11 deletions lib/less-browser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,20 +187,28 @@ module.exports = function(window, options) {
less.unwatch = function () {clearInterval(less.watchTimer); this.watchMode = false; return false; };

//
// Get all <link> tags with the 'rel' attribute set to "stylesheet/less"
// Synchronously get all <link> tags with the 'rel' attribute set to
// "stylesheet/less".
//
less.registerStylesheets = function() {
return new Promise(function(resolve, reject) {
var links = document.getElementsByTagName('link');
less.sheets = [];

for (var i = 0; i < links.length; i++) {
if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
(links[i].type.match(typePattern)))) {
less.sheets.push(links[i]);
}
less.registerStylesheetsImmediately = function() {
var links = document.getElementsByTagName('link');
less.sheets = [];

for (var i = 0; i < links.length; i++) {
if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
(links[i].type.match(typePattern)))) {
less.sheets.push(links[i]);
}
}
};

//
// Asynchronously get all <link> tags with the 'rel' attribute set to
// "stylesheet/less", returning a Promise.
//
less.registerStylesheets = function() {
return new Promise(function(resolve, reject) {
less.registerStylesheetsImmediately();
resolve();
});
};
Expand Down

0 comments on commit f667575

Please sign in to comment.