mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge fx-team to m-c. a=merge
This commit is contained in:
commit
743b35bc83
@ -5311,8 +5311,8 @@ function setStyleDisabled(disabled) {
|
||||
|
||||
var LanguageDetectionListener = {
|
||||
init: function() {
|
||||
window.messageManager.addMessageListener("LanguageDetection:Result", msg => {
|
||||
Translation.languageDetected(msg.target, msg.data);
|
||||
window.messageManager.addMessageListener("Translation:DocumentState", msg => {
|
||||
Translation.documentStateReceived(msg.target, msg.data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -24,6 +24,11 @@ const DAILY_LAST_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC
|
||||
|
||||
|
||||
this.Translation = {
|
||||
STATE_OFFER: 0,
|
||||
STATE_TRANSLATING: 1,
|
||||
STATE_TRANSLATED: 2,
|
||||
STATE_ERROR: 3,
|
||||
|
||||
supportedSourceLanguages: ["en", "zh", "ja", "es", "de", "fr", "ru", "ar", "ko", "pt"],
|
||||
supportedTargetLanguages: ["en", "pl", "tr", "vi"],
|
||||
|
||||
@ -38,21 +43,33 @@ this.Translation = {
|
||||
return this._defaultTargetLanguage;
|
||||
},
|
||||
|
||||
languageDetected: function(aBrowser, aDetectedLanguage) {
|
||||
if (this.supportedSourceLanguages.indexOf(aDetectedLanguage) == -1 ||
|
||||
aDetectedLanguage == this.defaultTargetLanguage)
|
||||
return;
|
||||
documentStateReceived: function(aBrowser, aData) {
|
||||
if (aData.state == this.STATE_OFFER) {
|
||||
if (this.supportedSourceLanguages.indexOf(aData.detectedLanguage) == -1 ||
|
||||
aData.detectedLanguage == this.defaultTargetLanguage)
|
||||
return;
|
||||
|
||||
TranslationHealthReport.recordTranslationOpportunity(aDetectedLanguage);
|
||||
TranslationHealthReport.recordTranslationOpportunity(aData.detectedLanguage);
|
||||
}
|
||||
|
||||
if (!Services.prefs.getBoolPref(TRANSLATION_PREF_SHOWUI))
|
||||
return;
|
||||
|
||||
if (!aBrowser.translationUI)
|
||||
aBrowser.translationUI = new TranslationUI(aBrowser);
|
||||
let trUI = aBrowser.translationUI;
|
||||
|
||||
// Set all values before showing a new translation infobar.
|
||||
trUI._state = aData.state;
|
||||
trUI.detectedLanguage = aData.detectedLanguage;
|
||||
trUI.translatedFrom = aData.translatedFrom;
|
||||
trUI.translatedTo = aData.translatedTo;
|
||||
trUI.originalShown = aData.originalShown;
|
||||
|
||||
aBrowser.translationUI.showTranslationUI(aDetectedLanguage);
|
||||
trUI.showURLBarIcon();
|
||||
|
||||
if (trUI.shouldShowInfoBar(aBrowser.currentURI))
|
||||
trUI.showTranslationInfoBar();
|
||||
}
|
||||
};
|
||||
|
||||
@ -62,7 +79,6 @@ this.Translation = {
|
||||
* the infobar are:
|
||||
* - detectedLanguage, code of the language detected on the web page.
|
||||
* - state, the state in which the infobar should be displayed
|
||||
* - STATE_{OFFER,TRANSLATING,TRANSLATED,ERROR} constants.
|
||||
* - translatedFrom, if already translated, source language code.
|
||||
* - translatedTo, if already translated, target language code.
|
||||
* - translate, method starting the translation of the current page.
|
||||
@ -78,20 +94,15 @@ function TranslationUI(aBrowser) {
|
||||
}
|
||||
|
||||
TranslationUI.prototype = {
|
||||
STATE_OFFER: 0,
|
||||
STATE_TRANSLATING: 1,
|
||||
STATE_TRANSLATED: 2,
|
||||
STATE_ERROR: 3,
|
||||
|
||||
translate: function(aFrom, aTo) {
|
||||
if (aFrom == aTo ||
|
||||
(this.state == this.STATE_TRANSLATED &&
|
||||
(this.state == Translation.STATE_TRANSLATED &&
|
||||
this.translatedFrom == aFrom && this.translatedTo == aTo)) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = this.STATE_TRANSLATING;
|
||||
this.state = Translation.STATE_TRANSLATING;
|
||||
this.translatedFrom = aFrom;
|
||||
this.translatedTo = aTo;
|
||||
|
||||
@ -101,10 +112,10 @@ TranslationUI.prototype = {
|
||||
);
|
||||
},
|
||||
|
||||
showURLBarIcon: function(aTranslated) {
|
||||
showURLBarIcon: function() {
|
||||
let chromeWin = this.browser.ownerGlobal;
|
||||
let PopupNotifications = chromeWin.PopupNotifications;
|
||||
let removeId = aTranslated ? "translate" : "translated";
|
||||
let removeId = this.originalShown ? "translated" : "translate";
|
||||
let notification =
|
||||
PopupNotifications.getNotification(removeId, this.browser);
|
||||
if (notification)
|
||||
@ -121,7 +132,7 @@ TranslationUI.prototype = {
|
||||
return true;
|
||||
};
|
||||
|
||||
let addId = aTranslated ? "translated" : "translate";
|
||||
let addId = this.originalShown ? "translate" : "translated";
|
||||
PopupNotifications.show(this.browser, addId, null,
|
||||
addId + "-notification-icon", null, null,
|
||||
{dismissed: true, eventCallback: callback});
|
||||
@ -138,14 +149,14 @@ TranslationUI.prototype = {
|
||||
|
||||
originalShown: true,
|
||||
showOriginalContent: function() {
|
||||
this.showURLBarIcon();
|
||||
this.originalShown = true;
|
||||
this.showURLBarIcon();
|
||||
this.browser.messageManager.sendAsyncMessage("Translation:ShowOriginal");
|
||||
},
|
||||
|
||||
showTranslatedContent: function() {
|
||||
this.showURLBarIcon(true);
|
||||
this.originalShown = false;
|
||||
this.showURLBarIcon();
|
||||
this.browser.messageManager.sendAsyncMessage("Translation:ShowTranslation");
|
||||
},
|
||||
|
||||
@ -159,11 +170,11 @@ TranslationUI.prototype = {
|
||||
return notif;
|
||||
},
|
||||
|
||||
shouldShowInfoBar: function(aURI, aDetectedLanguage) {
|
||||
shouldShowInfoBar: function(aURI) {
|
||||
// Check if we should never show the infobar for this language.
|
||||
let neverForLangs =
|
||||
Services.prefs.getCharPref("browser.translation.neverForLanguages");
|
||||
if (neverForLangs.split(",").indexOf(aDetectedLanguage) != -1)
|
||||
if (neverForLangs.split(",").indexOf(this.detectedLanguage) != -1)
|
||||
return false;
|
||||
|
||||
// or if we should never show the infobar for this domain.
|
||||
@ -182,7 +193,7 @@ TranslationUI.prototype = {
|
||||
|
||||
this.showURLBarIcon();
|
||||
|
||||
if (!this.shouldShowInfoBar(this.browser.currentURI, aDetectedLanguage))
|
||||
if (!this.shouldShowInfoBar(this.browser.currentURI))
|
||||
return null;
|
||||
|
||||
return this.showTranslationInfoBar();
|
||||
@ -192,11 +203,11 @@ TranslationUI.prototype = {
|
||||
switch (msg.name) {
|
||||
case "Translation:Finished":
|
||||
if (msg.data.success) {
|
||||
this.state = this.STATE_TRANSLATED;
|
||||
this.showURLBarIcon(true);
|
||||
this.state = Translation.STATE_TRANSLATED;
|
||||
this.originalShown = false;
|
||||
this.showURLBarIcon();
|
||||
} else {
|
||||
this.state = this.STATE_ERROR;
|
||||
this.state = Translation.STATE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -12,11 +12,17 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector",
|
||||
"resource:///modules/translation/LanguageDetector.jsm");
|
||||
|
||||
const STATE_OFFER = 0;
|
||||
const STATE_TRANSLATED = 2;
|
||||
const STATE_ERROR = 3;
|
||||
|
||||
this.TranslationContentHandler = function(global, docShell) {
|
||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
||||
|
||||
global.addEventListener("pageshow", this);
|
||||
|
||||
global.addMessageListener("Translation:TranslateDocument", this);
|
||||
global.addMessageListener("Translation:ShowTranslation", this);
|
||||
global.addMessageListener("Translation:ShowOriginal", this);
|
||||
@ -24,6 +30,35 @@ this.TranslationContentHandler = function(global, docShell) {
|
||||
}
|
||||
|
||||
TranslationContentHandler.prototype = {
|
||||
handleEvent: function(aEvent) {
|
||||
// We are only listening to pageshow events.
|
||||
let target = aEvent.target;
|
||||
|
||||
// Only handle top-level frames.
|
||||
let win = target.defaultView;
|
||||
if (win.parent !== win)
|
||||
return;
|
||||
|
||||
let content = this.global.content;
|
||||
if (!content.detectedLanguage)
|
||||
return;
|
||||
|
||||
let data = {};
|
||||
let trDoc = content.translationDocument;
|
||||
if (trDoc) {
|
||||
data.state = trDoc.translationError ? STATE_ERROR : STATE_TRANSLATED;
|
||||
data.translatedFrom = trDoc.translatedFrom;
|
||||
data.translatedTo = trDoc.translatedTo;
|
||||
data.originalShown = trDoc.originalShown;
|
||||
} else {
|
||||
data.state = STATE_OFFER;
|
||||
data.originalShown = true;
|
||||
}
|
||||
data.detectedLanguage = content.detectedLanguage;
|
||||
|
||||
this.global.sendAsyncMessage("Translation:DocumentState", data);
|
||||
},
|
||||
|
||||
/* nsIWebProgressListener implementation */
|
||||
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (!aWebProgress.isTopLevel ||
|
||||
@ -35,10 +70,14 @@ TranslationContentHandler.prototype = {
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://"))
|
||||
return;
|
||||
|
||||
let content = this.global.content;
|
||||
if (content.detectedLanguage)
|
||||
return;
|
||||
|
||||
// Grab a 60k sample of text from the page.
|
||||
let encoder = Cc["@mozilla.org/layout/documentEncoder;1?type=text/plain"]
|
||||
.createInstance(Ci.nsIDocumentEncoder);
|
||||
encoder.init(this.global.content.document, "text/plain", encoder.SkipInvisibleContent);
|
||||
encoder.init(content.document, "text/plain", encoder.SkipInvisibleContent);
|
||||
let string = encoder.encodeToStringWithMaxLength(60 * 1024);
|
||||
|
||||
// Language detection isn't reliable on very short strings.
|
||||
@ -46,8 +85,17 @@ TranslationContentHandler.prototype = {
|
||||
return;
|
||||
|
||||
LanguageDetector.detectLanguage(string).then(result => {
|
||||
if (result.confident)
|
||||
this.global.sendAsyncMessage("LanguageDetection:Result", result.language);
|
||||
if (!result.confident)
|
||||
return;
|
||||
|
||||
content.detectedLanguage = result.language;
|
||||
|
||||
let data = {
|
||||
state: STATE_OFFER,
|
||||
originalShown: true,
|
||||
detectedLanguage: result.language
|
||||
};
|
||||
this.global.sendAsyncMessage("Translation:DocumentState", data);
|
||||
});
|
||||
},
|
||||
|
||||
@ -78,12 +126,17 @@ TranslationContentHandler.prototype = {
|
||||
msg.data.to);
|
||||
|
||||
this.global.content.translationDocument = translationDocument;
|
||||
translationDocument.translatedFrom = msg.data.from;
|
||||
translationDocument.translatedTo = msg.data.to;
|
||||
translationDocument.translationError = false;
|
||||
|
||||
bingTranslation.translate().then(
|
||||
success => {
|
||||
this.global.sendAsyncMessage("Translation:Finished", {success: true});
|
||||
translationDocument.showTranslation();
|
||||
},
|
||||
error => {
|
||||
translationDocument.translationError = true;
|
||||
this.global.sendAsyncMessage("Translation:Finished", {success: false});
|
||||
}
|
||||
);
|
||||
|
@ -31,6 +31,11 @@ this.TranslationDocument = function(document) {
|
||||
};
|
||||
|
||||
this.TranslationDocument.prototype = {
|
||||
translatedFrom: "",
|
||||
translatedTo: "",
|
||||
translationError: false,
|
||||
originalShown: true,
|
||||
|
||||
/**
|
||||
* Initializes the object and populates
|
||||
* the roots lists.
|
||||
@ -185,6 +190,7 @@ this.TranslationDocument.prototype = {
|
||||
* content.
|
||||
*/
|
||||
showTranslation: function() {
|
||||
this.originalShown = false;
|
||||
this._swapDocumentContent("translation");
|
||||
},
|
||||
|
||||
@ -193,6 +199,7 @@ this.TranslationDocument.prototype = {
|
||||
* content.
|
||||
*/
|
||||
showOriginal: function() {
|
||||
this.originalShown = true;
|
||||
this._swapDocumentContent("original");
|
||||
},
|
||||
|
||||
|
@ -104,7 +104,10 @@ let gTests = [
|
||||
desc: "never for language",
|
||||
run: function* checkNeverForLanguage() {
|
||||
// Show the infobar for example.com and fr.
|
||||
Translation.languageDetected(gBrowser.selectedBrowser, "fr");
|
||||
Translation.documentStateReceived(gBrowser.selectedBrowser,
|
||||
{state: Translation.STATE_OFFER,
|
||||
originalShown: true,
|
||||
detectedLanguage: "fr"});
|
||||
let notif = getInfoBar();
|
||||
ok(notif, "the infobar is visible");
|
||||
let ui = gBrowser.selectedBrowser.translationUI;
|
||||
@ -150,7 +153,10 @@ let gTests = [
|
||||
desc: "never for site",
|
||||
run: function* checkNeverForSite() {
|
||||
// Show the infobar for example.com and fr.
|
||||
Translation.languageDetected(gBrowser.selectedBrowser, "fr");
|
||||
Translation.documentStateReceived(gBrowser.selectedBrowser,
|
||||
{state: Translation.STATE_OFFER,
|
||||
originalShown: true,
|
||||
detectedLanguage: "fr"});
|
||||
let notif = getInfoBar();
|
||||
ok(notif, "the infobar is visible");
|
||||
let ui = gBrowser.selectedBrowser.translationUI;
|
||||
|
@ -34,7 +34,7 @@ function waitForCondition(condition, nextTest, errorMsg) {
|
||||
|
||||
var TranslationStub = {
|
||||
translate: function(aFrom, aTo) {
|
||||
this.state = this.STATE_TRANSLATING;
|
||||
this.state = Translation.STATE_TRANSLATING;
|
||||
this.translatedFrom = aFrom;
|
||||
this.translatedTo = aTo;
|
||||
},
|
||||
@ -45,20 +45,22 @@ var TranslationStub = {
|
||||
},
|
||||
|
||||
failTranslation: function() {
|
||||
this.state = this.STATE_ERROR;
|
||||
this.state = Translation.STATE_ERROR;
|
||||
this._reset();
|
||||
},
|
||||
|
||||
finishTranslation: function() {
|
||||
this.showTranslatedContent();
|
||||
this.state = this.STATE_TRANSLATED;
|
||||
this.state = Translation.STATE_TRANSLATED;
|
||||
this._reset();
|
||||
}
|
||||
};
|
||||
|
||||
function showTranslationUI(aDetectedLanguage) {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
Translation.languageDetected(browser, aDetectedLanguage);
|
||||
Translation.documentStateReceived(browser, {state: Translation.STATE_OFFER,
|
||||
originalShown: true,
|
||||
detectedLanguage: aDetectedLanguage});
|
||||
let ui = browser.translationUI;
|
||||
for (let name of ["translate", "_reset", "failTranslation", "finishTranslation"])
|
||||
ui[name] = TranslationStub[name];
|
||||
@ -100,13 +102,13 @@ function checkURLBarIcon(aExpectTranslated = false) {
|
||||
function run_tests(aFinishCallback) {
|
||||
info("Show an info bar saying the current page is in French");
|
||||
let notif = showTranslationUI("fr");
|
||||
is(notif.state, notif.translation.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif.state, Translation.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed");
|
||||
checkURLBarIcon();
|
||||
|
||||
info("Click the 'Translate' button");
|
||||
notif._getAnonElt("translate").click();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "fr", "from language correct");
|
||||
is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "from language correct");
|
||||
@ -114,12 +116,12 @@ function run_tests(aFinishCallback) {
|
||||
|
||||
info("Make the translation fail and check we are in the error state.");
|
||||
notif.translation.failTranslation();
|
||||
is(notif.state, notif.translation.STATE_ERROR, "infobar in the error state");
|
||||
is(notif.state, Translation.STATE_ERROR, "infobar in the error state");
|
||||
checkURLBarIcon();
|
||||
|
||||
info("Click the try again button");
|
||||
notif._getAnonElt("tryAgain").click();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "fr", "from language correct");
|
||||
is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "from language correct");
|
||||
@ -127,7 +129,7 @@ function run_tests(aFinishCallback) {
|
||||
|
||||
info("Make the translation succeed and check we are in the 'translated' state.");
|
||||
notif.translation.finishTranslation();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATED, "infobar in the translated state");
|
||||
is(notif.state, Translation.STATE_TRANSLATED, "infobar in the translated state");
|
||||
checkURLBarIcon(true);
|
||||
|
||||
info("Test 'Show original' / 'Show Translation' buttons.");
|
||||
@ -153,7 +155,7 @@ function run_tests(aFinishCallback) {
|
||||
let from = notif._getAnonElt("fromLanguage");
|
||||
from.value = "es";
|
||||
from.doCommand();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "es", "from language correct");
|
||||
is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "to language correct");
|
||||
@ -167,7 +169,7 @@ function run_tests(aFinishCallback) {
|
||||
let to = notif._getAnonElt("toLanguage");
|
||||
to.value = "pl";
|
||||
to.doCommand();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "es", "from language correct");
|
||||
is(notif.translation.translatedTo, "pl", "to language correct");
|
||||
@ -180,12 +182,12 @@ function run_tests(aFinishCallback) {
|
||||
|
||||
info("Reopen the info bar to check that it's possible to override the detected language.");
|
||||
notif = showTranslationUI("fr");
|
||||
is(notif.state, notif.translation.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif.state, Translation.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed");
|
||||
// Change the language and click 'Translate'
|
||||
notif._getAnonElt("detectedLanguage").value = "ja";
|
||||
notif._getAnonElt("translate").click();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "ja", "from language correct");
|
||||
notif.close();
|
||||
|
@ -127,7 +127,7 @@
|
||||
|
||||
let stateName;
|
||||
for (let name of ["OFFER", "TRANSLATING", "TRANSLATED", "ERROR"]) {
|
||||
if (this.translation["STATE_" + name] == val) {
|
||||
if (Translation["STATE_" + name] == val) {
|
||||
stateName = name.toLowerCase();
|
||||
break;
|
||||
}
|
||||
@ -188,7 +188,7 @@
|
||||
<method name="translate">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.state == this.translation.STATE_OFFER) {
|
||||
if (this.state == Translation.STATE_OFFER) {
|
||||
this._getAnonElt("fromLanguage").value =
|
||||
this._getAnonElt("detectedLanguage").value;
|
||||
this._getAnonElt("toLanguage").value =
|
||||
@ -235,7 +235,7 @@
|
||||
<![CDATA[
|
||||
// Get the source language name.
|
||||
let lang;
|
||||
if (this.state == this.translation.STATE_OFFER)
|
||||
if (this.state == Translation.STATE_OFFER)
|
||||
lang = this._getAnonElt("detectedLanguage").value;
|
||||
else
|
||||
lang = this._getAnonElt("fromLanguage").value;
|
||||
|
@ -118,3 +118,17 @@ function spawnTest() {
|
||||
yield helpers.closeToolbar(options);
|
||||
yield helpers.closeTab(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a regular expression that matches a string. This greatly simplifies
|
||||
* matching and debugging long strings.
|
||||
*
|
||||
* @param {String} text
|
||||
* Text to convert
|
||||
* @return {RegExp}
|
||||
* Regular expression matching text
|
||||
*/
|
||||
function getRegexForString(str) {
|
||||
str = str.replace(/(\.|\\|\/|\(|\)|\[|\]|\*|\+|\?|\$|\^|\|)/g, "\\$1");
|
||||
return new RegExp(str);
|
||||
}
|
||||
|
@ -14,53 +14,7 @@ function testTask() {
|
||||
let options = yield helpers.openTab("about:blank");
|
||||
yield helpers.openToolbar(options);
|
||||
|
||||
let deferred = promise.defer();
|
||||
let scratchpadWin = null;
|
||||
let scratchpad = null;
|
||||
|
||||
let observer = {
|
||||
onReady: function() {
|
||||
scratchpad.removeObserver(observer);
|
||||
|
||||
let result = scratchpad.getText();
|
||||
result = result.replace(/[\r\n]]*/g, "\n");
|
||||
let correct = "function somefunc() {\n" +
|
||||
" if (true) // Some comment\n" +
|
||||
" doSomething();\n" +
|
||||
" for (let n = 0; n < 500; n++) {\n" +
|
||||
" if (n % 2 == 1) {\n" +
|
||||
" console.log(n);\n" +
|
||||
" console.log(n + 1);\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
is(result, correct, "JS has been correctly prettified");
|
||||
|
||||
if (scratchpadWin) {
|
||||
scratchpadWin.close();
|
||||
scratchpadWin = null;
|
||||
}
|
||||
deferred.resolve();
|
||||
},
|
||||
};
|
||||
|
||||
let onLoad = function GDT_onLoad() {
|
||||
scratchpadWin.removeEventListener("load", onLoad, false);
|
||||
scratchpad = scratchpadWin.Scratchpad;
|
||||
|
||||
scratchpad.addObserver(observer);
|
||||
};
|
||||
|
||||
let onNotify = function(subject, topic, data) {
|
||||
if (topic == "domwindowopened") {
|
||||
Services.ww.unregisterNotification(onNotify);
|
||||
|
||||
scratchpadWin = subject.QueryInterface(Ci.nsIDOMWindow);
|
||||
scratchpadWin.addEventListener("load", onLoad, false);
|
||||
}
|
||||
};
|
||||
|
||||
Services.ww.registerNotification(onNotify);
|
||||
let notifyPromise = wwNotifyOnce();
|
||||
|
||||
helpers.audit(options, [
|
||||
{
|
||||
@ -74,14 +28,73 @@ function testTask() {
|
||||
},
|
||||
{
|
||||
setup: 'jsb ' + TEST_URI,
|
||||
// Should result in a new window, which should fire onReady (eventually)
|
||||
exec: {
|
||||
}
|
||||
// Should result in a new scratchpad window
|
||||
exec: { }
|
||||
}
|
||||
]);
|
||||
|
||||
yield deferred.promise;
|
||||
let { subject } = yield notifyPromise;
|
||||
let scratchpadWin = subject.QueryInterface(Ci.nsIDOMWindow);
|
||||
yield helpers.listenOnce(scratchpadWin, "load");
|
||||
|
||||
let scratchpad = scratchpadWin.Scratchpad;
|
||||
|
||||
yield observeOnce(scratchpad);
|
||||
|
||||
let result = scratchpad.getText();
|
||||
result = result.replace(/[\r\n]]*/g, "\n");
|
||||
let correct = "function somefunc() {\n" +
|
||||
" if (true) // Some comment\n" +
|
||||
" doSomething();\n" +
|
||||
" for (let n = 0; n < 500; n++) {\n" +
|
||||
" if (n % 2 == 1) {\n" +
|
||||
" console.log(n);\n" +
|
||||
" console.log(n + 1);\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
is(result, correct, "JS has been correctly prettified");
|
||||
|
||||
if (scratchpadWin) {
|
||||
scratchpadWin.close();
|
||||
scratchpadWin = null;
|
||||
}
|
||||
|
||||
yield helpers.closeToolbar(options);
|
||||
yield helpers.closeTab(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper for calling Services.ww.[un]registerNotification using promises.
|
||||
* @return a promise that resolves when the notification service first notifies
|
||||
* with topic == "domwindowopened".
|
||||
* The value of the promise is { subject: subject, topic: topic, data: data }
|
||||
*/
|
||||
function wwNotifyOnce() {
|
||||
return new Promise(resolve => {
|
||||
let onNotify = (subject, topic, data) => {
|
||||
if (topic == "domwindowopened") {
|
||||
Services.ww.unregisterNotification(onNotify);
|
||||
resolve({ subject: subject, topic: topic, data: data });
|
||||
}
|
||||
};
|
||||
|
||||
Services.ww.registerNotification(onNotify);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* YET ANOTHER WRAPPER for a place where we are using events as poor-man's
|
||||
* promises. Perhaps this should be promoted to scratchpad?
|
||||
*/
|
||||
function observeOnce(scratchpad) {
|
||||
return new Promise(resolve => {
|
||||
let observer = {
|
||||
onReady: function() {
|
||||
scratchpad.removeObserver(observer);
|
||||
resolve();
|
||||
},
|
||||
};
|
||||
scratchpad.addObserver(observer);
|
||||
});
|
||||
}
|
||||
|
@ -322,11 +322,9 @@ function spawnTest() {
|
||||
}
|
||||
},
|
||||
post: function() {
|
||||
let deferred = promise.defer();
|
||||
executeSoon(function() {
|
||||
deferred.resolve();
|
||||
return new Promise(resolve => {
|
||||
executeSoon(resolve);
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -166,18 +166,16 @@ function addTabWithToolbarRunTests(win) {
|
||||
}
|
||||
|
||||
function addWindow(windowOptions) {
|
||||
let deferred = promise.defer();
|
||||
return new Promise(resolve => {
|
||||
let win = OpenBrowserWindow(windowOptions);
|
||||
|
||||
let win = OpenBrowserWindow(windowOptions);
|
||||
|
||||
// This feels hacky, we should refactor it
|
||||
whenDelayedStartupFinished(win, function() {
|
||||
// Would like to get rid of this executeSoon, but without it the url
|
||||
// (TEST_URI) provided in addTabWithToolbarRunTests hasn't loaded
|
||||
executeSoon(function() {
|
||||
deferred.resolve(win);
|
||||
// This feels hacky, we should refactor it
|
||||
whenDelayedStartupFinished(win, () => {
|
||||
// Would like to get rid of this executeSoon, but without it the url
|
||||
// (TEST_URI) provided in addTabWithToolbarRunTests hasn't loaded
|
||||
executeSoon(() => {
|
||||
resolve(win);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ function test() {
|
||||
|
||||
// var assert = require('../testharness/assert');
|
||||
|
||||
var promise = require('gcli/util/promise');
|
||||
var Promise = require('gcli/util/promise').Promise;
|
||||
var util = require('gcli/util/util');
|
||||
var resource = require('gcli/types/resource');
|
||||
var Status = require('gcli/types/types').Status;
|
||||
@ -162,7 +162,7 @@ function checkPrediction(res, prediction) {
|
||||
assert.is(typeof value.loadContents, 'function', 'resource for ' + name);
|
||||
assert.is(typeof value.element, 'object', 'resource for ' + name);
|
||||
|
||||
return promise.resolve(res.stringify(value, context)).then(function(strung) {
|
||||
return Promise.resolve(res.stringify(value, context)).then(function(strung) {
|
||||
assert.is(strung, name, 'stringify for ' + name);
|
||||
});
|
||||
});
|
||||
|
@ -42,7 +42,7 @@ function test() {
|
||||
|
||||
// var assert = require('../testharness/assert');
|
||||
var util = require('gcli/util/util');
|
||||
var promise = require('gcli/util/promise');
|
||||
var Promise = require('gcli/util/promise').Promise;
|
||||
var nodetype = require('gcli/types/node');
|
||||
|
||||
exports.setup = function(options) {
|
||||
@ -79,7 +79,7 @@ function forEachType(options, typeSpec, callback) {
|
||||
|
||||
var type = types.createType(typeSpec);
|
||||
var reply = callback(type);
|
||||
return promise.resolve(reply).then(function(value) {
|
||||
return Promise.resolve(reply).then(function(value) {
|
||||
// Clean up
|
||||
delete typeSpec.name;
|
||||
delete typeSpec.requisition;
|
||||
@ -125,7 +125,7 @@ exports.testNullDefault = function(options) {
|
||||
|
||||
return forEachType(options, { defaultValue: null }, function(type) {
|
||||
var reply = type.stringify(null, context);
|
||||
return promise.resolve(reply).then(function(str) {
|
||||
return Promise.resolve(reply).then(function(str) {
|
||||
assert.is(str, '', 'stringify(null) for ' + type.name);
|
||||
});
|
||||
});
|
||||
|
@ -27,20 +27,6 @@ function whenDelayedStartupFinished(aWindow, aCallback) {
|
||||
}, "browser-delayed-startup-finished", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a regular expression that matches a string. This greatly simplifies
|
||||
* matching and debugging long strings.
|
||||
*
|
||||
* @param {String} text
|
||||
* Text to convert
|
||||
* @return {RegExp}
|
||||
* Regular expression matching text
|
||||
*/
|
||||
function getRegexForString(str) {
|
||||
str = str.replace(/(\.|\\|\/|\(|\)|\[|\]|\*|\+|\?|\$|\^|\|)/g, "\\$1");
|
||||
return new RegExp(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force GC on shutdown, because it seems that GCLI can outrun the garbage
|
||||
* collector in some situations, which causes test failures in later tests
|
||||
@ -53,5 +39,5 @@ registerCleanupFunction(function tearDown() {
|
||||
});
|
||||
|
||||
function asyncTest(generator) {
|
||||
return () => Task.spawn(generator).then(null, ok.bind(null, false)).then(finish);
|
||||
return () => Task.spawn(generator).catch(ok.bind(null, false)).then(finish);
|
||||
}
|
||||
|
@ -18,16 +18,16 @@
|
||||
|
||||
// A copy of this code exists in firefox mochitests. They should be kept
|
||||
// in sync. Hence the exports synonym for non AMD contexts.
|
||||
this.EXPORTED_SYMBOLS = [ 'helpers' ];
|
||||
var { helpers, gcli, assert } = (function() {
|
||||
|
||||
var helpers = {};
|
||||
this.helpers = helpers;
|
||||
|
||||
var TargetFactory = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.TargetFactory;
|
||||
var require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
||||
var assert = { ok: ok, is: is, log: info };
|
||||
var util = require('gcli/util/util');
|
||||
var promise = require('gcli/util/promise');
|
||||
var Promise = require('gcli/util/promise').Promise;
|
||||
var cli = require('gcli/cli');
|
||||
var KeyEvent = require('gcli/util/util').KeyEvent;
|
||||
var gcli = require('gcli/index');
|
||||
@ -137,7 +137,7 @@ helpers.addTab = function(url, callback, options) {
|
||||
|
||||
var reply = callback.call(null, options);
|
||||
|
||||
return promise.resolve(reply).then(null, function(error) {
|
||||
return Promise.resolve(reply).then(null, function(error) {
|
||||
ok(false, error);
|
||||
}).then(function() {
|
||||
tabbrowser.removeTab(options.tab);
|
||||
@ -206,7 +206,7 @@ helpers.closeTab = function(options) {
|
||||
delete options.chromeWindow;
|
||||
delete options.isFirefox;
|
||||
|
||||
return promise.resolve(undefined);
|
||||
return Promise.resolve(undefined);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -283,13 +283,13 @@ helpers.handleError = function(ex) {
|
||||
* @return A promise resolved with the event object when the event first happens
|
||||
*/
|
||||
helpers.listenOnce = function(element, event, useCapture) {
|
||||
var deferred = promise.defer();
|
||||
var onEvent = function(ev) {
|
||||
element.removeEventListener(event, onEvent, useCapture);
|
||||
deferred.resolve(ev);
|
||||
};
|
||||
element.addEventListener(event, onEvent, useCapture);
|
||||
return deferred.promise;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var onEvent = function(ev) {
|
||||
element.removeEventListener(event, onEvent, useCapture);
|
||||
resolve(ev);
|
||||
};
|
||||
element.addEventListener(event, onEvent, useCapture);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -302,13 +302,13 @@ helpers.listenOnce = function(element, event, useCapture) {
|
||||
* function other parameters are dropped.
|
||||
*/
|
||||
helpers.observeOnce = function(topic, ownsWeak=false) {
|
||||
let deferred = promise.defer();
|
||||
let resolver = function(subject) {
|
||||
Services.obs.removeObserver(resolver, topic);
|
||||
deferred.resolve(subject);
|
||||
};
|
||||
Services.obs.addObserver(resolver, topic, ownsWeak);
|
||||
return deferred.promise;
|
||||
return new Promise(function(resolve, reject) {
|
||||
let resolver = function(subject) {
|
||||
Services.obs.removeObserver(resolver, topic);
|
||||
resolve(subject);
|
||||
};
|
||||
Services.obs.addObserver(resolver, topic, ownsWeak);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -317,22 +317,14 @@ helpers.observeOnce = function(topic, ownsWeak=false) {
|
||||
*/
|
||||
helpers.promiseify = function(functionWithLastParamCallback, scope) {
|
||||
return function() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let args = [].slice.call(arguments);
|
||||
args.push(function(callbackParam) {
|
||||
deferred.resolve(callbackParam);
|
||||
});
|
||||
|
||||
try {
|
||||
return new Promise(resolve => {
|
||||
args.push((...results) => {
|
||||
resolve(results.length > 1 ? results : results[0]);
|
||||
});
|
||||
functionWithLastParamCallback.apply(scope, args);
|
||||
}
|
||||
catch (ex) {
|
||||
deferred.resolve(ex);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@ -353,7 +345,7 @@ helpers.addTabWithToolbar = function(url, callback, options) {
|
||||
|
||||
var reply = callback.call(null, innerOptions);
|
||||
|
||||
return promise.resolve(reply).then(null, function(error) {
|
||||
return Promise.resolve(reply).then(null, function(error) {
|
||||
ok(false, error);
|
||||
console.error(error);
|
||||
}).then(function() {
|
||||
@ -389,8 +381,8 @@ helpers.runTests = function(options, tests) {
|
||||
|
||||
info("SETUP");
|
||||
var setupDone = (tests.setup != null) ?
|
||||
promise.resolve(tests.setup(options)) :
|
||||
promise.resolve();
|
||||
Promise.resolve(tests.setup(options)) :
|
||||
Promise.resolve();
|
||||
|
||||
var testDone = setupDone.then(function() {
|
||||
return util.promiseEach(testNames, function(testName) {
|
||||
@ -399,13 +391,13 @@ helpers.runTests = function(options, tests) {
|
||||
|
||||
if (typeof action === "function") {
|
||||
var reply = action.call(tests, options);
|
||||
return promise.resolve(reply);
|
||||
return Promise.resolve(reply);
|
||||
}
|
||||
else if (Array.isArray(action)) {
|
||||
return helpers.audit(options, action);
|
||||
}
|
||||
|
||||
return promise.reject("test action '" + testName +
|
||||
return Promise.reject("test action '" + testName +
|
||||
"' is not a function or helpers.audit() object");
|
||||
});
|
||||
}, recover);
|
||||
@ -413,8 +405,8 @@ helpers.runTests = function(options, tests) {
|
||||
return testDone.then(function() {
|
||||
info("SHUTDOWN");
|
||||
return (tests.shutdown != null) ?
|
||||
promise.resolve(tests.shutdown(options)) :
|
||||
promise.resolve();
|
||||
Promise.resolve(tests.shutdown(options)) :
|
||||
Promise.resolve();
|
||||
}, recover);
|
||||
};
|
||||
|
||||
@ -548,7 +540,7 @@ helpers._createDebugCheck = function(options) {
|
||||
var hintsPromise = helpers._actual.hints(options);
|
||||
var predictionsPromise = helpers._actual.predictions(options);
|
||||
|
||||
return promise.all(hintsPromise, predictionsPromise).then(function(values) {
|
||||
return Promise.all(hintsPromise, predictionsPromise).then(function(values) {
|
||||
var hints = values[0];
|
||||
var predictions = values[1];
|
||||
var output = '';
|
||||
@ -761,7 +753,7 @@ helpers._check = function(options, name, checks) {
|
||||
});
|
||||
|
||||
if (checks == null) {
|
||||
return promise.resolve();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
var outstanding = [];
|
||||
@ -916,7 +908,7 @@ helpers._check = function(options, name, checks) {
|
||||
});
|
||||
}
|
||||
|
||||
return promise.all(outstanding).then(function() {
|
||||
return Promise.all(outstanding).then(function() {
|
||||
// Ensure the promise resolves to nothing
|
||||
return undefined;
|
||||
});
|
||||
@ -932,7 +924,7 @@ helpers._check = function(options, name, checks) {
|
||||
helpers._exec = function(options, name, expected) {
|
||||
var requisition = options.requisition;
|
||||
if (expected == null) {
|
||||
return promise.resolve({});
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
var origLogErrors = cli.logErrors;
|
||||
@ -1016,7 +1008,7 @@ helpers._exec = function(options, name, expected) {
|
||||
if (expected.error) {
|
||||
cli.logErrors = origLogErrors;
|
||||
}
|
||||
return promise.resolve({});
|
||||
return Promise.resolve({});
|
||||
}
|
||||
};
|
||||
|
||||
@ -1029,10 +1021,10 @@ helpers._setup = function(options, name, audit) {
|
||||
}
|
||||
|
||||
if (typeof audit.setup === 'function') {
|
||||
return promise.resolve(audit.setup.call(audit));
|
||||
return Promise.resolve(audit.setup.call(audit));
|
||||
}
|
||||
|
||||
return promise.reject('\'setup\' property must be a string or a function. Is ' + audit.setup);
|
||||
return Promise.reject('\'setup\' property must be a string or a function. Is ' + audit.setup);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1040,9 +1032,9 @@ helpers._setup = function(options, name, audit) {
|
||||
*/
|
||||
helpers._post = function(name, audit, data) {
|
||||
if (typeof audit.post === 'function') {
|
||||
return promise.resolve(audit.post.call(audit, data.output, data.text));
|
||||
return Promise.resolve(audit.post.call(audit, data.output, data.text));
|
||||
}
|
||||
return promise.resolve(audit.post);
|
||||
return Promise.resolve(audit.post);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1178,7 +1170,7 @@ helpers.audit = function(options, audits) {
|
||||
'due to ' + audit.skipRemainingIf.name :
|
||||
'';
|
||||
assert.log('Skipped ' + name + ' ' + skipReason);
|
||||
return promise.resolve(undefined);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1189,13 +1181,13 @@ helpers.audit = function(options, audits) {
|
||||
if (skip) {
|
||||
var reason = audit.skipIf.name ? 'due to ' + audit.skipIf.name : '';
|
||||
assert.log('Skipped ' + name + ' ' + reason);
|
||||
return promise.resolve(undefined);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
if (skipReason != null) {
|
||||
assert.log('Skipped ' + name + ' ' + skipReason);
|
||||
return promise.resolve(undefined);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
var start = new Date().getTime();
|
||||
@ -1210,7 +1202,7 @@ helpers.audit = function(options, audits) {
|
||||
// a key-sequence (i.e. targeting terminal.js) when there is no terminal
|
||||
if (chunkLen === -1) {
|
||||
assert.log('Skipped ' + name + ' ' + skipReason);
|
||||
return promise.resolve(undefined);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
if (assert.currentTest) {
|
||||
@ -1269,3 +1261,6 @@ function log(message) {
|
||||
console.log(message);
|
||||
}
|
||||
}
|
||||
|
||||
return { helpers: helpers, gcli: gcli, assert: assert };
|
||||
})();
|
||||
|
@ -23,6 +23,7 @@
|
||||
// <INJECTED SOURCE:END>
|
||||
|
||||
|
||||
var Promise = require('gcli/util/promise').Promise;
|
||||
var mockCommands = {};
|
||||
|
||||
// We use an alias for exports here because this module is used in Firefox
|
||||
@ -506,29 +507,28 @@ mockCommands.items = [
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
var deferred;
|
||||
if (args.method === 'reject') {
|
||||
deferred = context.defer();
|
||||
setTimeout(function() {
|
||||
deferred.reject('rejected promise');
|
||||
}, 10);
|
||||
return deferred.promise;
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeout(function() {
|
||||
reject('rejected promise');
|
||||
}, 10);
|
||||
});
|
||||
}
|
||||
|
||||
if (args.method === 'rejecttyped') {
|
||||
deferred = context.defer();
|
||||
setTimeout(function() {
|
||||
deferred.reject(context.typedData('number', 54));
|
||||
}, 10);
|
||||
return deferred.promise;
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeout(function() {
|
||||
reject(context.typedData('number', 54));
|
||||
}, 10);
|
||||
});
|
||||
}
|
||||
|
||||
if (args.method === 'throwinpromise') {
|
||||
deferred = context.defer();
|
||||
setTimeout(function() {
|
||||
deferred.resolve('should be lost');
|
||||
}, 10);
|
||||
return deferred.promise.then(function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeout(function() {
|
||||
resolve('should be lost');
|
||||
}, 10);
|
||||
}).then(function() {
|
||||
var t = null;
|
||||
return t.foo;
|
||||
});
|
||||
@ -655,17 +655,14 @@ mockCommands.items = [
|
||||
type: {
|
||||
name: 'selection',
|
||||
data: function(context) {
|
||||
var deferred = context.defer();
|
||||
|
||||
var resolve = function() {
|
||||
deferred.resolve([
|
||||
'Shalom', 'Namasté', 'Hallo', 'Dydd-da',
|
||||
'Chào', 'Hej', 'Saluton', 'Sawubona'
|
||||
]);
|
||||
};
|
||||
|
||||
setTimeout(resolve, 10);
|
||||
return deferred.promise;
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeout(function() {
|
||||
resolve([
|
||||
'Shalom', 'Namasté', 'Hallo', 'Dydd-da',
|
||||
'Chào', 'Hej', 'Saluton', 'Sawubona'
|
||||
]);
|
||||
}, 10);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -430,6 +430,7 @@ let DebuggerController = {
|
||||
*/
|
||||
function ThreadState() {
|
||||
this._update = this._update.bind(this);
|
||||
this.interruptedByResumeButton = false;
|
||||
}
|
||||
|
||||
ThreadState.prototype = {
|
||||
@ -472,14 +473,17 @@ ThreadState.prototype = {
|
||||
/**
|
||||
* Update the UI after a thread state change.
|
||||
*/
|
||||
_update: function(aEvent) {
|
||||
// Ignore "interrupted" events, which are generated by the slow script
|
||||
// dialog and internal events such as setting breakpoints, to avoid UI
|
||||
// flicker.
|
||||
if (aEvent == "interrupted") {
|
||||
_update: function(aEvent, aPacket) {
|
||||
// Ignore "interrupted" events, to avoid UI flicker. These are generated
|
||||
// by the slow script dialog and internal events such as setting
|
||||
// breakpoints. Pressing the resume button does need to be shown, though.
|
||||
if (aEvent == "paused" &&
|
||||
aPacket.why.type == "interrupted" &&
|
||||
!this.interruptedByResumeButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.interruptedByResumeButton = false;
|
||||
DebuggerView.Toolbar.toggleResumeButtonState(this.activeThread.state);
|
||||
|
||||
if (gTarget && (aEvent == "paused" || aEvent == "resumed")) {
|
||||
|
@ -129,6 +129,7 @@ ToolbarView.prototype = {
|
||||
DebuggerController.StackFrames.currentFrameDepth = -1;
|
||||
DebuggerController.activeThread.resume(warn);
|
||||
} else {
|
||||
DebuggerController.ThreadState.interruptedByResumeButton = true;
|
||||
DebuggerController.activeThread.interrupt();
|
||||
}
|
||||
},
|
||||
|
@ -156,6 +156,7 @@ skip-if = true # Bug 933950 (leaky test)
|
||||
[browser_dbg_host-layout.js]
|
||||
[browser_dbg_iframes.js]
|
||||
[browser_dbg_instruments-pane-collapse.js]
|
||||
[browser_dbg_interrupts.js]
|
||||
[browser_dbg_listaddons.js]
|
||||
[browser_dbg_listtabs-01.js]
|
||||
[browser_dbg_listtabs-02.js]
|
||||
|
86
browser/devtools/debugger/test/browser_dbg_interrupts.js
Normal file
86
browser/devtools/debugger/test/browser_dbg_interrupts.js
Normal file
@ -0,0 +1,86 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test if the breakpoints toggle button works as advertised.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
|
||||
|
||||
function test() {
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gSources, gBreakpoints, gTarget, gResumeButton, gResumeKey, gThreadClient;
|
||||
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
|
||||
gTarget = gDebugger.gTarget;
|
||||
gThreadClient = gDebugger.gThreadClient;
|
||||
gResumeButton = gDebugger.document.getElementById("resume");
|
||||
gResumeKey = gDebugger.document.getElementById("resumeKey");
|
||||
|
||||
waitForSourceShown(gPanel, "-01.js")
|
||||
.then(() => { gTarget.on("thread-paused", failOnPause); })
|
||||
.then(addBreakpoints)
|
||||
.then(() => { gTarget.off("thread-paused", failOnPause); })
|
||||
.then(testResumeButton)
|
||||
.then(testResumeKeyboard)
|
||||
.then(() => closeDebuggerAndFinish(gPanel))
|
||||
.then(null, aError => {
|
||||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
});
|
||||
|
||||
function failOnPause() {
|
||||
ok (false, "A pause was sent, but it shouldn't have been");
|
||||
}
|
||||
|
||||
function addBreakpoints() {
|
||||
return promise.resolve(null)
|
||||
.then(() => gPanel.addBreakpoint({ url: gSources.values[0], line: 5 }))
|
||||
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 6 }))
|
||||
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 7 }))
|
||||
.then(() => ensureThreadClientState(gPanel, "resumed"));
|
||||
}
|
||||
|
||||
function resume() {
|
||||
let onceResumed = gTarget.once("thread-resumed");
|
||||
gThreadClient.resume();
|
||||
return onceResumed;
|
||||
}
|
||||
|
||||
function testResumeButton() {
|
||||
info ("Pressing the resume button, expecting a thread-paused");
|
||||
|
||||
ok (!gResumeButton.hasAttribute("checked"), "Resume button is not checked");
|
||||
let oncePaused = gTarget.once("thread-paused");
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, gResumeButton, gDebugger);
|
||||
|
||||
return oncePaused
|
||||
.then(() => {
|
||||
is (gResumeButton.getAttribute("checked"), "true", "Resume button is checked");
|
||||
})
|
||||
.then(() => gThreadClient.resume())
|
||||
.then(() => ensureThreadClientState(gPanel, "resumed"))
|
||||
}
|
||||
|
||||
function testResumeKeyboard() {
|
||||
let key = gResumeKey.getAttribute("keycode");
|
||||
info ("Triggering a pause with keyboard (" + key + "), expecting a thread-paused");
|
||||
|
||||
ok (!gResumeButton.hasAttribute("checked"), "Resume button is not checked");
|
||||
let oncePaused = gTarget.once("thread-paused");
|
||||
EventUtils.synthesizeKey(key, { }, gDebugger);
|
||||
|
||||
return oncePaused
|
||||
.then(() => {
|
||||
is (gResumeButton.getAttribute("checked"), "true", "Resume button is checked");
|
||||
})
|
||||
.then(() => gThreadClient.resume())
|
||||
.then(() => ensureThreadClientState(gPanel, "resumed"))
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", false);
|
||||
|
||||
let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
let { Promise: promise } = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let { require } = devtools;
|
||||
|
@ -6,6 +6,7 @@ const TEST_HOST = 'mochi.test:8888';
|
||||
|
||||
let { devtools } = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const { Eyedropper, EyedropperManager } = devtools.require("devtools/eyedropper/eyedropper");
|
||||
const { Promise: promise } = devtools.require("resource://gre/modules/Promise.jsm");
|
||||
|
||||
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
|
||||
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
|
||||
|
@ -245,7 +245,7 @@ Toolbox.prototype = {
|
||||
this._buildDockButtons();
|
||||
this._buildOptions();
|
||||
this._buildTabs();
|
||||
this._buildButtons();
|
||||
let buttonsPromise = this._buildButtons();
|
||||
this._addKeysToWindow();
|
||||
this._addReloadKeys();
|
||||
this._addToolSwitchingKeys();
|
||||
@ -255,8 +255,10 @@ Toolbox.prototype = {
|
||||
this._telemetry.toolOpened("toolbox");
|
||||
|
||||
this.selectTool(this._defaultToolId).then(panel => {
|
||||
this.emit("ready");
|
||||
deferred.resolve();
|
||||
buttonsPromise.then(() => {
|
||||
this.emit("ready");
|
||||
deferred.resolve();
|
||||
}, deferred.reject);
|
||||
});
|
||||
};
|
||||
|
||||
@ -546,17 +548,20 @@ Toolbox.prototype = {
|
||||
}
|
||||
|
||||
if (!this.target.isLocalTab) {
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let spec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
|
||||
let environment = CommandUtils.createEnvironment(this, '_target');
|
||||
this._requisition = CommandUtils.createRequisition(environment);
|
||||
let buttons = CommandUtils.createButtons(spec, this._target,
|
||||
this.doc, this._requisition);
|
||||
let container = this.doc.getElementById("toolbox-buttons");
|
||||
buttons.forEach(container.appendChild.bind(container));
|
||||
this.setToolboxButtonsVisibility();
|
||||
return CommandUtils.createRequisition(environment).then(requisition => {
|
||||
this._requisition = requisition;
|
||||
return CommandUtils.createButtons(spec, this.target, this.doc,
|
||||
requisition).then(buttons => {
|
||||
let container = this.doc.getElementById("toolbox-buttons");
|
||||
buttons.forEach(container.appendChild.bind(container));
|
||||
this.setToolboxButtonsVisibility();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -13,6 +13,9 @@ const Cc = Components.classes;
|
||||
|
||||
//Services.prefs.setBoolPref("devtools.dump.emit", true);
|
||||
|
||||
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tempScope);
|
||||
let LayoutHelpers = tempScope.LayoutHelpers;
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
|
||||
let {devtools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let TargetFactory = devtools.TargetFactory;
|
||||
|
||||
|
@ -41,10 +41,17 @@ const Telemetry = require("devtools/shared/telemetry");
|
||||
|
||||
// This lazy getter is needed to prevent a require loop
|
||||
XPCOMUtils.defineLazyGetter(this, "gcli", () => {
|
||||
let gcli = require("gcli/index");
|
||||
require("devtools/commandline/commands-index");
|
||||
gcli.load();
|
||||
return gcli;
|
||||
try {
|
||||
require("devtools/commandline/commands-index");
|
||||
return require("gcli/index");
|
||||
}
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "util", () => {
|
||||
return require("gcli/util/util");
|
||||
});
|
||||
|
||||
Object.defineProperty(this, "ConsoleServiceListener", {
|
||||
@ -65,9 +72,10 @@ let CommandUtils = {
|
||||
* Utility to ensure that things are loaded in the correct order
|
||||
*/
|
||||
createRequisition: function(environment) {
|
||||
let temp = gcli.createDisplay; // Ensure GCLI is loaded
|
||||
let Requisition = require("gcli/cli").Requisition
|
||||
return new Requisition({ environment: environment });
|
||||
return gcli.load().then(() => {
|
||||
let Requisition = require("gcli/cli").Requisition
|
||||
return new Requisition({ environment: environment });
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -80,36 +88,23 @@ let CommandUtils = {
|
||||
},
|
||||
|
||||
/**
|
||||
* A toolbarSpec is an array of buttonSpecs. A buttonSpec is an array of
|
||||
* strings each of which is a GCLI command (including args if needed).
|
||||
* A toolbarSpec is an array of strings each of which is a GCLI command.
|
||||
*
|
||||
* Warning: this method uses the unload event of the window that owns the
|
||||
* buttons that are of type checkbox. this means that we don't properly
|
||||
* unregister event handlers until the window is destroyed.
|
||||
*/
|
||||
createButtons: function(toolbarSpec, target, document, requisition) {
|
||||
let reply = [];
|
||||
|
||||
toolbarSpec.forEach(function(buttonSpec) {
|
||||
let button = document.createElement("toolbarbutton");
|
||||
reply.push(button);
|
||||
|
||||
if (typeof buttonSpec == "string") {
|
||||
buttonSpec = { typed: buttonSpec };
|
||||
}
|
||||
return util.promiseEach(toolbarSpec, typed => {
|
||||
// Ask GCLI to parse the typed string (doesn't execute it)
|
||||
requisition.update(buttonSpec.typed);
|
||||
return requisition.update(typed).then(() => {
|
||||
let button = document.createElement("toolbarbutton");
|
||||
|
||||
// Ignore invalid commands
|
||||
let command = requisition.commandAssignment.value;
|
||||
if (command == null) {
|
||||
// TODO: Have a broken icon
|
||||
// button.icon = 'Broken';
|
||||
button.setAttribute("label", "X");
|
||||
button.setAttribute("tooltip", "Unknown command: " + buttonSpec.typed);
|
||||
button.setAttribute("disabled", "true");
|
||||
}
|
||||
else {
|
||||
// Ignore invalid commands
|
||||
let command = requisition.commandAssignment.value;
|
||||
if (command == null) {
|
||||
throw new Error("No command '" + typed + "'");
|
||||
}
|
||||
if (command.buttonId != null) {
|
||||
button.id = command.buttonId;
|
||||
}
|
||||
@ -123,22 +118,14 @@ let CommandUtils = {
|
||||
button.setAttribute("tooltiptext", command.description);
|
||||
}
|
||||
|
||||
button.addEventListener("click", function() {
|
||||
requisition.update(buttonSpec.typed);
|
||||
//if (requisition.getStatus() == Status.VALID) {
|
||||
requisition.exec();
|
||||
/*
|
||||
}
|
||||
else {
|
||||
console.error('incomplete commands not yet supported');
|
||||
}
|
||||
*/
|
||||
button.addEventListener("click", () => {
|
||||
requisition.updateExec(typed);
|
||||
}, false);
|
||||
|
||||
// Allow the command button to be toggleable
|
||||
if (command.state) {
|
||||
button.setAttribute("autocheck", false);
|
||||
let onChange = function(event, eventTab) {
|
||||
let onChange = (event, eventTab) => {
|
||||
if (eventTab == target.tab) {
|
||||
if (command.state.isChecked(target)) {
|
||||
button.setAttribute("checked", true);
|
||||
@ -150,16 +137,16 @@ let CommandUtils = {
|
||||
};
|
||||
command.state.onChange(target, onChange);
|
||||
onChange(null, target.tab);
|
||||
document.defaultView.addEventListener("unload", function() {
|
||||
document.defaultView.addEventListener("unload", () => {
|
||||
command.state.offChange(target, onChange);
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
requisition.clear();
|
||||
|
||||
return button;
|
||||
});
|
||||
});
|
||||
|
||||
requisition.update('');
|
||||
|
||||
return reply;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -382,56 +369,58 @@ DeveloperToolbar.prototype.show = function(focus) {
|
||||
|
||||
this._doc.getElementById("Tools:DevToolbar").setAttribute("checked", "true");
|
||||
|
||||
this.display = gcli.createDisplay({
|
||||
contentDocument: this._chromeWindow.getBrowser().contentDocument,
|
||||
chromeDocument: this._doc,
|
||||
chromeWindow: this._chromeWindow,
|
||||
hintElement: this.tooltipPanel.hintElement,
|
||||
inputElement: this._input,
|
||||
completeElement: this._doc.querySelector(".gclitoolbar-complete-node"),
|
||||
backgroundElement: this._doc.querySelector(".gclitoolbar-stack-node"),
|
||||
outputDocument: this.outputPanel.document,
|
||||
environment: CommandUtils.createEnvironment(this, "target"),
|
||||
tooltipClass: "gcliterm-tooltip",
|
||||
eval: null,
|
||||
scratchpad: null
|
||||
return gcli.load().then(() => {
|
||||
this.display = gcli.createDisplay({
|
||||
contentDocument: this._chromeWindow.getBrowser().contentDocument,
|
||||
chromeDocument: this._doc,
|
||||
chromeWindow: this._chromeWindow,
|
||||
hintElement: this.tooltipPanel.hintElement,
|
||||
inputElement: this._input,
|
||||
completeElement: this._doc.querySelector(".gclitoolbar-complete-node"),
|
||||
backgroundElement: this._doc.querySelector(".gclitoolbar-stack-node"),
|
||||
outputDocument: this.outputPanel.document,
|
||||
environment: CommandUtils.createEnvironment(this, "target"),
|
||||
tooltipClass: "gcliterm-tooltip",
|
||||
eval: null,
|
||||
scratchpad: null
|
||||
});
|
||||
|
||||
this.display.focusManager.addMonitoredElement(this.outputPanel._frame);
|
||||
this.display.focusManager.addMonitoredElement(this._element);
|
||||
|
||||
this.display.onVisibilityChange.add(this.outputPanel._visibilityChanged,
|
||||
this.outputPanel);
|
||||
this.display.onVisibilityChange.add(this.tooltipPanel._visibilityChanged,
|
||||
this.tooltipPanel);
|
||||
this.display.onOutput.add(this.outputPanel._outputChanged, this.outputPanel);
|
||||
|
||||
let tabbrowser = this._chromeWindow.getBrowser();
|
||||
tabbrowser.tabContainer.addEventListener("TabSelect", this, false);
|
||||
tabbrowser.tabContainer.addEventListener("TabClose", this, false);
|
||||
tabbrowser.addEventListener("load", this, true);
|
||||
tabbrowser.addEventListener("beforeunload", this, true);
|
||||
|
||||
this._initErrorsCount(tabbrowser.selectedTab);
|
||||
this._devtoolsUnloaded = this._devtoolsUnloaded.bind(this);
|
||||
this._devtoolsLoaded = this._devtoolsLoaded.bind(this);
|
||||
Services.obs.addObserver(this._devtoolsUnloaded, "devtools-unloaded", false);
|
||||
Services.obs.addObserver(this._devtoolsLoaded, "devtools-loaded", false);
|
||||
|
||||
this._element.hidden = false;
|
||||
|
||||
if (focus) {
|
||||
this._input.focus();
|
||||
}
|
||||
|
||||
this._notify(NOTIFICATIONS.SHOW);
|
||||
|
||||
if (!DeveloperToolbar.introShownThisSession) {
|
||||
this.display.maybeShowIntro();
|
||||
DeveloperToolbar.introShownThisSession = true;
|
||||
}
|
||||
|
||||
this._showPromise = null;
|
||||
});
|
||||
|
||||
this.display.focusManager.addMonitoredElement(this.outputPanel._frame);
|
||||
this.display.focusManager.addMonitoredElement(this._element);
|
||||
|
||||
this.display.onVisibilityChange.add(this.outputPanel._visibilityChanged,
|
||||
this.outputPanel);
|
||||
this.display.onVisibilityChange.add(this.tooltipPanel._visibilityChanged,
|
||||
this.tooltipPanel);
|
||||
this.display.onOutput.add(this.outputPanel._outputChanged, this.outputPanel);
|
||||
|
||||
let tabbrowser = this._chromeWindow.getBrowser();
|
||||
tabbrowser.tabContainer.addEventListener("TabSelect", this, false);
|
||||
tabbrowser.tabContainer.addEventListener("TabClose", this, false);
|
||||
tabbrowser.addEventListener("load", this, true);
|
||||
tabbrowser.addEventListener("beforeunload", this, true);
|
||||
|
||||
this._initErrorsCount(tabbrowser.selectedTab);
|
||||
this._devtoolsUnloaded = this._devtoolsUnloaded.bind(this);
|
||||
this._devtoolsLoaded = this._devtoolsLoaded.bind(this);
|
||||
Services.obs.addObserver(this._devtoolsUnloaded, "devtools-unloaded", false);
|
||||
Services.obs.addObserver(this._devtoolsLoaded, "devtools-loaded", false);
|
||||
|
||||
this._element.hidden = false;
|
||||
|
||||
if (focus) {
|
||||
this._input.focus();
|
||||
}
|
||||
|
||||
this._notify(NOTIFICATIONS.SHOW);
|
||||
|
||||
if (!DeveloperToolbar.introShownThisSession) {
|
||||
this.display.maybeShowIntro();
|
||||
DeveloperToolbar.introShownThisSession = true;
|
||||
}
|
||||
|
||||
this._showPromise = null;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -6,24 +6,27 @@
|
||||
const TEST_URI = "data:text/html;charset=utf-8,<p>Tooltip Tests</p>";
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI, function(browser, tab) {
|
||||
info("Starting browser_toolbar_tooltip.js");
|
||||
openTest();
|
||||
addTab(TEST_URI, function() {
|
||||
Task.spawn(runTest).catch(err => {
|
||||
ok(false, ex);
|
||||
console.error(ex);
|
||||
}).then(finish);
|
||||
});
|
||||
}
|
||||
|
||||
function openTest() {
|
||||
function* runTest() {
|
||||
info("Starting browser_toolbar_tooltip.js");
|
||||
|
||||
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in runTest");
|
||||
|
||||
oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.SHOW, catchFail(runTest));
|
||||
let showPromise = observeOnce(DeveloperToolbar.NOTIFICATIONS.SHOW);
|
||||
document.getElementById("Tools:DevToolbar").doCommand();
|
||||
}
|
||||
yield showPromise;
|
||||
|
||||
function runTest() {
|
||||
let tooltipPanel = DeveloperToolbar.tooltipPanel;
|
||||
|
||||
DeveloperToolbar.display.focusManager.helpRequest();
|
||||
DeveloperToolbar.display.inputter.setInput('help help');
|
||||
yield DeveloperToolbar.display.inputter.setInput('help help');
|
||||
|
||||
DeveloperToolbar.display.inputter.setCursor({ start: 'help help'.length });
|
||||
is(tooltipPanel._dimensions.start, 'help '.length,
|
||||
@ -44,11 +47,19 @@ function runTest() {
|
||||
is(tooltipPanel._dimensions.start, 0,
|
||||
'search param start, when cursor at start');
|
||||
ok(getLeftMargin() > 9, 'tooltip offset, when cursor at start')
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
function getLeftMargin() {
|
||||
let style = DeveloperToolbar.tooltipPanel._panel.style.marginLeft;
|
||||
return parseInt(style.slice(0, -2), 10);
|
||||
}
|
||||
|
||||
function observeOnce(topic, ownsWeak=false) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
let resolver = function(subject) {
|
||||
Services.obs.removeObserver(resolver, topic);
|
||||
resolve(subject);
|
||||
};
|
||||
Services.obs.addObserver(resolver, topic, ownsWeak);
|
||||
}.bind(this));
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={BUGNUMBER}
|
||||
-->
|
||||
<window title="Mozilla Bug {BUGNUMBER}"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('./util/promise');
|
||||
var Promise = require('./util/promise').Promise;
|
||||
var centralCanon = require('./commands/commands').centralCanon;
|
||||
var connectors = require('./connectors/connectors');
|
||||
var converters = require('./converters/converters');
|
||||
@ -117,7 +117,7 @@ exports.getApi = function() {
|
||||
// And load the new items
|
||||
try {
|
||||
var loader = loadableModules[name];
|
||||
return promise.resolve(loader(name)).then(function(newModule) {
|
||||
return Promise.resolve(loader(name)).then(function(newModule) {
|
||||
if (existingModule === newModule) {
|
||||
return;
|
||||
}
|
||||
@ -138,10 +138,12 @@ exports.getApi = function() {
|
||||
}
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
return promise.reject('Failure when loading \'' + name + '\'');
|
||||
return Promise.reject('Failure when loading \'' + name + '\'');
|
||||
}
|
||||
};
|
||||
|
||||
var pendingChanges = false;
|
||||
|
||||
var api = {
|
||||
addCommand: function(item) { return canon.addCommand(item); },
|
||||
removeCommand: function(item) { return canon.removeCommand(item); },
|
||||
@ -175,7 +177,10 @@ exports.getApi = function() {
|
||||
}
|
||||
loadableModules[name] = options.loader;
|
||||
|
||||
if (!options.delayedLoad) {
|
||||
if (options.delayedLoad) {
|
||||
pendingChanges = true;
|
||||
}
|
||||
else {
|
||||
loadModule(name).then(null, console.error);
|
||||
}
|
||||
});
|
||||
@ -187,17 +192,24 @@ exports.getApi = function() {
|
||||
},
|
||||
|
||||
load: function() {
|
||||
if (!pendingChanges) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// clone loadedModules, so we can remove what is left at the end
|
||||
var modules = Object.keys(loadedModules).map(function(name) {
|
||||
return loadedModules[name];
|
||||
});
|
||||
|
||||
Object.keys(loadableModules).forEach(function(name) {
|
||||
var promises = Object.keys(loadableModules).map(function(name) {
|
||||
delete modules[name];
|
||||
loadModule(name).then(null, console.error);
|
||||
return loadModule(name);
|
||||
});
|
||||
|
||||
Object.keys(modules).forEach(unloadModule);
|
||||
pendingChanges = false;
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('./util/promise');
|
||||
var Promise = require('./util/promise').Promise;
|
||||
var util = require('./util/util');
|
||||
var host = require('./util/host');
|
||||
var l10n = require('./util/l10n');
|
||||
@ -40,7 +40,7 @@ var TrueNamedArgument = require('./types/types').TrueNamedArgument;
|
||||
var MergedArgument = require('./types/types').MergedArgument;
|
||||
var ScriptArgument = require('./types/types').ScriptArgument;
|
||||
|
||||
var RESOLVED = promise.resolve(undefined);
|
||||
var RESOLVED = Promise.resolve(undefined);
|
||||
|
||||
/**
|
||||
* This is a list of the known command line components to enable certain
|
||||
@ -196,7 +196,7 @@ Assignment.prototype.getPredictionRanked = function(context, rank) {
|
||||
}
|
||||
|
||||
if (this.isInName()) {
|
||||
return promise.resolve(undefined);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return this.getPredictions(context).then(function(predictions) {
|
||||
@ -550,7 +550,7 @@ Object.defineProperty(Requisition.prototype, 'executionContext', {
|
||||
if (this._executionContext == null) {
|
||||
this._executionContext = {
|
||||
defer: function() {
|
||||
return promise.defer();
|
||||
return Promise.defer();
|
||||
},
|
||||
typedData: function(type, data) {
|
||||
return {
|
||||
@ -607,7 +607,7 @@ Object.defineProperty(Requisition.prototype, 'conversionContext', {
|
||||
if (this._conversionContext == null) {
|
||||
this._conversionContext = {
|
||||
defer: function() {
|
||||
return promise.defer();
|
||||
return Promise.defer();
|
||||
},
|
||||
|
||||
createView: view.createView,
|
||||
@ -861,7 +861,7 @@ Requisition.prototype.toCanonicalString = function() {
|
||||
}
|
||||
|
||||
var val = assignment.param.type.stringify(assignment.value, ctx);
|
||||
return promise.resolve(val).then(function(str) {
|
||||
return Promise.resolve(val).then(function(str) {
|
||||
return ' ' + str;
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
@ -1017,7 +1017,7 @@ Requisition.prototype.setAssignment = function(assignment, arg, options) {
|
||||
this._endChangeCheckOrder(updateId);
|
||||
}
|
||||
|
||||
return promise.resolve(undefined);
|
||||
return Promise.resolve(undefined);
|
||||
}.bind(this);
|
||||
|
||||
if (arg == null) {
|
||||
@ -1210,7 +1210,7 @@ Requisition.prototype.getStateData = function(start, rank) {
|
||||
var context = this.executionContext;
|
||||
var predictionPromise = (typed.trim().length !== 0) ?
|
||||
current.getPredictionRanked(context, rank) :
|
||||
promise.resolve(null);
|
||||
Promise.resolve(null);
|
||||
|
||||
return predictionPromise.then(function(prediction) {
|
||||
// directTabText is for when the current input is a prefix of the completion
|
||||
@ -1349,7 +1349,7 @@ Requisition.prototype._addSpace = function(assignment) {
|
||||
return this.setAssignment(assignment, arg);
|
||||
}
|
||||
else {
|
||||
return promise.resolve(undefined);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1426,7 +1426,7 @@ Requisition.prototype.complete = function(cursor, rank) {
|
||||
outstanding.push(assignPromise);
|
||||
}
|
||||
|
||||
return promise.all(outstanding).then(function() {
|
||||
return Promise.all(outstanding).then(function() {
|
||||
return true;
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
@ -1438,10 +1438,10 @@ Requisition.prototype.complete = function(cursor, rank) {
|
||||
Requisition.prototype.decrement = function(assignment) {
|
||||
var ctx = this.executionContext;
|
||||
var val = assignment.param.type.decrement(assignment.value, ctx);
|
||||
return promise.resolve(val).then(function(replacement) {
|
||||
return Promise.resolve(val).then(function(replacement) {
|
||||
if (replacement != null) {
|
||||
var val = assignment.param.type.stringify(replacement, ctx);
|
||||
return promise.resolve(val).then(function(str) {
|
||||
return Promise.resolve(val).then(function(str) {
|
||||
var arg = assignment.arg.beget({ text: str });
|
||||
return this.setAssignment(assignment, arg);
|
||||
}.bind(this));
|
||||
@ -1455,10 +1455,10 @@ Requisition.prototype.decrement = function(assignment) {
|
||||
Requisition.prototype.increment = function(assignment) {
|
||||
var ctx = this.executionContext;
|
||||
var val = assignment.param.type.increment(assignment.value, ctx);
|
||||
return promise.resolve(val).then(function(replacement) {
|
||||
return Promise.resolve(val).then(function(replacement) {
|
||||
if (replacement != null) {
|
||||
var val = assignment.param.type.stringify(replacement, ctx);
|
||||
return promise.resolve(val).then(function(str) {
|
||||
return Promise.resolve(val).then(function(str) {
|
||||
var arg = assignment.arg.beget({ text: str });
|
||||
return this.setAssignment(assignment, arg);
|
||||
}.bind(this));
|
||||
@ -2046,7 +2046,7 @@ Requisition.prototype.exec = function(options) {
|
||||
var ex = new Error(this.getStatusMessage());
|
||||
// We only reject a call to exec if GCLI breaks. Errors with commands are
|
||||
// exposed in the 'error' status of the Output object
|
||||
return promise.resolve(onError(ex)).then(function(output) {
|
||||
return Promise.resolve(onError(ex)).then(function(output) {
|
||||
this.clear();
|
||||
return output;
|
||||
}.bind(this));
|
||||
@ -2060,7 +2060,7 @@ Requisition.prototype.exec = function(options) {
|
||||
catch (ex) {
|
||||
var data = (typeof ex.message === 'string' && ex.stack != null) ?
|
||||
ex.message : ex;
|
||||
return promise.resolve(onError(data, ex));
|
||||
return Promise.resolve(onError(data, ex));
|
||||
}
|
||||
finally {
|
||||
this.clear();
|
||||
@ -2099,8 +2099,9 @@ function Output(options) {
|
||||
this.error = false;
|
||||
this.start = new Date();
|
||||
|
||||
this._deferred = promise.defer();
|
||||
this.promise = this._deferred.promise;
|
||||
this.promise = new Promise(function(resolve, reject) {
|
||||
this._resolve = resolve;
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2128,7 +2129,7 @@ Output.prototype.complete = function(data, error) {
|
||||
throw new Error('No type from output of ' + this.typed);
|
||||
}
|
||||
|
||||
this._deferred.resolve();
|
||||
this._resolve();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var l10n = require('../util/l10n');
|
||||
var cli = require('../cli');
|
||||
|
||||
@ -68,13 +68,13 @@ function getHelpManData(commandData, context) {
|
||||
input = l10n.lookupFormat('helpManOptional');
|
||||
/*
|
||||
var val = param.type.stringify(param.defaultValue);
|
||||
input = promise.resolve(val).then(function(defaultValue) {
|
||||
input = Promise.resolve(val).then(function(defaultValue) {
|
||||
return l10n.lookupFormat('helpManDefault', [ defaultValue ]);
|
||||
}.bind(this));
|
||||
*/
|
||||
}
|
||||
|
||||
return promise.resolve(input).then(function(defaultDescr) {
|
||||
return Promise.resolve(input).then(function(defaultDescr) {
|
||||
return '(' + (param.type.name || param.type) + ', ' + defaultDescr + ')';
|
||||
}.bind(this));
|
||||
},
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
var l10n = require('../util/l10n');
|
||||
var settings = require('../settings');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
|
||||
/**
|
||||
* Format a list of settings for display
|
||||
@ -116,18 +117,16 @@ var prefList = {
|
||||
],
|
||||
returnType: 'prefsData',
|
||||
exec: function(args, context) {
|
||||
var deferred = context.defer();
|
||||
|
||||
// This can be slow, get out of the way of the main thread
|
||||
setTimeout(function() {
|
||||
var prefsData = {
|
||||
settings: settings.getAll(args.search),
|
||||
search: args.search
|
||||
};
|
||||
deferred.resolve(prefsData);
|
||||
}.bind(this), 10);
|
||||
|
||||
return deferred.promise;
|
||||
return new Promise(function(resolve, reject) {
|
||||
// This can be slow, get out of the way of the main thread
|
||||
setTimeout(function() {
|
||||
var prefsData = {
|
||||
settings: settings.getAll(args.search),
|
||||
search: args.search
|
||||
};
|
||||
resolve(prefsData);
|
||||
}.bind(this), 10);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
|
||||
/**
|
||||
* This is where we cache the connectors that we know about
|
||||
@ -30,7 +30,7 @@ var connectors = {};
|
||||
* name: 'foo',
|
||||
*
|
||||
* connect: function(url) {
|
||||
* return promise.resolve(new FooConnection(url));
|
||||
* return Promise.resolve(new FooConnection(url));
|
||||
* }
|
||||
* };
|
||||
*/
|
||||
@ -106,7 +106,7 @@ Connection.prototype.call = function(feature, data) {
|
||||
* common route back to being connected once this has been called
|
||||
*/
|
||||
Connection.prototype.disconnect = function() {
|
||||
return promise.resolve();
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
exports.Connection = Connection;
|
||||
|
@ -21,7 +21,7 @@ var Cu = require('chrome').Cu;
|
||||
var debuggerSocketConnect = Cu.import('resource://gre/modules/devtools/dbg-client.jsm', {}).debuggerSocketConnect;
|
||||
var DebuggerClient = Cu.import('resource://gre/modules/devtools/dbg-client.jsm', {}).DebuggerClient;
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var Connection = require('./connectors').Connection;
|
||||
|
||||
/**
|
||||
@ -71,45 +71,38 @@ RdpConnection.create = function(url) {
|
||||
|
||||
this._emit = this._emit.bind(this);
|
||||
|
||||
var deferred = promise.defer();
|
||||
|
||||
this.transport = debuggerSocketConnect(this.host, this.port);
|
||||
this.client = new DebuggerClient(this.transport);
|
||||
|
||||
this.client.connect(function() {
|
||||
this.client.listTabs(function(response) {
|
||||
this.actor = response.gcliActor;
|
||||
deferred.resolve();
|
||||
return new Promise(function(resolve, reject) {
|
||||
this.transport = debuggerSocketConnect(this.host, this.port);
|
||||
this.client = new DebuggerClient(this.transport);
|
||||
this.client.connect(function() {
|
||||
this.client.listTabs(function(response) {
|
||||
this.actor = response.gcliActor;
|
||||
resolve();
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
RdpConnection.prototype = Object.create(Connection.prototype);
|
||||
|
||||
RdpConnection.prototype.call = function(command, data) {
|
||||
var deferred = promise.defer();
|
||||
return new Promise(function(resolve, reject) {
|
||||
var request = { to: this.actor, type: command, data: data };
|
||||
|
||||
var request = { to: this.actor, type: command, data: data };
|
||||
|
||||
this.client.request(request, function(response) {
|
||||
deferred.resolve(response.commandSpecs);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
this.client.request(request, function(response) {
|
||||
resolve(response.commandSpecs);
|
||||
});
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
RdpConnection.prototype.disconnect = function() {
|
||||
var deferred = promise.defer();
|
||||
return new Promise(function(resolve, reject) {
|
||||
this.client.close(function() {
|
||||
resolve();
|
||||
});
|
||||
|
||||
this.client.close(function() {
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
delete this._emit;
|
||||
|
||||
return deferred.promise;
|
||||
delete this._emit;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
|
||||
@ -126,8 +119,9 @@ function Request(actor, typed, args) {
|
||||
requestId: 'id-' + Request._nextRequestId++,
|
||||
};
|
||||
|
||||
this._deferred = promise.defer();
|
||||
this.promise = this._deferred.promise;
|
||||
this.promise = new Promise(function(resolve, reject) {
|
||||
this._resolve = resolve;
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
Request._nextRequestId = 0;
|
||||
@ -139,7 +133,7 @@ Request._nextRequestId = 0;
|
||||
* @param data the data itself
|
||||
*/
|
||||
Request.prototype.complete = function(error, type, data) {
|
||||
this._deferred.resolve({
|
||||
this._resolve({
|
||||
error: error,
|
||||
type: type,
|
||||
data: data
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var host = require('../util/host');
|
||||
var fileparser = require('../util/fileparser');
|
||||
|
||||
@ -130,7 +130,7 @@ Remoter.prototype.exposed = {
|
||||
return this.requisition.update(typed).then(function() {
|
||||
var assignment = this.requisition.getAssignment(param);
|
||||
|
||||
return promise.resolve(assignment.predictions).then(function(predictions) {
|
||||
return Promise.resolve(assignment.predictions).then(function(predictions) {
|
||||
return {
|
||||
status: assignment.getStatus().toString(),
|
||||
message: assignment.message,
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var util = require('../util/util');
|
||||
var host = require('../util/host');
|
||||
|
||||
@ -233,7 +233,7 @@ function getFallbackConverter(from, to) {
|
||||
exports.convert = function(data, from, to, conversionContext) {
|
||||
try {
|
||||
if (from === to) {
|
||||
return promise.resolve(data);
|
||||
return Promise.resolve(data);
|
||||
}
|
||||
|
||||
var converter = getConverter(from, to);
|
||||
|
@ -17,7 +17,7 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('../util/util');
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var domtemplate = require('../util/domtemplate');
|
||||
var host = require('../util/host');
|
||||
|
||||
@ -28,7 +28,7 @@ var CommandAssignment = require('../cli').CommandAssignment;
|
||||
var fields = require('../fields/fields');
|
||||
var intro = require('../ui/intro');
|
||||
|
||||
var RESOLVED = promise.resolve(true);
|
||||
var RESOLVED = Promise.resolve(true);
|
||||
|
||||
/**
|
||||
* Various ways in which we need to manipulate the caret/selection position.
|
||||
@ -100,7 +100,7 @@ var commandLanguage = exports.commandLanguage = {
|
||||
}
|
||||
|
||||
return commandHtmlPromise.then(function(commandHtml) {
|
||||
this.commandDom = util.toDom(this.document, commandHtml);
|
||||
this.commandDom = host.toDom(this.document, commandHtml);
|
||||
|
||||
this.requisition.commandOutputManager.onOutput.add(this.outputted, this);
|
||||
var mapping = cli.getMapping(this.requisition.executionContext);
|
||||
@ -248,7 +248,7 @@ var commandLanguage = exports.commandLanguage = {
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
return promise.resolve(false);
|
||||
return Promise.resolve(false);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -263,7 +263,7 @@ var commandLanguage = exports.commandLanguage = {
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
return promise.resolve(false);
|
||||
return Promise.resolve(false);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -272,7 +272,7 @@ var commandLanguage = exports.commandLanguage = {
|
||||
handleReturn: function(input) {
|
||||
// Deny RETURN unless the command might work
|
||||
if (this.requisition.status !== Status.VALID) {
|
||||
return promise.resolve(false);
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
this.terminal.history.add(input);
|
||||
|
@ -17,9 +17,9 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('../util/util');
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
|
||||
var RESOLVED = promise.resolve(true);
|
||||
var RESOLVED = Promise.resolve(true);
|
||||
|
||||
/**
|
||||
* This is where we cache the languages that we know about
|
||||
@ -48,11 +48,11 @@ var baseLanguage = {
|
||||
caretMoved: function() {},
|
||||
|
||||
handleUpArrow: function() {
|
||||
return promise.resolve(false);
|
||||
return Promise.resolve(false);
|
||||
},
|
||||
|
||||
handleDownArrow: function() {
|
||||
return promise.resolve(false);
|
||||
return Promise.resolve(false);
|
||||
},
|
||||
|
||||
handleTab: function() {
|
||||
@ -96,7 +96,7 @@ var baseLanguage = {
|
||||
},
|
||||
|
||||
getCompleterTemplateData: function() {
|
||||
return promise.resolve({
|
||||
return Promise.resolve({
|
||||
statusMarkup: [
|
||||
{
|
||||
string: this.terminal.inputElement.value.replace(/ /g, '\u00a0'), // i.e.
|
||||
@ -163,11 +163,11 @@ exports.createLanguage = function(name, terminal) {
|
||||
|
||||
if (typeof newInstance.constructor === 'function') {
|
||||
var reply = newInstance.constructor(terminal);
|
||||
return promise.resolve(reply).then(function() {
|
||||
return Promise.resolve(reply).then(function() {
|
||||
return newInstance;
|
||||
});
|
||||
}
|
||||
else {
|
||||
return promise.resolve(newInstance);
|
||||
return Promise.resolve(newInstance);
|
||||
}
|
||||
};
|
||||
|
@ -17,6 +17,7 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('../util/util');
|
||||
var host = require('../util/host');
|
||||
var domtemplate = require('../util/domtemplate');
|
||||
|
||||
var completerHtml =
|
||||
@ -68,7 +69,7 @@ function Completer(components) {
|
||||
}
|
||||
}
|
||||
|
||||
this.template = util.toDom(this.document, completerHtml);
|
||||
this.template = host.toDom(this.document, completerHtml);
|
||||
// We want the spans to line up without the spaces in the template
|
||||
util.removeWhitespace(this.template, true);
|
||||
|
||||
@ -111,6 +112,10 @@ Completer.prototype.update = function(ev) {
|
||||
this.choice = (ev && ev.choice != null) ? ev.choice : 0;
|
||||
|
||||
this._getCompleterTemplateData().then(function(data) {
|
||||
if (this.template == null) {
|
||||
return; // destroy() has been called
|
||||
}
|
||||
|
||||
var template = this.template.cloneNode(true);
|
||||
domtemplate.template(template, data, { stack: 'completer.html' });
|
||||
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var util = require('../util/util');
|
||||
var KeyEvent = require('../util/util').KeyEvent;
|
||||
|
||||
var Status = require('../types/types').Status;
|
||||
var History = require('../ui/history').History;
|
||||
|
||||
var RESOLVED = promise.resolve(true);
|
||||
var RESOLVED = Promise.resolve(true);
|
||||
|
||||
/**
|
||||
* A wrapper to take care of the functions concerning an input element
|
||||
|
@ -17,6 +17,7 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('../util/util');
|
||||
var host = require('../util/host');
|
||||
var domtemplate = require('../util/domtemplate');
|
||||
|
||||
var CommandAssignment = require('../cli').CommandAssignment;
|
||||
@ -62,7 +63,7 @@ function Tooltip(options, components) {
|
||||
// We cache the fields we create so we can destroy them later
|
||||
this.fields = [];
|
||||
|
||||
this.template = util.toDom(this.document, tooltipHtml);
|
||||
this.template = host.toDom(this.document, tooltipHtml);
|
||||
this.templateOptions = { blankNullUndefined: true, stack: 'tooltip.html' };
|
||||
|
||||
this.inputter.onChoiceChange.add(this.choiceChanged, this);
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var ArrayConversion = require('./types').ArrayConversion;
|
||||
var ArrayArgument = require('./types').ArrayArgument;
|
||||
|
||||
@ -69,7 +69,7 @@ exports.items = [
|
||||
}.bind(this);
|
||||
|
||||
var conversionPromises = arg.getArguments().map(subArgParse);
|
||||
return promise.all(conversionPromises).then(function(conversions) {
|
||||
return Promise.all(conversionPromises).then(function(conversions) {
|
||||
return new ArrayConversion(conversions, arg);
|
||||
});
|
||||
},
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var Status = require('./types').Status;
|
||||
var Conversion = require('./types').Conversion;
|
||||
var BlankArgument = require('./types').BlankArgument;
|
||||
@ -40,10 +40,10 @@ exports.items = [
|
||||
|
||||
parse: function(arg, context) {
|
||||
if (arg.type === 'TrueNamedArgument') {
|
||||
return promise.resolve(new Conversion(true, arg));
|
||||
return Promise.resolve(new Conversion(true, arg));
|
||||
}
|
||||
if (arg.type === 'FalseNamedArgument') {
|
||||
return promise.resolve(new Conversion(false, arg));
|
||||
return Promise.resolve(new Conversion(false, arg));
|
||||
}
|
||||
return SelectionType.prototype.parse.call(this, arg, context);
|
||||
},
|
||||
@ -57,7 +57,7 @@ exports.items = [
|
||||
|
||||
getBlank: function(context) {
|
||||
return new Conversion(false, new BlankArgument(), Status.VALID, '',
|
||||
promise.resolve(this.lookup));
|
||||
Promise.resolve(this.lookup));
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var l10n = require('../util/l10n');
|
||||
var spell = require('../util/spell');
|
||||
var SelectionType = require('./selection').SelectionType;
|
||||
@ -48,7 +48,7 @@ exports.items = [
|
||||
}
|
||||
else {
|
||||
var message = l10n.lookup('cliUnusedArg');
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.ERROR, message));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, message));
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -78,7 +78,7 @@ exports.items = [
|
||||
|
||||
parse: function(arg, context) {
|
||||
var conversion = exports.parse(context, arg, this.allowNonExec);
|
||||
return promise.resolve(conversion);
|
||||
return Promise.resolve(conversion);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var l10n = require('../util/l10n');
|
||||
var Status = require('./types').Status;
|
||||
var Conversion = require('./types').Conversion;
|
||||
@ -174,7 +174,7 @@ exports.items = [
|
||||
var value;
|
||||
|
||||
if (arg.text.replace(/\s/g, '').length === 0) {
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, ''));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, ''));
|
||||
}
|
||||
|
||||
// Lots of room for improvement here: 1h ago, in two days, etc.
|
||||
@ -220,11 +220,11 @@ exports.items = [
|
||||
|
||||
if (isNaN(value.getTime())) {
|
||||
var msg = l10n.lookupFormat('typesDateNan', [ arg.text ]);
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
}
|
||||
}
|
||||
|
||||
return promise.resolve(new Conversion(value, arg));
|
||||
return Promise.resolve(new Conversion(value, arg));
|
||||
},
|
||||
|
||||
decrement: function(value, context) {
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var Conversion = require('./types').Conversion;
|
||||
var Status = require('./types').Status;
|
||||
|
||||
@ -84,7 +84,7 @@ exports.items = [
|
||||
if (typeof type.parse !== 'function') {
|
||||
type = this.types.createType(type);
|
||||
}
|
||||
return promise.resolve(type);
|
||||
return Promise.resolve(type);
|
||||
},
|
||||
|
||||
// DelegateType is designed to be inherited from, so DelegateField needs a way
|
||||
@ -147,7 +147,7 @@ exports.items = [
|
||||
},
|
||||
|
||||
parse: function(arg, context) {
|
||||
return promise.resolve(new Conversion(undefined, arg));
|
||||
return Promise.resolve(new Conversion(undefined, arg));
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var l10n = require('../util/l10n');
|
||||
|
||||
var Conversion = require('./types').Conversion;
|
||||
@ -86,15 +86,15 @@ JavascriptType.prototype.parse = function(arg, context) {
|
||||
|
||||
// No input is undefined
|
||||
if (typed === '') {
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE));
|
||||
}
|
||||
// Just accept numbers
|
||||
if (!isNaN(parseFloat(typed)) && isFinite(typed)) {
|
||||
return promise.resolve(new Conversion(typed, arg));
|
||||
return Promise.resolve(new Conversion(typed, arg));
|
||||
}
|
||||
// Just accept constants like true/false/null/etc
|
||||
if (typed.trim().match(/(null|undefined|NaN|Infinity|true|false)/)) {
|
||||
return promise.resolve(new Conversion(typed, arg));
|
||||
return Promise.resolve(new Conversion(typed, arg));
|
||||
}
|
||||
|
||||
// Analyze the input text and find the beginning of the last part that
|
||||
@ -103,19 +103,19 @@ JavascriptType.prototype.parse = function(arg, context) {
|
||||
|
||||
// There was an error analyzing the string.
|
||||
if (beginning.err) {
|
||||
return promise.resolve(new Conversion(typed, arg, Status.ERROR, beginning.err));
|
||||
return Promise.resolve(new Conversion(typed, arg, Status.ERROR, beginning.err));
|
||||
}
|
||||
|
||||
// If the current state is ParseState.COMPLEX, then we can't do completion.
|
||||
// so bail out now
|
||||
if (beginning.state === ParseState.COMPLEX) {
|
||||
return promise.resolve(new Conversion(typed, arg));
|
||||
return Promise.resolve(new Conversion(typed, arg));
|
||||
}
|
||||
|
||||
// If the current state is not ParseState.NORMAL, then we are inside of a
|
||||
// string which means that no completion is possible.
|
||||
if (beginning.state !== ParseState.NORMAL) {
|
||||
return promise.resolve(new Conversion(typed, arg, Status.INCOMPLETE, ''));
|
||||
return Promise.resolve(new Conversion(typed, arg, Status.INCOMPLETE, ''));
|
||||
}
|
||||
|
||||
var completionPart = typed.substring(beginning.startPos);
|
||||
@ -130,18 +130,18 @@ JavascriptType.prototype.parse = function(arg, context) {
|
||||
|
||||
// We can't complete on null.foo, so bail out
|
||||
if (scope == null) {
|
||||
return promise.resolve(new Conversion(typed, arg, Status.ERROR,
|
||||
return Promise.resolve(new Conversion(typed, arg, Status.ERROR,
|
||||
l10n.lookup('jstypeParseScope')));
|
||||
}
|
||||
|
||||
if (prop === '') {
|
||||
return promise.resolve(new Conversion(typed, arg, Status.INCOMPLETE, ''));
|
||||
return Promise.resolve(new Conversion(typed, arg, Status.INCOMPLETE, ''));
|
||||
}
|
||||
|
||||
// Check if prop is a getter function on 'scope'. Functions can change
|
||||
// other stuff so we can't execute them to get the next object. Stop here.
|
||||
if (this._isSafeProperty(scope, prop)) {
|
||||
return promise.resolve(new Conversion(typed, arg));
|
||||
return Promise.resolve(new Conversion(typed, arg));
|
||||
}
|
||||
|
||||
try {
|
||||
@ -151,7 +151,7 @@ JavascriptType.prototype.parse = function(arg, context) {
|
||||
// It would be nice to be able to report this error in some way but
|
||||
// as it can happen just when someone types '{sessionStorage.', it
|
||||
// almost doesn't really count as an error, so we ignore it
|
||||
return promise.resolve(new Conversion(typed, arg, Status.VALID, ''));
|
||||
return Promise.resolve(new Conversion(typed, arg, Status.VALID, ''));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -162,24 +162,24 @@ JavascriptType.prototype.parse = function(arg, context) {
|
||||
// If the reason we just stopped adjusting the scope was a non-simple string,
|
||||
// then we're not sure if the input is valid or invalid, so accept it
|
||||
if (prop && !prop.match(/^[0-9A-Za-z]*$/)) {
|
||||
return promise.resolve(new Conversion(typed, arg));
|
||||
return Promise.resolve(new Conversion(typed, arg));
|
||||
}
|
||||
|
||||
// However if the prop was a simple string, it is an error
|
||||
if (scope == null) {
|
||||
var msg = l10n.lookupFormat('jstypeParseMissing', [ prop ]);
|
||||
return promise.resolve(new Conversion(typed, arg, Status.ERROR, msg));
|
||||
return Promise.resolve(new Conversion(typed, arg, Status.ERROR, msg));
|
||||
}
|
||||
|
||||
// If the thing we're looking for isn't a simple string, then we're not going
|
||||
// to find it, but we're not sure if it's valid or invalid, so accept it
|
||||
if (!matchProp.match(/^[0-9A-Za-z]*$/)) {
|
||||
return promise.resolve(new Conversion(typed, arg));
|
||||
return Promise.resolve(new Conversion(typed, arg));
|
||||
}
|
||||
|
||||
// Skip Iterators and Generators.
|
||||
if (this._isIteratorOrGenerator(scope)) {
|
||||
return promise.resolve(new Conversion(typed, arg));
|
||||
return Promise.resolve(new Conversion(typed, arg));
|
||||
}
|
||||
|
||||
var matchLen = matchProp.length;
|
||||
@ -219,7 +219,7 @@ JavascriptType.prototype.parse = function(arg, context) {
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
return promise.resolve(new Conversion(typed, arg, Status.INCOMPLETE, ''));
|
||||
return Promise.resolve(new Conversion(typed, arg, Status.INCOMPLETE, ''));
|
||||
}
|
||||
|
||||
// Convert to an array for sorting, and while we're at it, note if we got
|
||||
@ -313,8 +313,8 @@ JavascriptType.prototype.parse = function(arg, context) {
|
||||
predictions = [];
|
||||
}
|
||||
|
||||
return promise.resolve(new Conversion(typed, arg, status, message,
|
||||
promise.resolve(predictions)));
|
||||
return Promise.resolve(new Conversion(typed, arg, status, message,
|
||||
Promise.resolve(predictions)));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var Highlighter = require('../util/host').Highlighter;
|
||||
var l10n = require('../util/l10n');
|
||||
var util = require('../util/util');
|
||||
@ -151,7 +151,7 @@ exports.items = [
|
||||
}
|
||||
}
|
||||
|
||||
return promise.resolve(reply);
|
||||
return Promise.resolve(reply);
|
||||
},
|
||||
|
||||
onEnter: onEnter,
|
||||
@ -223,7 +223,7 @@ exports.items = [
|
||||
reply.matches = util.createEmptyNodeList(doc);
|
||||
}
|
||||
|
||||
return promise.resolve(reply);
|
||||
return Promise.resolve(reply);
|
||||
},
|
||||
|
||||
onEnter: onEnter,
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var l10n = require('../util/l10n');
|
||||
var Status = require('./types').Status;
|
||||
var Conversion = require('./types').Conversion;
|
||||
@ -96,12 +96,12 @@ exports.items = [
|
||||
parse: function(arg, context) {
|
||||
var msg;
|
||||
if (arg.text.replace(/^\s*-?/, '').length === 0) {
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, ''));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, ''));
|
||||
}
|
||||
|
||||
if (!this.allowFloat && (arg.text.indexOf('.') !== -1)) {
|
||||
msg = l10n.lookupFormat('typesNumberNotInt2', [ arg.text ]);
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
}
|
||||
|
||||
var value;
|
||||
@ -114,22 +114,22 @@ exports.items = [
|
||||
|
||||
if (isNaN(value)) {
|
||||
msg = l10n.lookupFormat('typesNumberNan', [ arg.text ]);
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
}
|
||||
|
||||
var max = this.getMax(context);
|
||||
if (max != null && value > max) {
|
||||
msg = l10n.lookupFormat('typesNumberMax', [ value, max ]);
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
}
|
||||
|
||||
var min = this.getMin(context);
|
||||
if (min != null && value < min) {
|
||||
msg = l10n.lookupFormat('typesNumberMin', [ value, min ]);
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
|
||||
}
|
||||
|
||||
return promise.resolve(new Conversion(value, arg));
|
||||
return Promise.resolve(new Conversion(value, arg));
|
||||
},
|
||||
|
||||
decrement: function(value, context) {
|
||||
|
@ -16,8 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
|
||||
var Promise = require('../util/promise').Promise;
|
||||
|
||||
exports.clearResourceCache = function() {
|
||||
ResourceCache.clear();
|
||||
@ -72,7 +71,7 @@ function Resource(name, type, inline, element) {
|
||||
* Get the contents of the given resource as a string.
|
||||
* The base Resource leaves this unimplemented.
|
||||
*/
|
||||
Resource.prototype.getContents = function() {
|
||||
Resource.prototype.loadContents = function() {
|
||||
throw new Error('not implemented');
|
||||
};
|
||||
|
||||
@ -98,8 +97,10 @@ function CssResource(domSheet) {
|
||||
|
||||
CssResource.prototype = Object.create(Resource.prototype);
|
||||
|
||||
CssResource.prototype.loadContents = function(callback) {
|
||||
callback(this.element.ownerNode.innerHTML);
|
||||
CssResource.prototype.loadContents = function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolve(this.element.ownerNode.innerHTML);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
CssResource._getAllStyles = function() {
|
||||
@ -161,22 +162,24 @@ function ScriptResource(scriptNode) {
|
||||
|
||||
ScriptResource.prototype = Object.create(Resource.prototype);
|
||||
|
||||
ScriptResource.prototype.loadContents = function(callback) {
|
||||
if (this.inline) {
|
||||
callback(this.element.innerHTML);
|
||||
}
|
||||
else {
|
||||
// It would be good if there was a better way to get the script source
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState !== xhr.DONE) {
|
||||
return;
|
||||
}
|
||||
callback(xhr.responseText);
|
||||
};
|
||||
xhr.open('GET', this.element.src, true);
|
||||
xhr.send();
|
||||
}
|
||||
ScriptResource.prototype.loadContents = function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (this.inline) {
|
||||
resolve(this.element.innerHTML);
|
||||
}
|
||||
else {
|
||||
// It would be good if there was a better way to get the script source
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState !== xhr.DONE) {
|
||||
return;
|
||||
}
|
||||
resolve(xhr.responseText);
|
||||
};
|
||||
xhr.open('GET', this.element.src, true);
|
||||
xhr.send();
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ScriptResource._getAllScripts = function() {
|
||||
@ -289,9 +292,11 @@ exports.items = [
|
||||
Array.prototype.push.apply(resources, ScriptResource._getAllScripts());
|
||||
}
|
||||
|
||||
return promise.resolve(resources.map(function(resource) {
|
||||
return { name: resource.name, value: resource };
|
||||
}));
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolve(resources.map(function(resource) {
|
||||
return { name: resource.name, value: resource };
|
||||
}));
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var l10n = require('../util/l10n');
|
||||
var spell = require('../util/spell');
|
||||
var Type = require('./types').Type;
|
||||
@ -171,7 +171,7 @@ SelectionType.prototype.getLookup = function(context) {
|
||||
* returns a promise of actual values.
|
||||
*/
|
||||
function resolve(thing, context) {
|
||||
return promise.resolve(thing).then(function(resolved) {
|
||||
return Promise.resolve(thing).then(function(resolved) {
|
||||
if (typeof resolved === 'function') {
|
||||
return resolve(resolved(context), context);
|
||||
}
|
||||
@ -279,7 +279,7 @@ exports.findPredictions = function(arg, lookup) {
|
||||
};
|
||||
|
||||
SelectionType.prototype.parse = function(arg, context) {
|
||||
return promise.resolve(this.getLookup(context)).then(function(lookup) {
|
||||
return Promise.resolve(this.getLookup(context)).then(function(lookup) {
|
||||
var predictions = exports.findPredictions(arg, lookup);
|
||||
return exports.convertPredictions(arg, predictions);
|
||||
}.bind(this));
|
||||
@ -293,22 +293,22 @@ exports.convertPredictions = function(arg, predictions) {
|
||||
if (predictions.length === 0) {
|
||||
var msg = l10n.lookupFormat('typesSelectionNomatch', [ arg.text ]);
|
||||
return new Conversion(undefined, arg, Status.ERROR, msg,
|
||||
promise.resolve(predictions));
|
||||
Promise.resolve(predictions));
|
||||
}
|
||||
|
||||
if (predictions[0].name === arg.text) {
|
||||
var value = predictions[0].value;
|
||||
return new Conversion(value, arg, Status.VALID, '',
|
||||
promise.resolve(predictions));
|
||||
Promise.resolve(predictions));
|
||||
}
|
||||
|
||||
return new Conversion(undefined, arg, Status.INCOMPLETE, '',
|
||||
promise.resolve(predictions));
|
||||
Promise.resolve(predictions));
|
||||
};
|
||||
|
||||
SelectionType.prototype.getBlank = function(context) {
|
||||
var predictFunc = function(context2) {
|
||||
return promise.resolve(this.getLookup(context2)).then(function(lookup) {
|
||||
return Promise.resolve(this.getLookup(context2)).then(function(lookup) {
|
||||
return lookup.filter(function(option) {
|
||||
return !option.value.hidden;
|
||||
}).slice(0, Conversion.maxPredictions - 1);
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var Status = require('./types').Status;
|
||||
var Conversion = require('./types').Conversion;
|
||||
|
||||
@ -64,7 +64,7 @@ exports.items = [
|
||||
|
||||
parse: function(arg, context) {
|
||||
if (!this.allowBlank && (arg.text == null || arg.text === '')) {
|
||||
return promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, ''));
|
||||
return Promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, ''));
|
||||
}
|
||||
|
||||
// The string '\\' (i.e. an escaped \ (represented here as '\\\\' because it
|
||||
@ -87,7 +87,7 @@ exports.items = [
|
||||
.replace(/\\}/g, '}')
|
||||
.replace(/\uF000/g, '\\');
|
||||
|
||||
return promise.resolve(new Conversion(value, arg));
|
||||
return Promise.resolve(new Conversion(value, arg));
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -17,7 +17,7 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('../util/util');
|
||||
var promise = require('../util/promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
|
||||
/**
|
||||
* We record where in the input string an argument comes so we can report
|
||||
@ -814,7 +814,7 @@ Conversion.prototype.getPredictions = function(context) {
|
||||
if (typeof this.predictions === 'function') {
|
||||
return this.predictions(context);
|
||||
}
|
||||
return promise.resolve(this.predictions || []);
|
||||
return Promise.resolve(this.predictions || []);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -825,7 +825,7 @@ Conversion.prototype.getPredictions = function(context) {
|
||||
*/
|
||||
Conversion.prototype.constrainPredictionIndex = function(context, index) {
|
||||
if (index == null) {
|
||||
return promise.resolve();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return this.getPredictions(context).then(function(value) {
|
||||
|
@ -67,7 +67,11 @@ function Menu(options) {
|
||||
menuHtmlPromise = host.staticRequire(module, './menu.html');
|
||||
}
|
||||
menuHtmlPromise.then(function(menuHtml) {
|
||||
this.template = util.toDom(this.document, menuHtml);
|
||||
if (this.document == null) {
|
||||
return; // destroy() has been called
|
||||
}
|
||||
|
||||
this.template = host.toDom(this.document, menuHtml);
|
||||
}.bind(this), console.error);
|
||||
|
||||
// Contains the items that should be displayed
|
||||
|
@ -17,6 +17,7 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('../util/util');
|
||||
var host = require('../util/host');
|
||||
var domtemplate = require('../util/domtemplate');
|
||||
|
||||
|
||||
@ -78,7 +79,7 @@ exports.createView = function(options) {
|
||||
util.importCss(options.css, document, options.cssId);
|
||||
}
|
||||
|
||||
var child = util.toDom(document, options.html);
|
||||
var child = host.toDom(document, options.html);
|
||||
domtemplate.template(child, options.data || {}, options.options || {});
|
||||
return child;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ var Cc = require('chrome').Cc;
|
||||
var Ci = require('chrome').Ci;
|
||||
|
||||
var OS = Cu.import('resource://gre/modules/osfile.jsm', {}).OS;
|
||||
var promise = require('./promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
|
||||
/**
|
||||
* A set of functions that don't really belong in 'fs' (because they're not
|
||||
@ -122,5 +122,5 @@ exports.stat = function(pathname) {
|
||||
* Right now, however, we do nothing.
|
||||
*/
|
||||
exports.describe = function(pathname) {
|
||||
return promise.resolve('');
|
||||
return Promise.resolve('');
|
||||
};
|
||||
|
@ -21,7 +21,7 @@ var Ci = require('chrome').Ci;
|
||||
|
||||
var Task = require('resource://gre/modules/Task.jsm').Task;
|
||||
|
||||
var promise = require('./promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
var util = require('./util');
|
||||
|
||||
function Highlighter(document) {
|
||||
@ -71,17 +71,27 @@ exports.exec = function(task) {
|
||||
return Task.spawn(task);
|
||||
};
|
||||
|
||||
/**
|
||||
* Load some HTML into the given document and return a DOM element.
|
||||
* This utility assumes that the html has a single root (other than whitespace)
|
||||
*/
|
||||
exports.toDom = function(document, html) {
|
||||
var div = util.createElement(document, 'div');
|
||||
util.setContents(div, html);
|
||||
return div.children[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* When dealing with module paths on windows we want to use the unix
|
||||
* directory separator rather than the windows one, so we avoid using
|
||||
* OS.Path.dirname, and use unix version on all platforms.
|
||||
*/
|
||||
let resourceDirName = function(path) {
|
||||
let index = path.lastIndexOf("/");
|
||||
var resourceDirName = function(path) {
|
||||
var index = path.lastIndexOf('/');
|
||||
if (index == -1) {
|
||||
return ".";
|
||||
return '.';
|
||||
}
|
||||
while (index >= 0 && path[index] == "/") {
|
||||
while (index >= 0 && path[index] == '/') {
|
||||
--index;
|
||||
}
|
||||
return path.slice(0, index + 1);
|
||||
@ -92,37 +102,30 @@ let resourceDirName = function(path) {
|
||||
* @see lib/gcli/util/host.js
|
||||
*/
|
||||
exports.staticRequire = function(requistingModule, name) {
|
||||
var deferred = promise.defer();
|
||||
|
||||
if (name.match(/\.css$/)) {
|
||||
deferred.resolve('');
|
||||
return Promise.resolve('');
|
||||
}
|
||||
else {
|
||||
var filename = resourceDirName(requistingModule.id) + '/' + name;
|
||||
filename = filename.replace(/\/\.\//g, '/');
|
||||
filename = 'resource://gre/modules/devtools/' + filename;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var filename = resourceDirName(requistingModule.id) + '/' + name;
|
||||
filename = filename.replace(/\/\.\//g, '/');
|
||||
filename = 'resource://gre/modules/devtools/' + filename;
|
||||
|
||||
var xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
var xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
|
||||
xhr.onload = function onload() {
|
||||
deferred.resolve(xhr.responseText);
|
||||
}.bind(this);
|
||||
xhr.onload = function onload() {
|
||||
resolve(xhr.responseText);
|
||||
}.bind(this);
|
||||
|
||||
xhr.onabort = xhr.onerror = xhr.ontimeout = function(err) {
|
||||
deferred.reject(err);
|
||||
}.bind(this);
|
||||
xhr.onabort = xhr.onerror = xhr.ontimeout = function(err) {
|
||||
reject(err);
|
||||
}.bind(this);
|
||||
|
||||
try {
|
||||
xhr.open('GET', filename);
|
||||
xhr.send();
|
||||
}
|
||||
catch (ex) {
|
||||
deferred.reject(ex);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -146,64 +149,62 @@ exports.script.useTarget = function(tgt) {
|
||||
|
||||
// Local debugging needs to make the target remote.
|
||||
var targetPromise = target.isRemote ?
|
||||
promise.resolve(target) :
|
||||
Promise.resolve(target) :
|
||||
target.makeRemote();
|
||||
|
||||
return targetPromise.then(function() {
|
||||
var deferred = promise.defer();
|
||||
return new Promise(function(resolve, reject) {
|
||||
client = target._client;
|
||||
|
||||
client = target._client;
|
||||
client.addListener('pageError', function(packet) {
|
||||
if (packet.from === consoleActor) {
|
||||
// console.log('pageError', packet.pageError);
|
||||
exports.script.onOutput({
|
||||
level: 'exception',
|
||||
message: packet.exception.class
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
client.addListener('pageError', function(packet) {
|
||||
if (packet.from === consoleActor) {
|
||||
// console.log('pageError', packet.pageError);
|
||||
exports.script.onOutput({
|
||||
level: 'exception',
|
||||
message: packet.exception.class
|
||||
});
|
||||
}
|
||||
});
|
||||
client.addListener('consoleAPICall', function(type, packet) {
|
||||
if (packet.from === consoleActor) {
|
||||
var data = packet.message;
|
||||
|
||||
client.addListener('consoleAPICall', function(type, packet) {
|
||||
if (packet.from === consoleActor) {
|
||||
var data = packet.message;
|
||||
|
||||
var ev = {
|
||||
level: data.level,
|
||||
arguments: data.arguments,
|
||||
};
|
||||
|
||||
if (data.filename !== 'debugger eval code') {
|
||||
ev.source = {
|
||||
filename: data.filename,
|
||||
lineNumber: data.lineNumber,
|
||||
functionName: data.functionName
|
||||
var ev = {
|
||||
level: data.level,
|
||||
arguments: data.arguments,
|
||||
};
|
||||
|
||||
if (data.filename !== 'debugger eval code') {
|
||||
ev.source = {
|
||||
filename: data.filename,
|
||||
lineNumber: data.lineNumber,
|
||||
functionName: data.functionName
|
||||
};
|
||||
}
|
||||
|
||||
exports.script.onOutput(ev);
|
||||
}
|
||||
});
|
||||
|
||||
consoleActor = target._form.consoleActor;
|
||||
|
||||
var onAttach = function(response, wcc) {
|
||||
webConsoleClient = wcc;
|
||||
|
||||
if (response.error != null) {
|
||||
reject(response);
|
||||
}
|
||||
else {
|
||||
resolve(response);
|
||||
}
|
||||
|
||||
exports.script.onOutput(ev);
|
||||
}
|
||||
});
|
||||
// TODO: add _onTabNavigated code?
|
||||
};
|
||||
|
||||
consoleActor = target._form.consoleActor;
|
||||
|
||||
var onAttach = function(response, wcc) {
|
||||
webConsoleClient = wcc;
|
||||
|
||||
if (response.error != null) {
|
||||
deferred.reject(response);
|
||||
}
|
||||
else {
|
||||
deferred.resolve(response);
|
||||
}
|
||||
|
||||
// TODO: add _onTabNavigated code?
|
||||
};
|
||||
|
||||
var listeners = [ 'PageError', 'ConsoleAPI' ];
|
||||
client.attachConsole(consoleActor, listeners, onAttach);
|
||||
|
||||
return deferred.promise;
|
||||
var listeners = [ 'PageError', 'ConsoleAPI' ];
|
||||
client.attachConsole(consoleActor, listeners, onAttach);
|
||||
}.bind(this));
|
||||
});
|
||||
};
|
||||
|
||||
@ -211,21 +212,20 @@ exports.script.useTarget = function(tgt) {
|
||||
* Execute some JavaScript
|
||||
*/
|
||||
exports.script.eval = function(javascript) {
|
||||
var deferred = promise.defer();
|
||||
return new Promise(function(resolve, reject) {
|
||||
var onResult = function(response) {
|
||||
var output = response.result;
|
||||
if (typeof output === 'object' && output.type === 'undefined') {
|
||||
output = undefined;
|
||||
}
|
||||
|
||||
var onResult = function(response) {
|
||||
var output = response.result;
|
||||
if (typeof output === 'object' && output.type === 'undefined') {
|
||||
output = undefined;
|
||||
}
|
||||
resolve({
|
||||
input: response.input,
|
||||
output: output,
|
||||
exception: response.exception
|
||||
});
|
||||
};
|
||||
|
||||
deferred.resolve({
|
||||
input: response.input,
|
||||
output: output,
|
||||
exception: response.exception
|
||||
});
|
||||
};
|
||||
|
||||
webConsoleClient.evaluateJS(javascript, onResult, {});
|
||||
return deferred.promise;
|
||||
webConsoleClient.evaluateJS(javascript, onResult, {});
|
||||
}.bind(this));
|
||||
};
|
||||
|
@ -17,9 +17,94 @@
|
||||
'use strict';
|
||||
|
||||
var Cu = require('chrome').Cu;
|
||||
module.exports = exports =
|
||||
Cu.import('resource://gre/modules/devtools/deprecated-sync-thenables.js', {}).Promise;
|
||||
var Cc = require('chrome').Cc;
|
||||
var Ci = require('chrome').Ci;
|
||||
|
||||
// When we've solved the debugger/sdk/promise/gcli/helpers/overlap problem then
|
||||
// we should use this instead:
|
||||
// module.exports = exports = require('resource://gre/modules/Promise.jsm').Promise;
|
||||
/*
|
||||
* Minimalist implementation of ES6 promises built on SDK promises. 2 things to
|
||||
* know:
|
||||
* - There is a hack in .then() to be async which matches A+ and toolkit
|
||||
* promises. GCLI code works with either sync or async promises, but async
|
||||
* is more correct
|
||||
* - There is an additional Promise.defer function which to matches the call
|
||||
* in toolkit promises, which in turn matches the call in SDK promises
|
||||
*
|
||||
* Why not use toolkit promises directly? Because there is a strange bug that
|
||||
* we are investigating where thread executions vanish.
|
||||
*
|
||||
* When we've solved the debugger/sdk/promise/gcli/helpers/overlap problem then
|
||||
* we should use this instead:
|
||||
* module.exports = exports = require('resource://gre/modules/Promise.jsm');
|
||||
*/
|
||||
|
||||
var promise = require('resource://gre/modules/devtools/deprecated-sync-thenables.js', {});
|
||||
|
||||
/**
|
||||
* An implementation of ES6 promises in terms of SDK promises
|
||||
*/
|
||||
var Promise = function(executor) {
|
||||
this.deferred = promise.defer();
|
||||
try {
|
||||
executor.call(null, this.deferred.resolve, this.deferred.reject);
|
||||
}
|
||||
catch (ex) {
|
||||
this.deferred.reject(ex);
|
||||
}
|
||||
}
|
||||
|
||||
var async = true;
|
||||
|
||||
/**
|
||||
* The sync version of this would look like
|
||||
* Promise.prototype.then = function(onResolve, onReject) {
|
||||
* return this.deferred.promise.then(onResolve, onReject);
|
||||
* };
|
||||
*/
|
||||
Promise.prototype.then = function(onResolve, onReject) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeout(function() {
|
||||
try {
|
||||
resolve(this.deferred.promise.then(onResolve, onReject));
|
||||
}
|
||||
catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
}.bind(this), 0);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
Promise.all = promise.all;
|
||||
Promise.resolve = promise.resolve;
|
||||
Promise.defer = promise.defer;
|
||||
|
||||
exports.Promise = Promise;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of the setTimeout/clearTimeout web APIs taken from the old
|
||||
* Timer.jsm module
|
||||
*/
|
||||
|
||||
// This gives us >=2^30 unique timer IDs, enough for 1 per ms for 12.4 days.
|
||||
var nextTimeoutId = 1; // setTimeout must return a positive integer
|
||||
|
||||
var timeoutTable = new Map(); // int -> nsITimer
|
||||
|
||||
var setTimeout = function(callback, millis) {
|
||||
let id = nextTimeoutId++;
|
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(function setTimeout_timer() {
|
||||
timeoutTable.delete(id);
|
||||
callback.call(undefined);
|
||||
}, millis, timer.TYPE_ONE_SHOT);
|
||||
|
||||
timeoutTable.set(id, timer);
|
||||
return id;
|
||||
}
|
||||
|
||||
var clearTimeout = function(aId) {
|
||||
if (timeoutTable.has(aId)) {
|
||||
timeoutTable.get(aId).cancel();
|
||||
timeoutTable.delete(aId);
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ exports.createEvent = function(name) {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
var promise = require('./promise');
|
||||
var Promise = require('../util/promise').Promise;
|
||||
|
||||
/**
|
||||
* promiseEach is roughly like Array.forEach except that the action is taken to
|
||||
@ -252,34 +252,34 @@ var promise = require('./promise');
|
||||
*/
|
||||
exports.promiseEach = function(array, action, scope) {
|
||||
if (array.length === 0) {
|
||||
return promise.resolve([]);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
var deferred = promise.defer();
|
||||
var replies = [];
|
||||
return new Promise(function(resolve, reject) {
|
||||
var replies = [];
|
||||
|
||||
var callNext = function(index) {
|
||||
var onSuccess = function(reply) {
|
||||
replies[index] = reply;
|
||||
var callNext = function(index) {
|
||||
var onSuccess = function(reply) {
|
||||
replies[index] = reply;
|
||||
|
||||
if (index + 1 >= array.length) {
|
||||
deferred.resolve(replies);
|
||||
}
|
||||
else {
|
||||
callNext(index + 1);
|
||||
}
|
||||
if (index + 1 >= array.length) {
|
||||
resolve(replies);
|
||||
}
|
||||
else {
|
||||
callNext(index + 1);
|
||||
}
|
||||
};
|
||||
|
||||
var onFailure = function(ex) {
|
||||
reject(ex);
|
||||
};
|
||||
|
||||
var reply = action.call(scope, array[index], index, array);
|
||||
Promise.resolve(reply).then(onSuccess).then(null, onFailure);
|
||||
};
|
||||
|
||||
var onFailure = function(ex) {
|
||||
deferred.reject(ex);
|
||||
};
|
||||
|
||||
var reply = action.call(scope, array[index], index, array);
|
||||
promise.resolve(reply).then(onSuccess).then(null, onFailure);
|
||||
};
|
||||
|
||||
callNext(0);
|
||||
return deferred.promise;
|
||||
callNext(0);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -517,16 +517,6 @@ exports.setContents = function(elem, contents) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Load some HTML into the given document and return a DOM element.
|
||||
* This utility assumes that the html has a single root (other than whitespace)
|
||||
*/
|
||||
exports.toDom = function(document, html) {
|
||||
var div = exports.createElement(document, 'div');
|
||||
exports.setContents(div, html);
|
||||
return div.children[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* How to detect if we're in an XML document.
|
||||
* In a Mozilla we check that document.xmlVersion = null, however in Chrome
|
||||
|
Loading…
Reference in New Issue
Block a user