Skip to content

Commit

Permalink
fix: convert value to DOMString
Browse files Browse the repository at this point in the history
  • Loading branch information
cdoublev committed Apr 29, 2021
1 parent b527ed7 commit 86a3490
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 22 deletions.
8 changes: 5 additions & 3 deletions lib/CSSStyleDeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var CSSOM = require('cssom');
var allProperties = require('./allProperties');
var allExtraProperties = require('./allExtraProperties');
var implementedProperties = require('./implementedProperties');
var { dashedToCamelCase } = require('./parsers');
var { dashedToCamelCase, toDOMString } = require('./parsers');
var getBasicPropertyDescriptor = require('./utils/getBasicPropertyDescriptor');

/**
Expand Down Expand Up @@ -49,10 +49,11 @@ CSSStyleDeclaration.prototype = {
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-setProperty
*/
setProperty: function(name, value, priority) {
value = toDOMString(value);
if (value === undefined) {
return;
}
if (value === null || value === '') {
if (value === '') {
this.removeProperty(name);
return;
}
Expand All @@ -70,10 +71,11 @@ CSSStyleDeclaration.prototype = {
this._importants[lowercaseName] = priority;
},
_setProperty: function(name, value, priority) {
value = toDOMString(value);
if (value === undefined) {
return;
}
if (value === null || value === '') {
if (value === '') {
this.removeProperty(name);
return;
}
Expand Down
81 changes: 81 additions & 0 deletions lib/CSSStyleDeclaration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ var allowedProperties = dashedProperties.map(parsers.dashedToCamelCase);
implementedProperties = Array.from(implementedProperties).map(parsers.dashedToCamelCase);
var invalidProperties = implementedProperties.filter(prop => !allowedProperties.includes(prop));

var BigInt = BigInt || Number;

describe('CSSStyleDeclaration', () => {
test('has only valid properties implemented', () => {
expect(invalidProperties.length).toEqual(0);
Expand Down Expand Up @@ -352,6 +354,85 @@ describe('CSSStyleDeclaration', () => {
expect(style.fillOpacity).toEqual('0');
});

test('setting a property with a value that can not be converted to string', () => {
const style = new CSSStyleDeclaration();

style.setProperty('--custom', '1');
expect(style.getPropertyValue('--custom')).toBe('1');

style.setProperty('--custom', undefined);
expect(style.getPropertyValue('--custom')).toBe('1');

expect(() => {
style.setProperty('--custom', Symbol('0'));
}).toThrow('Cannot convert symbol to string');

style.setProperty('--custom', {
toString() {
return null;
},
});
expect(style.getPropertyValue('--custom')).toBe('1');

expect(() => {
style.setProperty('--custom', {
toString() {
return [0];
},
});
}).toThrow('Cannot convert value to string');
});

test('setting a property with a value that can be converted to string', () => {
const style = new CSSStyleDeclaration();

style.setProperty('--custom', '1');
expect(style.getPropertyValue('--custom')).toBe('1');

style.setProperty('--custom', null);
expect(style.getPropertyValue('--custom')).toBe('');
style.setProperty('--custom', '1');

style.setProperty('--custom', false);
expect(style.getPropertyValue('--custom')).toBe('false');

style.setProperty('--custom', 0);
expect(style.getPropertyValue('--custom')).toBe('0');
style.setProperty('--custom', '1');

style.setProperty('--custom', BigInt(0));
expect(style.getPropertyValue('--custom')).toBe('0');
style.setProperty('--custom', '1');

style.setProperty('--custom', [0]);
expect(style.getPropertyValue('--custom')).toEqual('0');
style.setProperty('--custom', '1');

style.setProperty('--custom', {
toString: function() {
return '0';
},
});
expect(style.getPropertyValue('--custom')).toEqual('0');
style.setProperty('--custom', '1');

style.setProperty('--custom', {
toString: function() {
return 0;
},
});
expect(style.getPropertyValue('--custom')).toEqual('0');
style.setProperty('--custom', '1');

style.setProperty('--custom', {
toString: function() {
return BigInt(0);
},
});
expect(style.getPropertyValue('--custom')).toEqual('0');
style.setProperty('--custom', '1');
});

test('onchange callback should be called when the csstext changes', () => {
var style = new CSSStyleDeclaration(function(cssText) {
expect(cssText).toEqual('opacity: 0;');
Expand Down
65 changes: 46 additions & 19 deletions lib/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ exports.TYPES = {
STRING: 7,
ANGLE: 8,
KEYWORD: 9,
NULL_OR_EMPTY_STR: 10,
EMPTY: 10,
CALC: 11,
};

Expand All @@ -35,19 +35,46 @@ var calcRegEx = /^calc\(([^)]*)\)$/;
var colorRegEx4 = /^hsla?\(\s*(-?\d+|-?\d*.\d+)\s*,\s*(-?\d+|-?\d*.\d+)%\s*,\s*(-?\d+|-?\d*.\d+)%\s*(,\s*(-?\d+|-?\d*.\d+)\s*)?\)/;
var angleRegEx = /^([-+]?[0-9]*\.?[0-9]+)(deg|grad|rad)$/;

// This will return one of the above types based on the passed in string
exports.valueType = function valueType(val) {
if (val === '' || val === null) {
return exports.TYPES.NULL_OR_EMPTY_STR;
// https://heycam.github.io/webidl/#es-DOMString
exports.toDOMString = function toDOMString(val) {
if (val === null) {
return '';
}
if (val === undefined) {
return val;
}
if (typeof val === 'string') {
return val;
}
if (typeof val === 'symbol') {
throw Error('Cannot convert symbol to string');
}
if (typeof val === 'number') {
if (typeof val.toString === 'function') {
val = val.toString();
if (val === null) {
return undefined;
}
if (typeof val !== 'string') {
if (typeof val === 'number' || typeof val === 'bigint') {
val = val.toString();
} else {
throw Error('Cannot convert value to string');
}
}
}
return val.toString();
};

if (typeof val !== 'string') {
return undefined;
}
// This will return one of the above types based on the passed in string
exports.valueType = function valueType(val) {
val = exports.toDOMString(val);

if (val === undefined) {
return val;
}
if (val === '') {
return exports.TYPES.EMPTY;
}
if (integerRegEx.test(val)) {
return exports.TYPES.INTEGER;
}
Expand Down Expand Up @@ -157,7 +184,7 @@ exports.valueType = function valueType(val) {

exports.parseInteger = function parseInteger(val) {
var type = exports.valueType(val);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
return val;
}
if (type !== exports.TYPES.INTEGER) {
Expand All @@ -168,7 +195,7 @@ exports.parseInteger = function parseInteger(val) {

exports.parseNumber = function parseNumber(val) {
var type = exports.valueType(val);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
return val;
}
if (type !== exports.TYPES.NUMBER && type !== exports.TYPES.INTEGER) {
Expand All @@ -182,7 +209,7 @@ exports.parseLength = function parseLength(val) {
return '0px';
}
var type = exports.valueType(val);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
return val;
}
if (type !== exports.TYPES.LENGTH) {
Expand All @@ -196,7 +223,7 @@ exports.parsePercent = function parsePercent(val) {
return '0%';
}
var type = exports.valueType(val);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
return val;
}
if (type !== exports.TYPES.PERCENT) {
Expand All @@ -221,7 +248,7 @@ exports.parseMeasurement = function parseMeasurement(val) {

exports.parseUrl = function parseUrl(val) {
var type = exports.valueType(val);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
return val;
}
var res = urlRegEx.exec(val);
Expand Down Expand Up @@ -260,7 +287,7 @@ exports.parseUrl = function parseUrl(val) {

exports.parseString = function parseString(val) {
var type = exports.valueType(val);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
return val;
}
if (type !== exports.TYPES.STRING) {
Expand All @@ -287,7 +314,7 @@ exports.parseString = function parseString(val) {

exports.parseColor = function parseColor(val) {
var type = exports.valueType(val);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
return val;
}
var red,
Expand Down Expand Up @@ -406,7 +433,7 @@ exports.parseColor = function parseColor(val) {

exports.parseAngle = function parseAngle(val) {
var type = exports.valueType(val);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
return val;
}
if (type !== exports.TYPES.ANGLE) {
Expand All @@ -431,7 +458,7 @@ exports.parseAngle = function parseAngle(val) {

exports.parseKeyword = function parseKeyword(val, valid_keywords) {
var type = exports.valueType(val);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
return val;
}
if (type !== exports.TYPES.KEYWORD) {
Expand Down Expand Up @@ -520,7 +547,7 @@ var getParts = function(str) {
exports.shorthandParser = function parse(v, shorthand_for) {
var obj = {};
var type = exports.valueType(v);
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
if (type === exports.TYPES.EMPTY) {
Object.keys(shorthand_for).forEach(function(property) {
obj[property] = '';
});
Expand Down

0 comments on commit 86a3490

Please sign in to comment.