qnap 192.168.0.123:419 "await is a reserved identifier" error

For support with specific websites

Moderator: trava90

Forum rules
Please always mention the name/domain of the website in question in your topic title.
Please one website per topic thread (to help keep things organized). While behavior on different sites might at first glance seem similar, they are not necessarily caused by the same.

Please try to include any relevant output from the Toolkit Error Console or the Developer Tools Web Console using the following procedure:
  1. Clear any current output
  2. Navigate or refresh the page in question
  3. Copy and paste Errors or seemingly relevant Warnings into a single [ code ] block.
User avatar
sciuro
Hobby Astronomer
Hobby Astronomer
Posts: 15
Joined: 2018-09-15, 18:16

qnap 192.168.0.123:419 "await is a reserved identifier" error

Post by sciuro » 2025-05-28, 03:33

Please, can you advise what filter to add in JustOff / modify-http-response
for
accesing a local qnap 192.168.0.123:419
with
"await is a reserved identifier" error?

I know this can happen when the browser encounters a top-level await statement, which is not yet fully supported in Pale Moon.
Still, it will be very nice to avoid starting Chrome just for local access to my Qnap, if it is possible of course.

User avatar
adoxa
Lunatic
Lunatic
Posts: 441
Joined: 2019-03-16, 13:26
Location: Qld, Aus.

Re: qnap 192.168.0.123:419 "await is a reserved identifier" error

Post by adoxa » 2025-05-28, 06:25

Without access to the script in question it's hard to advise anything. You could try replacing /await /g with nothing, but that's not likely to work (it will fix this error, but probably break a lot of other things). Unless you can make the script available, that's the best we can do.

User avatar
sciuro
Hobby Astronomer
Hobby Astronomer
Posts: 15
Joined: 2018-09-15, 18:16

Re: qnap 192.168.0.123:419 "await is a reserved identifier" error

Post by sciuro » 2025-05-28, 17:18

Code: Select all

const { appCenterSetting } = await import(`./appCenterSetting.js?${window.URL_RANDOM_NUM}`);

const APP_REQUEST_CGI = '/cgi-bin/application/appRequest.cgi';

function convertPlatformInfo(v, itemNode) {
const platformNodes = Ext.DomQuery.select('platform', itemNode);
const platform = {};

const extractPlatformsData = platformNodes.map((node) => ({
platformIDs: Ext.DomQuery.selectValue('platformID', node).split(','),
platformExcls: Ext.DomQuery.selectValue('platformExcl', node, '').split(','),
location: Ext.DomQuery.selectValue('location', node, ''),
}));

extractPlatformsData.forEach(({ platformIDs, platformExcls, location }) => {
platformIDs.forEach((platformID) => {
platform[platformID] = {
location,
platformExcls,
};
});
});

return platform;
}

function convertIconPath(path, itemNode) {
const version = Ext.DomQuery.selectValue('version', itemNode, window.URL_RANDOM_NUM);
const newPath = path.replace(/(\?.*)?$/, `?${version}`);

try {
return new URL(newPath).href;
} catch (e) {
}

return encodeURIComponent(newPath);
}

function updateOptField(record) {
record.set('priority', record.get('phase') === 'beta' ? 2 : 1);
record.set('sourceXml', 'opt');
}

