зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1152721 - Extract styleinspector common methods to utils.js, r=mratcliffe
--HG-- extra : histedit_source : f17b92c98d8ad47f41beef79a0ea9521793beec8
This commit is contained in:
Родитель
54ed420cc1
Коммит
543ca99816
|
@ -10,7 +10,7 @@
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
let {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
let {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||||
let {_advanceValidate} = require("devtools/styleinspector/rule-view");
|
let {advanceValidate} = require("devtools/styleinspector/utils");
|
||||||
|
|
||||||
// 1 2 3
|
// 1 2 3
|
||||||
// 0123456789012345678901234567890
|
// 0123456789012345678901234567890
|
||||||
|
@ -18,8 +18,8 @@ let sampleInput = '\\symbol "string" url(somewhere)';
|
||||||
|
|
||||||
function testInsertion(where, result, testName) {
|
function testInsertion(where, result, testName) {
|
||||||
do_print(testName);
|
do_print(testName);
|
||||||
equal(_advanceValidate(Ci.nsIDOMKeyEvent.DOM_VK_SEMICOLON, sampleInput, where),
|
equal(advanceValidate(Ci.nsIDOMKeyEvent.DOM_VK_SEMICOLON, sampleInput, where),
|
||||||
result, "testing _advanceValidate at " + where);
|
result, "testing advanceValidate at " + where);
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
|
|
|
@ -15,8 +15,10 @@ const ToolDefinitions = require("main").Tools;
|
||||||
const {CssLogic} = require("devtools/styleinspector/css-logic");
|
const {CssLogic} = require("devtools/styleinspector/css-logic");
|
||||||
const {ELEMENT_STYLE} = require("devtools/server/actors/styles");
|
const {ELEMENT_STYLE} = require("devtools/server/actors/styles");
|
||||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||||
|
const {setTimeout, clearTimeout} = Cu.import("resource://gre/modules/Timer.jsm", {});
|
||||||
const {OutputParser} = require("devtools/output-parser");
|
const {OutputParser} = require("devtools/output-parser");
|
||||||
const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/styleeditor/utils");
|
const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/styleeditor/utils");
|
||||||
|
const {createChild} = require("devtools/styleinspector/utils");
|
||||||
const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||||
|
|
||||||
loader.lazyRequireGetter(this, "overlays",
|
loader.lazyRequireGetter(this, "overlays",
|
||||||
|
@ -70,7 +72,7 @@ UpdateProcess.prototype = {
|
||||||
if (this.canceled) {
|
if (this.canceled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._timeout = this.win.setTimeout(this._timeoutHandler.bind(this), 0);
|
this._timeout = setTimeout(this._timeoutHandler.bind(this), 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +81,7 @@ UpdateProcess.prototype = {
|
||||||
*/
|
*/
|
||||||
cancel: function() {
|
cancel: function() {
|
||||||
if (this._timeout) {
|
if (this._timeout) {
|
||||||
this.win.clearTimeout(this._timeout);
|
clearTimeout(this._timeout);
|
||||||
this._timeout = 0;
|
this._timeout = 0;
|
||||||
}
|
}
|
||||||
this.canceled = true;
|
this.canceled = true;
|
||||||
|
@ -515,17 +517,15 @@ CssComputedView.prototype = {
|
||||||
* Called when the user enters a search term in the filter style search box.
|
* Called when the user enters a search term in the filter style search box.
|
||||||
*/
|
*/
|
||||||
_onFilterStyles: function() {
|
_onFilterStyles: function() {
|
||||||
let win = this.styleWindow;
|
|
||||||
|
|
||||||
if (this._filterChangedTimeout) {
|
if (this._filterChangedTimeout) {
|
||||||
win.clearTimeout(this._filterChangedTimeout);
|
clearTimeout(this._filterChangedTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
let filterTimeout = (this.searchField.value.length > 0)
|
let filterTimeout = (this.searchField.value.length > 0)
|
||||||
? FILTER_CHANGED_TIMEOUT : 0;
|
? FILTER_CHANGED_TIMEOUT : 0;
|
||||||
this.searchClearButton.hidden = this.searchField.value.length === 0;
|
this.searchClearButton.hidden = this.searchField.value.length === 0;
|
||||||
|
|
||||||
this._filterChangedTimeout = win.setTimeout(() => {
|
this._filterChangedTimeout = setTimeout(() => {
|
||||||
if (this.searchField.value.length > 0) {
|
if (this.searchField.value.length > 0) {
|
||||||
this.searchField.setAttribute("filled", true);
|
this.searchField.setAttribute("filled", true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1397,32 +1397,5 @@ SelectorView.prototype = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a child element with a set of attributes.
|
|
||||||
*
|
|
||||||
* @param {Element} parent
|
|
||||||
* The parent node.
|
|
||||||
* @param {String} tag
|
|
||||||
* The tag name.
|
|
||||||
* @param {Object} attributes
|
|
||||||
* A set of attributes to set on the node.
|
|
||||||
*/
|
|
||||||
function createChild(parent, tag, attributes={}) {
|
|
||||||
let elt = parent.ownerDocument.createElementNS(HTML_NS, tag);
|
|
||||||
for (let attr in attributes) {
|
|
||||||
if (attributes.hasOwnProperty(attr)) {
|
|
||||||
if (attr === "textContent") {
|
|
||||||
elt.textContent = attributes[attr];
|
|
||||||
} else if (attr === "child") {
|
|
||||||
elt.appendChild(attributes[attr]);
|
|
||||||
} else {
|
|
||||||
elt.setAttribute(attr, attributes[attr]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parent.appendChild(elt);
|
|
||||||
return elt;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.CssComputedView = CssComputedView;
|
exports.CssComputedView = CssComputedView;
|
||||||
exports.PropertyView = PropertyView;
|
exports.PropertyView = PropertyView;
|
||||||
|
|
|
@ -14,4 +14,5 @@ EXTRA_JS_MODULES.devtools.styleinspector += [
|
||||||
'style-inspector-menu.js',
|
'style-inspector-menu.js',
|
||||||
'style-inspector-overlays.js',
|
'style-inspector-overlays.js',
|
||||||
'style-inspector.js',
|
'style-inspector.js',
|
||||||
|
'utils.js',
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
const {Cc, Ci, Cu} = require("chrome");
|
const {Cc, Ci, Cu} = require("chrome");
|
||||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||||
|
const {setTimeout, clearTimeout} =
|
||||||
|
Cu.import("resource://gre/modules/Timer.jsm", {});
|
||||||
const {CssLogic} = require("devtools/styleinspector/css-logic");
|
const {CssLogic} = require("devtools/styleinspector/css-logic");
|
||||||
const {InplaceEditor, editableField, editableItem} =
|
const {InplaceEditor, editableField, editableItem} =
|
||||||
require("devtools/shared/inplace-editor");
|
require("devtools/shared/inplace-editor");
|
||||||
|
@ -19,6 +21,14 @@ const {ELEMENT_STYLE, PSEUDO_ELEMENTS} =
|
||||||
require("devtools/server/actors/styles");
|
require("devtools/server/actors/styles");
|
||||||
const {OutputParser} = require("devtools/output-parser");
|
const {OutputParser} = require("devtools/output-parser");
|
||||||
const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/styleeditor/utils");
|
const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/styleeditor/utils");
|
||||||
|
const {
|
||||||
|
createChild,
|
||||||
|
appendText,
|
||||||
|
advanceValidate,
|
||||||
|
blurOnMultipleProperties,
|
||||||
|
promiseWarn,
|
||||||
|
throttle
|
||||||
|
} = require("devtools/styleinspector/utils");
|
||||||
const {
|
const {
|
||||||
parseDeclarations,
|
parseDeclarations,
|
||||||
parseSingleValue,
|
parseSingleValue,
|
||||||
|
@ -27,7 +37,6 @@ const {
|
||||||
SELECTOR_ELEMENT,
|
SELECTOR_ELEMENT,
|
||||||
SELECTOR_PSEUDO_CLASS
|
SELECTOR_PSEUDO_CLASS
|
||||||
} = require("devtools/styleinspector/css-parsing-utils");
|
} = require("devtools/styleinspector/css-parsing-utils");
|
||||||
|
|
||||||
loader.lazyRequireGetter(this, "overlays",
|
loader.lazyRequireGetter(this, "overlays",
|
||||||
"devtools/styleinspector/style-inspector-overlays");
|
"devtools/styleinspector/style-inspector-overlays");
|
||||||
loader.lazyRequireGetter(this, "EventEmitter",
|
loader.lazyRequireGetter(this, "EventEmitter",
|
||||||
|
@ -53,11 +62,6 @@ const FILTER_PROP_RE = /\s*([^:\s]*)\s*:\s*(.*?)\s*;?$/;
|
||||||
const IOService = Cc["@mozilla.org/network/io-service;1"]
|
const IOService = Cc["@mozilla.org/network/io-service;1"]
|
||||||
.getService(Ci.nsIIOService);
|
.getService(Ci.nsIIOService);
|
||||||
|
|
||||||
function promiseWarn(err) {
|
|
||||||
console.error(err);
|
|
||||||
return promise.reject(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To figure out how shorthand properties are interpreted by the
|
* To figure out how shorthand properties are interpreted by the
|
||||||
* engine, we will set properties on a dummy element and observe
|
* engine, we will set properties on a dummy element and observe
|
||||||
|
@ -3642,77 +3646,6 @@ UserProperties.prototype = {
|
||||||
* Helper functions
|
* Helper functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a child element with a set of attributes.
|
|
||||||
*
|
|
||||||
* @param {Element} parent
|
|
||||||
* The parent node.
|
|
||||||
* @param {String} tag
|
|
||||||
* The tag name.
|
|
||||||
* @param {Object} attributes
|
|
||||||
* A set of attributes to set on the node.
|
|
||||||
*/
|
|
||||||
function createChild(parent, tag, attributes) {
|
|
||||||
let elt = parent.ownerDocument.createElementNS(HTML_NS, tag);
|
|
||||||
for (let attr in attributes) {
|
|
||||||
if (attributes.hasOwnProperty(attr)) {
|
|
||||||
if (attr === "textContent") {
|
|
||||||
elt.textContent = attributes[attr];
|
|
||||||
} else if (attr === "child") {
|
|
||||||
elt.appendChild(attributes[attr]);
|
|
||||||
} else {
|
|
||||||
elt.setAttribute(attr, attributes[attr]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parent.appendChild(elt);
|
|
||||||
return elt;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTimeout() {
|
|
||||||
let window = Services.appShell.hiddenDOMWindow;
|
|
||||||
return window.setTimeout.apply(window, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearTimeout() {
|
|
||||||
let window = Services.appShell.hiddenDOMWindow;
|
|
||||||
return window.clearTimeout.apply(window, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
function throttle(func, wait, scope) {
|
|
||||||
let timer = null;
|
|
||||||
return function() {
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
}
|
|
||||||
let args = arguments;
|
|
||||||
timer = setTimeout(function() {
|
|
||||||
timer = null;
|
|
||||||
func.apply(scope, args);
|
|
||||||
}, wait);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler that causes a blur on the target if the input has
|
|
||||||
* multiple CSS properties as the value.
|
|
||||||
*/
|
|
||||||
function blurOnMultipleProperties(e) {
|
|
||||||
setTimeout(() => {
|
|
||||||
let props = parseDeclarations(e.target.value);
|
|
||||||
if (props.length > 1) {
|
|
||||||
e.target.blur();
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a text node to an element.
|
|
||||||
*/
|
|
||||||
function appendText(aParent, aText) {
|
|
||||||
aParent.appendChild(aParent.ownerDocument.createTextNode(aText));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walk up the DOM from a given node until a parent property holder is found.
|
* Walk up the DOM from a given node until a parent property holder is found.
|
||||||
* For elements inside the computed property list, the non-computed parent
|
* For elements inside the computed property list, the non-computed parent
|
||||||
|
@ -3781,51 +3714,6 @@ function getPropertyNameAndValue(node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a character is typed in a value editor. This decides
|
|
||||||
* whether to advance or not, first by checking to see if ";" was
|
|
||||||
* typed, and then by lexing the input and seeing whether the ";"
|
|
||||||
* would be a terminator at this point.
|
|
||||||
*
|
|
||||||
* @param {Number} keyCode
|
|
||||||
* Key code to be checked.
|
|
||||||
* @param {String} value
|
|
||||||
* Current text editor value.
|
|
||||||
* @param {Number} insertionPoint
|
|
||||||
* The index of the insertion point.
|
|
||||||
* @return {Boolean} True if the focus should advance; false if
|
|
||||||
* the character should be inserted.
|
|
||||||
*/
|
|
||||||
function advanceValidate(keyCode, value, insertionPoint) {
|
|
||||||
// Only ";" has special handling here.
|
|
||||||
if (keyCode !== Ci.nsIDOMKeyEvent.DOM_VK_SEMICOLON) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the character provisionally and see what happens. If we
|
|
||||||
// end up with a ";" symbol token, then the semicolon terminates the
|
|
||||||
// value. Otherwise it's been inserted in some spot where it has a
|
|
||||||
// valid meaning, like a comment or string.
|
|
||||||
value = value.slice(0, insertionPoint) + ";" +
|
|
||||||
value.slice(insertionPoint);
|
|
||||||
let lexer = domUtils.getCSSLexer(value);
|
|
||||||
while (true) {
|
|
||||||
let token = lexer.nextToken();
|
|
||||||
if (token.endOffset > insertionPoint) {
|
|
||||||
if (token.tokenType === "symbol" && token.text === ";") {
|
|
||||||
// The ";" is a terminator.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// The ";" is not a terminator in this context.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're exporting _advanceValidate for unit tests.
|
|
||||||
exports._advanceValidate = advanceValidate;
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
|
XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
|
||||||
return Cc["@mozilla.org/widget/clipboardhelper;1"]
|
return Cc["@mozilla.org/widget/clipboardhelper;1"]
|
||||||
.getService(Ci.nsIClipboardHelper);
|
.getService(Ci.nsIClipboardHelper);
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/* global domUtils */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const {Cc, Ci, Cu} = require("chrome");
|
||||||
|
const {setTimeout, clearTimeout} =
|
||||||
|
Cu.import("resource://gre/modules/Timer.jsm", {});
|
||||||
|
const {parseDeclarations} =
|
||||||
|
require("devtools/styleinspector/css-parsing-utils");
|
||||||
|
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||||
|
|
||||||
|
loader.lazyServiceGetter(this, "domUtils",
|
||||||
|
"@mozilla.org/inspector/dom-utils;1", "inIDOMUtils");
|
||||||
|
|
||||||
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a child element with a set of attributes.
|
||||||
|
*
|
||||||
|
* @param {Element} parent
|
||||||
|
* The parent node.
|
||||||
|
* @param {string} tagName
|
||||||
|
* The tag name.
|
||||||
|
* @param {object} attributes
|
||||||
|
* A set of attributes to set on the node.
|
||||||
|
*/
|
||||||
|
function createChild(parent, tagName, attributes={}) {
|
||||||
|
let elt = parent.ownerDocument.createElementNS(HTML_NS, tagName);
|
||||||
|
for (let attr in attributes) {
|
||||||
|
if (attributes.hasOwnProperty(attr)) {
|
||||||
|
if (attr === "textContent") {
|
||||||
|
elt.textContent = attributes[attr];
|
||||||
|
} else if (attr === "child") {
|
||||||
|
elt.appendChild(attributes[attr]);
|
||||||
|
} else {
|
||||||
|
elt.setAttribute(attr, attributes[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent.appendChild(elt);
|
||||||
|
return elt;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.createChild = createChild;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a text node to an element.
|
||||||
|
*
|
||||||
|
* @param {Element} parent
|
||||||
|
* The parent node.
|
||||||
|
* @param {string} text
|
||||||
|
* The text content for the text node.
|
||||||
|
*/
|
||||||
|
function appendText(parent, text) {
|
||||||
|
parent.appendChild(parent.ownerDocument.createTextNode(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.appendText = appendText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a character is typed in a value editor. This decides
|
||||||
|
* whether to advance or not, first by checking to see if ";" was
|
||||||
|
* typed, and then by lexing the input and seeing whether the ";"
|
||||||
|
* would be a terminator at this point.
|
||||||
|
*
|
||||||
|
* @param {number} keyCode
|
||||||
|
* Key code to be checked.
|
||||||
|
* @param {string} aValue
|
||||||
|
* Current text editor value.
|
||||||
|
* @param {number} insertionPoint
|
||||||
|
* The index of the insertion point.
|
||||||
|
* @return {Boolean} True if the focus should advance; false if
|
||||||
|
* the character should be inserted.
|
||||||
|
*/
|
||||||
|
function advanceValidate(keyCode, value, insertionPoint) {
|
||||||
|
// Only ";" has special handling here.
|
||||||
|
if (keyCode !== Ci.nsIDOMKeyEvent.DOM_VK_SEMICOLON) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the character provisionally and see what happens. If we
|
||||||
|
// end up with a ";" symbol token, then the semicolon terminates the
|
||||||
|
// value. Otherwise it's been inserted in some spot where it has a
|
||||||
|
// valid meaning, like a comment or string.
|
||||||
|
value = value.slice(0, insertionPoint) + ";" + value.slice(insertionPoint);
|
||||||
|
let lexer = domUtils.getCSSLexer(value);
|
||||||
|
while (true) {
|
||||||
|
let token = lexer.nextToken();
|
||||||
|
if (token.endOffset > insertionPoint) {
|
||||||
|
if (token.tokenType === "symbol" && token.text === ";") {
|
||||||
|
// The ";" is a terminator.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// The ";" is not a terminator in this context.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.advanceValidate = advanceValidate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a throttling function wrapper to regulate its frequency.
|
||||||
|
*
|
||||||
|
* @param {Function} func
|
||||||
|
* The function to throttle
|
||||||
|
* @param {number} wait
|
||||||
|
* The throttling period
|
||||||
|
* @param {Object} scope
|
||||||
|
* The scope to use for func
|
||||||
|
* @return {Function} The throttled function
|
||||||
|
*/
|
||||||
|
function throttle(func, wait, scope) {
|
||||||
|
let timer = null;
|
||||||
|
|
||||||
|
return function() {
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
let args = arguments;
|
||||||
|
timer = setTimeout(function() {
|
||||||
|
timer = null;
|
||||||
|
func.apply(scope, args);
|
||||||
|
}, wait);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.throttle = throttle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler that causes a blur on the target if the input has
|
||||||
|
* multiple CSS properties as the value.
|
||||||
|
*/
|
||||||
|
function blurOnMultipleProperties(e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
let props = parseDeclarations(e.target.value);
|
||||||
|
if (props.length > 1) {
|
||||||
|
e.target.blur();
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.blurOnMultipleProperties = blurOnMultipleProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log the provided error to the console and return a rejected Promise for
|
||||||
|
* this error.
|
||||||
|
*
|
||||||
|
* @param {Error} error
|
||||||
|
* The error to log
|
||||||
|
* @return {Promise} A rejected promise
|
||||||
|
*/
|
||||||
|
function promiseWarn(error) {
|
||||||
|
console.error(error);
|
||||||
|
return promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.promiseWarn = promiseWarn;
|
Загрузка…
Ссылка в новой задаче