From dc734dbb0fd19f4689847f95e88db303d3710ce5 Mon Sep 17 00:00:00 2001 From: DeBaschdi Date: Thu, 9 Apr 2026 04:39:34 +0200 Subject: [PATCH 1/3] Fix calendar observers on Thunderbird 149 by replacing cal.createAdapter Replace cal.createAdapter-based calendar observers with explicit calIObserver objects ## Summary This replaces `cal.createAdapter(Ci.calIObserver, ...)` usage in the calendar experiment with explicit `calIObserver` objects using: ```js QueryInterface: ChromeUtils.generateQI(["calIObserver"]) --- .../calendar/parent/ext-calendar-calendars.js | 25 +++++++++++++++- .../calendar/parent/ext-calendar-items.js | 29 +++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/calendar/experiments/calendar/parent/ext-calendar-calendars.js b/calendar/experiments/calendar/parent/ext-calendar-calendars.js index d47a3a4..f3c1f0e 100644 --- a/calendar/experiments/calendar/parent/ext-calendar-calendars.js +++ b/calendar/experiments/calendar/parent/ext-calendar-calendars.js @@ -7,6 +7,29 @@ var { ExtensionUtils: { ExtensionError } } = ChromeUtils.importESModule("resourc var { cal } = ChromeUtils.importESModule("resource:///modules/calendar/calUtils.sys.mjs"); +/** + * Thunderbird 149 no longer exposes cal.createAdapter(). Build explicit + * calIObserver objects so the vendored calendar experiment keeps working on + * newer release channels as well as ESR. + * + * @param {object} methods + * @returns {object} + */ +function createCalendarObserver(methods = {}) { + return Object.assign({ + QueryInterface: ChromeUtils.generateQI(["calIObserver"]), + onStartBatch() {}, + onEndBatch() {}, + onLoad() {}, + onAddItem() {}, + onModifyItem() {}, + onDeleteItem() {}, + onError() {}, + onPropertyChanged() {}, + onPropertyDeleting() {}, + }, methods); +} + this.calendar_calendars = class extends ExtensionAPI { getAPI(context) { const uuid = context.extension.uuid; @@ -275,7 +298,7 @@ this.calendar_calendars = class extends ExtensionAPI { context, name: "calendar.calendars.onUpdated", register: fire => { - const observer = cal.createAdapter(Ci.calIObserver, { + const observer = createCalendarObserver({ onPropertyChanged(calendar, name, value, _oldValue) { const converted = convertCalendar(context.extension, calendar); switch (name) { diff --git a/calendar/experiments/calendar/parent/ext-calendar-items.js b/calendar/experiments/calendar/parent/ext-calendar-items.js index f36b5b0..316b4c7 100644 --- a/calendar/experiments/calendar/parent/ext-calendar-items.js +++ b/calendar/experiments/calendar/parent/ext-calendar-items.js @@ -7,6 +7,29 @@ var { ExtensionUtils: { ExtensionError } } = ChromeUtils.importESModule("resourc var { cal } = ChromeUtils.importESModule("resource:///modules/calendar/calUtils.sys.mjs"); +/** + * Thunderbird 149 no longer exposes cal.createAdapter(). Build explicit + * calIObserver objects so the vendored calendar experiment keeps working on + * newer release channels as well as ESR. + * + * @param {object} methods + * @returns {object} + */ +function createCalendarObserver(methods = {}) { + return Object.assign({ + QueryInterface: ChromeUtils.generateQI(["calIObserver"]), + onStartBatch() {}, + onEndBatch() {}, + onLoad() {}, + onAddItem() {}, + onModifyItem() {}, + onDeleteItem() {}, + onError() {}, + onPropertyChanged() {}, + onPropertyDeleting() {}, + }, methods); +} + this.calendar_items = class extends ExtensionAPI { getAPI(context) { const uuid = context.extension.uuid; @@ -164,7 +187,7 @@ this.calendar_items = class extends ExtensionAPI { context, name: "calendar.items.onCreated", register: (fire, options) => { - const observer = cal.createAdapter(Ci.calIObserver, { + const observer = createCalendarObserver({ onAddItem: item => { fire.sync(convertItem(item, options, context.extension)); }, @@ -181,7 +204,7 @@ this.calendar_items = class extends ExtensionAPI { context, name: "calendar.items.onUpdated", register: (fire, options) => { - const observer = cal.createAdapter(Ci.calIObserver, { + const observer = createCalendarObserver({ onModifyItem: (newItem, _oldItem) => { // TODO calculate changeInfo const changeInfo = {}; @@ -200,7 +223,7 @@ this.calendar_items = class extends ExtensionAPI { context, name: "calendar.items.onRemoved", register: fire => { - const observer = cal.createAdapter(Ci.calIObserver, { + const observer = createCalendarObserver({ onDeleteItem: item => { fire.sync(item.calendar.id, item.id); }, From d7acd7dec5100061eb7bd3ffdef85864712f8a34 Mon Sep 17 00:00:00 2001 From: DeBaschdi Date: Thu, 16 Apr 2026 06:40:46 +0200 Subject: [PATCH 2/3] Adjust JSDoc types --- .../experiments/calendar/parent/ext-calendar-calendars.js | 4 ++-- calendar/experiments/calendar/parent/ext-calendar-items.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/calendar/experiments/calendar/parent/ext-calendar-calendars.js b/calendar/experiments/calendar/parent/ext-calendar-calendars.js index f3c1f0e..b54785f 100644 --- a/calendar/experiments/calendar/parent/ext-calendar-calendars.js +++ b/calendar/experiments/calendar/parent/ext-calendar-calendars.js @@ -8,12 +8,12 @@ var { ExtensionUtils: { ExtensionError } } = ChromeUtils.importESModule("resourc var { cal } = ChromeUtils.importESModule("resource:///modules/calendar/calUtils.sys.mjs"); /** - * Thunderbird 149 no longer exposes cal.createAdapter(). Build explicit + * Thunderbird >=148 no longer exposes cal.createAdapter(). Build explicit * calIObserver objects so the vendored calendar experiment keeps working on * newer release channels as well as ESR. * * @param {object} methods - * @returns {object} + * @returns {calIObserver} */ function createCalendarObserver(methods = {}) { return Object.assign({ diff --git a/calendar/experiments/calendar/parent/ext-calendar-items.js b/calendar/experiments/calendar/parent/ext-calendar-items.js index 316b4c7..3d75322 100644 --- a/calendar/experiments/calendar/parent/ext-calendar-items.js +++ b/calendar/experiments/calendar/parent/ext-calendar-items.js @@ -8,12 +8,12 @@ var { ExtensionUtils: { ExtensionError } } = ChromeUtils.importESModule("resourc var { cal } = ChromeUtils.importESModule("resource:///modules/calendar/calUtils.sys.mjs"); /** - * Thunderbird 149 no longer exposes cal.createAdapter(). Build explicit + * Thunderbird >=148 no longer exposes cal.createAdapter(). Build explicit * calIObserver objects so the vendored calendar experiment keeps working on * newer release channels as well as ESR. * * @param {object} methods - * @returns {object} + * @returns {calIObserver} */ function createCalendarObserver(methods = {}) { return Object.assign({ From aaf5adbef4fd6624663bf24302e40dec81f4c00d Mon Sep 17 00:00:00 2001 From: DeBaschdi Date: Mon, 20 Apr 2026 06:10:12 +0200 Subject: [PATCH 3/3] refactor(calendar): deduplicate createCalendarObserver into shared utils Move createCalendarObserver() into ext-calendar-utils.sys.mjs and import it from ext-calendar-calendars.js and ext-calendar-items.js. This removes duplicate observer factory code while preserving behavior. --- .../calendar/ext-calendar-utils.sys.mjs | 23 ++++++++++++++++++ .../calendar/parent/ext-calendar-calendars.js | 24 +------------------ .../calendar/parent/ext-calendar-items.js | 24 +------------------ 3 files changed, 25 insertions(+), 46 deletions(-) diff --git a/calendar/experiments/calendar/ext-calendar-utils.sys.mjs b/calendar/experiments/calendar/ext-calendar-utils.sys.mjs index 3aa1354..d50d9d8 100644 --- a/calendar/experiments/calendar/ext-calendar-utils.sys.mjs +++ b/calendar/experiments/calendar/ext-calendar-utils.sys.mjs @@ -239,6 +239,29 @@ export function convertAlarm(item, alarm) { }; } +/** + * Thunderbird >=148 no longer exposes cal.createAdapter(). Build explicit + * calIObserver objects so the calendar experiment keeps working on newer + * release channels as well as ESR. + * + * @param {object} methods + * @returns {calIObserver} + */ +export function createCalendarObserver(methods = {}) { + return Object.assign({ + QueryInterface: ChromeUtils.generateQI(["calIObserver"]), + onStartBatch() {}, + onEndBatch() {}, + onLoad() {}, + onAddItem() {}, + onModifyItem() {}, + onDeleteItem() {}, + onError() {}, + onPropertyChanged() {}, + onPropertyDeleting() {}, + }, methods); +} + export async function setupE10sBrowser(extension, browser, parent, initOptions={}) { browser.setAttribute("type", "content"); browser.setAttribute("disableglobalhistory", "true"); diff --git a/calendar/experiments/calendar/parent/ext-calendar-calendars.js b/calendar/experiments/calendar/parent/ext-calendar-calendars.js index b54785f..f6fbd69 100644 --- a/calendar/experiments/calendar/parent/ext-calendar-calendars.js +++ b/calendar/experiments/calendar/parent/ext-calendar-calendars.js @@ -7,35 +7,13 @@ var { ExtensionUtils: { ExtensionError } } = ChromeUtils.importESModule("resourc var { cal } = ChromeUtils.importESModule("resource:///modules/calendar/calUtils.sys.mjs"); -/** - * Thunderbird >=148 no longer exposes cal.createAdapter(). Build explicit - * calIObserver objects so the vendored calendar experiment keeps working on - * newer release channels as well as ESR. - * - * @param {object} methods - * @returns {calIObserver} - */ -function createCalendarObserver(methods = {}) { - return Object.assign({ - QueryInterface: ChromeUtils.generateQI(["calIObserver"]), - onStartBatch() {}, - onEndBatch() {}, - onLoad() {}, - onAddItem() {}, - onModifyItem() {}, - onDeleteItem() {}, - onError() {}, - onPropertyChanged() {}, - onPropertyDeleting() {}, - }, methods); -} - this.calendar_calendars = class extends ExtensionAPI { getAPI(context) { const uuid = context.extension.uuid; const root = `experiments-calendar-${uuid}`; const query = context.extension.manifest.version; const { + createCalendarObserver, unwrapCalendar, getResolvedCalendarById, isOwnCalendar, diff --git a/calendar/experiments/calendar/parent/ext-calendar-items.js b/calendar/experiments/calendar/parent/ext-calendar-items.js index 3d75322..255ac83 100644 --- a/calendar/experiments/calendar/parent/ext-calendar-items.js +++ b/calendar/experiments/calendar/parent/ext-calendar-items.js @@ -7,35 +7,13 @@ var { ExtensionUtils: { ExtensionError } } = ChromeUtils.importESModule("resourc var { cal } = ChromeUtils.importESModule("resource:///modules/calendar/calUtils.sys.mjs"); -/** - * Thunderbird >=148 no longer exposes cal.createAdapter(). Build explicit - * calIObserver objects so the vendored calendar experiment keeps working on - * newer release channels as well as ESR. - * - * @param {object} methods - * @returns {calIObserver} - */ -function createCalendarObserver(methods = {}) { - return Object.assign({ - QueryInterface: ChromeUtils.generateQI(["calIObserver"]), - onStartBatch() {}, - onEndBatch() {}, - onLoad() {}, - onAddItem() {}, - onModifyItem() {}, - onDeleteItem() {}, - onError() {}, - onPropertyChanged() {}, - onPropertyDeleting() {}, - }, methods); -} - this.calendar_items = class extends ExtensionAPI { getAPI(context) { const uuid = context.extension.uuid; const root = `experiments-calendar-${uuid}`; const query = context.extension.manifest.version; const { + createCalendarObserver, getResolvedCalendarById, getCachedCalendar, isCachedCalendar,