class OnlineQPKGStore extends Ext.data.XmlStore {
record = 'item';

fields = [
'name',
'internalName',
'category',
{
name: 'icon',
convert: convertIconPath,
},
{
name: 'icon80',
convert: convertIconPath,
},
{
name: 'icon100',
convert: convertIconPath,
},
'description',
'moreDescription',
'version',
'keyword',
'publishedDate',
'maintainer',
'forumLink',
{
name: 'ccode',
defaultValue: '0',
},
{
name: 'licChk',
defaultValue: '0',
},
'wikiLink',
{
name: 'platform',
convert: convertPlatformInfo,
},
'status',
{
name: 'class',
defaultValue: 'appCenter',
},
{
name: 'minVersion',
mapping: 'min_version',
defaultValue: '-1',
},
{
name: 'memGT',
mapping: 'memGT',
defaultValue: 0,
type: 'NUMBER',
},
{
name: 'firmwareReq',
},
{
name: 'postInstallNotice',
defaultValue: '',
},
{
name: 'phase',
defaultValue: 'official',
},
{
name: 'priority',
defaultValue: 0,
},
{
name: 'sourceXml',
defaultValue: 'standard',
},
];

loaded = false;

remoteSort = false;

sortInfo = {
field: 'priority',
direction: 'ASC',
};

static filterUnSupport(record) {
let systemMemory;
let support = true;

if (record.get('phase') === 'beta' && appCenterSetting.joinBeta === false) {
return true;
}

const { displayModelName, modelName, platform } = QNAP.QOS.config;
const { firmwareReq } = record.data;

if (!Ext.isEmpty(firmwareReq) && firmwareReq !== QNAP.QOS.config.display_firmware) {
return true; // not support
}

const { memGT } = record.data;

if (memGT > 0) {
try {
systemMemory = os.dataStore.hardware.getAt(0).get('totalMemory');
} catch (e) {
systemMemory = 0;
}

if (systemMemory === 0) {
return true; // not support
}

if (record.get('memGT') > systemMemory) {
return true; // not support
}
}

Ext.iterate(record.data.platform, (platformID, data) => {
support = false;
switch (platformID) {
case displayModelName:
case modelName:
case platform:
if (data.location.length > 0) {
support = true;
}

data.platformExcls.some((platformExcl) => {
switch (platformExcl) {
case displayModelName:
case modelName:
case platform:
support = false;
return true;
default:
}

return false;
});

if (support === true) {
return false;
}
break;
default:
}

return true;
});

if (support === false) {
return true; // not support
}

support = QNAP.QOS.lib.chkCCode(os.qpkgStore.countryCode, record.data.ccode);

return !support;
}

constructor(options) {
super(options);

this.initProxy();
this.initReader();
this.initListeners();
}

initProxy() {
if (!this.proxy) {
this.resetUrl();

this.proxy = new Ext.data.HttpProxy({ url: this.url, api: this.api });
this.proxyOpt = new Ext.data.HttpProxy({ url: this.urlOpt, api: this.api });

this.relayEvents(this.proxy, ['loadexception', 'exception']);
this.relayEvents(this.proxyOpt, ['loadexception', 'exception']);
}
}

resetUrl() {
const langCode = QNAP.QOS.lib.getLanguageCode();

this.url = QNAP.QOS.lib.getCgiUrl(APP_REQUEST_CGI, {
subfunc: 'get_qpkg_xml',
lang: langCode,
});

this.urlOpt = QNAP.QOS.lib.getCgiUrl(APP_REQUEST_CGI, {
subfunc: 'get_qpkg_xml_opt',
lang: langCode,
});
}

initReader() {
if (!this.reader) {
this.reader = new Ext.data.XmlReader(this);
if (!this.recordType) {
this.recordType = this.reader.recordType;
}
if (this.reader.onMetaChange) {
this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
}
if (this.writer) {
if (this.writer instanceof Ext.data.DataWriter === false) {
this.writer = this.buildWriter(this.writer);
}
this.writer.meta = this.reader.meta;
this.pruneModifiedRecords = true;
}
}

if (this.recordType) {
this.fields = this.recordType.prototype.fields;
}
}

initListeners() {
this.on({
load: this.onLoad.bind(this),
});
}

onLoad() {
this.loaded = true;

delete this.proxy.conn.headers;

this.removeUnSupportItem();
}

execute(action, rs, options, batch) {
if (!Ext.data.Api.isAction(action)) {
throw new Ext.data.Api.Error('execute', action);
}

options = Ext.applyIf(options || {}, {
params: {},
});

if (batch !== undefined) {
this.addToBatch(batch);
}

let doRequest = true;

if (action === 'read') {
doRequest = this.fireEvent('beforeload', this, options);
Ext.applyIf(options.params, this.baseParams);
} else {
if (this.writer.listful === true && this.restful !== true) {
rs = Ext.isArray(rs) ? rs : [rs];
} else if (Ext.isArray(rs) && rs.length === 1) {
rs = rs.shift();
}

if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
this.writer.apply(options.params, this.baseParams, action, rs);
}
}

if (doRequest !== false) {
if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
options.params.xaction = action; // <-- really old, probaby unecessary.
}

/**
* OnlineQPKGStore: 同時讀取 proxy 及 proxyOpt 資料
*/
const [standardXmlCallback, optXmlCallback] = this.createPromiseCallback(action, rs, batch);
this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, standardXmlCallback, this, options);
this.proxyOpt.request(Ext.data.Api.actions[action], rs, options.params, this.reader, optXmlCallback, this, options);
}

return doRequest;
}

/** Create promise wait proxy and proxyOpt complete */
createPromiseCallback(action, rs, batch) {
if (action !== 'read') {
return this.createCallback(action, rs, batch);
}

let resolveStandardXml;
let resolveOptXml;

const readStandardXmlPromise = new window.Promise((resolve) => {
resolveStandardXml = resolve;
});

const readOptXmlPromise = new window.Promise((resolve) => {
resolveOptXml = resolve;
});

window.Promise.all([readStandardXmlPromise, readOptXmlPromise]).then((results) => {
const combinedData = results.reduce(
(acc, { data }) => ({
records: [...acc.records, ...data.records],
totalRecords: acc.totalRecords + data.totalRecords,
success: acc.success && data.success,
}),
{ records: [], totalRecords: 0, success: true },
);

combinedData.records.sort((a, b) => a.get('priority') - b.get('priority'));
this.loadRecords(combinedData, results[0].options, combinedData.success);
});

const defData = { records: [], totalRecords: 0, success: true };

const standardXmlCallback = (data, options, success) => {
resolveStandardXml({ data: data || defData, options, success });
};

const optXmlCallback = (data, options, success) => {
data?.records.forEach(updateOptField);

resolveOptXml({ data: data || defData, options, success });
};

return [standardXmlCallback, optXmlCallback];
}

