Bug 1396600 - Make some efforts to lazy load properties-db. r=tromey
MozReview-Commit-ID: LGgVb5kxN7X
--- a/devtools/client/shared/css-angle.js
+++ b/devtools/client/shared/css-angle.js
@@ -1,15 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
-const {CSS_ANGLEUNIT} = require("devtools/shared/css/properties-db");
+loader.lazyRequireGetter(this, "CSS_ANGLEUNIT",
+ "devtools/shared/css/properties-db", true);
const SPECIALVALUES = new Set([
"initial",
"inherit",
"unset"
]);
const {getCSSLexer} = require("devtools/shared/css/lexer");
@@ -36,19 +37,22 @@ function CssAngle(angleValue) {
this.newAngle(angleValue);
}
module.exports.angleUtils = {
CssAngle: CssAngle,
classifyAngle: classifyAngle
};
-CssAngle.ANGLEUNIT = CSS_ANGLEUNIT;
+CssAngle.prototype = {
+ // Still keep trying to lazy load properties-db by lazily getting ANGLEUNIT
+ get ANGLEUNIT() {
+ return CSS_ANGLEUNIT;
+ },
-CssAngle.prototype = {
_angleUnit: null,
_angleUnitUppercase: false,
// The value as-authored.
authored: null,
// A lower-cased copy of |authored|.
lowerCased: null,
@@ -64,157 +68,157 @@ CssAngle.prototype = {
},
get valid() {
let token = getCSSLexer(this.authored).nextToken();
if (!token) {
return false;
}
return (token.tokenType === "dimension"
- && token.text.toLowerCase() in CssAngle.ANGLEUNIT);
+ && token.text.toLowerCase() in this.ANGLEUNIT);
},
get specialValue() {
return SPECIALVALUES.has(this.lowerCased) ? this.authored : null;
},
get deg() {
let invalidOrSpecialValue = this._getInvalidOrSpecialValue();
if (invalidOrSpecialValue !== false) {
return invalidOrSpecialValue;
}
let angleUnit = classifyAngle(this.authored);
- if (angleUnit === CssAngle.ANGLEUNIT.deg) {
+ if (angleUnit === this.ANGLEUNIT.deg) {
// The angle is valid and is in degree.
return this.authored;
}
let degValue;
- if (angleUnit === CssAngle.ANGLEUNIT.rad) {
+ if (angleUnit === this.ANGLEUNIT.rad) {
// The angle is valid and is in radian.
degValue = this.authoredAngleValue / (Math.PI / 180);
}
- if (angleUnit === CssAngle.ANGLEUNIT.grad) {
+ if (angleUnit === this.ANGLEUNIT.grad) {
// The angle is valid and is in gradian.
degValue = this.authoredAngleValue * 0.9;
}
- if (angleUnit === CssAngle.ANGLEUNIT.turn) {
+ if (angleUnit === this.ANGLEUNIT.turn) {
// The angle is valid and is in turn.
degValue = this.authoredAngleValue * 360;
}
- let unitStr = CssAngle.ANGLEUNIT.deg;
+ let unitStr = this.ANGLEUNIT.deg;
if (this._angleUnitUppercase === true) {
unitStr = unitStr.toUpperCase();
}
return `${Math.round(degValue * 100) / 100}${unitStr}`;
},
get rad() {
let invalidOrSpecialValue = this._getInvalidOrSpecialValue();
if (invalidOrSpecialValue !== false) {
return invalidOrSpecialValue;
}
let unit = classifyAngle(this.authored);
- if (unit === CssAngle.ANGLEUNIT.rad) {
+ if (unit === this.ANGLEUNIT.rad) {
// The angle is valid and is in radian.
return this.authored;
}
let radValue;
- if (unit === CssAngle.ANGLEUNIT.deg) {
+ if (unit === this.ANGLEUNIT.deg) {
// The angle is valid and is in degree.
radValue = this.authoredAngleValue * (Math.PI / 180);
}
- if (unit === CssAngle.ANGLEUNIT.grad) {
+ if (unit === this.ANGLEUNIT.grad) {
// The angle is valid and is in gradian.
radValue = this.authoredAngleValue * 0.9 * (Math.PI / 180);
}
- if (unit === CssAngle.ANGLEUNIT.turn) {
+ if (unit === this.ANGLEUNIT.turn) {
// The angle is valid and is in turn.
radValue = this.authoredAngleValue * 360 * (Math.PI / 180);
}
- let unitStr = CssAngle.ANGLEUNIT.rad;
+ let unitStr = this.ANGLEUNIT.rad;
if (this._angleUnitUppercase === true) {
unitStr = unitStr.toUpperCase();
}
return `${Math.round(radValue * 10000) / 10000}${unitStr}`;
},
get grad() {
let invalidOrSpecialValue = this._getInvalidOrSpecialValue();
if (invalidOrSpecialValue !== false) {
return invalidOrSpecialValue;
}
let unit = classifyAngle(this.authored);
- if (unit === CssAngle.ANGLEUNIT.grad) {
+ if (unit === this.ANGLEUNIT.grad) {
// The angle is valid and is in gradian
return this.authored;
}
let gradValue;
- if (unit === CssAngle.ANGLEUNIT.deg) {
+ if (unit === this.ANGLEUNIT.deg) {
// The angle is valid and is in degree
gradValue = this.authoredAngleValue / 0.9;
}
- if (unit === CssAngle.ANGLEUNIT.rad) {
+ if (unit === this.ANGLEUNIT.rad) {
// The angle is valid and is in radian
gradValue = this.authoredAngleValue / 0.9 / (Math.PI / 180);
}
- if (unit === CssAngle.ANGLEUNIT.turn) {
+ if (unit === this.ANGLEUNIT.turn) {
// The angle is valid and is in turn
gradValue = this.authoredAngleValue * 400;
}
- let unitStr = CssAngle.ANGLEUNIT.grad;
+ let unitStr = this.ANGLEUNIT.grad;
if (this._angleUnitUppercase === true) {
unitStr = unitStr.toUpperCase();
}
return `${Math.round(gradValue * 100) / 100}${unitStr}`;
},
get turn() {
let invalidOrSpecialValue = this._getInvalidOrSpecialValue();
if (invalidOrSpecialValue !== false) {
return invalidOrSpecialValue;
}
let unit = classifyAngle(this.authored);
- if (unit === CssAngle.ANGLEUNIT.turn) {
+ if (unit === this.ANGLEUNIT.turn) {
// The angle is valid and is in turn
return this.authored;
}
let turnValue;
- if (unit === CssAngle.ANGLEUNIT.deg) {
+ if (unit === this.ANGLEUNIT.deg) {
// The angle is valid and is in degree
turnValue = this.authoredAngleValue / 360;
}
- if (unit === CssAngle.ANGLEUNIT.rad) {
+ if (unit === this.ANGLEUNIT.rad) {
// The angle is valid and is in radian
turnValue = (this.authoredAngleValue / (Math.PI / 180)) / 360;
}
- if (unit === CssAngle.ANGLEUNIT.grad) {
+ if (unit === this.ANGLEUNIT.grad) {
// The angle is valid and is in gradian
turnValue = this.authoredAngleValue / 400;
}
- let unitStr = CssAngle.ANGLEUNIT.turn;
+ let unitStr = this.ANGLEUNIT.turn;
if (this._angleUnitUppercase === true) {
unitStr = unitStr.toUpperCase();
}
return `${Math.round(turnValue * 100) / 100}${unitStr}`;
},
/**
* Check whether the angle value is in the special list e.g.
@@ -247,66 +251,66 @@ CssAngle.prototype = {
// Store a lower-cased version of the angle to help with format
// testing. The original text is kept as well so it can be
// returned when needed.
this.lowerCased = angle.toLowerCase();
this._angleUnitUppercase = (angle === angle.toUpperCase());
this.authored = angle;
let reg = new RegExp(
- `(${Object.keys(CssAngle.ANGLEUNIT).join("|")})$`, "i");
+ `(${Object.keys(this.ANGLEUNIT).join("|")})$`, "i");
let unitStartIdx = angle.search(reg);
this.authoredAngleValue = angle.substring(0, unitStartIdx);
this.authoredAngleUnit = angle.substring(unitStartIdx, angle.length);
return this;
},
nextAngleUnit: function () {
// Get a reordered array from the formats object
// to have the current format at the front so we can cycle through.
- let formats = Object.keys(CssAngle.ANGLEUNIT);
+ let formats = Object.keys(this.ANGLEUNIT);
let putOnEnd = formats.splice(0, formats.indexOf(this.angleUnit));
formats = formats.concat(putOnEnd);
let currentDisplayedValue = this[formats[0]];
for (let format of formats) {
if (this[format].toLowerCase() !== currentDisplayedValue.toLowerCase()) {
- this.angleUnit = CssAngle.ANGLEUNIT[format];
+ this.angleUnit = this.ANGLEUNIT[format];
break;
}
}
return this.toString();
},
/**
* Return a string representing a angle
*/
toString: function () {
let angle;
switch (this.angleUnit) {
- case CssAngle.ANGLEUNIT.deg:
+ case this.ANGLEUNIT.deg:
angle = this.deg;
break;
- case CssAngle.ANGLEUNIT.rad:
+ case this.ANGLEUNIT.rad:
angle = this.rad;
break;
- case CssAngle.ANGLEUNIT.grad:
+ case this.ANGLEUNIT.grad:
angle = this.grad;
break;
- case CssAngle.ANGLEUNIT.turn:
+ case this.ANGLEUNIT.turn:
angle = this.turn;
break;
default:
angle = this.deg;
}
if (this._angleUnitUppercase &&
- this.angleUnit != CssAngle.ANGLEUNIT.authored) {
+ this.angleUnit != this.ANGLEUNIT.authored) {
angle = angle.toUpperCase();
}
return angle;
},
/**
* This method allows comparison of CssAngle objects using ===.
*/
@@ -322,24 +326,24 @@ CssAngle.prototype = {
* @param {String} value
* The angle, in any form accepted by CSS.
* @return {String}
* The angle classification, one of "deg", "rad", "grad", or "turn".
*/
function classifyAngle(value) {
value = value.toLowerCase();
if (value.endsWith("deg")) {
- return CssAngle.ANGLEUNIT.deg;
+ return CSS_ANGLEUNIT.deg;
}
if (value.endsWith("grad")) {
- return CssAngle.ANGLEUNIT.grad;
+ return CSS_ANGLEUNIT.grad;
}
if (value.endsWith("rad")) {
- return CssAngle.ANGLEUNIT.rad;
+ return CSS_ANGLEUNIT.rad;
}
if (value.endsWith("turn")) {
- return CssAngle.ANGLEUNIT.turn;
+ return CSS_ANGLEUNIT.turn;
}
- return CssAngle.ANGLEUNIT.deg;
+ return CSS_ANGLEUNIT.deg;
}
--- a/devtools/client/shared/output-parser.js
+++ b/devtools/client/shared/output-parser.js
@@ -1,25 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
+loader.lazyRequireGetter(this, "ANGLE_TAKING_FUNCTIONS",
+ "devtools/shared/css/properties-db", true);
+loader.lazyRequireGetter(this, "BASIC_SHAPE_FUNCTIONS",
+ "devtools/shared/css/properties-db", true);
+loader.lazyRequireGetter(this, "BEZIER_KEYWORDS",
+ "devtools/shared/css/properties-db", true);
+loader.lazyRequireGetter(this, "COLOR_TAKING_FUNCTIONS",
+ "devtools/shared/css/properties-db", true);
+loader.lazyRequireGetter(this, "CSS_TYPES",
+ "devtools/shared/css/properties-db", true);
+
const {angleUtils} = require("devtools/client/shared/css-angle");
const {colorUtils} = require("devtools/shared/css/color");
const {getCSSLexer} = require("devtools/shared/css/lexer");
const EventEmitter = require("devtools/shared/old-event-emitter");
-const {
- ANGLE_TAKING_FUNCTIONS,
- BASIC_SHAPE_FUNCTIONS,
- BEZIER_KEYWORDS,
- COLOR_TAKING_FUNCTIONS,
- CSS_TYPES
-} = require("devtools/shared/css/properties-db");
const {appendText} = require("devtools/client/inspector/shared/utils");
const Services = require("Services");
const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
const {LocalizationHelper} = require("devtools/shared/l10n");
const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
const HTML_NS = "http://www.w3.org/1999/xhtml";
--- a/devtools/client/shared/test/browser_css_angle.js
+++ b/devtools/client/shared/test/browser_css_angle.js
@@ -43,26 +43,27 @@ function testAngleValidity() {
let validString = testAngle.valid ? " a valid" : "an invalid";
is(testAngle.valid, result,
`Testing that "${angle}" is ${validString} angle`);
}
}
function testToString(angle, deg, rad, grad, turn) {
- angle.angleUnit = angleUtils.CssAngle.ANGLEUNIT.deg;
+ let { ANGLEUNIT } = angleUtils.CssAngle.prototype;
+ angle.angleUnit = ANGLEUNIT.deg;
is(angle.toString(), deg, "toString() with deg type");
- angle.angleUnit = angleUtils.CssAngle.ANGLEUNIT.rad;
+ angle.angleUnit = ANGLEUNIT.rad;
is(angle.toString(), rad, "toString() with rad type");
- angle.angleUnit = angleUtils.CssAngle.ANGLEUNIT.grad;
+ angle.angleUnit = ANGLEUNIT.grad;
is(angle.toString(), grad, "toString() with grad type");
- angle.angleUnit = angleUtils.CssAngle.ANGLEUNIT.turn;
+ angle.angleUnit = ANGLEUNIT.turn;
is(angle.toString(), turn, "toString() with turn type");
}
function getAngleValidityData() {
return [{
angle: "0.2turn",
result: true
}, {
--- a/devtools/server/actors/css-properties.js
+++ b/devtools/server/actors/css-properties.js
@@ -1,24 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
-const { Cc, Ci } = require("chrome");
-
-loader.lazyGetter(this, "DOMUtils", () => {
- return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
-});
+loader.lazyServiceGetter(this, "DOMUtils",
+ "@mozilla.org/inspector/dom-utils;1", "inIDOMUtils");
+loader.lazyRequireGetter(this, "CSS_TYPES",
+ "devtools/shared/css/properties-db", true);
const protocol = require("devtools/shared/protocol");
const { ActorClassWithSpec, Actor } = protocol;
const { cssPropertiesSpec } = require("devtools/shared/specs/css-properties");
-const { CSS_TYPES } = require("devtools/shared/css/properties-db");
const { cssColors } = require("devtools/shared/css/color-db");
exports.CssPropertiesActor = ActorClassWithSpec(cssPropertiesSpec, {
typeName: "cssProperties",
initialize(conn) {
Actor.prototype.initialize.call(this, conn);
},
--- a/devtools/shared/css/color.js
+++ b/devtools/shared/css/color.js
@@ -1,17 +1,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Services = require("Services");
-const {CSS_ANGLEUNIT} = require("devtools/shared/css/properties-db");
+loader.lazyRequireGetter(this, "CSS_ANGLEUNIT",
+ "devtools/shared/css/properties-db", true);
+
const {getAngleValueInDegrees} = require("devtools/shared/css/parsing-utils");
const {getCSSLexer} = require("devtools/shared/css/lexer");
const {cssColors} = require("devtools/shared/css/color-db");
const COLOR_UNIT_PREF = "devtools.defaultColorUnit";
const SPECIALVALUES = new Set([
--- a/devtools/shared/css/parsing-utils.js
+++ b/devtools/shared/css/parsing-utils.js
@@ -9,17 +9,18 @@
// parseDeclarations - parse a CSS rule into declarations
// RuleRewriter - rewrite CSS rule text
// parsePseudoClassesAndAttributes - parse selector and extract
// pseudo-classes
// parseSingleValue - parse a single CSS property value
"use strict";
-const {CSS_ANGLEUNIT} = require("devtools/shared/css/properties-db");
+loader.lazyRequireGetter(this, "CSS_ANGLEUNIT",
+ "devtools/shared/css/properties-db", true);
const promise = require("promise");
const {getCSSLexer} = require("devtools/shared/css/lexer");
const {Task} = require("devtools/shared/task");
const SELECTOR_ATTRIBUTE = exports.SELECTOR_ATTRIBUTE = 1;
const SELECTOR_ELEMENT = exports.SELECTOR_ELEMENT = 2;
const SELECTOR_PSEUDO_CLASS = exports.SELECTOR_PSEUDO_CLASS = 3;
--- a/devtools/shared/fronts/css-properties.js
+++ b/devtools/shared/fronts/css-properties.js
@@ -1,17 +1,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
+loader.lazyRequireGetter(this, "CSS_PROPERTIES_DB",
+ "devtools/shared/css/properties-db", true);
+
const { FrontClassWithSpec, Front } = require("devtools/shared/protocol");
const { cssPropertiesSpec } = require("devtools/shared/specs/css-properties");
const { Task } = require("devtools/shared/task");
-const { CSS_PROPERTIES_DB } = require("devtools/shared/css/properties-db");
const { cssColors } = require("devtools/shared/css/color-db");
/**
* Build up a regular expression that matches a CSS variable token. This is an
* ident token that starts with two dashes "--".
*
* https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
*/
@@ -275,49 +277,59 @@ function getClientCssProperties() {
/**
* Even if the target has the cssProperties actor, the returned data may not be in the
* same shape or have all of the data we need. This normalizes the data and fills in
* any missing information like color values.
*
* @return {Object} The normalized CSS database.
*/
function normalizeCssData(db) {
- if (db !== CSS_PROPERTIES_DB) {
+ // If there is a `from` attributes, it means that it comes from RDP
+ // and it is not the client CSS_PROPERTIES_DB object.
+ // (prevent comparing to CSS_PROPERTIES_DB to avoid loading client database)
+ if (typeof (db.from) == "string") {
// Firefox 49's getCSSDatabase() just returned the properties object, but
// now it returns an object with multiple types of CSS information.
if (!db.properties) {
db = { properties: db };
}
let missingSupports = !db.properties.color.supports;
let missingValues = !db.properties.color.values;
let missingSubproperties = !db.properties.background.subproperties;
+ let missingIsInherited = !db.properties.font.isInherited;
- for (let name in db.properties) {
- // Skip the current property if we can't find it in CSS_PROPERTIES_DB.
- if (typeof CSS_PROPERTIES_DB.properties[name] !== "object") {
- continue;
- }
+ let missingSomething = missingSupports || missingValues || missingSubproperties ||
+ missingIsInherited;
+
+ if (missingSomething) {
+ for (let name in db.properties) {
+ // Skip the current property if we can't find it in CSS_PROPERTIES_DB.
+ if (typeof CSS_PROPERTIES_DB.properties[name] !== "object") {
+ continue;
+ }
- // Add "supports" information to the css properties if it's missing.
- if (missingSupports) {
- db.properties[name].supports = CSS_PROPERTIES_DB.properties[name].supports;
- }
- // Add "values" information to the css properties if it's missing.
- if (missingValues) {
- db.properties[name].values = CSS_PROPERTIES_DB.properties[name].values;
- }
- // Add "subproperties" information to the css properties if it's missing.
- if (missingSubproperties) {
- db.properties[name].subproperties =
- CSS_PROPERTIES_DB.properties[name].subproperties;
- }
- // Add "isInherited" information to the css properties if it's missing.
- if (db.properties.font.isInherited) {
- db.properties[name].isInherited = CSS_PROPERTIES_DB.properties[name].isInherited;
+ // Add "supports" information to the css properties if it's missing.
+ if (missingSupports) {
+ db.properties[name].supports = CSS_PROPERTIES_DB.properties[name].supports;
+ }
+ // Add "values" information to the css properties if it's missing.
+ if (missingValues) {
+ db.properties[name].values = CSS_PROPERTIES_DB.properties[name].values;
+ }
+ // Add "subproperties" information to the css properties if it's missing.
+ if (missingSubproperties) {
+ db.properties[name].subproperties =
+ CSS_PROPERTIES_DB.properties[name].subproperties;
+ }
+ // Add "isInherited" information to the css properties if it's missing.
+ if (missingIsInherited) {
+ db.properties[name].isInherited =
+ CSS_PROPERTIES_DB.properties[name].isInherited;
+ }
}
}
}
reattachCssColorValues(db);
// If there is no supportedFeature in db, create an empty one.
if (!db.supportedFeature) {