Лоадер применительно к mjs не изменился?
Предполагаю что нет, так как один конвертированный скрипт в нем уже работает.
Не понял. Если сделал как написано в первой строке
конвертированного скрипта — значит изменился.
Неизменившийся у меня не работает, хотя мне казалось, что будет.
Но зачем искать себе приключений?
Для сконвертированных модулей следует использовать метод,
который сейчас в браузере для этого предназначен — ChromeUtils.importESModule("……….mjs");
И, пожалуйста, переделайте в mjs jsm-ки:
Хорошо, попробую.
[spoiler][code]var clickInterval = 5*60;
var intervals = [
10, 15, 30, 60, 3*60,/* 5*60,*/ 15*60, 30*60, 60*60,
];
var name = "TreeStyleTabAutoReloader";
var addonId =
Stkvsky
А вот это, наоборот.
Удаление закладки — вещь глобальная, лучше в этот добавлять.
Сначала, дописываем CustomizableUI
/* var {PlacesUtils: pu, ContextualIdentityService: cis, PlacesUIUtils, PrivateBrowsingUtils} = Services.wm.getMostRecentBrowserWindow(); */ var { PlacesUtils: pu, ContextualIdentityService: cis, PlacesUIUtils, PrivateBrowsingUtils, CustomizableUI } = Services.wm.getMostRecentBrowserWindow();
Это возможно как-то поправить?
Даже не знаю, может так попробовать
/* var root = doc.documentElement; var body = doc.body || root; var scroller = body.scrollHeight > root.scrollHeight ? body : root; */ var scroller = doc.scrollingElement;
код обновления не пашет в подменю
Разве? Код-то как раз пашет, но пункт не render'ится.
Когда добавляешь пункт в основное меню он render'ится сразу,
но когда в субменю, тогда нет. А когда будет следующий вызов render()
метод уже переопределён и ничего не render'ит.
Можно сразу принудительно отрендерить, но лучше, наверно, отложить.
Плюс, upd() вызывается для пунктов субменю даже просто при открытии основного меню,
а это слегка нехорошо. Возможно, стоит проверять, что субменю открыто.
Вобщем, так поменял фрагмент кода создания виджета
[spoiler][code]CustomizableUI.getWidget(id)?.label || (self => CustomizableUI.createWidget(self = {
id, label: id,
еще и этот код добавить
Код совершенно оконный, не нужно его добавлять ни в какой другой.
Просто дописать в конец, как отдельный, как следующий.
Он при открытии закладки
Нет, не так. Не просто «при открытии закладки»,
а при открытии закладки в новой вкладке (не в текущей).
в новой версии перестал работать
Можно попробовать такую правку применить, и посмотреть как пойдёт.
/* var {loadURI} = br; br.loadURI = () => { br.loadURI = loadURI; gBrowser.removeTab(tab); } */ br.fixupAndLoadURIString = () => { delete br.fixupAndLoadURIString; gBrowser.removeTab(tab); }
Получаеться что и эта кнпка не будет работать
Ну, что значит не будет работать?
В данном случае речь о том, что перестанут подхватываться иконки
встроенных поисковиков (не поисковиков, которые поставил пользователь),
когда включат search-config-v2 (пока что, только в Nightly).
А правка там простая
/* node.setAttribute("image", engine._iconURI ? engine._iconURI.spec : engine.iconURI ? engine.iconURI.spec : this.defaultImg); */ node.setAttribute("image", await engine.getIconURL?.() || engine.iconURI?.spec || this.defaultImg);
в консоль пишет: CustomizableUI: Could not localize property 'ucf-cbbtn-ToggleCurrentSearchEngine.tooltiptext'.
Да, есть такое, за всем не уследишь.
Можно добавить, например, второй строкой
localized: false,
переделать на mjs?
Что-то я не вижу там ничего такого,
что могло бы помешать сделать это самому.
Никаких выкрутасов, никаких __U
…нашел решение от Vitaliy V
Не, Виталий такую шляпу не пишет, у него всё как-то более академично.
Это моё, наверно. Кстати, ошибку свою заметил.
Настройка "browser.search.hiddenOneOffs" дефолтно существовала (до 116),
а значит, если там ничего не было, то значением возвращалась пустая строка.
А выражение ""?.split(",") возвращает массив с пустой строкой, и это совсем не то, что нужно.
А когда приземлится это, надо будет смотреть,
не слетят ли иконки встроенных лисьих поисковиков.
Ха, оказывается они уже слетели (причём, во всём браузере),
если руками включить настройку browser.search.newSearchConfig.enabled
Впрочем, теперь не важно, баг приземлился, настройку включили,
иконки встроенных лисьих поисковиков в брузере в порядке,
а в кнопке пропали
Пытаюсь разобраться
Это Bug 1870644 - Provide a single function for obtaining icon URLs from search engines
Farby предложил такую конструкцию:
engine._iconURI ? engine._iconURI.spec : engine.iconURI ? engine.iconURI.spec : this.defaultImg
что слегка замудро. Надеюсь, чуть лучше так:
(engine._iconURI || engine.iconURI)?.spec || this.defaultImg
Затем getIconURL() сделали асинхронной,
но пока ещё работает, то есть
img: e => (e._iconURI || e.iconURI)?.spec || "chrome://browser/skin/search-engine-placeholder.png",
А когда приземлится это, надо будет смотреть,
не слетят ли иконки встроенных лисьих поисковиков.
Ну, и на самой кнопке иконка не подхватывается, нужно прицепить wrappedJSObject.
[spoiler][code]/*
var engine = popup.getDefaultEngine();
*/
var e
Можно вас попросить еще добавить открытие закладки в контейнере?
В смысле вписать в первый код
результирующую фаргментов второго и третьего?
Тогда как-то так, наверно
[spoiler][code](proto => {
var g = Cu.getGlobalForObject(Cu);
var name = "userContextId2FolderGuid.json";
var obj = g[name] ??= g.eval(`(${name => {
var title;
var obj = globalThis[name] = Object.create(null);
var path = obj.path = PathUtils.join(PathUtils.profileDir, name);
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
obj.deleted = new Map();
var map = Object.create(null), guids = new Map();
var running, write = () => {
running = false;
for(var k in map) return IOUtils.writeJSON(path, map);
IOUtils.remove(path);
}
var save = () => {
if (running) timer.cancel();
timer.initWithCallback(write, 500, timer.TYPE_ONE_SHOT);
running = true;
}
var reg = (id, guid) => {
if (guid) guids.set(map[id] = guid, +id);
else guids.delete(map[id
Что ж пусть так и будет.
Сунул в custom_script.js
некий рандомно-тестовый код, и всё работает так, как ожидалось.
var bla = "bla"; var test = { "globalThis.bla": globalThis.bla, // user box, expected string "SystemGlobal.bla": Cu.getGlobalForObject(Cu).bla, // SystemGlobal, expected undefined // expected all exsists // dom idl PathUtils: PathUtils, AbortController: AbortController, HTMLAnchorElement: HTMLAnchorElement, // global properties FileReader: FileReader, XMLSerializer: XMLSerializer, URLSearchParams: URLSearchParams, // modules PlacesUtils: PlacesUtils, AppConstants: AppConstants, CustomizableUI: CustomizableUI, // internal stuff UcfPrefs: UcfPrefs, user_chrome: user_chrome, user_chrome_files_sandbox: user_chrome_files_sandbox, }; for(let key in test) test[key] = typeof test[key]; console.log(JSON.stringify(test, null, "\t"));
Это типа оператором присваивания ?
Да-да, именно им.
Они всё равно перебираются в цикле, вот прямо там и присвоить.
Можно ещё в виде прототипа все унаследовать
sandboxPrototype: UcfPrefs.global
Ууу, мысль, несомненно, интересная.
Это был бы эпический сдвиг само́й парадигмы.
Но тогда, да, действительно, мы получим вообще всё и сразу.
тогда нужно будет опять загружать CustomizableUI и UcfPrefs
Не загружать, а сослаться. Они уже загружены.
О, спасибо!
Тогда код «Восстановить удалённое», будет, наверно, таким
[spoiler][code](async sep => {
if (!sep) return;
var key = "hasRemoveTransaction";
var raws = UcfPrefs.dbg.ref("lazy", PlacesTransactions.undo).TransactionsHistory.proxifiedToRaw;
raws[key] ??= entry => {
for(var transaction of entry) {
if (raws.get(transaction) instanceof PlacesTransactions.Remove)
return true;
}
}
var menuitem = document.createXULElement("menuitem");
for(var args of Object.entries({
closemenu: "single",
class: "menuitem-iconic",
id: "placesCmd_undoRemove",
label: "Восстановить удалённое",
oncommand: "PlacesTransactions.undo().catch(Cu.reportError);",
image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAA
именно для BrowserUsageTelemetry я бы не стал добавлять его, но если нужно для некоего кода
Не-не, конечно же, в первую очередь, для пользовательского кода.
Просто когда он уже есть, возникает соблазн
воспользоваться им и для усмирения BrowserUsageTelemetry.
Мягонькое такое воздействие, никакого насилия,
добавляем id'шники как пустые строки, и это дело умолкает.
Если будет принято решение заткнуть BrowserUsageTelemetry
как-то иначе, или не делать с этим ничего, тогда дебаггер мог бы быть lazy getter'ом.
Наверно лучше как свойство UcfPrefs. Он определён как в сандбоксе, так и в окнах браузера.
В других окнах UcfPrefs можно просто импортировать, если вдруг понадобится.
Вот, поискал, нашёл, например, такой код.
Здесь TransactionsHistory не вытащишь никак, когда исчезнет Cu.import()
А с дебаггером просто пишем UcfPrefs.dbg.ref("lazy", PlacesTransactions.undo).TransactionsHistory
Что за проект?
Поскольку никто не мог знать, что нарисуется UCF 2024 от самого́ Автора,
а желающих обезопасить педыдущий UCF от последствий завершения JSM-геноцида
как-то не наблюдалось, то чувствовалось, что отдуваться придётся мне.
Я уже упоминал, что, увы, для некоторых задач, необходим дебаггер.
Вот когда приступил пробовать править UCF, решил, что он будет встроен.
Собственно, ничего особо сделать не успел,
пока там подформатировал всякий xml-like стафф в более человеко-читаемый вид,
пока заменил все четырёх-пробелья на благородную tab'уляцию,
случилось то, что случилось, и проект, соответственно, был мгновенно остановлен.
И это, несомненно, к лучшему.
Так вот, в config.js предполагалось оставить только самый минимум,
определение nsIFile'а с путём %профиль%/chrome/user_chrome_files/init.js
проверка, что он существует, и является файлом,
и загрузка этого init.js в объект {file: этот_файл};
А сырой набросок init.js был такой, скину какой был.
Не г
добавить что это происходит только один раз при первом вызове
Да, разумеется. Но могло бы не происходить вовсе.
а где гарантии что это сейчас заведомо существующее не станет потом просто существующим или вообще не существующим
Ну так можно вообще обо всём сказать.
Хорошо, пусть сочтётся как осторожность.
Кстати, Console.sys.mjs же собираются выпилить,
неплохо бы что-то предусмотреть на такой случай.
Ещё, при переключении тулбаров посредством контекстного меню,
BrowserUsageTelemetry мусорит в консоль записью "widgetId is undefined".
Когда был проект встроить в UCF дебаггер,
то я просто добавлял id'шники в BROWSER_UI_CONTAINER_IDS
А теперь, наверно, надо какую-то функцию переопределять.
Ну, или ничего не делать, в консоль всё равно никто не смотрит.
не было цели чтобы локали изменялись без перезагрузки
OK, принято.
В XPCOMUtils.sys.mjs так и записано
Точно. Запись довольно старая, старше чем globalThis.
В чем проблемма геттера?
Проблем нет никаких.
Геттер это функция. Обратился к свойству — считай вызвал функцию.
А функция всегда возвращает одно и то же.
оставил может пригодится для использования в пользовательском коде
OK, принято.
Возможно излишняя но мне нравится lazy, не используешь не загружается лишнее
Наоборот.
В цикле всё равно идёт перебор свойств, где для каждого из них
низачем создаётся своя отдельная функция и назначается как геттер.
Когда случится обращение к этому свойству,
геттер-функция низачем проверит, есть ли такое свойство в SystemGlobal,
ведь оно есть и было, перезапишет как свойство сандбокса, и вернёт значение.
Создание множества этих функций, которые проверяют уже заранее известное,
и возвращающих нечто заведомо сущест
вот эта кнопка отвалиться когда выпилят jsm?
В этом смысле — вроде не должна.
Vitaliy V.
Насчёт UcfPrefs.mjs. Сперва по Fluent'у.
Лис 124 ru. Поставил langpack'и uk и de.
STR: Включаю de, рестарт. Открываю «Настройки UserChromeFiles»,
окно локализировано как ru, это нормально, сборка ведь ru, а de отсутствует.
Теперь переключаюсь на uk.
ER: Локализация в окне меняется на uk, ведь uk есть.
AR: Ничего не происходит, локализация остаётся ru.
Да, я понимаю, что STR довольно экзотичен.
Но, может быть, заменить appLocalesAsBCP47 на availableLocales
И по коду.
Первая строка var global = Cu.getGlobalForObject({}); Разве это не globalThis?
И, UcfPrefs.global да, полезно пробросить, но почему геттер, а не просто значение?
UcfPrefs.defineGlobalGetters есть, но в само́м UCF нигде не используется.
UcfPrefs.defineLazyGlobalGetters есть, но нужно ли это?
Вот, добавил в config.js, в самое начало, ещё до антиподписячего (мне можно),
чтобы не было никаки
ifln
Вроде помогает заменить setTimeout на content.setTimeout
Bug 1878401 - Always pass BrowsingContext to nsIFilePicker::Init (Firefox 125+)
Соберу, на всякий случай, Custom Buttons 0.0.7.0.0.33.
Массив вместе с субменю есть в ucf_hookClicks.js, вложенность любая.
Да, теперь чуть понятнее, наверно.
А то я думал, к чему это /^(sub|sep|inf|lab|img)$/.test(key)
Оказывается, что если вписан sub, код прогоняет через for in
объект в который вписан sub.
То есть, и для ключей, упомянутых в этом регулярном выражении
тоже создаётся (ненужный) элемент (как минимум <menuitem>)
и ему присваивается одноимённый атрибут "label".
Если значение ключа окажется строкой, то тогда создаётся не <menuitem>,
а <menu>, и создаётся <menupopup>, который добавляется к этому menu.
Всё потому, что у строки есть sub.
Вот проверь с консоли: var {sub} = "bla-bla"; alert(sub);
Это будет — String.prototype.sub().
Эти ненужные элементы можно посмотреть в консоли,
если добавить в конец метода fill() строку
if (!item.parentNode) console.log(item.outerHTML);
Вот чтобы всё это низачем-со
…Ссылки кликабельны
Здесь можно переделать. Переименовать UcfTextToLinkActorChild.{ jsm —> mjs } и правки
[spoiler]
В text-to-link.js
/* moduleURI: "chrome://user_chrome_files/content/custom_scripts/UcfTextToLinkActorChild.jsm", */ esModuleURI: "chrome://user_chrome_files/content/custom_scripts/UcfTextToLinkActorChild.mjs"
В UcfTextToLinkActorChild.mjs
[code]/*
var EXPORTED_SYMBOLS = ["UcfTextToLinkActorChild"];
var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGlobalGetters(this, ["NodeFilter", "Node"]);
XPCOMUtils.defineLazyGetter(this, "excludedTags", () => {
return new Set(["a","svg","canvas","applet","input","button","area","embed","noembed","frame","frameset","head","iframe","img","select","option","datalist","map","meta","noscript","video","audio","object","param","script","style","textarea","code"]);
});
class UcfTextToLinkActorC
…Stkvsky
Ууу, это сложновато для меня.
Нужно карту сопоставления userContextId и guid'а папки
куда-то на диск сбрасывать.
Вот, не всё, что хотелось бы, да и запутаться могу запросто,
и тестировать это весьма заморочно.
[spoiler][code](proto => {
var g = Cu.getGlobalForObject(Cu);
var name = "userContextId2FolderGuid.json";
var obj = g[name] ??= g.eval(`(${name => {
var obj = globalThis[name] = Object.create(null);
var path = obj.path = PathUtils.join(PathUtils.profileDir, name);
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
obj.deleted = new Map();
var map = Object.create(null), guids = new Map();
var running, write = () => {
running = false;
for(var k in map) return IOUtils.writeJSON(path, map);
IOUtils.remove(path);
}
var save = () => {
if (running) timer.cancel();
timer.initWithCallback(write, 500, timer.TYPE_ONE_SHOT);
running = true;
}
var reg = (id, guid) => {
if (guid) guids.set(map[id] = guid, +id);
Раз это не в скрипте проблема
Кстати, скрипт под багом ходит (1552815).
Движуха там затихла, но в любой момент это дело могут пнуть,
и баг вывалится как "FIXED". Прикинь тогда разгребать.
.jsm
А вот и баг о временах и сроках.
Может завести какую-нибудь папку с любым условным названием типа «129».
Запилить на неё readme, мол здесь вам (пока) не что-то готовое,
но всего лишь WIP-полигон миграции JSM —> ESM.
Это я в том смысле, что время пока есть,
и «подстелить соломку», а не чтобы как «снег на голову».
Совместимость, разумеется, может и должна быть сброшена.
Stkvsky
Проблема в том, что закладке хорошо бы назначить имя,
такое же, как у этой вкладки в итоге.
Но вкладка свежеиспечённая, ещё только пошла грузиться,
и когда она разродится своим окончательным именем поймать не получается.
Хотел подрядить ProgressListener, но успеха не снискал,
а пробовать что-то ещё мудрёнее желания нет.
Таким образом, могу предложить лишь таймаут,
типа ждём секунду, и добавляем закладку с таким именем,
которое будет у таба на тот момент. Надеюсь, лучше чем ничего.
Код на замену
[spoiler][code](proto => {
var title, bm = PlacesUtils.bookmarks;
var {toolbarGuid: parentGuid, TYPE_FOLDER: type} = bm;
var wait = resolve => setTimeout(resolve, 1000);
var ntc = async br => {
var tab = gBrowser.getTabForBrowser(br);
var {guid} = await bm.insert({title, parentGuid, type});
await new Promise(wait);
bm.insert({title: tab.label, url: br.currentURI.spec, parentGuid: guid});
}
var ds = proto.doSearch;
proto.doSearch = function(str, where, e, para
Чтобы если создается контейнер, тогда на панели закладок создается папка с таким же названием как у контейнера
и в эту папку добавляется вкладка из этого контейнера
Не смог понять что за вкладка такая особенная,
и чем обеспечивается её предсуществование
в момент создания контейнера.
А с первой не поможите?
Это баг 1872673 - Remove 'console' export from Console.sys.mjs
То есть, дело не в коде кнопки, а в само́м UCF.
Но держать отладочный консольский стафф в кнопке постоянно
не требуется, можешь просто удалить console.log(req)
Однако, вернуть в укфский сандбокс консоль не помешает.
Я тут в user_chrome.js так переставлял
[spoiler][code]/*
if ("defineLazyModuleGetters" in XPCOMUtils)
XPCOMUtils.defineLazyModuleGetters(scope, {
console: "resource://gre/modules/Console.jsm",
AddonManager: "resource://gre/modules/AddonManager.jsm",
AppConstants: "resource://gre/modules/AppConstants.jsm",
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
FileUtils: "resource://gre/modules/FileUtils.jsm",
OS: "resour