filterUnSupport(record) {
return OnlineQPKGStore.filterUnSupport(record);
}

isUnSupport(record) {
return this.filterUnSupport(record);
}

isSupport(record) {
return !this.filterUnSupport(record);
}

removeUnSupportItem() {
const removeList = this.queryBy(this.filterUnSupport);
this.remove(removeList.getRange().reverse());
this.commitChanges();
}

reset_lang() {
this.current_lang = QNAP.QOS.lib.getLanguageCode();

this.resetUrl();

this.proxy.setUrl(this.url);
this.proxyOpt.setUrl(this.urlOpt);
}

load_after_hardware() {
if (this.load_after_hardware_flag) {
this.load_after_hardware_flag = false;
this.load();
}
}

/**
*
* @param {string} name QPKG internal name
* @param {object} options
* @param {string} options.version QPKG target version
*/
getQPKGWith(name, options = {}) {
const items = this.query('internalName', new RegExp(`^${RegExp.escape(name)}$`, 'i'));

if (!options) {
return items.get(0);
}

const { version } = options;

let filterItems;
if (version) {
filterItems = items.filterBy((item) => item.get('version') === version);
}

return filterItems?.get(0) || items.get(0);
}

updateStandardXmlData(data) {
this.suspendEvents(false);
const standardItems = this.query('sourceXml', 'standard');
this.remove(standardItems.items);
this.resumeEvents();
this.loadRecords(data, { add: true }, true);
this.applySort();
}

updateOptData(data) {
this.suspendEvents(false);
const optItems = this.query('sourceXml', 'opt');
this.remove(optItems.items);
this.resumeEvents();
data.records.forEach(updateOptField);
this.loadRecords(data, { add: true }, true);
this.applySort();
}
}

export { OnlineQPKGStore };


User avatar
Moonchild
Pale Moon guru
Pale Moon guru
Posts: 37776
Joined: 2011-08-28, 17:27
Location: Motala, SE

Re: qnap 192.168.0.123:419 "await is a reserved identifier" error

Post by Moonchild » 2025-05-28, 17:24

yup, looks like the issue is the very top of the script. const { appCenterSetting } = await import(path)
you should be able to just remove the "await" there. Not sure what they are trying to achieve by cheesing async for it, anyway.
"A dead end street is a place to turn around and go into a new direction" - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite

vannilla
Moon Magic practitioner
Moon Magic practitioner
Posts: 2420
Joined: 2018-05-05, 13:29

Re: qnap 192.168.0.123:419 "await is a reserved identifier" error

Post by vannilla » 2025-05-28, 18:18

Moonchild wrote:
2025-05-28, 17:24
Not sure what they are trying to achieve by cheesing async for it, anyway.
A wild guess. "await" at the top level "pauses" the script so that the browser can move to the next one, which on paper is nice as heavy scripts do not block the loading of the page. However these "async modules" are often loaded inside the very core of the application effectively invalidating the advantages of pausing it, since the entire thing will not function until the paused script is resumed. Effectively, it's a bandwagoning effect where devs use async following some supposed belief of benefit, but in places where async would either have no effect or even make it worse.

User avatar
RealityRipple
Keeps coming back
Keeps coming back
Posts: 863
Joined: 2018-05-17, 02:34
Location: Los Berros Canyon, California

Re: qnap 192.168.0.123:419 "await is a reserved identifier" error

Post by RealityRipple » 2025-05-28, 19:55

It's just so they can use Node.JS code in a browser. They wrap everything in promises for the modularity of it, not necessarily because it's asynchronous.

User avatar
Moonchild
Pale Moon guru
Pale Moon guru
Posts: 37776
Joined: 2011-08-28, 17:27
Location: Motala, SE

Re: qnap 192.168.0.123:419 "await is a reserved identifier" error

Post by Moonchild » 2025-05-28, 21:37

RealityRipple wrote:
2025-05-28, 19:55
It's just so they can use Node.JS code in a browser. They wrap everything in promises for the modularity of it, not necessarily because it's asynchronous.
Then why don't they load it as a js module? I mean, if you're going to shove node.js into the browser anyway, might as well go all the way and modularize it.
"A dead end street is a place to turn around and go into a new direction" - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite