Atom eve seo

This commit is contained in:
2026-07-15 18:08:51 +02:00
parent 48e9e2992c
commit 7b81464a1d
665 changed files with 219503 additions and 894 deletions

File diff suppressed because it is too large Load Diff

7834
.output/server/_libs/ai.mjs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,743 @@
import { fileURLToPath as __eveFileURLToPath } from "node:url";
import { dirname as __eveDirname } from "node:path";
__eveDirname(__eveFileURLToPath(import.meta.url));
//#region node_modules/nitro/dist/node_modules/croner/dist/croner.js
function T(s) {
return Date.UTC(s.y, s.m - 1, s.d, s.h, s.i, s.s);
}
function D(s, e) {
return s.y === e.y && s.m === e.m && s.d === e.d && s.h === e.h && s.i === e.i && s.s === e.s;
}
function A(s, e) {
let t = new Date(Date.parse(s));
if (isNaN(t)) throw new Error("Invalid ISO8601 passed to timezone parser.");
let r = s.substring(9);
return r.includes("Z") || r.includes("+") || r.includes("-") ? b(t.getUTCFullYear(), t.getUTCMonth() + 1, t.getUTCDate(), t.getUTCHours(), t.getUTCMinutes(), t.getUTCSeconds(), "Etc/UTC") : b(t.getFullYear(), t.getMonth() + 1, t.getDate(), t.getHours(), t.getMinutes(), t.getSeconds(), e);
}
function v(s, e, t) {
return k(A(s, e), t);
}
function k(s, e) {
let t = new Date(T(s)), r = g(t, s.tz), a = T(s) - T(r), o = new Date(t.getTime() + a), h = g(o, s.tz);
if (D(h, s)) {
let u = /* @__PURE__ */ new Date(o.getTime() - 36e5);
return D(g(u, s.tz), s) ? u : o;
}
let l = new Date(o.getTime() + T(s) - T(h));
if (D(g(l, s.tz), s)) return l;
if (e) throw new Error("Invalid date passed to fromTZ()");
return o.getTime() > l.getTime() ? o : l;
}
function g(s, e) {
let t, r;
try {
t = new Intl.DateTimeFormat("en-US", {
timeZone: e,
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
hour12: !1
}), r = t.formatToParts(s);
} catch (i) {
let a = i instanceof Error ? i.message : String(i);
throw new RangeError(`toTZ: Invalid timezone '${e}' or date. Please provide a valid IANA timezone (e.g., 'America/New_York', 'Europe/Stockholm'). Original error: ${a}`);
}
let n = {
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0
};
for (let i of r) (i.type === "year" || i.type === "month" || i.type === "day" || i.type === "hour" || i.type === "minute" || i.type === "second") && (n[i.type] = parseInt(i.value, 10));
if (isNaN(n.year) || isNaN(n.month) || isNaN(n.day) || isNaN(n.hour) || isNaN(n.minute) || isNaN(n.second)) throw new Error(`toTZ: Failed to parse all date components from timezone '${e}'. This may indicate an invalid date or timezone configuration. Parsed components: ${JSON.stringify(n)}`);
return n.hour === 24 && (n.hour = 0), {
y: n.year,
m: n.month,
d: n.day,
h: n.hour,
i: n.minute,
s: n.second,
tz: e
};
}
function b(s, e, t, r, n, i, a) {
return {
y: s,
m: e,
d: t,
h: r,
i: n,
s: i,
tz: a
};
}
var O = [
1,
2,
4,
8,
16
];
var C = class {
pattern;
timezone;
mode;
alternativeWeekdays;
sloppyRanges;
second;
minute;
hour;
day;
month;
dayOfWeek;
year;
lastDayOfMonth;
lastWeekday;
nearestWeekdays;
starDOM;
starDOW;
starYear;
useAndLogic;
constructor(e, t, r) {
this.pattern = e, this.timezone = t, this.mode = r?.mode ?? "auto", this.alternativeWeekdays = r?.alternativeWeekdays ?? !1, this.sloppyRanges = r?.sloppyRanges ?? !1, this.second = Array(60).fill(0), this.minute = Array(60).fill(0), this.hour = Array(24).fill(0), this.day = Array(31).fill(0), this.month = Array(12).fill(0), this.dayOfWeek = Array(7).fill(0), this.year = Array(1e4).fill(0), this.lastDayOfMonth = !1, this.lastWeekday = !1, this.nearestWeekdays = Array(31).fill(0), this.starDOM = !1, this.starDOW = !1, this.starYear = !1, this.useAndLogic = !1, this.parse();
}
parse() {
if (!(typeof this.pattern == "string" || this.pattern instanceof String)) throw new TypeError("CronPattern: Pattern has to be of type string.");
this.pattern.indexOf("@") >= 0 && (this.pattern = this.handleNicknames(this.pattern).trim());
let e = this.pattern.match(/\S+/g) || [""], t = e.length;
if (e.length < 5 || e.length > 7) throw new TypeError("CronPattern: invalid configuration format ('" + this.pattern + "'), exactly five, six, or seven space separated parts are required.");
if (this.mode !== "auto") {
let n;
switch (this.mode) {
case "5-part":
n = 5;
break;
case "6-part":
n = 6;
break;
case "7-part":
n = 7;
break;
case "5-or-6-parts":
n = [5, 6];
break;
case "6-or-7-parts":
n = [6, 7];
break;
default: n = 0;
}
if (!(Array.isArray(n) ? n.includes(t) : t === n)) {
let a = Array.isArray(n) ? n.join(" or ") : n.toString();
throw new TypeError(`CronPattern: mode '${this.mode}' requires exactly ${a} parts, but pattern '${this.pattern}' has ${t} parts.`);
}
}
if (e.length === 5 && e.unshift("0"), e.length === 6 && e.push("*"), e[3].toUpperCase() === "LW" ? (this.lastWeekday = !0, e[3] = "") : e[3].toUpperCase().indexOf("L") >= 0 && (e[3] = e[3].replace(/L/gi, ""), this.lastDayOfMonth = !0), e[3] == "*" && (this.starDOM = !0), e[6] == "*" && (this.starYear = !0), e[4].length >= 3 && (e[4] = this.replaceAlphaMonths(e[4])), e[5].length >= 3 && (e[5] = this.alternativeWeekdays ? this.replaceAlphaDaysQuartz(e[5]) : this.replaceAlphaDays(e[5])), e[5].startsWith("+") && (this.useAndLogic = !0, e[5] = e[5].substring(1), e[5] === "")) throw new TypeError("CronPattern: Day-of-week field cannot be empty after '+' modifier.");
switch (e[5] == "*" && (this.starDOW = !0), this.pattern.indexOf("?") >= 0 && (e[0] = e[0].replace(/\?/g, "*"), e[1] = e[1].replace(/\?/g, "*"), e[2] = e[2].replace(/\?/g, "*"), e[3] = e[3].replace(/\?/g, "*"), e[4] = e[4].replace(/\?/g, "*"), e[5] = e[5].replace(/\?/g, "*"), e[6] && (e[6] = e[6].replace(/\?/g, "*"))), this.mode) {
case "5-part":
e[0] = "0", e[6] = "*";
break;
case "6-part":
e[6] = "*";
break;
case "5-or-6-parts":
e[6] = "*";
break;
case "6-or-7-parts": break;
case "7-part":
case "auto": break;
}
this.throwAtIllegalCharacters(e), this.partToArray("second", e[0], 0, 1), this.partToArray("minute", e[1], 0, 1), this.partToArray("hour", e[2], 0, 1), this.partToArray("day", e[3], -1, 1), this.partToArray("month", e[4], -1, 1);
let r = this.alternativeWeekdays ? -1 : 0;
this.partToArray("dayOfWeek", e[5], r, 63), this.partToArray("year", e[6], 0, 1), !this.alternativeWeekdays && this.dayOfWeek[7] && (this.dayOfWeek[0] = this.dayOfWeek[7]);
}
partToArray(e, t, r, n) {
let i = this[e], a = e === "day" && this.lastDayOfMonth, o = e === "day" && this.lastWeekday;
if (t === "" && !a && !o) throw new TypeError("CronPattern: configuration entry " + e + " (" + t + ") is empty, check for trailing spaces.");
if (t === "*") return i.fill(n);
let h = t.split(",");
if (h.length > 1) for (let l = 0; l < h.length; l++) this.partToArray(e, h[l], r, n);
else t.indexOf("-") !== -1 && t.indexOf("/") !== -1 ? this.handleRangeWithStepping(t, e, r, n) : t.indexOf("-") !== -1 ? this.handleRange(t, e, r, n) : t.indexOf("/") !== -1 ? this.handleStepping(t, e, r, n) : t !== "" && this.handleNumber(t, e, r, n);
}
throwAtIllegalCharacters(e) {
for (let t = 0; t < e.length; t++) if ((t === 3 ? /[^/*0-9,\-WwLl]+/ : t === 5 ? /[^/*0-9,\-#Ll]+/ : /[^/*0-9,\-]+/).test(e[t])) throw new TypeError("CronPattern: configuration entry " + t + " (" + e[t] + ") contains illegal characters.");
}
handleNumber(e, t, r, n) {
let i = this.extractNth(e, t), a = e.toUpperCase().includes("W");
if (t !== "day" && a) throw new TypeError("CronPattern: Nearest weekday modifier (W) only allowed in day-of-month.");
a && (t = "nearestWeekdays");
let o = parseInt(i[0], 10) + r;
if (isNaN(o)) throw new TypeError("CronPattern: " + t + " is not a number: '" + e + "'");
this.setPart(t, o, i[1] || n);
}
setPart(e, t, r) {
if (!Object.prototype.hasOwnProperty.call(this, e)) throw new TypeError("CronPattern: Invalid part specified: " + e);
if (e === "dayOfWeek") {
if (t === 7 && (t = 0), t < 0 || t > 6) throw new RangeError("CronPattern: Invalid value for dayOfWeek: " + t);
this.setNthWeekdayOfMonth(t, r);
return;
}
if (e === "second" || e === "minute") {
if (t < 0 || t >= 60) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
} else if (e === "hour") {
if (t < 0 || t >= 24) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
} else if (e === "day" || e === "nearestWeekdays") {
if (t < 0 || t >= 31) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
} else if (e === "month") {
if (t < 0 || t >= 12) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
} else if (e === "year" && (t < 1 || t >= 1e4)) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t + " (supported range: 1-9999)");
this[e][t] = r;
}
validateNotNaN(e, t) {
if (isNaN(e)) throw new TypeError(t);
}
validateRange(e, t, r, n, i) {
if (e > t) throw new TypeError("CronPattern: From value is larger than to value: '" + i + "'");
if (r !== void 0) {
if (r === 0) throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");
if (r > this[n].length) throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part (" + this[n].length + ")");
}
}
handleRangeWithStepping(e, t, r, n) {
if (e.toUpperCase().includes("W")) throw new TypeError("CronPattern: Syntax error, W is not allowed in ranges with stepping.");
let i = this.extractNth(e, t), a = i[0].match(/^(\d+)-(\d+)\/(\d+)$/);
if (a === null) throw new TypeError("CronPattern: Syntax error, illegal range with stepping: '" + e + "'");
let [, o, h, l] = a, y = parseInt(o, 10) + r, u = parseInt(h, 10) + r, d = parseInt(l, 10);
this.validateNotNaN(y, "CronPattern: Syntax error, illegal lower range (NaN)"), this.validateNotNaN(u, "CronPattern: Syntax error, illegal upper range (NaN)"), this.validateNotNaN(d, "CronPattern: Syntax error, illegal stepping: (NaN)"), this.validateRange(y, u, d, t, e);
for (let c = y; c <= u; c += d) this.setPart(t, c, i[1] || n);
}
extractNth(e, t) {
let r = e, n;
if (r.includes("#")) {
if (t !== "dayOfWeek") throw new Error("CronPattern: nth (#) only allowed in day-of-week field");
n = r.split("#")[1], r = r.split("#")[0];
} else if (r.toUpperCase().endsWith("L")) {
if (t !== "dayOfWeek") throw new Error("CronPattern: L modifier only allowed in day-of-week field (use L alone for day-of-month)");
n = "L", r = r.slice(0, -1);
}
return [r, n];
}
handleRange(e, t, r, n) {
if (e.toUpperCase().includes("W")) throw new TypeError("CronPattern: Syntax error, W is not allowed in a range.");
let i = this.extractNth(e, t), a = i[0].split("-");
if (a.length !== 2) throw new TypeError("CronPattern: Syntax error, illegal range: '" + e + "'");
let o = parseInt(a[0], 10) + r, h = parseInt(a[1], 10) + r;
this.validateNotNaN(o, "CronPattern: Syntax error, illegal lower range (NaN)"), this.validateNotNaN(h, "CronPattern: Syntax error, illegal upper range (NaN)"), this.validateRange(o, h, void 0, t, e);
for (let l = o; l <= h; l++) this.setPart(t, l, i[1] || n);
}
handleStepping(e, t, r, n) {
if (e.toUpperCase().includes("W")) throw new TypeError("CronPattern: Syntax error, W is not allowed in parts with stepping.");
let i = this.extractNth(e, t), a = i[0].split("/");
if (a.length !== 2) throw new TypeError("CronPattern: Syntax error, illegal stepping: '" + e + "'");
if (this.sloppyRanges) a[0] === "" && (a[0] = "*");
else {
if (a[0] === "") throw new TypeError("CronPattern: Syntax error, stepping with missing prefix ('" + e + "') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");
if (a[0] !== "*") throw new TypeError("CronPattern: Syntax error, stepping with numeric prefix ('" + e + "') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");
}
let o = 0;
a[0] !== "*" && (o = parseInt(a[0], 10) + r);
let h = parseInt(a[1], 10);
this.validateNotNaN(h, "CronPattern: Syntax error, illegal stepping: (NaN)"), this.validateRange(0, this[t].length - 1, h, t, e);
for (let l = o; l < this[t].length; l += h) this.setPart(t, l, i[1] || n);
}
replaceAlphaDays(e) {
return e.replace(/-sun/gi, "-7").replace(/sun/gi, "0").replace(/mon/gi, "1").replace(/tue/gi, "2").replace(/wed/gi, "3").replace(/thu/gi, "4").replace(/fri/gi, "5").replace(/sat/gi, "6");
}
replaceAlphaDaysQuartz(e) {
return e.replace(/sun/gi, "1").replace(/mon/gi, "2").replace(/tue/gi, "3").replace(/wed/gi, "4").replace(/thu/gi, "5").replace(/fri/gi, "6").replace(/sat/gi, "7");
}
replaceAlphaMonths(e) {
return e.replace(/jan/gi, "1").replace(/feb/gi, "2").replace(/mar/gi, "3").replace(/apr/gi, "4").replace(/may/gi, "5").replace(/jun/gi, "6").replace(/jul/gi, "7").replace(/aug/gi, "8").replace(/sep/gi, "9").replace(/oct/gi, "10").replace(/nov/gi, "11").replace(/dec/gi, "12");
}
handleNicknames(e) {
let t = e.trim().toLowerCase();
if (t === "@yearly" || t === "@annually") return "0 0 1 1 *";
if (t === "@monthly") return "0 0 1 * *";
if (t === "@weekly") return "0 0 * * 0";
if (t === "@daily" || t === "@midnight") return "0 0 * * *";
if (t === "@hourly") return "0 * * * *";
if (t === "@reboot") throw new TypeError("CronPattern: @reboot is not supported in this environment. This is an event-based trigger that requires system startup detection.");
return e;
}
setNthWeekdayOfMonth(e, t) {
if (typeof t != "number" && t.toUpperCase() === "L") this.dayOfWeek[e] = this.dayOfWeek[e] | 32;
else if (t === 63) this.dayOfWeek[e] = 63;
else if (t < 6 && t > 0) this.dayOfWeek[e] = this.dayOfWeek[e] | O[t - 1];
else throw new TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${t}, Type: ${typeof t}`);
}
};
var P = [
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
];
var f = [
[
"month",
"year",
0
],
[
"day",
"month",
-1
],
[
"hour",
"day",
0
],
[
"minute",
"hour",
0
],
[
"second",
"minute",
0
]
];
var m = class s {
tz;
ms;
second;
minute;
hour;
day;
month;
year;
constructor(e, t) {
if (this.tz = t, e && e instanceof Date) if (!isNaN(e)) this.fromDate(e);
else throw new TypeError("CronDate: Invalid date passed to CronDate constructor");
else if (e == null) this.fromDate(/* @__PURE__ */ new Date());
else if (e && typeof e == "string") this.fromString(e);
else if (e instanceof s) this.fromCronDate(e);
else throw new TypeError("CronDate: Invalid type (" + typeof e + ") passed to CronDate constructor");
}
getLastDayOfMonth(e, t) {
return t !== 1 ? P[t] : new Date(Date.UTC(e, t + 1, 0)).getUTCDate();
}
getLastWeekday(e, t) {
let r = this.getLastDayOfMonth(e, t), i = new Date(Date.UTC(e, t, r)).getUTCDay();
return i === 0 ? r - 2 : i === 6 ? r - 1 : r;
}
getNearestWeekday(e, t, r) {
let n = this.getLastDayOfMonth(e, t);
if (r > n) return -1;
let a = new Date(Date.UTC(e, t, r)).getUTCDay();
return a === 0 ? r === n ? r - 2 : r + 1 : a === 6 ? r === 1 ? r + 2 : r - 1 : r;
}
isNthWeekdayOfMonth(e, t, r, n) {
let a = new Date(Date.UTC(e, t, r)).getUTCDay(), o = 0;
for (let h = 1; h <= r; h++) new Date(Date.UTC(e, t, h)).getUTCDay() === a && o++;
if (n & 63 && O[o - 1] & n) return !0;
if (n & 32) {
let h = this.getLastDayOfMonth(e, t);
for (let l = r + 1; l <= h; l++) if (new Date(Date.UTC(e, t, l)).getUTCDay() === a) return !1;
return !0;
}
return !1;
}
fromDate(e) {
if (this.tz !== void 0) if (typeof this.tz == "number") this.ms = e.getUTCMilliseconds(), this.second = e.getUTCSeconds(), this.minute = e.getUTCMinutes() + this.tz, this.hour = e.getUTCHours(), this.day = e.getUTCDate(), this.month = e.getUTCMonth(), this.year = e.getUTCFullYear(), this.apply();
else try {
let t = g(e, this.tz);
this.ms = e.getMilliseconds(), this.second = t.s, this.minute = t.i, this.hour = t.h, this.day = t.d, this.month = t.m - 1, this.year = t.y;
} catch (t) {
let r = t instanceof Error ? t.message : String(t);
throw new TypeError(`CronDate: Failed to convert date to timezone '${this.tz}'. This may happen with invalid timezone names or dates. Original error: ${r}`);
}
else this.ms = e.getMilliseconds(), this.second = e.getSeconds(), this.minute = e.getMinutes(), this.hour = e.getHours(), this.day = e.getDate(), this.month = e.getMonth(), this.year = e.getFullYear();
}
fromCronDate(e) {
this.tz = e.tz, this.year = e.year, this.month = e.month, this.day = e.day, this.hour = e.hour, this.minute = e.minute, this.second = e.second, this.ms = e.ms;
}
apply() {
if (this.month > 11 || this.month < 0 || this.day > P[this.month] || this.day < 1 || this.hour > 59 || this.minute > 59 || this.second > 59 || this.hour < 0 || this.minute < 0 || this.second < 0) {
let e = new Date(Date.UTC(this.year, this.month, this.day, this.hour, this.minute, this.second, this.ms));
return this.ms = e.getUTCMilliseconds(), this.second = e.getUTCSeconds(), this.minute = e.getUTCMinutes(), this.hour = e.getUTCHours(), this.day = e.getUTCDate(), this.month = e.getUTCMonth(), this.year = e.getUTCFullYear(), !0;
} else return !1;
}
fromString(e) {
if (typeof this.tz == "number") {
let t = v(e);
this.ms = t.getUTCMilliseconds(), this.second = t.getUTCSeconds(), this.minute = t.getUTCMinutes(), this.hour = t.getUTCHours(), this.day = t.getUTCDate(), this.month = t.getUTCMonth(), this.year = t.getUTCFullYear(), this.apply();
} else return this.fromDate(v(e, this.tz));
}
findNext(e, t, r, n) {
return this._findMatch(e, t, r, n, 1);
}
_findMatch(e, t, r, n, i) {
let a = this[t], o;
r.lastDayOfMonth && (o = this.getLastDayOfMonth(this.year, this.month));
let h = !r.starDOW && t == "day" ? new Date(Date.UTC(this.year, this.month, 1, 0, 0, 0, 0)).getUTCDay() : void 0, l = this[t] + n, y = i === 1 ? (u) => u < r[t].length : (u) => u >= 0;
for (let u = l; y(u); u += i) {
let d = r[t][u];
if (t === "day" && !d) {
for (let c = 0; c < r.nearestWeekdays.length; c++) if (r.nearestWeekdays[c]) {
let M = this.getNearestWeekday(this.year, this.month, c - n);
if (M === -1) continue;
if (M === u - n) {
d = 1;
break;
}
}
}
if (t === "day" && r.lastWeekday) {
let c = this.getLastWeekday(this.year, this.month);
u - n === c && (d = 1);
}
if (t === "day" && r.lastDayOfMonth && u - n == o && (d = 1), t === "day" && !r.starDOW) {
let c = r.dayOfWeek[(h + (u - n - 1)) % 7];
if (c && c & 63) c = this.isNthWeekdayOfMonth(this.year, this.month, u - n, c) ? 1 : 0;
else if (c) throw new Error(`CronDate: Invalid value for dayOfWeek encountered. ${c}`);
r.useAndLogic ? d = d && c : !e.domAndDow && !r.starDOM ? d = d || c : d = d && c;
}
if (d) return this[t] = u - n, a !== this[t] ? 2 : 1;
}
return 3;
}
recurse(e, t, r) {
if (r === 0 && !e.starYear) {
if (this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0) {
let i = -1;
for (let a = this.year + 1; a < e.year.length && a < 1e4; a++) if (e.year[a] === 1) {
i = a;
break;
}
if (i === -1) return null;
this.year = i, this.month = 0, this.day = 1, this.hour = 0, this.minute = 0, this.second = 0, this.ms = 0;
}
if (this.year >= 1e4) return null;
}
let n = this.findNext(t, f[r][0], e, f[r][2]);
if (n > 1) {
let i = r + 1;
for (; i < f.length;) this[f[i][0]] = -f[i][2], i++;
if (n === 3) {
if (this[f[r][1]]++, this[f[r][0]] = -f[r][2], this.apply(), r === 0 && !e.starYear) {
for (; this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0 && this.year < 1e4;) this.year++;
if (this.year >= 1e4 || this.year >= e.year.length) return null;
}
return this.recurse(e, t, 0);
} else if (this.apply()) return this.recurse(e, t, r - 1);
}
return r += 1, r >= f.length ? this : (e.starYear ? this.year >= 3e3 : this.year >= 1e4) ? null : this.recurse(e, t, r);
}
increment(e, t, r) {
return this.second += t.interval !== void 0 && t.interval > 1 && r ? t.interval : 1, this.ms = 0, this.apply(), this.recurse(e, t, 0);
}
decrement(e, t) {
return this.second -= t.interval !== void 0 && t.interval > 1 ? t.interval : 1, this.ms = 0, this.apply(), this.recurseBackward(e, t, 0, 0);
}
recurseBackward(e, t, r, n = 0) {
if (n > 1e4) return null;
if (r === 0 && !e.starYear) {
if (this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0) {
let a = -1;
for (let o = this.year - 1; o >= 0; o--) if (e.year[o] === 1) {
a = o;
break;
}
if (a === -1) return null;
this.year = a, this.month = 11, this.day = 31, this.hour = 23, this.minute = 59, this.second = 59, this.ms = 0;
}
if (this.year < 0) return null;
}
let i = this.findPrevious(t, f[r][0], e, f[r][2]);
if (i > 1) {
let a = r + 1;
for (; a < f.length;) {
let o = f[a][0], h = f[a][2], l = this.getMaxPatternValue(o, e, h);
this[o] = l, a++;
}
if (i === 3) {
if (this[f[r][1]]--, r === 0) {
let y = this.getLastDayOfMonth(this.year, this.month);
this.day > y && (this.day = y);
}
if (r === 1) if (this.day <= 0) this.day = 1;
else {
let y = this.year, u = this.month;
for (; u < 0;) u += 12, y--;
for (; u > 11;) u -= 12, y++;
let d = u !== 1 ? P[u] : new Date(Date.UTC(y, u + 1, 0)).getUTCDate();
this.day > d && (this.day = d);
}
this.apply();
let o = f[r][0], h = f[r][2], l = this.getMaxPatternValue(o, e, h);
if (o === "day") {
let y = this.getLastDayOfMonth(this.year, this.month);
this[o] = Math.min(l, y);
} else this[o] = l;
if (this.apply(), r === 0) {
let y = f[1][2], u = this.getMaxPatternValue("day", e, y), d = this.getLastDayOfMonth(this.year, this.month), c = Math.min(u, d);
c !== this.day && (this.day = c, this.hour = this.getMaxPatternValue("hour", e, f[2][2]), this.minute = this.getMaxPatternValue("minute", e, f[3][2]), this.second = this.getMaxPatternValue("second", e, f[4][2]));
}
if (r === 0 && !e.starYear) {
for (; this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0;) this.year--;
if (this.year < 0) return null;
}
return this.recurseBackward(e, t, 0, n + 1);
} else if (this.apply()) return this.recurseBackward(e, t, r - 1, n + 1);
}
return r += 1, r >= f.length ? this : this.year < 0 ? null : this.recurseBackward(e, t, r, n + 1);
}
getMaxPatternValue(e, t, r) {
if (e === "day" && t.lastDayOfMonth) return this.getLastDayOfMonth(this.year, this.month);
if (e === "day" && !t.starDOW) return this.getLastDayOfMonth(this.year, this.month);
for (let n = t[e].length - 1; n >= 0; n--) if (t[e][n]) return n - r;
return t[e].length - 1 - r;
}
findPrevious(e, t, r, n) {
return this._findMatch(e, t, r, n, -1);
}
getDate(e) {
return e || this.tz === void 0 ? new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.ms) : typeof this.tz == "number" ? new Date(Date.UTC(this.year, this.month, this.day, this.hour, this.minute - this.tz, this.second, this.ms)) : k(b(this.year, this.month + 1, this.day, this.hour, this.minute, this.second, this.tz), !1);
}
getTime() {
return this.getDate(!1).getTime();
}
match(e, t) {
if (!e.starYear && (this.year < 0 || this.year >= e.year.length || e.year[this.year] === 0)) return !1;
for (let r = 0; r < f.length; r++) {
let n = f[r][0], i = f[r][2], a = this[n];
if (a + i < 0 || a + i >= e[n].length) return !1;
let o = e[n][a + i];
if (n === "day") {
if (!o) {
for (let h = 0; h < e.nearestWeekdays.length; h++) if (e.nearestWeekdays[h]) {
let l = this.getNearestWeekday(this.year, this.month, h - i);
if (l !== -1 && l === a) {
o = 1;
break;
}
}
}
if (e.lastWeekday) a === this.getLastWeekday(this.year, this.month) && (o = 1);
if (e.lastDayOfMonth) a === this.getLastDayOfMonth(this.year, this.month) && (o = 1);
if (!e.starDOW) {
let h = new Date(Date.UTC(this.year, this.month, 1, 0, 0, 0, 0)).getUTCDay(), l = e.dayOfWeek[(h + (a - 1)) % 7];
l && l & 63 && (l = this.isNthWeekdayOfMonth(this.year, this.month, a, l) ? 1 : 0), e.useAndLogic ? o = o && l : !t.domAndDow && !e.starDOM ? o = o || l : o = o && l;
}
}
if (!o) return !1;
}
return !0;
}
};
function R(s) {
if (s === void 0 && (s = {}), delete s.name, s.legacyMode !== void 0 && s.domAndDow === void 0 ? s.domAndDow = !s.legacyMode : s.domAndDow === void 0 && (s.domAndDow = !1), s.legacyMode = !s.domAndDow, s.paused = s.paused === void 0 ? !1 : s.paused, s.maxRuns = s.maxRuns === void 0 ? Infinity : s.maxRuns, s.catch = s.catch === void 0 ? !1 : s.catch, s.interval = s.interval === void 0 ? 0 : parseInt(s.interval.toString(), 10), s.utcOffset = s.utcOffset === void 0 ? void 0 : parseInt(s.utcOffset.toString(), 10), s.dayOffset = s.dayOffset === void 0 ? 0 : parseInt(s.dayOffset.toString(), 10), s.unref = s.unref === void 0 ? !1 : s.unref, s.mode = s.mode === void 0 ? "auto" : s.mode, s.alternativeWeekdays = s.alternativeWeekdays === void 0 ? !1 : s.alternativeWeekdays, s.sloppyRanges = s.sloppyRanges === void 0 ? !1 : s.sloppyRanges, ![
"auto",
"5-part",
"6-part",
"7-part",
"5-or-6-parts",
"6-or-7-parts"
].includes(s.mode)) throw new Error("CronOptions: mode must be one of 'auto', '5-part', '6-part', '7-part', '5-or-6-parts', or '6-or-7-parts'.");
if (s.startAt && (s.startAt = new m(s.startAt, s.timezone)), s.stopAt && (s.stopAt = new m(s.stopAt, s.timezone)), s.interval !== null) {
if (isNaN(s.interval)) throw new Error("CronOptions: Supplied value for interval is not a number");
if (s.interval < 0) throw new Error("CronOptions: Supplied value for interval can not be negative");
}
if (s.utcOffset !== void 0) {
if (isNaN(s.utcOffset)) throw new Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");
if (s.utcOffset < -870 || s.utcOffset > 870) throw new Error("CronOptions: utcOffset out of bounds.");
if (s.utcOffset !== void 0 && s.timezone) throw new Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.");
}
if (s.unref !== !0 && s.unref !== !1) throw new Error("CronOptions: Unref should be either true, false or undefined(false).");
if (s.dayOffset !== void 0 && s.dayOffset !== 0 && isNaN(s.dayOffset)) throw new Error("CronOptions: Invalid value passed for dayOffset, should be a number representing days to offset.");
return s;
}
function p(s) {
return Object.prototype.toString.call(s) === "[object Function]" || typeof s == "function" || s instanceof Function;
}
function _(s) {
return p(s);
}
function x(s) {
typeof Deno < "u" && typeof Deno.unrefTimer < "u" ? Deno.unrefTimer(s) : s && typeof s.unref < "u" && s.unref();
}
var W = 30 * 1e3;
var w = [];
var E = class {
name;
options;
_states;
fn;
getTz() {
return this.options.timezone || this.options.utcOffset;
}
applyDayOffset(e) {
if (this.options.dayOffset !== void 0 && this.options.dayOffset !== 0) {
let t = this.options.dayOffset * 24 * 60 * 60 * 1e3;
return new Date(e.getTime() + t);
}
return e;
}
constructor(e, t, r) {
let n, i;
if (p(t)) i = t;
else if (typeof t == "object") n = t;
else if (t !== void 0) throw new Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");
if (p(r)) i = r;
else if (typeof r == "object") n = r;
else if (r !== void 0) throw new Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");
if (this.name = n?.name, this.options = R(n), this._states = {
kill: !1,
blocking: !1,
previousRun: void 0,
currentRun: void 0,
once: void 0,
currentTimeout: void 0,
maxRuns: n ? n.maxRuns : void 0,
paused: n ? n.paused : !1,
pattern: new C("* * * * *", void 0, { mode: "auto" })
}, e && (e instanceof Date || typeof e == "string" && e.indexOf(":") > 0) ? this._states.once = new m(e, this.getTz()) : this._states.pattern = new C(e, this.options.timezone, {
mode: this.options.mode,
alternativeWeekdays: this.options.alternativeWeekdays,
sloppyRanges: this.options.sloppyRanges
}), this.name) {
if (w.find((o) => o.name === this.name)) throw new Error("Cron: Tried to initialize new named job '" + this.name + "', but name already taken.");
w.push(this);
}
return i !== void 0 && _(i) && (this.fn = i, this.schedule()), this;
}
nextRun(e) {
let t = this._next(e);
return t ? this.applyDayOffset(t.getDate(!1)) : null;
}
nextRuns(e, t) {
this._states.maxRuns !== void 0 && e > this._states.maxRuns && (e = this._states.maxRuns);
let r = t || this._states.currentRun || void 0;
return this._enumerateRuns(e, r, "next");
}
previousRuns(e, t) {
return this._enumerateRuns(e, t || void 0, "previous");
}
_enumerateRuns(e, t, r) {
let n = [], i = t ? new m(t, this.getTz()) : null, a = r === "next" ? this._next : this._previous;
for (; e--;) {
let o = a.call(this, i);
if (!o) break;
let h = o.getDate(!1);
n.push(this.applyDayOffset(h)), i = o;
}
return n;
}
match(e) {
if (this._states.once) {
let r = new m(e, this.getTz());
r.ms = 0;
let n = new m(this._states.once, this.getTz());
return n.ms = 0, r.getTime() === n.getTime();
}
let t = new m(e, this.getTz());
return t.ms = 0, t.match(this._states.pattern, this.options);
}
getPattern() {
if (!this._states.once) return this._states.pattern ? this._states.pattern.pattern : void 0;
}
getOnce() {
return this._states.once ? this._states.once.getDate() : null;
}
isRunning() {
let e = this.nextRun(this._states.currentRun), t = !this._states.paused, r = this.fn !== void 0, n = !this._states.kill;
return t && r && n && e !== null;
}
isStopped() {
return this._states.kill;
}
isBusy() {
return this._states.blocking;
}
currentRun() {
return this._states.currentRun ? this._states.currentRun.getDate() : null;
}
previousRun() {
return this._states.previousRun ? this._states.previousRun.getDate() : null;
}
msToNext(e) {
let t = this._next(e);
return t ? e instanceof m || e instanceof Date ? t.getTime() - e.getTime() : t.getTime() - new m(e).getTime() : null;
}
stop() {
this._states.kill = !0, this._states.currentTimeout && clearTimeout(this._states.currentTimeout);
let e = w.indexOf(this);
e >= 0 && w.splice(e, 1);
}
pause() {
return this._states.paused = !0, !this._states.kill;
}
resume() {
return this._states.paused = !1, !this._states.kill;
}
schedule(e) {
if (e && this.fn) throw new Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");
e && (this.fn = e);
let t = this.msToNext(), r = this.nextRun(this._states.currentRun);
return t == null || isNaN(t) || r === null ? this : (t > W && (t = W), this._states.currentTimeout = setTimeout(() => this._checkTrigger(r), t), this._states.currentTimeout && this.options.unref && x(this._states.currentTimeout), this);
}
async _trigger(e) {
this._states.blocking = !0, this._states.currentRun = new m(void 0, this.getTz());
try {
if (this.options.catch) try {
this.fn !== void 0 && await this.fn(this, this.options.context);
} catch (t) {
if (p(this.options.catch)) try {
this.options.catch(t, this);
} catch {}
}
else this.fn !== void 0 && await this.fn(this, this.options.context);
} finally {
this._states.previousRun = new m(e, this.getTz()), this._states.blocking = !1;
}
}
async trigger() {
await this._trigger();
}
runsLeft() {
return this._states.maxRuns;
}
_checkTrigger(e) {
let t = /* @__PURE__ */ new Date(), r = !this._states.paused && t.getTime() >= e.getTime(), n = this._states.blocking && this.options.protect;
r && !n ? (this._states.maxRuns !== void 0 && this._states.maxRuns--, this._trigger()) : r && n && p(this.options.protect) && setTimeout(() => this.options.protect(this), 0), this.schedule();
}
_next(e) {
let t = !!(e || this._states.currentRun), r = !1;
!e && this.options.startAt && this.options.interval && ([e, t] = this._calculatePreviousRun(e, t), r = !e), e = new m(e, this.getTz()), this.options.startAt && e && e.getTime() < this.options.startAt.getTime() && (e = this.options.startAt);
let n = this._states.once || new m(e, this.getTz());
return !r && n !== this._states.once && (n = n.increment(this._states.pattern, this.options, t)), this._states.once && this._states.once.getTime() <= e.getTime() || n === null || this._states.maxRuns !== void 0 && this._states.maxRuns <= 0 || this._states.kill || this.options.stopAt && n.getTime() >= this.options.stopAt.getTime() ? null : n;
}
_previous(e) {
let t = new m(e, this.getTz());
this.options.stopAt && t.getTime() > this.options.stopAt.getTime() && (t = this.options.stopAt);
let r = new m(t, this.getTz());
return this._states.once ? this._states.once.getTime() < t.getTime() ? this._states.once : null : (r = r.decrement(this._states.pattern, this.options), r === null || this.options.startAt && r.getTime() < this.options.startAt.getTime() ? null : r);
}
_calculatePreviousRun(e, t) {
let r = new m(void 0, this.getTz()), n = e;
if (this.options.startAt.getTime() <= r.getTime()) {
n = this.options.startAt;
let i = n.getTime() + this.options.interval * 1e3;
for (; i <= r.getTime();) n = new m(n, this.getTz()).increment(this._states.pattern, this.options, !0), i = n.getTime() + this.options.interval * 1e3;
t = !0;
}
return n === null && (n = void 0), [n, t];
}
};
//#endregion
export { E as t };

141580
.output/server/_libs/eve.mjs Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
import { fileURLToPath as __eveFileURLToPath } from "node:url";
import { dirname as __eveDirname } from "node:path";
__eveDirname(__eveFileURLToPath(import.meta.url));
//#region node_modules/hookable/dist/index.mjs
function callHooks(hooks, args, startIndex, task) {
for (let i = startIndex; i < hooks.length; i += 1) try {
const result = task ? task.run(() => hooks[i](...args)) : hooks[i](...args);
if (result && typeof result.then === "function") return Promise.resolve(result).then(() => callHooks(hooks, args, i + 1, task));
} catch (error) {
return Promise.reject(error);
}
}
var HookableCore = class {
_hooks;
constructor() {
this._hooks = {};
}
hook(name, fn) {
if (!name || typeof fn !== "function") return () => {};
this._hooks[name] = this._hooks[name] || [];
this._hooks[name].push(fn);
return () => {
if (fn) {
this.removeHook(name, fn);
fn = void 0;
}
};
}
removeHook(name, function_) {
const hooks = this._hooks[name];
if (hooks) {
const index = hooks.indexOf(function_);
if (index !== -1) hooks.splice(index, 1);
if (hooks.length === 0) this._hooks[name] = void 0;
}
}
callHook(name, ...args) {
const hooks = this._hooks[name];
if (!hooks || hooks.length === 0) return;
return callHooks(hooks, args, 0);
}
};
//#endregion
export { HookableCore as t };

View File

@@ -0,0 +1,67 @@
import { fileURLToPath as __eveFileURLToPath } from "node:url";
import { dirname as __eveDirname } from "node:path";
__eveDirname(__eveFileURLToPath(import.meta.url));
String.fromCharCode;
const ENC_SLASH_RE = /%2f/gi;
function decode(text = "") {
try {
return decodeURIComponent("" + text);
} catch {
return "" + text;
}
}
function decodePath(text) {
return decode(text.replace(ENC_SLASH_RE, "%252F"));
}
const TRAILING_SLASH_RE = /\/$|\/\?|\/#/;
const JOIN_LEADING_SLASH_RE = /^\.?\//;
function hasTrailingSlash(input = "", respectQueryAndFragment) {
if (!respectQueryAndFragment) return input.endsWith("/");
return TRAILING_SLASH_RE.test(input);
}
function withoutTrailingSlash(input = "", respectQueryAndFragment) {
if (!respectQueryAndFragment) return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
if (!hasTrailingSlash(input, true)) return input || "/";
let path = input;
let fragment = "";
const fragmentIndex = input.indexOf("#");
if (fragmentIndex !== -1) {
path = input.slice(0, fragmentIndex);
fragment = input.slice(fragmentIndex);
}
const [s0, ...s] = path.split("?");
return ((s0.endsWith("/") ? s0.slice(0, -1) : s0) || "/") + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
}
function withTrailingSlash(input = "", respectQueryAndFragment) {
if (!respectQueryAndFragment) return input.endsWith("/") ? input : input + "/";
if (hasTrailingSlash(input, true)) return input || "/";
let path = input;
let fragment = "";
const fragmentIndex = input.indexOf("#");
if (fragmentIndex !== -1) {
path = input.slice(0, fragmentIndex);
fragment = input.slice(fragmentIndex);
if (!path) return fragment;
}
const [s0, ...s] = path.split("?");
return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
}
function hasLeadingSlash(input = "") {
return input.startsWith("/");
}
function withLeadingSlash(input = "") {
return hasLeadingSlash(input) ? input : "/" + input;
}
function isNonEmptyURL(url) {
return url && url !== "/";
}
function joinURL(base, ...input) {
let url = base || "";
for (const segment of input.filter((url2) => isNonEmptyURL(url2))) if (url) {
const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
url = withTrailingSlash(url) + _segment;
} else url = segment;
return url;
}
//#endregion
export { withoutTrailingSlash as i, joinURL as n, withLeadingSlash as r, decodePath as t };

View File

@@ -0,0 +1,58 @@
import { fileURLToPath as __eveFileURLToPath } from "node:url";
import { dirname as __eveDirname } from "node:path";
__eveDirname(__eveFileURLToPath(import.meta.url));
import { t as __commonJSMin } from "../_runtime.mjs";
import { a as require_token_error, i as require_token_util } from "./@ai-sdk/gateway+[...].mjs";
//#region node_modules/@vercel/oidc/dist/token.js
var require_token = /* @__PURE__ */ __commonJSMin(((exports, module) => {
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all) __defProp(target, name, {
get: all[name],
enumerable: true
});
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var token_exports = {};
__export(token_exports, { refreshToken: () => refreshToken });
module.exports = __toCommonJS(token_exports);
var import_token_error = require_token_error();
var import_token_util = require_token_util();
async function refreshToken(options) {
let projectId = options?.project;
let teamId = options?.team;
if (!projectId && !teamId) {
const projectInfo = (0, import_token_util.findProjectInfo)();
projectId = projectInfo.projectId;
teamId = projectInfo.teamId;
} else if (!projectId || !teamId) {
const projectInfo = (0, import_token_util.findProjectInfo)();
projectId = projectId ?? projectInfo.projectId;
teamId = teamId ?? projectInfo.teamId;
}
if (!projectId) throw new import_token_error.VercelOidcTokenError("Failed to refresh OIDC token: No project specified. Try re-linking your project with `vc link`");
let maybeToken = (0, import_token_util.loadToken)(projectId);
if (!maybeToken || (0, import_token_util.isExpired)((0, import_token_util.getTokenPayload)(maybeToken.token), options?.expirationBufferMs)) {
const authToken = await (0, import_token_util.getVercelToken)({ expirationBufferMs: options?.expirationBufferMs });
maybeToken = await (0, import_token_util.getVercelOidcToken)(authToken, projectId, teamId);
if (!maybeToken) throw new import_token_error.VercelOidcTokenError("Failed to refresh OIDC token");
(0, import_token_util.saveToken)(maybeToken, projectId);
}
process.env.VERCEL_OIDC_TOKEN = maybeToken.token;
}
0 && (module.exports = { refreshToken });
}));
//#endregion
export { require_token as t };

View File

@@ -0,0 +1,38 @@
import { fileURLToPath as __eveFileURLToPath } from "node:url";
import { dirname as __eveDirname } from "node:path";
__eveDirname(__eveFileURLToPath(import.meta.url));
import { createRequire } from "node:module";
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
var __exportAll = (all, no_symbols) => {
let target = {};
for (var name in all) __defProp(target, name, {
get: all[name],
enumerable: true
});
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
return target;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
//#endregion
export { __toESM as i, __exportAll as n, __require as r, __commonJSMin as t };

View File

@@ -0,0 +1,17 @@
import { fileURLToPath as __eveFileURLToPath } from "node:url";
import { dirname as __eveDirname } from "node:path";
__eveDirname(__eveFileURLToPath(import.meta.url));
import { t as dispatchScheduleTask } from "../_libs/eve.mjs";
//#region #eve-schedule-task/eve.schedule.c2NoZWR1bGVzL3dlZWtseS50cw
const config = {
"appRoot": "C:\\Users\\timo\\Documents\\qrmaster\\QR-master",
"dev": false
};
var eve_schedule_default = {
meta: { description: "Run eve schedule \"weekly\" from \"schedules/weekly.ts\"." },
async run(event) {
return { result: await dispatchScheduleTask(event.name, config) };
}
};
//#endregion
export { eve_schedule_default as default };

2180
.output/server/index.mjs Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
function assertSync(fn){return function(...args){let result=fn(...args);if(result&&typeof result=="object"&&result instanceof Promise)throw new Error("Function unexpectedly returned a Promise");return result}}var EvalFlags={JS_EVAL_TYPE_GLOBAL:0,JS_EVAL_TYPE_MODULE:1,JS_EVAL_TYPE_DIRECT:2,JS_EVAL_TYPE_INDIRECT:3,JS_EVAL_TYPE_MASK:3,JS_EVAL_FLAG_STRICT:8,JS_EVAL_FLAG_STRIP:16,JS_EVAL_FLAG_COMPILE_ONLY:32,JS_EVAL_FLAG_BACKTRACE_BARRIER:64},IntrinsicsFlags={BaseObjects:1,Date:2,Eval:4,StringNormalize:8,RegExp:16,RegExpCompiler:32,JSON:64,Proxy:128,MapSet:256,TypedArrays:512,Promise:1024,BigInt:2048,BigFloat:4096,BigDecimal:8192,OperatorOverloading:16384,BignumExt:32768},JSPromiseStateEnum={Pending:0,Fulfilled:1,Rejected:2},GetOwnPropertyNamesFlags={JS_GPN_STRING_MASK:1,JS_GPN_SYMBOL_MASK:2,JS_GPN_PRIVATE_MASK:4,JS_GPN_ENUM_ONLY:16,JS_GPN_SET_ENUM:32,QTS_GPN_NUMBER_MASK:64,QTS_STANDARD_COMPLIANT_NUMBER:128},IsEqualOp={IsStrictlyEqual:0,IsSameValue:1,IsSameValueZero:2};export{EvalFlags,GetOwnPropertyNamesFlags,IntrinsicsFlags,IsEqualOp,JSPromiseStateEnum,assertSync};
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1,36 @@
{
"name": "@jitl/quickjs-ffi-types",
"version": "0.32.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/justjake/quickjs-emscripten"
},
"author": {
"name": "Jake Teton-Landis",
"url": "https://jake.tl"
},
"scripts": {
"check": "npx tsc --project . --noEmit",
"build": "npx tsup",
"clean": "git clean -fx dist"
},
"files": [
"LICENSE",
"dist/**/*"
],
"types": "dist/index.d.ts",
"main": "dist/index.js",
"module": "dist/index.mjs",
"exports": {
"./package.json": "./package.json",
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
}
},
"devDependencies": {
"@jitl/tsconfig": "0.32.0"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
var variant={type:"async",importFFI:()=>import("./ffi.mjs").then(mod=>mod.QuickJSAsyncFFI),importModuleLoader:()=>import("@jitl/quickjs-wasmfile-debug-asyncify/emscripten-module").then(mod=>mod.default)},src_default=variant;export{src_default as default};
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1,61 @@
{
"name": "@jitl/quickjs-wasmfile-debug-asyncify",
"license": "MIT",
"version": "0.32.0",
"description": "Variant of quickjs library: Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS CommonJS.",
"sideEffects": false,
"repository": {
"type": "git",
"url": "https://github.com/justjake/quickjs-emscripten"
},
"author": {
"name": "Jake Teton-Landis",
"url": "https://jake.tl"
},
"scripts": {
"build": "yarn build:c && yarn build:ts",
"build:c": "make",
"build:ts": "npx tsup",
"check:types": "npx tsc --project . --noEmit",
"clean": "make clean",
"prepare": "yarn clean && yarn build"
},
"files": [
"LICENSE",
"README.md",
"dist/**/*",
"!dist/*.tsbuildinfo"
],
"types": "./dist/index.d.ts",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"browser": "./dist/index.mjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"default": "./dist/index.js"
},
"./package.json": "./package.json",
"./ffi": {
"types": "./dist/ffi.d.ts",
"import": "./dist/ffi.mjs",
"require": "./dist/ffi.js",
"default": "./dist/ffi.js"
},
"./wasm": "./dist/emscripten-module.wasm",
"./emscripten-module": {
"types": "./dist/emscripten-module.browser.d.ts",
"iife": "./dist/emscripten-module.cjs",
"workerd": "./dist/emscripten-module.cloudflare.cjs",
"browser": "./dist/emscripten-module.browser.mjs",
"import": "./dist/emscripten-module.mjs",
"require": "./dist/emscripten-module.cjs",
"default": "./dist/emscripten-module.cjs"
}
},
"dependencies": {
"@jitl/quickjs-ffi-types": "0.32.0"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
var variant={type:"sync",importFFI:()=>import("./ffi.mjs").then(mod=>mod.QuickJSFFI),importModuleLoader:()=>import("@jitl/quickjs-wasmfile-debug-sync/emscripten-module").then(mod=>mod.default)},src_default=variant;export{src_default as default};
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1,61 @@
{
"name": "@jitl/quickjs-wasmfile-debug-sync",
"license": "MIT",
"version": "0.32.0",
"description": "Variant of quickjs library: Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS CommonJS.",
"sideEffects": false,
"repository": {
"type": "git",
"url": "https://github.com/justjake/quickjs-emscripten"
},
"author": {
"name": "Jake Teton-Landis",
"url": "https://jake.tl"
},
"scripts": {
"build": "yarn build:c && yarn build:ts",
"build:c": "make",
"build:ts": "npx tsup",
"check:types": "npx tsc --project . --noEmit",
"clean": "make clean",
"prepare": "yarn clean && yarn build"
},
"files": [
"LICENSE",
"README.md",
"dist/**/*",
"!dist/*.tsbuildinfo"
],
"types": "./dist/index.d.ts",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"browser": "./dist/index.mjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"default": "./dist/index.js"
},
"./package.json": "./package.json",
"./ffi": {
"types": "./dist/ffi.d.ts",
"import": "./dist/ffi.mjs",
"require": "./dist/ffi.js",
"default": "./dist/ffi.js"
},
"./wasm": "./dist/emscripten-module.wasm",
"./emscripten-module": {
"types": "./dist/emscripten-module.browser.d.ts",
"iife": "./dist/emscripten-module.cjs",
"workerd": "./dist/emscripten-module.cloudflare.cjs",
"browser": "./dist/emscripten-module.browser.mjs",
"import": "./dist/emscripten-module.mjs",
"require": "./dist/emscripten-module.cjs",
"default": "./dist/emscripten-module.cjs"
}
},
"dependencies": {
"@jitl/quickjs-ffi-types": "0.32.0"
}
}

View File

@@ -0,0 +1,30 @@
async function QuickJSRaw(moduleArg={}){var moduleRtn;var d=moduleArg,aa=!!globalThis.window,f=!!globalThis.WorkerGlobalScope,m=globalThis.process?.versions?.node&&"renderer"!=globalThis.process?.type;if(m){const {createRequire:a}=await import("node:module");var require=a(import.meta.url)}function r(a){a={log:a||function(){}};for(const c of r.eb)c(a);return d.quickJSEmscriptenExtensions=a}r.eb=[];d.quickjsEmscriptenInit=r;r.eb.push(a=>{a.getWasmMemory=function(){return t}});
var w="./this.program",x=(a,c)=>{throw c;},y=import.meta.url,z="",A,B;
if(m){var fs=require("node:fs");y.startsWith("file:")&&(z=require("node:path").dirname(require("node:url").fileURLToPath(y))+"/");B=a=>{a=C(a)?new URL(a):a;return fs.readFileSync(a)};A=async a=>{a=C(a)?new URL(a):a;return fs.readFileSync(a,void 0)};1<process.argv.length&&(w=process.argv[1].replace(/\\/g,"/"));process.argv.slice(2);x=(a,c)=>{process.exitCode=a;throw c;}}else if(aa||f){try{z=(new URL(".",y)).href}catch{}f&&(B=a=>{var c=new XMLHttpRequest;c.open("GET",a,!1);c.responseType="arraybuffer";
c.send(null);return new Uint8Array(c.response)});A=async a=>{if(C(a))return new Promise((b,e)=>{var g=new XMLHttpRequest;g.open("GET",a,!0);g.responseType="arraybuffer";g.onload=()=>{200==g.status||0==g.status&&g.response?b(g.response):e(g.status)};g.onerror=e;g.send(null)});var c=await fetch(a,{credentials:"same-origin"});if(c.ok)return c.arrayBuffer();throw Error(c.status+" : "+c.url);}}
var ba=console.log.bind(console),D=console.error.bind(console),E,F=!1,G,C=a=>a.startsWith("file://"),ca,da,ea,H,I,J,fa=!1;function ha(){var a=t.buffer;d.HEAP8=ea=new Int8Array(a);new Int16Array(a);d.HEAPU8=H=new Uint8Array(a);new Uint16Array(a);I=new Int32Array(a);J=new Uint32Array(a);new Float32Array(a);new Float64Array(a);new BigInt64Array(a);new BigUint64Array(a)}
function K(a){d.onAbort?.(a);a="Aborted("+a+")";D(a);F=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");da?.(a);throw a;}var L;async function ia(a){if(!E)try{var c=await A(a);return new Uint8Array(c)}catch{}if(a==L&&E)a=new Uint8Array(E);else if(B)a=B(a);else throw"both async and sync fetching of the wasm failed";return a}
async function ja(a,c){try{var b=await ia(a);return await WebAssembly.instantiate(b,c)}catch(e){D(`failed to asynchronously prepare wasm: ${e}`),K(e)}}async function ka(a){var c=L;if(!E&&!C(c)&&!m)try{var b=fetch(c,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(b,a)}catch(e){D(`wasm streaming compile failed: ${e}`),D("falling back to ArrayBuffer instantiation")}return ja(c,a)}
class M{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}}
var la=a=>{for(;0<a.length;)a.shift()(d)},ma=[],na=[],oa=()=>{var a=d.preRun.shift();na.push(a)},N=!0,t,pa=new TextDecoder,qa=(a,c,b,e)=>{b=c+b;if(e)return b;for(;a[c]&&!(c>=b);)++c;return c},O=(a,c,b)=>a?pa.decode(H.subarray(a,qa(H,a,c,b))):"",P=0,ra=[0,31,60,91,121,152,182,213,244,274,305,335],sa=[0,31,59,90,120,151,181,212,243,273,304,334],Q={},ta=a=>{G=a;N||0<P||(d.onExit?.(a),F=!0);x(a,new M(a))},R=a=>{if(!F)try{return a()}catch(c){c instanceof M||"unwind"==c||x(1,c)}finally{if(!(N||0<P))try{G=
a=G,ta(a)}catch(c){c instanceof M||"unwind"==c||x(1,c)}}},S=(a,c,b)=>{var e=H;if(!(0<b))return 0;var g=c;b=c+b-1;for(var h=0;h<a.length;++h){var k=a.codePointAt(h);if(127>=k){if(c>=b)break;e[c++]=k}else if(2047>=k){if(c+1>=b)break;e[c++]=192|k>>6;e[c++]=128|k&63}else if(65535>=k){if(c+2>=b)break;e[c++]=224|k>>12;e[c++]=128|k>>6&63;e[c++]=128|k&63}else{if(c+3>=b)break;e[c++]=240|k>>18;e[c++]=128|k>>12&63;e[c++]=128|k>>6&63;e[c++]=128|k&63;h++}}e[c]=0;return c-g},T={},ua=()=>{if(!U){var a={USER:"web_user",
LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:(globalThis.navigator?.language??"C").replace("-","_")+".UTF-8",_:w||"./this.program"},c;for(c in T)void 0===T[c]?delete a[c]:a[c]=T[c];var b=[];for(c in a)b.push(`${c}=${a[c]}`);U=b}return U},U,V=a=>{for(var c=0,b=0;b<a.length;++b){var e=a.charCodeAt(b);127>=e?c++:2047>=e?c+=2:55296<=e&&57343>=e?(c+=4,++b):c+=3}return c},wa=[null,[],[]],W=a=>{try{a()}catch(c){K(c)}};
function xa(a){var c=(...b)=>{X.Sa.push(a);try{return a(...b)}finally{F||(X.Sa.pop(),X.Qa&&X.state===X.Ra.Za&&0===X.Sa.length&&(X.state=X.Ra.Ua,W(ya),"undefined"!=typeof Fibers&&Fibers.nb()))}};X.ab.set(a,c);return c}function za(){return new Promise((a,c)=>{X.Wa={resolve:a,reject:c}})}function Aa(){var a=Ba(12+X.Va),c=a+12,b=X.Va;J[a>>2]=c;J[a+4>>2]=c+b;c=X.Sa[0];X.Xa.has(c)||(b=X.fb++,X.Xa.set(c,b),X.$a.set(b,c));c=X.Xa.get(c);I[a+8>>2]=c;return a}
function Ca(){var a=X.$a.get(I[X.Qa+8>>2]);a=X.ab.get(a);return R(a)}
var X={kb(a){var c=/^(qts_host_call_function|qts_host_load_module_source|qts_host_normalize_module|invoke_.*|__asyncjs__.*)$/;for(let [b,e]of Object.entries(a))"function"==typeof e&&(e.lb||c.test(b))},Ra:{Ua:0,Za:1,Ya:2,ib:3},state:0,Va:81920,Qa:null,cb:0,Sa:[],Xa:new Map,$a:new Map,ab:new Map,fb:0,Wa:null,hb:[],Ta(a){if(!F){if(X.state===X.Ra.Ua){var c=!1,b=!1;a((e=0)=>{if(!F&&(X.cb=e,c=!0,b)){X.state=X.Ra.Ya;W(()=>Da(X.Qa));"undefined"!=typeof MainLoop&&MainLoop.gb&&MainLoop.resume();e=!1;try{var g=
Ca()}catch(p){g=p,e=!0}var h=!1;if(!X.Qa){var k=X.Wa;k&&(X.Wa=null,(e?k.reject:k.resolve)(g),h=!0)}if(e&&!h)throw g;}});b=!0;c||(X.state=X.Ra.Za,X.Qa=Aa(),"undefined"!=typeof MainLoop&&MainLoop.gb&&MainLoop.pause(),W(()=>Ea(X.Qa)))}else X.state===X.Ra.Ya?(X.state=X.Ra.Ua,W(Fa),Ga(X.Qa),X.Qa=null,X.hb.forEach(R)):K(`invalid state: ${X.state}`);return X.cb}},jb:a=>X.Ta(async c=>{c(await a())})},Ja=(a,c,b,e,g)=>{function h(l){--P;0!==u&&Ha(u);return"string"===c?O(l):"boolean"===c?!!l:l}var k={string:l=>
{var v=0;if(null!==l&&void 0!==l&&0!==l){v=V(l)+1;var va=Y(v);S(l,va,v);v=va}return v},array:l=>{var v=Y(l.length);ea.set(l,v);return v}};a=d["_"+a];var p=[],u=0;if(e)for(var n=0;n<e.length;n++){var q=k[b[n]];q?(0===u&&(u=Ia()),p[n]=q(e[n])):p[n]=e[n]}b=X.Qa;e=a(...p);g=g?.async;P+=1;if(X.Qa!=b)return za().then(h);e=h(e);return g?Promise.resolve(e):e};d.wasmMemory?t=d.wasmMemory:t=new WebAssembly.Memory({initial:(d.INITIAL_MEMORY||16777216)/65536,maximum:32768});ha();d.noExitRuntime&&(N=d.noExitRuntime);
d.print&&(ba=d.print);d.printErr&&(D=d.printErr);d.wasmBinary&&(E=d.wasmBinary);d.thisProgram&&(w=d.thisProgram);if(d.preInit)for("function"==typeof d.preInit&&(d.preInit=[d.preInit]);0<d.preInit.length;)d.preInit.shift()();d.cwrap=(a,c,b,e)=>{var g=!b||b.every(h=>"number"===h||"boolean"===h);return"string"!==c&&g&&!e?d["_"+a]:(...h)=>Ja(a,c,b,h,e)};d.UTF8ToString=O;d.stringToUTF8=(a,c,b)=>S(a,c,b);d.lengthBytesUTF8=V;d.Asyncify=X;
var Ba,Ga,Ka,Ha,Y,Ia,dynCall_iii,dynCall_vii,dynCall_vi,Ea,ya,Da,Fa,La={b:(a,c,b,e)=>K(`Assertion failed: ${O(a)}, at: `+[c?O(c):"unknown filename",b,e?O(e):"unknown function"]),q:()=>K(""),l:()=>{N=!1;P=0},m:function(a,c){a=-9007199254740992>a||9007199254740992<a?NaN:Number(a);a=new Date(1E3*a);I[c>>2]=a.getSeconds();I[c+4>>2]=a.getMinutes();I[c+8>>2]=a.getHours();I[c+12>>2]=a.getDate();I[c+16>>2]=a.getMonth();I[c+20>>2]=a.getFullYear()-1900;I[c+24>>2]=a.getDay();var b=a.getFullYear();I[c+28>>2]=
(0!==b%4||0===b%100&&0!==b%400?sa:ra)[a.getMonth()]+a.getDate()-1|0;I[c+36>>2]=-(60*a.getTimezoneOffset());b=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();var e=(new Date(a.getFullYear(),0,1)).getTimezoneOffset();I[c+32>>2]=(b!=e&&a.getTimezoneOffset()==Math.min(e,b))|0},j:(a,c)=>{Q[a]&&(clearTimeout(Q[a].id),delete Q[a]);if(!c)return 0;var b=setTimeout(()=>{delete Q[a];R(()=>Ka(a,performance.now()))},c);Q[a]={id:b,mb:c};return 0},n:(a,c,b,e)=>{var g=(new Date).getFullYear(),h=(new Date(g,0,
1)).getTimezoneOffset();g=(new Date(g,6,1)).getTimezoneOffset();J[a>>2]=60*Math.max(h,g);I[c>>2]=Number(h!=g);c=k=>{var p=Math.abs(k);return`UTC${0<=k?"-":"+"}${String(Math.floor(p/60)).padStart(2,"0")}${String(p%60).padStart(2,"0")}`};a=c(h);c=c(g);g<h?(S(a,b,17),S(c,e,17)):(S(a,e,17),S(c,b,17))},p:()=>Date.now(),k:a=>{var c=H.length;a>>>=0;if(2147483648<a)return!1;for(var b=1;4>=b;b*=2){var e=c*(1+.2/b);e=Math.min(e,a+100663296);a:{e=(Math.min(2147483648,65536*Math.ceil(Math.max(a,e)/65536))-t.buffer.byteLength+
65535)/65536|0;try{t.grow(e);ha();var g=1;break a}catch(h){}g=void 0}if(g)return!0}return!1},d:(a,c)=>{var b=0,e=0,g;for(g of ua()){var h=c+b;J[a+e>>2]=h;b+=S(g,h,Infinity)+1;e+=4}return 0},e:(a,c)=>{var b=ua();J[a>>2]=b.length;a=0;for(var e of b)a+=V(e)+1;J[c>>2]=a;return 0},c:()=>52,o:function(){return 70},s:(a,c,b,e)=>{for(var g=0,h=0;h<b;h++){var k=J[c>>2],p=J[c+4>>2];c+=8;for(var u=0;u<p;u++){var n=a,q=H[k+u],l=wa[n];0===q||10===q?(n=1===n?ba:D,q=qa(l,0),q=pa.decode(l.buffer?l.subarray(0,q):
new Uint8Array(l.slice(0,q))),n(q),l.length=0):l.push(q)}g+=p}J[e>>2]=g;return 0},a:t,r:ta,i:function(a,c,b,e,g){return d.callbacks.callFunction({handleSleep:X.Ta},a,c,b,e,g)},h:function(a){return d.callbacks.shouldInterrupt(void 0,a)},g:function(a,c,b){const e={handleSleep:X.Ta};b=O(b);return d.callbacks.loadModuleSource(e,a,c,b)},f:function(a,c,b,e){const g={handleSleep:X.Ta};b=O(b);e=O(e);return d.callbacks.normalizeModule(g,a,c,b,e)},t:function(a,c){d.callbacks.freeHostRef(void 0,a,c)},u:function(a,
c){X.Va=a||c}},Z;
Z=await (async function(){function a(b){var e=Z=b.exports;b={};for(let [g,h]of Object.entries(e))"function"==typeof h?(e=xa(h),b[g]=e):b[g]=h;b=Z=b;Ba=d._malloc=b.w;d._QTS_Throw=b.x;d._QTS_NewError=b.y;d._QTS_RuntimeSetMemoryLimit=b.z;d._QTS_RuntimeComputeMemoryUsage=b.A;d._QTS_RuntimeDumpMemoryUsage=b.B;d._QTS_RecoverableLeakCheck=b.C;d._QTS_BuildIsSanitizeLeak=b.D;d._QTS_RuntimeSetMaxStackSize=b.E;d._QTS_GetUndefined=b.F;d._QTS_GetNull=b.G;d._QTS_GetFalse=b.H;d._QTS_GetTrue=b.I;d._QTS_NewHostRef=
b.J;d._QTS_GetHostRefId=b.K;d._QTS_NewRuntime=b.L;d._QTS_FreeRuntime=b.M;Ga=d._free=b.N;d._QTS_NewContext=b.O;d._QTS_FreeContext=b.P;d._QTS_FreeValuePointer=b.Q;d._QTS_FreeValuePointerRuntime=b.R;d._QTS_FreeVoidPointer=b.S;d._QTS_FreeCString=b.T;d._QTS_DupValuePointer=b.U;d._QTS_NewObject=b.V;d._QTS_NewObjectProto=b.W;d._QTS_NewArray=b.X;d._QTS_NewArrayBuffer=b.Y;d._QTS_NewFloat64=b.Z;d._QTS_GetFloat64=b._;d._QTS_NewString=b.$;d._QTS_GetString=b.aa;d._QTS_GetArrayBuffer=b.ba;d._QTS_GetArrayBufferLength=
b.ca;d._QTS_NewSymbol=b.da;d._QTS_GetSymbolDescriptionOrKey=b.ea;d._QTS_IsGlobalSymbol=b.fa;d._QTS_IsJobPending=b.ga;d._QTS_ExecutePendingJob=b.ha;d._QTS_GetProp=b.ia;d._QTS_GetPropNumber=b.ja;d._QTS_SetProp=b.ka;d._QTS_DefineProp=b.la;d._QTS_GetOwnPropertyNames=b.ma;d._QTS_Call=b.na;d._QTS_ResolveException=b.oa;d._QTS_Dump=b.pa;d._QTS_Eval=b.qa;d._QTS_GetModuleNamespace=b.ra;d._QTS_Typeof=b.sa;d._QTS_GetLength=b.ta;d._QTS_IsEqual=b.ua;d._QTS_GetGlobalObject=b.va;d._QTS_NewPromiseCapability=b.wa;
d._QTS_PromiseState=b.xa;d._QTS_PromiseResult=b.ya;d._QTS_TestStringArg=b.za;d._QTS_GetDebugLogEnabled=b.Aa;d._QTS_SetDebugLogEnabled=b.Ba;d._QTS_BuildIsDebug=b.Ca;d._QTS_BuildIsAsyncify=b.Da;d._QTS_NewFunction=b.Ea;d._QTS_ArgvGetJSValueConstPointer=b.Fa;d._QTS_RuntimeEnableInterruptHandler=b.Ga;d._QTS_RuntimeDisableInterruptHandler=b.Ha;d._QTS_RuntimeEnableModuleLoader=b.Ia;d._QTS_RuntimeDisableModuleLoader=b.Ja;d._QTS_bjson_encode=b.Ka;d._QTS_bjson_decode=b.La;Ka=b.Ma;Ha=b.Na;Y=b.Oa;Ia=b.Pa;dynCall_iii=
b._a;dynCall_vii=b.bb;dynCall_vi=b.sb;Ea=b.tb;ya=b.ub;Da=b.vb;Fa=b.wb;return Z}var c={a:La};if(d.instantiateWasm)return new Promise(b=>{d.instantiateWasm(c,(e,g)=>{b(a(e,g))})});L??=d.locateFile?d.locateFile?d.locateFile("emscripten-module.wasm",z):z+"emscripten-module.wasm":(new URL("emscripten-module.wasm",import.meta.url)).href;return a((await ka(c)).instance)}());
(function(){function a(){d.calledRun=!0;if(!F){fa=!0;Z.v();ca?.(d);d.onRuntimeInitialized?.();if(d.postRun)for("function"==typeof d.postRun&&(d.postRun=[d.postRun]);d.postRun.length;){var c=d.postRun.shift();ma.push(c)}la(ma)}}if(d.preRun)for("function"==typeof d.preRun&&(d.preRun=[d.preRun]);d.preRun.length;)oa();la(na);d.setStatus?(d.setStatus("Running..."),setTimeout(()=>{setTimeout(()=>d.setStatus(""),1);a()},1)):a()})();fa?moduleRtn=d:moduleRtn=new Promise((a,c)=>{ca=a;da=c});
;return moduleRtn}export default QuickJSRaw;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
var variant={type:"async",importFFI:()=>import("./ffi.mjs").then(mod=>mod.QuickJSAsyncFFI),importModuleLoader:()=>import("@jitl/quickjs-wasmfile-release-asyncify/emscripten-module").then(mod=>mod.default)},src_default=variant;export{src_default as default};
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1,61 @@
{
"name": "@jitl/quickjs-wasmfile-release-asyncify",
"license": "MIT",
"version": "0.32.0",
"description": "Variant of quickjs library: Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS CommonJS.",
"sideEffects": false,
"repository": {
"type": "git",
"url": "https://github.com/justjake/quickjs-emscripten"
},
"author": {
"name": "Jake Teton-Landis",
"url": "https://jake.tl"
},
"scripts": {
"build": "yarn build:c && yarn build:ts",
"build:c": "make",
"build:ts": "npx tsup",
"check:types": "npx tsc --project . --noEmit",
"clean": "make clean",
"prepare": "yarn clean && yarn build"
},
"files": [
"LICENSE",
"README.md",
"dist/**/*",
"!dist/*.tsbuildinfo"
],
"types": "./dist/index.d.ts",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"browser": "./dist/index.mjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"default": "./dist/index.js"
},
"./package.json": "./package.json",
"./ffi": {
"types": "./dist/ffi.d.ts",
"import": "./dist/ffi.mjs",
"require": "./dist/ffi.js",
"default": "./dist/ffi.js"
},
"./wasm": "./dist/emscripten-module.wasm",
"./emscripten-module": {
"types": "./dist/emscripten-module.browser.d.ts",
"iife": "./dist/emscripten-module.cjs",
"workerd": "./dist/emscripten-module.cloudflare.cjs",
"browser": "./dist/emscripten-module.browser.mjs",
"import": "./dist/emscripten-module.mjs",
"require": "./dist/emscripten-module.cjs",
"default": "./dist/emscripten-module.cjs"
}
},
"dependencies": {
"@jitl/quickjs-ffi-types": "0.32.0"
}
}

View File

@@ -0,0 +1,25 @@
async function QuickJSRaw(moduleArg={}){var moduleRtn;var d=moduleArg,aa=!!globalThis.window,n=!!globalThis.WorkerGlobalScope,q=globalThis.process?.versions?.node&&"renderer"!=globalThis.process?.type;if(q){const {createRequire:a}=await import("node:module");var require=a(import.meta.url)}function r(a){a={log:a||function(){}};for(const c of r.Pa)c(a);return d.quickJSEmscriptenExtensions=a}r.Pa=[];d.quickjsEmscriptenInit=r;r.Pa.push(a=>{a.getWasmMemory=function(){return t}});
var u="./this.program",v=(a,c)=>{throw c;},w=import.meta.url,y="",z,A;
if(q){var fs=require("node:fs");w.startsWith("file:")&&(y=require("node:path").dirname(require("node:url").fileURLToPath(w))+"/");A=a=>{a=B(a)?new URL(a):a;return fs.readFileSync(a)};z=async a=>{a=B(a)?new URL(a):a;return fs.readFileSync(a,void 0)};1<process.argv.length&&(u=process.argv[1].replace(/\\/g,"/"));process.argv.slice(2);v=(a,c)=>{process.exitCode=a;throw c;}}else if(aa||n){try{y=(new URL(".",w)).href}catch{}n&&(A=a=>{var c=new XMLHttpRequest;c.open("GET",a,!1);c.responseType="arraybuffer";
c.send(null);return new Uint8Array(c.response)});z=async a=>{if(B(a))return new Promise((b,e)=>{var f=new XMLHttpRequest;f.open("GET",a,!0);f.responseType="arraybuffer";f.onload=()=>{200==f.status||0==f.status&&f.response?b(f.response):e(f.status)};f.onerror=e;f.send(null)});var c=await fetch(a,{credentials:"same-origin"});if(c.ok)return c.arrayBuffer();throw Error(c.status+" : "+c.url);}}
var C=console.log.bind(console),D=console.error.bind(console),E,F=!1,G,B=a=>a.startsWith("file://"),H,I,J,K,L,M,ba=!1;function ca(){var a=t.buffer;d.HEAP8=J=new Int8Array(a);new Int16Array(a);d.HEAPU8=K=new Uint8Array(a);new Uint16Array(a);L=new Int32Array(a);M=new Uint32Array(a);new Float32Array(a);new Float64Array(a);new BigInt64Array(a);new BigUint64Array(a)}
function N(a){d.onAbort?.(a);a="Aborted("+a+")";D(a);F=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");I?.(a);throw a;}var O;async function da(a){if(!E)try{var c=await z(a);return new Uint8Array(c)}catch{}if(a==O&&E)a=new Uint8Array(E);else if(A)a=A(a);else throw"both async and sync fetching of the wasm failed";return a}
async function ea(a,c){try{var b=await da(a);return await WebAssembly.instantiate(b,c)}catch(e){D(`failed to asynchronously prepare wasm: ${e}`),N(e)}}async function fa(a){var c=O;if(!E&&!B(c)&&!q)try{var b=fetch(c,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(b,a)}catch(e){D(`wasm streaming compile failed: ${e}`),D("falling back to ArrayBuffer instantiation")}return ea(c,a)}
class P{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}}
var ha=a=>{for(;0<a.length;)a.shift()(d)},ia=[],ja=[],ka=()=>{var a=d.preRun.shift();ja.push(a)},Q=!0,t,la=new TextDecoder,ma=(a,c,b,e)=>{b=c+b;if(e)return b;for(;a[c]&&!(c>=b);)++c;return c},R=(a,c,b)=>a?la.decode(K.subarray(a,ma(K,a,c,b))):"",S=0,na=[0,31,60,91,121,152,182,213,244,274,305,335],oa=[0,31,59,90,120,151,181,212,243,273,304,334],T={},pa=a=>{G=a;Q||0<S||(d.onExit?.(a),F=!0);v(a,new P(a))},qa=a=>{if(!F)try{a()}catch(c){c instanceof P||"unwind"==c||v(1,c)}finally{if(!(Q||0<S))try{G=a=G,
pa(a)}catch(c){c instanceof P||"unwind"==c||v(1,c)}}},U=(a,c,b)=>{var e=K;if(!(0<b))return 0;var f=c;b=c+b-1;for(var g=0;g<a.length;++g){var h=a.codePointAt(g);if(127>=h){if(c>=b)break;e[c++]=h}else if(2047>=h){if(c+1>=b)break;e[c++]=192|h>>6;e[c++]=128|h&63}else if(65535>=h){if(c+2>=b)break;e[c++]=224|h>>12;e[c++]=128|h>>6&63;e[c++]=128|h&63}else{if(c+3>=b)break;e[c++]=240|h>>18;e[c++]=128|h>>12&63;e[c++]=128|h>>6&63;e[c++]=128|h&63;g++}}e[c]=0;return c-f},V={},ra=()=>{if(!W){var a={USER:"web_user",
LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:(globalThis.navigator?.language??"C").replace("-","_")+".UTF-8",_:u||"./this.program"},c;for(c in V)void 0===V[c]?delete a[c]:a[c]=V[c];var b=[];for(c in a)b.push(`${c}=${a[c]}`);W=b}return W},W,X=a=>{for(var c=0,b=0;b<a.length;++b){var e=a.charCodeAt(b);127>=e?c++:2047>=e?c+=2:55296<=e&&57343>=e?(c+=4,++b):c+=3}return c},sa=[null,[],[]],va=(a,c,b,e)=>{var f={string:k=>{var l=0;if(null!==k&&void 0!==k&&0!==k){l=X(k)+1;var p=Y(l);U(k,p,
l);l=p}return l},array:k=>{var l=Y(k.length);J.set(k,l);return l}};a=d["_"+a];var g=[],h=0;if(e)for(var m=0;m<e.length;m++){var x=f[b[m]];x?(0===h&&(h=ta()),g[m]=x(e[m])):g[m]=e[m]}b=a(...g);return b=function(k){0!==h&&ua(h);return"string"===c?R(k):"boolean"===c?!!k:k}(b)};d.wasmMemory?t=d.wasmMemory:t=new WebAssembly.Memory({initial:(d.INITIAL_MEMORY||16777216)/65536,maximum:32768});ca();d.noExitRuntime&&(Q=d.noExitRuntime);d.print&&(C=d.print);d.printErr&&(D=d.printErr);d.wasmBinary&&(E=d.wasmBinary);
d.thisProgram&&(u=d.thisProgram);if(d.preInit)for("function"==typeof d.preInit&&(d.preInit=[d.preInit]);0<d.preInit.length;)d.preInit.shift()();d.cwrap=(a,c,b,e)=>{var f=!b||b.every(g=>"number"===g||"boolean"===g);return"string"!==c&&f&&!e?d["_"+a]:(...g)=>va(a,c,b,g)};d.UTF8ToString=R;d.stringToUTF8=(a,c,b)=>U(a,c,b);d.lengthBytesUTF8=X;
var wa,ua,Y,ta,xa={b:(a,c,b,e)=>N(`Assertion failed: ${R(a)}, at: `+[c?R(c):"unknown filename",b,e?R(e):"unknown function"]),q:()=>N(""),l:()=>{Q=!1;S=0},m:function(a,c){a=-9007199254740992>a||9007199254740992<a?NaN:Number(a);a=new Date(1E3*a);L[c>>2]=a.getSeconds();L[c+4>>2]=a.getMinutes();L[c+8>>2]=a.getHours();L[c+12>>2]=a.getDate();L[c+16>>2]=a.getMonth();L[c+20>>2]=a.getFullYear()-1900;L[c+24>>2]=a.getDay();var b=a.getFullYear();L[c+28>>2]=(0!==b%4||0===b%100&&0!==b%400?oa:na)[a.getMonth()]+
a.getDate()-1|0;L[c+36>>2]=-(60*a.getTimezoneOffset());b=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();var e=(new Date(a.getFullYear(),0,1)).getTimezoneOffset();L[c+32>>2]=(b!=e&&a.getTimezoneOffset()==Math.min(e,b))|0},j:(a,c)=>{T[a]&&(clearTimeout(T[a].id),delete T[a]);if(!c)return 0;var b=setTimeout(()=>{delete T[a];qa(()=>wa(a,performance.now()))},c);T[a]={id:b,Qa:c};return 0},n:(a,c,b,e)=>{var f=(new Date).getFullYear(),g=(new Date(f,0,1)).getTimezoneOffset();f=(new Date(f,6,1)).getTimezoneOffset();
M[a>>2]=60*Math.max(g,f);L[c>>2]=Number(g!=f);c=h=>{var m=Math.abs(h);return`UTC${0<=h?"-":"+"}${String(Math.floor(m/60)).padStart(2,"0")}${String(m%60).padStart(2,"0")}`};a=c(g);c=c(f);f<g?(U(a,b,17),U(c,e,17)):(U(a,e,17),U(c,b,17))},p:()=>Date.now(),k:a=>{var c=K.length;a>>>=0;if(2147483648<a)return!1;for(var b=1;4>=b;b*=2){var e=c*(1+.2/b);e=Math.min(e,a+100663296);a:{e=(Math.min(2147483648,65536*Math.ceil(Math.max(a,e)/65536))-t.buffer.byteLength+65535)/65536|0;try{t.grow(e);ca();var f=1;break a}catch(g){}f=
void 0}if(f)return!0}return!1},e:(a,c)=>{var b=0,e=0,f;for(f of ra()){var g=c+b;M[a+e>>2]=g;b+=U(f,g,Infinity)+1;e+=4}return 0},f:(a,c)=>{var b=ra();M[a>>2]=b.length;a=0;for(var e of b)a+=X(e)+1;M[c>>2]=a;return 0},d:()=>52,o:function(){return 70},c:(a,c,b,e)=>{for(var f=0,g=0;g<b;g++){var h=M[c>>2],m=M[c+4>>2];c+=8;for(var x=0;x<m;x++){var k=a,l=K[h+x],p=sa[k];0===l||10===l?(k=1===k?C:D,l=ma(p,0),l=la.decode(p.buffer?p.subarray(0,l):new Uint8Array(p.slice(0,l))),k(l),p.length=0):p.push(l)}f+=m}M[e>>
2]=f;return 0},a:t,r:pa,s:function(a,c,b,e,f){return d.callbacks.callFunction(void 0,a,c,b,e,f)},i:function(a){return d.callbacks.shouldInterrupt(void 0,a)},h:function(a,c,b){b=R(b);return d.callbacks.loadModuleSource(void 0,a,c,b)},g:function(a,c,b,e){b=R(b);e=R(e);return d.callbacks.normalizeModule(void 0,a,c,b,e)},t:function(a,c){d.callbacks.freeHostRef(void 0,a,c)}},Z;
Z=await (async function(){function a(b){b=Z=b.exports;d._malloc=b.v;d._QTS_Throw=b.w;d._QTS_NewError=b.x;d._QTS_RuntimeSetMemoryLimit=b.y;d._QTS_RuntimeComputeMemoryUsage=b.z;d._QTS_RuntimeDumpMemoryUsage=b.A;d._QTS_RecoverableLeakCheck=b.B;d._QTS_BuildIsSanitizeLeak=b.C;d._QTS_RuntimeSetMaxStackSize=b.D;d._QTS_GetUndefined=b.E;d._QTS_GetNull=b.F;d._QTS_GetFalse=b.G;d._QTS_GetTrue=b.H;d._QTS_NewHostRef=b.I;d._QTS_GetHostRefId=b.J;d._QTS_NewRuntime=b.K;d._QTS_FreeRuntime=b.L;d._free=b.M;
d._QTS_NewContext=b.N;d._QTS_FreeContext=b.O;d._QTS_FreeValuePointer=b.P;d._QTS_FreeValuePointerRuntime=b.Q;d._QTS_FreeVoidPointer=b.R;d._QTS_FreeCString=b.S;d._QTS_DupValuePointer=b.T;d._QTS_NewObject=b.U;d._QTS_NewObjectProto=b.V;d._QTS_NewArray=b.W;d._QTS_NewArrayBuffer=b.X;d._QTS_NewFloat64=b.Y;d._QTS_GetFloat64=b.Z;d._QTS_NewString=b._;d._QTS_GetString=b.$;d._QTS_GetArrayBuffer=b.aa;d._QTS_GetArrayBufferLength=b.ba;d._QTS_NewSymbol=b.ca;d._QTS_GetSymbolDescriptionOrKey=b.da;d._QTS_IsGlobalSymbol=
b.ea;d._QTS_IsJobPending=b.fa;d._QTS_ExecutePendingJob=b.ga;d._QTS_GetProp=b.ha;d._QTS_GetPropNumber=b.ia;d._QTS_SetProp=b.ja;d._QTS_DefineProp=b.ka;d._QTS_GetOwnPropertyNames=b.la;d._QTS_Call=b.ma;d._QTS_ResolveException=b.na;d._QTS_Dump=b.oa;d._QTS_Eval=b.pa;d._QTS_GetModuleNamespace=b.qa;d._QTS_Typeof=b.ra;d._QTS_GetLength=b.sa;d._QTS_IsEqual=b.ta;d._QTS_GetGlobalObject=b.ua;d._QTS_NewPromiseCapability=b.va;d._QTS_PromiseState=b.wa;d._QTS_PromiseResult=b.xa;d._QTS_TestStringArg=b.ya;d._QTS_GetDebugLogEnabled=
b.za;d._QTS_SetDebugLogEnabled=b.Aa;d._QTS_BuildIsDebug=b.Ba;d._QTS_BuildIsAsyncify=b.Ca;d._QTS_NewFunction=b.Da;d._QTS_ArgvGetJSValueConstPointer=b.Ea;d._QTS_RuntimeEnableInterruptHandler=b.Fa;d._QTS_RuntimeDisableInterruptHandler=b.Ga;d._QTS_RuntimeEnableModuleLoader=b.Ha;d._QTS_RuntimeDisableModuleLoader=b.Ia;d._QTS_bjson_encode=b.Ja;d._QTS_bjson_decode=b.Ka;wa=b.La;ua=b.Ma;Y=b.Na;ta=b.Oa;return Z}var c={a:xa};if(d.instantiateWasm)return new Promise(b=>{d.instantiateWasm(c,(e,f)=>{b(a(e,f))})});
O??=d.locateFile?d.locateFile?d.locateFile("emscripten-module.wasm",y):y+"emscripten-module.wasm":(new URL("emscripten-module.wasm",import.meta.url)).href;return a((await fa(c)).instance)}());
(function(){function a(){d.calledRun=!0;if(!F){ba=!0;Z.u();H?.(d);d.onRuntimeInitialized?.();if(d.postRun)for("function"==typeof d.postRun&&(d.postRun=[d.postRun]);d.postRun.length;){var c=d.postRun.shift();ia.push(c)}ha(ia)}}if(d.preRun)for("function"==typeof d.preRun&&(d.preRun=[d.preRun]);d.preRun.length;)ka();ha(ja);d.setStatus?(d.setStatus("Running..."),setTimeout(()=>{setTimeout(()=>d.setStatus(""),1);a()},1)):a()})();ba?moduleRtn=d:moduleRtn=new Promise((a,c)=>{H=a;I=c});
;return moduleRtn}export default QuickJSRaw;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
var variant={type:"sync",importFFI:()=>import("./ffi.mjs").then(mod=>mod.QuickJSFFI),importModuleLoader:()=>import("@jitl/quickjs-wasmfile-release-sync/emscripten-module").then(mod=>mod.default)},src_default=variant;export{src_default as default};
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1,61 @@
{
"name": "@jitl/quickjs-wasmfile-release-sync",
"license": "MIT",
"version": "0.32.0",
"description": "Variant of quickjs library: Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS CommonJS.",
"sideEffects": false,
"repository": {
"type": "git",
"url": "https://github.com/justjake/quickjs-emscripten"
},
"author": {
"name": "Jake Teton-Landis",
"url": "https://jake.tl"
},
"scripts": {
"build": "yarn build:c && yarn build:ts",
"build:c": "make",
"build:ts": "npx tsup",
"check:types": "npx tsc --project . --noEmit",
"clean": "make clean",
"prepare": "yarn clean && yarn build"
},
"files": [
"LICENSE",
"README.md",
"dist/**/*",
"!dist/*.tsbuildinfo"
],
"types": "./dist/index.d.ts",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"browser": "./dist/index.mjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"default": "./dist/index.js"
},
"./package.json": "./package.json",
"./ffi": {
"types": "./dist/ffi.d.ts",
"import": "./dist/ffi.mjs",
"require": "./dist/ffi.js",
"default": "./dist/ffi.js"
},
"./wasm": "./dist/emscripten-module.wasm",
"./emscripten-module": {
"types": "./dist/emscripten-module.browser.d.ts",
"iife": "./dist/emscripten-module.cjs",
"workerd": "./dist/emscripten-module.cloudflare.cjs",
"browser": "./dist/emscripten-module.browser.mjs",
"import": "./dist/emscripten-module.mjs",
"require": "./dist/emscripten-module.cjs",
"default": "./dist/emscripten-module.cjs"
}
},
"dependencies": {
"@jitl/quickjs-ffi-types": "0.32.0"
}
}

View File

@@ -0,0 +1,234 @@
"use strict";
const { parse } = require('./style_parser');
module.exports = function (elt) {
const style = new CSSStyleDeclaration(elt)
const handler = {
get: function(target, property) {
return property in target ? target[property] : target.getPropertyValue(dasherizeProperty(property));
},
has: function(target, key) {
return true;
},
set: function(target, property, value) {
if (property in target) {
target[property] = value;
} else {
target.setProperty(dasherizeProperty(property), value ?? undefined);
}
return true;
}
};
return new Proxy(style, handler);
};
function dasherizeProperty(property) {
return property.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
function CSSStyleDeclaration(elt) {
this._element = elt;
}
const IMPORTANT_BANG = '!important';
// Utility function for parsing style declarations
// Pass in a string like "margin-left: 5px; border-style: solid"
// and this function returns an object like
// {"margin-left":"5px", "border-style":"solid"}
function parseStyles(value) {
const result = {
property: {},
priority: {},
}
if (!value) {
return result;
}
const styleValues = parse(value);
if (styleValues.length < 2) {
return result;
}
for (let i = 0; i < styleValues.length; i += 2) {
const name = styleValues[i];
let value = styleValues[i+1];
if (value.endsWith(IMPORTANT_BANG)) {
result.priority[name] = 'important';
value = value.slice(0, -IMPORTANT_BANG.length).trim();
}
result.property[name] = value;
}
return result;
}
var NO_CHANGE = {}; // Private marker object
CSSStyleDeclaration.prototype = Object.create(Object.prototype, {
// Return the parsed form of the element's style attribute.
// If the element's style attribute has never been parsed
// or if it has changed since the last parse, then reparse it
// Note that the styles don't get parsed until they're actually needed
_parsed: { get: function() {
if (!this._parsedStyles || this.cssText !== this._lastParsedText) {
var text = this.cssText;
this._parsedStyles = parseStyles(text);
this._lastParsedText = text;
delete this._names;
}
return this._parsedStyles;
}},
// Call this method any time the parsed representation of the
// style changes. It converts the style properties to a string and
// sets cssText and the element's style attribute
_serialize: { value: function() {
var styles = this._parsed;
var s = "";
for(var name in styles.property) {
if (s) s += " ";
s += name + ": " + styles.property[name];
if (styles.priority[name]) {
s += " !" + styles.priority[name];
}
s += ";";
}
this.cssText = s; // also sets the style attribute
this._lastParsedText = s; // so we don't reparse
delete this._names;
}},
cssText: {
get: function() {
// XXX: this is a CSSStyleDeclaration for an element.
// A different impl might be necessary for a set of styles
// associated returned by getComputedStyle(), e.g.
return this._element.getAttribute("style");
},
set: function(value) {
// XXX: I should parse and serialize the value to
// normalize it and remove errors. FF and chrome do that.
this._element.setAttribute("style", value);
}
},
length: { get: function() {
if (!this._names)
this._names = Object.getOwnPropertyNames(this._parsed.property);
return this._names.length;
}},
item: { value: function(n) {
if (!this._names)
this._names = Object.getOwnPropertyNames(this._parsed.property);
return this._names[n];
}},
getPropertyValue: { value: function(property) {
property = property.toLowerCase();
return this._parsed.property[property] || "";
}},
getPropertyPriority: { value: function(property) {
property = property.toLowerCase();
return this._parsed.priority[property] || "";
}},
setProperty: { value: function(property, value, priority) {
property = property.toLowerCase();
if (value === null || value === undefined) {
value = "";
}
if (priority === null || priority === undefined) {
priority = "";
}
// String coercion
if (value !== NO_CHANGE) {
value = "" + value;
}
value = value.trim();
if (value === "") {
this.removeProperty(property);
return;
}
if (priority !== "" && priority !== NO_CHANGE &&
!/^important$/i.test(priority)) {
return;
}
var styles = this._parsed;
if (value === NO_CHANGE) {
if (!styles.property[property]) {
return; // Not a valid property name.
}
if (priority !== "") {
styles.priority[property] = "important";
} else {
delete styles.priority[property];
}
} else {
// We don't just accept the property value. Instead
// we parse it to ensure that it is something valid.
// If it contains a semicolon it is invalid
if (value.indexOf(";") !== -1) return;
var newprops = parseStyles(property + ":" + value);
if (Object.getOwnPropertyNames(newprops.property).length === 0) {
return; // no valid property found
}
if (Object.getOwnPropertyNames(newprops.priority).length !== 0) {
return; // if the value included '!important' it wasn't valid.
}
// XXX handle shorthand properties
for (var p in newprops.property) {
styles.property[p] = newprops.property[p];
if (priority === NO_CHANGE) {
continue;
} else if (priority !== "") {
styles.priority[p] = "important";
} else if (styles.priority[p]) {
delete styles.priority[p];
}
}
}
// Serialize and update cssText and element.style!
this._serialize();
}},
setPropertyValue: { value: function(property, value) {
return this.setProperty(property, value, NO_CHANGE);
}},
setPropertyPriority: { value: function(property, priority) {
return this.setProperty(property, NO_CHANGE, priority);
}},
removeProperty: { value: function(property) {
property = property.toLowerCase();
var styles = this._parsed;
if (property in styles.property) {
delete styles.property[property];
delete styles.priority[property];
// Serialize and update cssText and element.style!
this._serialize();
}
}},
});

View File

@@ -0,0 +1,120 @@
/* jshint bitwise: false */
"use strict";
module.exports = CharacterData;
var Leaf = require('./Leaf');
var utils = require('./utils');
var ChildNode = require('./ChildNode');
var NonDocumentTypeChildNode = require('./NonDocumentTypeChildNode');
function CharacterData() {
Leaf.call(this);
}
CharacterData.prototype = Object.create(Leaf.prototype, {
// DOMString substringData(unsigned long offset,
// unsigned long count);
// The substringData(offset, count) method must run these steps:
//
// If offset is greater than the context object's
// length, throw an INDEX_SIZE_ERR exception and
// terminate these steps.
//
// If offset+count is greater than the context
// object's length, return a DOMString whose value is
// the UTF-16 code units from the offsetth UTF-16 code
// unit to the end of data.
//
// Return a DOMString whose value is the UTF-16 code
// units from the offsetth UTF-16 code unit to the
// offset+countth UTF-16 code unit in data.
substringData: { value: function substringData(offset, count) {
if (arguments.length < 2) { throw new TypeError("Not enough arguments"); }
// Convert arguments to WebIDL "unsigned long"
offset = offset >>> 0;
count = count >>> 0;
if (offset > this.data.length || offset < 0 || count < 0) {
utils.IndexSizeError();
}
return this.data.substring(offset, offset+count);
}},
// void appendData(DOMString data);
// The appendData(data) method must append data to the context
// object's data.
appendData: { value: function appendData(data) {
if (arguments.length < 1) { throw new TypeError("Not enough arguments"); }
this.data += String(data);
}},
// void insertData(unsigned long offset, DOMString data);
// The insertData(offset, data) method must run these steps:
//
// If offset is greater than the context object's
// length, throw an INDEX_SIZE_ERR exception and
// terminate these steps.
//
// Insert data into the context object's data after
// offset UTF-16 code units.
//
insertData: { value: function insertData(offset, data) {
return this.replaceData(offset, 0, data);
}},
// void deleteData(unsigned long offset, unsigned long count);
// The deleteData(offset, count) method must run these steps:
//
// If offset is greater than the context object's
// length, throw an INDEX_SIZE_ERR exception and
// terminate these steps.
//
// If offset+count is greater than the context
// object's length var count be length-offset.
//
// Starting from offset UTF-16 code units remove count
// UTF-16 code units from the context object's data.
deleteData: { value: function deleteData(offset, count) {
return this.replaceData(offset, count, '');
}},
// void replaceData(unsigned long offset, unsigned long count,
// DOMString data);
//
// The replaceData(offset, count, data) method must act as
// if the deleteData() method is invoked with offset and
// count as arguments followed by the insertData() method
// with offset and data as arguments and re-throw any
// exceptions these methods might have thrown.
replaceData: { value: function replaceData(offset, count, data) {
var curtext = this.data, len = curtext.length;
// Convert arguments to correct WebIDL type
offset = offset >>> 0;
count = count >>> 0;
data = String(data);
if (offset > len || offset < 0) utils.IndexSizeError();
if (offset+count > len)
count = len - offset;
var prefix = curtext.substring(0, offset),
suffix = curtext.substring(offset+count);
this.data = prefix + data + suffix;
}},
// Utility method that Node.isEqualNode() calls to test Text and
// Comment nodes for equality. It is okay to put it here, since
// Node will have already verified that nodeType is equal
isEqual: { value: function isEqual(n) {
return this._data === n._data;
}},
length: { get: function() { return this.data.length; }}
});
Object.defineProperties(CharacterData.prototype, ChildNode);
Object.defineProperties(CharacterData.prototype, NonDocumentTypeChildNode);

View File

@@ -0,0 +1,119 @@
"use strict";
var Node = require('./Node');
var LinkedList = require('./LinkedList');
var createDocumentFragmentFromArguments = function(document, args) {
var docFrag = document.createDocumentFragment();
for (var i=0; i<args.length; i++) {
var argItem = args[i];
var isNode = argItem instanceof Node;
docFrag.appendChild(isNode ? argItem :
document.createTextNode(String(argItem)));
}
return docFrag;
};
// The ChildNode interface contains methods that are particular to `Node`
// objects that can have a parent. It is implemented by `Element`,
// `DocumentType`, and `CharacterData` objects.
var ChildNode = {
// Inserts a set of Node or String objects in the children list of this
// ChildNode's parent, just after this ChildNode. String objects are
// inserted as the equivalent Text nodes.
after: { value: function after() {
var argArr = Array.prototype.slice.call(arguments);
var parentNode = this.parentNode, nextSibling = this.nextSibling;
if (parentNode === null) { return; }
// Find "viable next sibling"; that is, next one not in argArr
while (nextSibling && argArr.some(function(v) { return v===nextSibling; }))
nextSibling = nextSibling.nextSibling;
// ok, parent and sibling are saved away since this node could itself
// appear in argArr and we're about to move argArr to a document fragment.
var docFrag = createDocumentFragmentFromArguments(this.doc, argArr);
parentNode.insertBefore(docFrag, nextSibling);
}},
// Inserts a set of Node or String objects in the children list of this
// ChildNode's parent, just before this ChildNode. String objects are
// inserted as the equivalent Text nodes.
before: { value: function before() {
var argArr = Array.prototype.slice.call(arguments);
var parentNode = this.parentNode, prevSibling = this.previousSibling;
if (parentNode === null) { return; }
// Find "viable prev sibling"; that is, prev one not in argArr
while (prevSibling && argArr.some(function(v) { return v===prevSibling; }))
prevSibling = prevSibling.previousSibling;
// ok, parent and sibling are saved away since this node could itself
// appear in argArr and we're about to move argArr to a document fragment.
var docFrag = createDocumentFragmentFromArguments(this.doc, argArr);
var nextSibling =
prevSibling ? prevSibling.nextSibling : parentNode.firstChild;
parentNode.insertBefore(docFrag, nextSibling);
}},
// Remove this node from its parent
remove: { value: function remove() {
if (this.parentNode === null) return;
// Send mutation events if necessary
if (this.doc) {
this.doc._preremoveNodeIterators(this);
if (this.rooted) {
this.doc.mutateRemove(this);
}
}
// Remove this node from its parents array of children
// and update the structure id for all ancestors
this._remove();
// Forget this node's parent
this.parentNode = null;
}},
// Remove this node w/o uprooting or sending mutation events
// (But do update the structure id for all ancestors)
_remove: { value: function _remove() {
var parent = this.parentNode;
if (parent === null) return;
if (parent._childNodes) {
parent._childNodes.splice(this.index, 1);
} else if (parent._firstChild === this) {
if (this._nextSibling === this) {
parent._firstChild = null;
} else {
parent._firstChild = this._nextSibling;
}
}
LinkedList.remove(this);
parent.modify();
}},
// Replace this node with the nodes or strings provided as arguments.
replaceWith: { value: function replaceWith() {
var argArr = Array.prototype.slice.call(arguments);
var parentNode = this.parentNode, nextSibling = this.nextSibling;
if (parentNode === null) { return; }
// Find "viable next sibling"; that is, next one not in argArr
while (nextSibling && argArr.some(function(v) { return v===nextSibling; }))
nextSibling = nextSibling.nextSibling;
// ok, parent and sibling are saved away since this node could itself
// appear in argArr and we're about to move argArr to a document fragment.
var docFrag = createDocumentFragmentFromArguments(this.doc, argArr);
if (this.parentNode === parentNode) {
parentNode.replaceChild(docFrag, this);
} else {
// `this` was inserted into docFrag
parentNode.insertBefore(docFrag, nextSibling);
}
}},
};
module.exports = ChildNode;

View File

@@ -0,0 +1,40 @@
"use strict";
module.exports = Comment;
var Node = require('./Node');
var CharacterData = require('./CharacterData');
function Comment(doc, data) {
CharacterData.call(this);
this.nodeType = Node.COMMENT_NODE;
this.ownerDocument = doc;
this._data = data;
}
var nodeValue = {
get: function() { return this._data; },
set: function(v) {
if (v === null || v === undefined) { v = ''; } else { v = String(v); }
this._data = v;
if (this.rooted)
this.ownerDocument.mutateValue(this);
}
};
Comment.prototype = Object.create(CharacterData.prototype, {
nodeName: { value: '#comment' },
nodeValue: nodeValue,
textContent: nodeValue,
innerText: nodeValue,
data: {
get: nodeValue.get,
set: function(v) {
nodeValue.set.call(this, v===null ? '' : String(v));
},
},
// Utility methods
clone: { value: function clone() {
return new Comment(this.ownerDocument, this._data);
}},
});

View File

@@ -0,0 +1,80 @@
"use strict";
module.exports = ContainerNode;
var Node = require('./Node');
var NodeList = require('./NodeList');
// This class defines common functionality for node subtypes that
// can have children
function ContainerNode() {
Node.call(this);
this._firstChild = this._childNodes = null;
}
// Primary representation is a circular linked list of siblings
ContainerNode.prototype = Object.create(Node.prototype, {
hasChildNodes: { value: function() {
if (this._childNodes) {
return this._childNodes.length > 0;
}
return this._firstChild !== null;
}},
childNodes: { get: function() {
this._ensureChildNodes();
return this._childNodes;
}},
firstChild: { get: function() {
if (this._childNodes) {
return this._childNodes.length === 0 ? null : this._childNodes[0];
}
return this._firstChild;
}},
lastChild: { get: function() {
var kids = this._childNodes, first;
if (kids) {
return kids.length === 0 ? null: kids[kids.length-1];
}
first = this._firstChild;
if (first === null) { return null; }
return first._previousSibling; // circular linked list
}},
_ensureChildNodes: { value: function() {
if (this._childNodes) { return; }
var first = this._firstChild,
kid = first,
childNodes = this._childNodes = new NodeList();
if (first) do {
childNodes.push(kid);
kid = kid._nextSibling;
} while (kid !== first); // circular linked list
this._firstChild = null; // free memory
}},
// Remove all of this node's children. This is a minor
// optimization that only calls modify() once.
removeChildren: { value: function removeChildren() {
var root = this.rooted ? this.ownerDocument : null,
next = this.firstChild,
kid;
while (next !== null) {
kid = next;
next = kid.nextSibling;
if (root) root.mutateRemove(kid);
kid.parentNode = null;
}
if (this._childNodes) {
this._childNodes.length = 0;
} else {
this._firstChild = null;
}
this.modify(); // Update last modified type once only
}},
});

View File

@@ -0,0 +1,12 @@
"use strict";
module.exports = CustomEvent;
var Event = require('./Event');
function CustomEvent(type, dictionary) {
// Just use the superclass constructor to initialize
Event.call(this, type, dictionary);
}
CustomEvent.prototype = Object.create(Event.prototype, {
constructor: { value: CustomEvent }
});

View File

@@ -0,0 +1,134 @@
"use strict";
module.exports = DOMException;
var INDEX_SIZE_ERR = 1;
var HIERARCHY_REQUEST_ERR = 3;
var WRONG_DOCUMENT_ERR = 4;
var INVALID_CHARACTER_ERR = 5;
var NO_MODIFICATION_ALLOWED_ERR = 7;
var NOT_FOUND_ERR = 8;
var NOT_SUPPORTED_ERR = 9;
var INVALID_STATE_ERR = 11;
var SYNTAX_ERR = 12;
var INVALID_MODIFICATION_ERR = 13;
var NAMESPACE_ERR = 14;
var INVALID_ACCESS_ERR = 15;
var TYPE_MISMATCH_ERR = 17;
var SECURITY_ERR = 18;
var NETWORK_ERR = 19;
var ABORT_ERR = 20;
var URL_MISMATCH_ERR = 21;
var QUOTA_EXCEEDED_ERR = 22;
var TIMEOUT_ERR = 23;
var INVALID_NODE_TYPE_ERR = 24;
var DATA_CLONE_ERR = 25;
// Code to name
var names = [
null, // No error with code 0
'INDEX_SIZE_ERR',
null, // historical
'HIERARCHY_REQUEST_ERR',
'WRONG_DOCUMENT_ERR',
'INVALID_CHARACTER_ERR',
null, // historical
'NO_MODIFICATION_ALLOWED_ERR',
'NOT_FOUND_ERR',
'NOT_SUPPORTED_ERR',
'INUSE_ATTRIBUTE_ERR', // historical
'INVALID_STATE_ERR',
'SYNTAX_ERR',
'INVALID_MODIFICATION_ERR',
'NAMESPACE_ERR',
'INVALID_ACCESS_ERR',
null, // historical
'TYPE_MISMATCH_ERR',
'SECURITY_ERR',
'NETWORK_ERR',
'ABORT_ERR',
'URL_MISMATCH_ERR',
'QUOTA_EXCEEDED_ERR',
'TIMEOUT_ERR',
'INVALID_NODE_TYPE_ERR',
'DATA_CLONE_ERR',
];
// Code to message
// These strings are from the 13 May 2011 Editor's Draft of DOM Core.
// http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
// Copyright © 2011 W3C® (MIT, ERCIM, Keio), All Rights Reserved.
// Used under the terms of the W3C Document License:
// http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231
var messages = [
null, // No error with code 0
'INDEX_SIZE_ERR (1): the index is not in the allowed range',
null,
'HIERARCHY_REQUEST_ERR (3): the operation would yield an incorrect nodes model',
'WRONG_DOCUMENT_ERR (4): the object is in the wrong Document, a call to importNode is required',
'INVALID_CHARACTER_ERR (5): the string contains invalid characters',
null,
'NO_MODIFICATION_ALLOWED_ERR (7): the object can not be modified',
'NOT_FOUND_ERR (8): the object can not be found here',
'NOT_SUPPORTED_ERR (9): this operation is not supported',
'INUSE_ATTRIBUTE_ERR (10): setAttributeNode called on owned Attribute',
'INVALID_STATE_ERR (11): the object is in an invalid state',
'SYNTAX_ERR (12): the string did not match the expected pattern',
'INVALID_MODIFICATION_ERR (13): the object can not be modified in this way',
'NAMESPACE_ERR (14): the operation is not allowed by Namespaces in XML',
'INVALID_ACCESS_ERR (15): the object does not support the operation or argument',
null,
'TYPE_MISMATCH_ERR (17): the type of the object does not match the expected type',
'SECURITY_ERR (18): the operation is insecure',
'NETWORK_ERR (19): a network error occurred',
'ABORT_ERR (20): the user aborted an operation',
'URL_MISMATCH_ERR (21): the given URL does not match another URL',
'QUOTA_EXCEEDED_ERR (22): the quota has been exceeded',
'TIMEOUT_ERR (23): a timeout occurred',
'INVALID_NODE_TYPE_ERR (24): the supplied node is invalid or has an invalid ancestor for this operation',
'DATA_CLONE_ERR (25): the object can not be cloned.'
];
// Name to code
var constants = {
INDEX_SIZE_ERR: INDEX_SIZE_ERR,
DOMSTRING_SIZE_ERR: 2, // historical
HIERARCHY_REQUEST_ERR: HIERARCHY_REQUEST_ERR,
WRONG_DOCUMENT_ERR: WRONG_DOCUMENT_ERR,
INVALID_CHARACTER_ERR: INVALID_CHARACTER_ERR,
NO_DATA_ALLOWED_ERR: 6, // historical
NO_MODIFICATION_ALLOWED_ERR: NO_MODIFICATION_ALLOWED_ERR,
NOT_FOUND_ERR: NOT_FOUND_ERR,
NOT_SUPPORTED_ERR: NOT_SUPPORTED_ERR,
INUSE_ATTRIBUTE_ERR: 10, // historical
INVALID_STATE_ERR: INVALID_STATE_ERR,
SYNTAX_ERR: SYNTAX_ERR,
INVALID_MODIFICATION_ERR: INVALID_MODIFICATION_ERR,
NAMESPACE_ERR: NAMESPACE_ERR,
INVALID_ACCESS_ERR: INVALID_ACCESS_ERR,
VALIDATION_ERR: 16, // historical
TYPE_MISMATCH_ERR: TYPE_MISMATCH_ERR,
SECURITY_ERR: SECURITY_ERR,
NETWORK_ERR: NETWORK_ERR,
ABORT_ERR: ABORT_ERR,
URL_MISMATCH_ERR: URL_MISMATCH_ERR,
QUOTA_EXCEEDED_ERR: QUOTA_EXCEEDED_ERR,
TIMEOUT_ERR: TIMEOUT_ERR,
INVALID_NODE_TYPE_ERR: INVALID_NODE_TYPE_ERR,
DATA_CLONE_ERR: DATA_CLONE_ERR
};
function DOMException(code) {
Error.call(this);
Error.captureStackTrace(this, this.constructor);
this.code = code;
this.message = messages[code];
this.name = names[code];
}
DOMException.prototype.__proto__ = Error.prototype;
// Initialize the constants on DOMException and DOMException.prototype
for(var c in constants) {
var v = { value: constants[c] };
Object.defineProperty(DOMException, c, v);
Object.defineProperty(DOMException.prototype, c, v);
}

View File

@@ -0,0 +1,94 @@
"use strict";
module.exports = DOMImplementation;
var Document = require('./Document');
var DocumentType = require('./DocumentType');
var HTMLParser = require('./HTMLParser');
var utils = require('./utils');
var xml = require('./xmlnames');
// Each document must have its own instance of the domimplementation object
function DOMImplementation(contextObject) {
this.contextObject = contextObject;
}
// Feature/version pairs that DOMImplementation.hasFeature() returns
// true for. It returns false for anything else.
var supportedFeatures = {
'xml': { '': true, '1.0': true, '2.0': true }, // DOM Core
'core': { '': true, '2.0': true }, // DOM Core
'html': { '': true, '1.0': true, '2.0': true} , // HTML
'xhtml': { '': true, '1.0': true, '2.0': true} , // HTML
};
DOMImplementation.prototype = {
hasFeature: function hasFeature(feature, version) {
var f = supportedFeatures[(feature || '').toLowerCase()];
return (f && f[version || '']) || false;
},
createDocumentType: function createDocumentType(qualifiedName, publicId, systemId) {
if (!xml.isValidQName(qualifiedName)) utils.InvalidCharacterError();
return new DocumentType(this.contextObject, qualifiedName, publicId, systemId);
},
createDocument: function createDocument(namespace, qualifiedName, doctype) {
//
// Note that the current DOMCore spec makes it impossible to
// create an HTML document with this function, even if the
// namespace and doctype are propertly set. See this thread:
// http://lists.w3.org/Archives/Public/www-dom/2011AprJun/0132.html
//
var d = new Document(false, null);
var e;
if (qualifiedName)
e = d.createElementNS(namespace, qualifiedName);
else
e = null;
if (doctype) {
d.appendChild(doctype);
}
if (e) d.appendChild(e);
if (namespace === utils.NAMESPACE.HTML) {
d._contentType = 'application/xhtml+xml';
} else if (namespace === utils.NAMESPACE.SVG) {
d._contentType = 'image/svg+xml';
} else {
d._contentType = 'application/xml';
}
return d;
},
createHTMLDocument: function createHTMLDocument(titleText) {
var d = new Document(true, null);
d.appendChild(new DocumentType(d, 'html'));
var html = d.createElement('html');
d.appendChild(html);
var head = d.createElement('head');
html.appendChild(head);
if (titleText !== undefined) {
var title = d.createElement('title');
head.appendChild(title);
title.appendChild(d.createTextNode(titleText));
}
html.appendChild(d.createElement('body'));
d.modclock = 1; // Start tracking modifications
return d;
},
mozSetOutputMutationHandler: function(doc, handler) {
doc.mutationHandler = handler;
},
mozGetInputMutationHandler: function(doc) {
utils.nyi();
},
mozHTMLParser: HTMLParser,
};

View File

@@ -0,0 +1,186 @@
"use strict";
// DOMTokenList implementation based on https://github.com/Raynos/DOM-shim
var utils = require('./utils');
module.exports = DOMTokenList;
function DOMTokenList(getter, setter) {
this._getString = getter;
this._setString = setter;
this._length = 0;
this._lastStringValue = '';
this._update();
}
Object.defineProperties(DOMTokenList.prototype, {
length: { get: function() { return this._length; } },
item: { value: function(index) {
var list = getList(this);
if (index < 0 || index >= list.length) {
return null;
}
return list[index];
}},
contains: { value: function(token) {
token = String(token); // no error checking for contains()
var list = getList(this);
return list.indexOf(token) > -1;
}},
add: { value: function() {
var list = getList(this);
for (var i = 0, len = arguments.length; i < len; i++) {
var token = handleErrors(arguments[i]);
if (list.indexOf(token) < 0) {
list.push(token);
}
}
// Note: as per spec, if handleErrors() throws any errors, we never
// make it here and none of the changes take effect.
// Also per spec: we run the "update steps" even if no change was
// made (ie, if the token already existed)
this._update(list);
}},
remove: { value: function() {
var list = getList(this);
for (var i = 0, len = arguments.length; i < len; i++) {
var token = handleErrors(arguments[i]);
var index = list.indexOf(token);
if (index > -1) {
list.splice(index, 1);
}
}
// Note: as per spec, if handleErrors() throws any errors, we never
// make it here and none of the changes take effect.
// Also per spec: we run the "update steps" even if no change was
// made (ie, if the token wasn't previously present)
this._update(list);
}},
toggle: { value: function toggle(token, force) {
token = handleErrors(token);
if (this.contains(token)) {
if (force === undefined || force === false) {
this.remove(token);
return false;
}
return true;
} else {
if (force === undefined || force === true) {
this.add(token);
return true;
}
return false;
}
}},
replace: { value: function replace(token, newToken) {
// weird corner case of spec: if `token` contains whitespace, but
// `newToken` is the empty string, we must throw SyntaxError not
// InvalidCharacterError (sigh)
if (String(newToken)==='') { utils.SyntaxError(); }
token = handleErrors(token);
newToken = handleErrors(newToken);
var list = getList(this);
var idx = list.indexOf(token);
if (idx < 0) {
// Note that, per spec, we do not run the update steps on this path.
return false;
}
var idx2 = list.indexOf(newToken);
if (idx2 < 0) {
list[idx] = newToken;
} else {
// "replace the first instance of either `token` or `newToken` with
// `newToken` and remove all other instances"
if (idx < idx2) {
list[idx] = newToken;
list.splice(idx2, 1);
} else {
// idx2 is already `newToken`
list.splice(idx, 1);
}
}
this._update(list);
return true;
}},
toString: { value: function() {
return this._getString();
}},
value: {
get: function() {
return this._getString();
},
set: function(v) {
this._setString(v);
this._update();
}
},
// Called when the setter is called from outside this interface.
_update: { value: function(list) {
if (list) {
fixIndex(this, list);
this._setString(list.join(" ").trim());
} else {
fixIndex(this, getList(this));
}
this._lastStringValue = this._getString();
} },
});
function fixIndex(clist, list) {
var oldLength = clist._length;
var i;
clist._length = list.length;
for (i = 0; i < list.length; i++) {
clist[i] = list[i];
}
// Clear/free old entries.
for (; i < oldLength; i++) {
clist[i] = undefined;
}
}
function handleErrors(token) {
token = String(token);
if (token === "") {
utils.SyntaxError();
}
if (/[ \t\r\n\f]/.test(token)) {
utils.InvalidCharacterError();
}
return token;
}
function toArray(clist) {
var length = clist._length;
var arr = Array(length);
for (var i = 0; i < length; i++) {
arr[i] = clist[i];
}
return arr;
}
function getList(clist) {
var strProp = clist._getString();
if (strProp === clist._lastStringValue) {
return toArray(clist);
}
var str = strProp.replace(/(^[ \t\r\n\f]+)|([ \t\r\n\f]+$)/g, '');
if (str === "") {
return [];
} else {
var seen = Object.create(null);
return str.split(/[ \t\r\n\f]+/g).filter(function(n) {
var key = '$' + n;
if (seen[key]) { return false; }
seen[key] = true;
return true;
});
}
}

View File

@@ -0,0 +1,884 @@
"use strict";
module.exports = Document;
var Node = require('./Node');
var NodeList = require('./NodeList');
var ContainerNode = require('./ContainerNode');
var Element = require('./Element');
var Text = require('./Text');
var Comment = require('./Comment');
var Event = require('./Event');
var DocumentFragment = require('./DocumentFragment');
var ProcessingInstruction = require('./ProcessingInstruction');
var DOMImplementation = require('./DOMImplementation');
var TreeWalker = require('./TreeWalker');
var NodeIterator = require('./NodeIterator');
var NodeFilter = require('./NodeFilter');
var URL = require('./URL');
var select = require('./select');
var events = require('./events');
var xml = require('./xmlnames');
var html = require('./htmlelts');
var svg = require('./svg');
var utils = require('./utils');
var MUTATE = require('./MutationConstants');
var NAMESPACE = utils.NAMESPACE;
var isApiWritable = require("./config").isApiWritable;
function Document(isHTML, address) {
ContainerNode.call(this);
this.nodeType = Node.DOCUMENT_NODE;
this.isHTML = isHTML;
this._address = address || 'about:blank';
this.readyState = 'loading';
this.implementation = new DOMImplementation(this);
// DOMCore says that documents are always associated with themselves
this.ownerDocument = null; // ... but W3C tests expect null
this._contentType = isHTML ? 'text/html' : 'application/xml';
// These will be initialized by our custom versions of
// appendChild and insertBefore that override the inherited
// Node methods.
// XXX: override those methods!
this.doctype = null;
this.documentElement = null;
// "Associated inert template document"
this._templateDocCache = null;
// List of active NodeIterators, see NodeIterator#_preremove()
this._nodeIterators = null;
// Documents are always rooted, by definition
this._nid = 1;
this._nextnid = 2; // For numbering children of the document
this._nodes = [null, this]; // nid to node map
// This maintains the mapping from element ids to element nodes.
// We may need to update this mapping every time a node is rooted
// or uprooted, and any time an attribute is added, removed or changed
// on a rooted element.
this.byId = Object.create(null);
// This property holds a monotonically increasing value akin to
// a timestamp used to record the last modification time of nodes
// and their subtrees. See the lastModTime attribute and modify()
// method of the Node class. And see FilteredElementList for an example
// of the use of lastModTime
this.modclock = 0;
}
// Map from lowercase event category names (used as arguments to
// createEvent()) to the property name in the impl object of the
// event constructor.
var supportedEvents = {
event: 'Event',
customevent: 'CustomEvent',
uievent: 'UIEvent',
mouseevent: 'MouseEvent'
};
// Certain arguments to document.createEvent() must be treated specially
var replacementEvent = {
events: 'event',
htmlevents: 'event',
mouseevents: 'mouseevent',
mutationevents: 'mutationevent',
uievents: 'uievent'
};
var mirrorAttr = function(f, name, defaultValue) {
return {
get: function() {
var o = f.call(this);
if (o) { return o[name]; }
return defaultValue;
},
set: function(value) {
var o = f.call(this);
if (o) { o[name] = value; }
},
};
};
/** @spec https://dom.spec.whatwg.org/#validate-and-extract */
function validateAndExtract(namespace, qualifiedName) {
var prefix, localName, pos;
if (namespace==='') { namespace = null; }
// See https://github.com/whatwg/dom/issues/671
// and https://github.com/whatwg/dom/issues/319
if (!xml.isValidQName(qualifiedName)) {
utils.InvalidCharacterError();
}
prefix = null;
localName = qualifiedName;
pos = qualifiedName.indexOf(':');
if (pos >= 0) {
prefix = qualifiedName.substring(0, pos);
localName = qualifiedName.substring(pos+1);
}
if (prefix !== null && namespace === null) {
utils.NamespaceError();
}
if (prefix === 'xml' && namespace !== NAMESPACE.XML) {
utils.NamespaceError();
}
if ((prefix === 'xmlns' || qualifiedName === 'xmlns') &&
namespace !== NAMESPACE.XMLNS) {
utils.NamespaceError();
}
if (namespace === NAMESPACE.XMLNS && !(prefix==='xmlns' || qualifiedName==='xmlns')) {
utils.NamespaceError();
}
return { namespace: namespace, prefix: prefix, localName: localName };
}
Document.prototype = Object.create(ContainerNode.prototype, {
// This method allows dom.js to communicate with a renderer
// that displays the document in some way
// XXX: I should probably move this to the window object
_setMutationHandler: { value: function(handler) {
this.mutationHandler = handler;
}},
// This method allows dom.js to receive event notifications
// from the renderer.
// XXX: I should probably move this to the window object
_dispatchRendererEvent: { value: function(targetNid, type, details) {
var target = this._nodes[targetNid];
if (!target) return;
target._dispatchEvent(new Event(type, details), true);
}},
nodeName: { value: '#document'},
nodeValue: {
get: function() {
return null;
},
set: function() {}
},
// XXX: DOMCore may remove documentURI, so it is NYI for now
documentURI: { get: function() { return this._address; }, set: utils.nyi },
compatMode: { get: function() {
// The _quirks property is set by the HTML parser
return this._quirks ? 'BackCompat' : 'CSS1Compat';
}},
createTextNode: { value: function(data) {
return new Text(this, String(data));
}},
createComment: { value: function(data) {
return new Comment(this, data);
}},
createDocumentFragment: { value: function() {
return new DocumentFragment(this);
}},
createProcessingInstruction: { value: function(target, data) {
if (!xml.isValidName(target) || data.indexOf('?>') !== -1)
utils.InvalidCharacterError();
return new ProcessingInstruction(this, target, data);
}},
createAttribute: { value: function(localName) {
localName = String(localName);
if (!xml.isValidName(localName)) utils.InvalidCharacterError();
if (this.isHTML) {
localName = utils.toASCIILowerCase(localName);
}
return new Element._Attr(null, localName, null, null, '');
}},
createAttributeNS: { value: function(namespace, qualifiedName) {
// Convert parameter types according to WebIDL
namespace =
(namespace === null || namespace === undefined || namespace === '') ? null :
String(namespace);
qualifiedName = String(qualifiedName);
var ve = validateAndExtract(namespace, qualifiedName);
return new Element._Attr(null, ve.localName, ve.prefix, ve.namespace, '');
}},
createElement: { value: function(localName) {
localName = String(localName);
if (!xml.isValidName(localName)) utils.InvalidCharacterError();
// Per spec, namespace should be HTML namespace if "context object is
// an HTML document or context object's content type is
// "application/xhtml+xml", and null otherwise.
if (this.isHTML) {
if (/[A-Z]/.test(localName))
localName = utils.toASCIILowerCase(localName);
return html.createElement(this, localName, null);
} else if (this.contentType === 'application/xhtml+xml') {
return html.createElement(this, localName, null);
} else {
return new Element(this, localName, null, null);
}
}, writable: isApiWritable },
createElementNS: { value: function(namespace, qualifiedName) {
// Convert parameter types according to WebIDL
namespace =
(namespace === null || namespace === undefined || namespace === '') ? null :
String(namespace);
qualifiedName = String(qualifiedName);
var ve = validateAndExtract(namespace, qualifiedName);
return this._createElementNS(ve.localName, ve.namespace, ve.prefix);
}, writable: isApiWritable },
// This is used directly by HTML parser, which allows it to create
// elements with localNames containing ':' and non-default namespaces
_createElementNS: { value: function(localName, namespace, prefix) {
if (namespace === NAMESPACE.HTML) {
return html.createElement(this, localName, prefix);
}
else if (namespace === NAMESPACE.SVG) {
return svg.createElement(this, localName, prefix);
}
return new Element(this, localName, namespace, prefix);
}},
createEvent: { value: function createEvent(interfaceName) {
interfaceName = interfaceName.toLowerCase();
var name = replacementEvent[interfaceName] || interfaceName;
var constructor = events[supportedEvents[name]];
if (constructor) {
var e = new constructor();
e._initialized = false;
return e;
}
else {
utils.NotSupportedError();
}
}},
// See: http://www.w3.org/TR/dom/#dom-document-createtreewalker
createTreeWalker: {value: function (root, whatToShow, filter) {
if (!root) { throw new TypeError("root argument is required"); }
if (!(root instanceof Node)) { throw new TypeError("root not a node"); }
whatToShow = whatToShow === undefined ? NodeFilter.SHOW_ALL : (+whatToShow);
filter = filter === undefined ? null : filter;
return new TreeWalker(root, whatToShow, filter);
}},
// See: http://www.w3.org/TR/dom/#dom-document-createnodeiterator
createNodeIterator: {value: function (root, whatToShow, filter) {
if (!root) { throw new TypeError("root argument is required"); }
if (!(root instanceof Node)) { throw new TypeError("root not a node"); }
whatToShow = whatToShow === undefined ? NodeFilter.SHOW_ALL : (+whatToShow);
filter = filter === undefined ? null : filter;
return new NodeIterator(root, whatToShow, filter);
}},
_attachNodeIterator: { value: function(ni) {
// XXX ideally this should be a weak reference from Document to NodeIterator
if (!this._nodeIterators) { this._nodeIterators = []; }
this._nodeIterators.push(ni);
}},
_detachNodeIterator: { value: function(ni) {
// ni should always be in list of node iterators
var idx = this._nodeIterators.indexOf(ni);
this._nodeIterators.splice(idx, 1);
}},
_preremoveNodeIterators: { value: function(toBeRemoved) {
if (this._nodeIterators) {
this._nodeIterators.forEach(function(ni) { ni._preremove(toBeRemoved); });
}
}},
// Maintain the documentElement and
// doctype properties of the document. Each of the following
// methods chains to the Node implementation of the method
// to do the actual inserting, removal or replacement.
_updateDocTypeElement: { value: function _updateDocTypeElement() {
this.doctype = this.documentElement = null;
for (var kid = this.firstChild; kid !== null; kid = kid.nextSibling) {
if (kid.nodeType === Node.DOCUMENT_TYPE_NODE)
this.doctype = kid;
else if (kid.nodeType === Node.ELEMENT_NODE)
this.documentElement = kid;
}
}},
insertBefore: { value: function insertBefore(child, refChild) {
Node.prototype.insertBefore.call(this, child, refChild);
this._updateDocTypeElement();
return child;
}},
replaceChild: { value: function replaceChild(node, child) {
Node.prototype.replaceChild.call(this, node, child);
this._updateDocTypeElement();
return child;
}},
removeChild: { value: function removeChild(child) {
Node.prototype.removeChild.call(this, child);
this._updateDocTypeElement();
return child;
}},
getElementById: { value: function(id) {
var n = this.byId[id];
if (!n) return null;
if (n instanceof MultiId) { // there was more than one element with this id
return n.getFirst();
}
return n;
}},
_hasMultipleElementsWithId: { value: function(id) {
// Used internally by querySelectorAll optimization
return (this.byId[id] instanceof MultiId);
}},
// Just copy this method from the Element prototype
getElementsByName: { value: Element.prototype.getElementsByName },
getElementsByTagName: { value: Element.prototype.getElementsByTagName },
getElementsByTagNameNS: { value: Element.prototype.getElementsByTagNameNS },
getElementsByClassName: { value: Element.prototype.getElementsByClassName },
adoptNode: { value: function adoptNode(node) {
if (node.nodeType === Node.DOCUMENT_NODE) utils.NotSupportedError();
if (node.nodeType === Node.ATTRIBUTE_NODE) { return node; }
if (node.parentNode) node.parentNode.removeChild(node);
if (node.ownerDocument !== this)
recursivelySetOwner(node, this);
return node;
}},
importNode: { value: function importNode(node, deep) {
return this.adoptNode(node.cloneNode(deep));
}, writable: isApiWritable },
// The following attributes and methods are from the HTML spec
origin: { get: function origin() { return null; } },
characterSet: { get: function characterSet() { return "UTF-8"; } },
contentType: { get: function contentType() { return this._contentType; } },
URL: { get: function URL() { return this._address; } },
domain: { get: utils.nyi, set: utils.nyi },
referrer: { get: utils.nyi },
cookie: { get: utils.nyi, set: utils.nyi },
lastModified: { get: utils.nyi },
location: {
get: function() {
return this.defaultView ? this.defaultView.location : null; // gh #75
},
set: utils.nyi
},
_titleElement: {
get: function() {
// The title element of a document is the first title element in the
// document in tree order, if there is one, or null otherwise.
return this.getElementsByTagName('title').item(0) || null;
}
},
title: {
get: function() {
var elt = this._titleElement;
// The child text content of the title element, or '' if null.
var value = elt ? elt.textContent : '';
// Strip and collapse whitespace in value
return value.replace(/[ \t\n\r\f]+/g, ' ').replace(/(^ )|( $)/g, '');
},
set: function(value) {
var elt = this._titleElement;
var head = this.head;
if (!elt && !head) { return; /* according to spec */ }
if (!elt) {
elt = this.createElement('title');
head.appendChild(elt);
}
elt.textContent = value;
}
},
dir: mirrorAttr(function() {
var htmlElement = this.documentElement;
if (htmlElement && htmlElement.tagName === 'HTML') { return htmlElement; }
}, 'dir', ''),
fgColor: mirrorAttr(function() { return this.body; }, 'text', ''),
linkColor: mirrorAttr(function() { return this.body; }, 'link', ''),
vlinkColor: mirrorAttr(function() { return this.body; }, 'vLink', ''),
alinkColor: mirrorAttr(function() { return this.body; }, 'aLink', ''),
bgColor: mirrorAttr(function() { return this.body; }, 'bgColor', ''),
// Historical aliases of Document#characterSet
charset: { get: function() { return this.characterSet; } },
inputEncoding: { get: function() { return this.characterSet; } },
scrollingElement: {
get: function() {
return this._quirks ? this.body : this.documentElement;
}
},
// Return the first <body> child of the document element.
// XXX For now, setting this attribute is not implemented.
body: {
get: function() {
return namedHTMLChild(this.documentElement, 'body');
},
set: utils.nyi
},
// Return the first <head> child of the document element.
head: { get: function() {
return namedHTMLChild(this.documentElement, 'head');
}},
images: { get: utils.nyi },
embeds: { get: utils.nyi },
plugins: { get: utils.nyi },
links: { get: utils.nyi },
forms: { get: utils.nyi },
scripts: { get: utils.nyi },
applets: { get: function() { return []; } },
activeElement: { get: function() { return null; } },
innerHTML: {
get: function() { return this.serialize(); },
set: utils.nyi
},
outerHTML: {
get: function() { return this.serialize(); },
set: utils.nyi
},
write: { value: function(args) {
if (!this.isHTML) utils.InvalidStateError();
// XXX: still have to implement the ignore part
if (!this._parser /* && this._ignore_destructive_writes > 0 */ )
return;
if (!this._parser) {
// XXX call document.open, etc.
}
var s = arguments.join('');
// If the Document object's reload override flag is set, then
// append the string consisting of the concatenation of all the
// arguments to the method to the Document's reload override
// buffer.
// XXX: don't know what this is about. Still have to do it
// If there is no pending parsing-blocking script, have the
// tokenizer process the characters that were inserted, one at a
// time, processing resulting tokens as they are emitted, and
// stopping when the tokenizer reaches the insertion point or when
// the processing of the tokenizer is aborted by the tree
// construction stage (this can happen if a script end tag token is
// emitted by the tokenizer).
// XXX: still have to do the above. Sounds as if we don't
// always call parse() here. If we're blocked, then we just
// insert the text into the stream but don't parse it reentrantly...
// Invoke the parser reentrantly
this._parser.parse(s);
}},
writeln: { value: function writeln(args) {
this.write(Array.prototype.join.call(arguments, '') + '\n');
}},
open: { value: function() {
this.documentElement = null;
}},
close: { value: function() {
this.readyState = 'interactive';
this._dispatchEvent(new Event('readystatechange'), true);
this._dispatchEvent(new Event('DOMContentLoaded'), true);
this.readyState = 'complete';
this._dispatchEvent(new Event('readystatechange'), true);
if (this.defaultView) {
this.defaultView._dispatchEvent(new Event('load'), true);
}
}},
// Utility methods
clone: { value: function clone() {
var d = new Document(this.isHTML, this._address);
d._quirks = this._quirks;
d._contentType = this._contentType;
return d;
}},
// We need to adopt the nodes if we do a deep clone
cloneNode: { value: function cloneNode(deep) {
var clone = Node.prototype.cloneNode.call(this, false);
if (deep) {
for (var kid = this.firstChild; kid !== null; kid = kid.nextSibling) {
clone._appendChild(clone.importNode(kid, true));
}
}
clone._updateDocTypeElement();
return clone;
}},
isEqual: { value: function isEqual(n) {
// Any two documents are shallowly equal.
// Node.isEqualNode will also test the children
return true;
}},
// Implementation-specific function. Called when a text, comment,
// or pi value changes.
mutateValue: { value: function(node) {
if (this.mutationHandler) {
this.mutationHandler({
type: MUTATE.VALUE,
target: node,
data: node.data
});
}
}},
// Invoked when an attribute's value changes. Attr holds the new
// value. oldval is the old value. Attribute mutations can also
// involve changes to the prefix (and therefore the qualified name)
mutateAttr: { value: function(attr, oldval) {
// Manage id->element mapping for getElementsById()
// XXX: this special case id handling should not go here,
// but in the attribute declaration for the id attribute
/*
if (attr.localName === 'id' && attr.namespaceURI === null) {
if (oldval) delId(oldval, attr.ownerElement);
addId(attr.value, attr.ownerElement);
}
*/
if (this.mutationHandler) {
this.mutationHandler({
type: MUTATE.ATTR,
target: attr.ownerElement,
attr: attr
});
}
}},
// Used by removeAttribute and removeAttributeNS for attributes.
mutateRemoveAttr: { value: function(attr) {
/*
* This is now handled in Attributes.js
// Manage id to element mapping
if (attr.localName === 'id' && attr.namespaceURI === null) {
this.delId(attr.value, attr.ownerElement);
}
*/
if (this.mutationHandler) {
this.mutationHandler({
type: MUTATE.REMOVE_ATTR,
target: attr.ownerElement,
attr: attr
});
}
}},
// Called by Node.removeChild, etc. to remove a rooted element from
// the tree. Only needs to generate a single mutation event when a
// node is removed, but must recursively mark all descendants as not
// rooted.
mutateRemove: { value: function(node) {
// Send a single mutation event
if (this.mutationHandler) {
this.mutationHandler({
type: MUTATE.REMOVE,
target: node.parentNode,
node: node
});
}
// Mark this and all descendants as not rooted
recursivelyUproot(node);
}},
// Called when a new element becomes rooted. It must recursively
// generate mutation events for each of the children, and mark them all
// as rooted.
mutateInsert: { value: function(node) {
// Mark node and its descendants as rooted
recursivelyRoot(node);
// Send a single mutation event
if (this.mutationHandler) {
this.mutationHandler({
type: MUTATE.INSERT,
target: node.parentNode,
node: node
});
}
}},
// Called when a rooted element is moved within the document
mutateMove: { value: function(node) {
if (this.mutationHandler) {
this.mutationHandler({
type: MUTATE.MOVE,
target: node
});
}
}},
// Add a mapping from id to n for n.ownerDocument
addId: { value: function addId(id, n) {
var val = this.byId[id];
if (!val) {
this.byId[id] = n;
}
else {
// TODO: Add a way to opt-out console warnings
//console.warn('Duplicate element id ' + id);
if (!(val instanceof MultiId)) {
val = new MultiId(val);
this.byId[id] = val;
}
val.add(n);
}
}},
// Delete the mapping from id to n for n.ownerDocument
delId: { value: function delId(id, n) {
var val = this.byId[id];
utils.assert(val);
if (val instanceof MultiId) {
val.del(n);
if (val.length === 1) { // convert back to a single node
this.byId[id] = val.downgrade();
}
}
else {
this.byId[id] = undefined;
}
}},
_resolve: { value: function(href) {
//XXX: Cache the URL
return new URL(this._documentBaseURL).resolve(href);
}},
_documentBaseURL: { get: function() {
// XXX: This is not implemented correctly yet
var url = this._address;
if (url === 'about:blank') url = '/';
var base = this.querySelector('base[href]');
if (base) {
return new URL(url).resolve(base.getAttribute('href'));
}
return url;
// The document base URL of a Document object is the
// absolute URL obtained by running these substeps:
// Let fallback base url be the document's address.
// If fallback base url is about:blank, and the
// Document's browsing context has a creator browsing
// context, then let fallback base url be the document
// base URL of the creator Document instead.
// If the Document is an iframe srcdoc document, then
// let fallback base url be the document base URL of
// the Document's browsing context's browsing context
// container's Document instead.
// If there is no base element that has an href
// attribute, then the document base URL is fallback
// base url; abort these steps. Otherwise, let url be
// the value of the href attribute of the first such
// element.
// Resolve url relative to fallback base url (thus,
// the base href attribute isn't affected by xml:base
// attributes).
// The document base URL is the result of the previous
// step if it was successful; otherwise it is fallback
// base url.
}},
_templateDoc: { get: function() {
if (!this._templateDocCache) {
// "associated inert template document"
var newDoc = new Document(this.isHTML, this._address);
this._templateDocCache = newDoc._templateDocCache = newDoc;
}
return this._templateDocCache;
}},
querySelector: { value: function(selector) {
return select(selector, this)[0];
}},
querySelectorAll: { value: function(selector) {
var nodes = select(selector, this);
return nodes.item ? nodes : new NodeList(nodes);
}}
});
var eventHandlerTypes = [
'abort', 'canplay', 'canplaythrough', 'change', 'click', 'contextmenu',
'cuechange', 'dblclick', 'drag', 'dragend', 'dragenter', 'dragleave',
'dragover', 'dragstart', 'drop', 'durationchange', 'emptied', 'ended',
'input', 'invalid', 'keydown', 'keypress', 'keyup', 'loadeddata',
'loadedmetadata', 'loadstart', 'mousedown', 'mousemove', 'mouseout',
'mouseover', 'mouseup', 'mousewheel', 'pause', 'play', 'playing',
'progress', 'ratechange', 'readystatechange', 'reset', 'seeked',
'seeking', 'select', 'show', 'stalled', 'submit', 'suspend',
'timeupdate', 'volumechange', 'waiting',
'blur', 'error', 'focus', 'load', 'scroll'
];
// Add event handler idl attribute getters and setters to Document
eventHandlerTypes.forEach(function(type) {
// Define the event handler registration IDL attribute for this type
Object.defineProperty(Document.prototype, 'on' + type, {
get: function() {
return this._getEventHandler(type);
},
set: function(v) {
this._setEventHandler(type, v);
}
});
});
function namedHTMLChild(parent, name) {
if (parent && parent.isHTML) {
for (var kid = parent.firstChild; kid !== null; kid = kid.nextSibling) {
if (kid.nodeType === Node.ELEMENT_NODE &&
kid.localName === name &&
kid.namespaceURI === NAMESPACE.HTML) {
return kid;
}
}
}
return null;
}
function root(n) {
n._nid = n.ownerDocument._nextnid++;
n.ownerDocument._nodes[n._nid] = n;
// Manage id to element mapping
if (n.nodeType === Node.ELEMENT_NODE) {
var id = n.getAttribute('id');
if (id) n.ownerDocument.addId(id, n);
// Script elements need to know when they're inserted
// into the document
if (n._roothook) n._roothook();
}
}
function uproot(n) {
// Manage id to element mapping
if (n.nodeType === Node.ELEMENT_NODE) {
var id = n.getAttribute('id');
if (id) n.ownerDocument.delId(id, n);
}
n.ownerDocument._nodes[n._nid] = undefined;
n._nid = undefined;
}
function recursivelyRoot(node) {
root(node);
// XXX:
// accessing childNodes on a leaf node creates a new array the
// first time, so be careful to write this loop so that it
// doesn't do that. node is polymorphic, so maybe this is hard to
// optimize? Try switching on nodeType?
/*
if (node.hasChildNodes()) {
var kids = node.childNodes;
for(var i = 0, n = kids.length; i < n; i++)
recursivelyRoot(kids[i]);
}
*/
if (node.nodeType === Node.ELEMENT_NODE) {
for (var kid = node.firstChild; kid !== null; kid = kid.nextSibling)
recursivelyRoot(kid);
}
}
function recursivelyUproot(node) {
uproot(node);
for (var kid = node.firstChild; kid !== null; kid = kid.nextSibling)
recursivelyUproot(kid);
}
function recursivelySetOwner(node, owner) {
node.ownerDocument = owner;
node._lastModTime = undefined; // mod times are document-based
if (Object.prototype.hasOwnProperty.call(node, '_tagName')) {
node._tagName = undefined; // Element subclasses might need to change case
}
for (var kid = node.firstChild; kid !== null; kid = kid.nextSibling)
recursivelySetOwner(kid, owner);
}
// A class for storing multiple nodes with the same ID
function MultiId(node) {
this.nodes = Object.create(null);
this.nodes[node._nid] = node;
this.length = 1;
this.firstNode = undefined;
}
// Add a node to the list, with O(1) time
MultiId.prototype.add = function(node) {
if (!this.nodes[node._nid]) {
this.nodes[node._nid] = node;
this.length++;
this.firstNode = undefined;
}
};
// Remove a node from the list, with O(1) time
MultiId.prototype.del = function(node) {
if (this.nodes[node._nid]) {
delete this.nodes[node._nid];
this.length--;
this.firstNode = undefined;
}
};
// Get the first node from the list, in the document order
// Takes O(N) time in the size of the list, with a cache that is invalidated
// when the list is modified.
MultiId.prototype.getFirst = function() {
/* jshint bitwise: false */
if (!this.firstNode) {
var nid;
for (nid in this.nodes) {
if (this.firstNode === undefined ||
this.firstNode.compareDocumentPosition(this.nodes[nid]) & Node.DOCUMENT_POSITION_PRECEDING) {
this.firstNode = this.nodes[nid];
}
}
}
return this.firstNode;
};
// If there is only one node left, return it. Otherwise return "this".
MultiId.prototype.downgrade = function() {
if (this.length === 1) {
var nid;
for (nid in this.nodes) {
return this.nodes[nid];
}
}
return this;
};

View File

@@ -0,0 +1,71 @@
"use strict";
module.exports = DocumentFragment;
var Node = require('./Node');
var NodeList = require('./NodeList');
var ContainerNode = require('./ContainerNode');
var Element = require('./Element');
var select = require('./select');
var utils = require('./utils');
function DocumentFragment(doc) {
ContainerNode.call(this);
this.nodeType = Node.DOCUMENT_FRAGMENT_NODE;
this.ownerDocument = doc;
}
DocumentFragment.prototype = Object.create(ContainerNode.prototype, {
nodeName: { value: '#document-fragment' },
nodeValue: {
get: function() {
return null;
},
set: function() {}
},
// Copy the text content getter/setter from Element
textContent: Object.getOwnPropertyDescriptor(Element.prototype, 'textContent'),
// Copy the text content getter/setter from Element
innerText: Object.getOwnPropertyDescriptor(Element.prototype, 'innerText'),
querySelector: { value: function(selector) {
// implement in terms of querySelectorAll
var nodes = this.querySelectorAll(selector);
return nodes.length ? nodes[0] : null;
}},
querySelectorAll: { value: function(selector) {
// create a context
var context = Object.create(this);
// add some methods to the context for zest implementation, without
// adding them to the public DocumentFragment API
context.isHTML = true; // in HTML namespace (case-insensitive match)
context.getElementsByTagName = Element.prototype.getElementsByTagName;
context.nextElement =
Object.getOwnPropertyDescriptor(Element.prototype, 'firstElementChild').
get;
// invoke zest
var nodes = select(selector, context);
return nodes.item ? nodes : new NodeList(nodes);
}},
// Utility methods
clone: { value: function clone() {
return new DocumentFragment(this.ownerDocument);
}},
isEqual: { value: function isEqual(n) {
// Any two document fragments are shallowly equal.
// Node.isEqualNode() will test their children for equality
return true;
}},
// Non-standard, but useful (github issue #73)
innerHTML: {
get: function() { return this.serialize(); },
set: utils.nyi
},
outerHTML: {
get: function() { return this.serialize(); },
set: utils.nyi
},
});

View File

@@ -0,0 +1,36 @@
"use strict";
module.exports = DocumentType;
var Node = require('./Node');
var Leaf = require('./Leaf');
var ChildNode = require('./ChildNode');
function DocumentType(ownerDocument, name, publicId, systemId) {
Leaf.call(this);
this.nodeType = Node.DOCUMENT_TYPE_NODE;
this.ownerDocument = ownerDocument || null;
this.name = name;
this.publicId = publicId || "";
this.systemId = systemId || "";
}
DocumentType.prototype = Object.create(Leaf.prototype, {
nodeName: { get: function() { return this.name; }},
nodeValue: {
get: function() { return null; },
set: function() {}
},
// Utility methods
clone: { value: function clone() {
return new DocumentType(this.ownerDocument, this.name, this.publicId, this.systemId);
}},
isEqual: { value: function isEqual(n) {
return this.name === n.name &&
this.publicId === n.publicId &&
this.systemId === n.systemId;
}}
});
Object.defineProperties(DocumentType.prototype, ChildNode);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
"use strict";
module.exports = Event;
Event.CAPTURING_PHASE = 1;
Event.AT_TARGET = 2;
Event.BUBBLING_PHASE = 3;
function Event(type, dictionary) {
// Initialize basic event properties
this.type = '';
this.target = null;
this.currentTarget = null;
this.eventPhase = Event.AT_TARGET;
this.bubbles = false;
this.cancelable = false;
this.isTrusted = false;
this.defaultPrevented = false;
this.timeStamp = Date.now();
// Initialize internal flags
// XXX: Would it be better to inherit these defaults from the prototype?
this._propagationStopped = false;
this._immediatePropagationStopped = false;
this._initialized = true;
this._dispatching = false;
// Now initialize based on the constructor arguments (if any)
if (type) this.type = type;
if (dictionary) {
for(var p in dictionary) {
this[p] = dictionary[p];
}
}
}
Event.prototype = Object.create(Object.prototype, {
constructor: { value: Event },
stopPropagation: { value: function stopPropagation() {
this._propagationStopped = true;
}},
stopImmediatePropagation: { value: function stopImmediatePropagation() {
this._propagationStopped = true;
this._immediatePropagationStopped = true;
}},
preventDefault: { value: function preventDefault() {
if (this.cancelable) this.defaultPrevented = true;
}},
initEvent: { value: function initEvent(type, bubbles, cancelable) {
this._initialized = true;
if (this._dispatching) return;
this._propagationStopped = false;
this._immediatePropagationStopped = false;
this.defaultPrevented = false;
this.isTrusted = false;
this.target = null;
this.type = type;
this.bubbles = bubbles;
this.cancelable = cancelable;
}},
});

View File

@@ -0,0 +1,298 @@
"use strict";
var Event = require('./Event');
var MouseEvent = require('./MouseEvent');
var utils = require('./utils');
module.exports = EventTarget;
function EventTarget() {}
EventTarget.prototype = {
// XXX
// See WebIDL §4.8 for details on object event handlers
// and how they should behave. We actually have to accept
// any object to addEventListener... Can't type check it.
// on registration.
// XXX:
// Capturing event listeners are sort of rare. I think I can optimize
// them so that dispatchEvent can skip the capturing phase (or much of
// it). Each time a capturing listener is added, increment a flag on
// the target node and each of its ancestors. Decrement when removed.
// And update the counter when nodes are added and removed from the
// tree as well. Then, in dispatch event, the capturing phase can
// abort if it sees any node with a zero count.
addEventListener: function addEventListener(type, listener, capture) {
if (!listener) return;
if (capture === undefined) capture = false;
if (!this._listeners) this._listeners = Object.create(null);
if (!this._listeners[type]) this._listeners[type] = [];
var list = this._listeners[type];
// If this listener has already been registered, just return
for(var i = 0, n = list.length; i < n; i++) {
var l = list[i];
if (l.listener === listener && l.capture === capture)
return;
}
// Add an object to the list of listeners
var obj = { listener: listener, capture: capture };
if (typeof listener === 'function') obj.f = listener;
list.push(obj);
},
removeEventListener: function removeEventListener(type,
listener,
capture) {
if (capture === undefined) capture = false;
if (this._listeners) {
var list = this._listeners[type];
if (list) {
// Find the listener in the list and remove it
for(var i = 0, n = list.length; i < n; i++) {
var l = list[i];
if (l.listener === listener && l.capture === capture) {
if (list.length === 1) {
this._listeners[type] = undefined;
}
else {
list.splice(i, 1);
}
return;
}
}
}
}
},
// This is the public API for dispatching untrusted public events.
// See _dispatchEvent for the implementation
dispatchEvent: function dispatchEvent(event) {
// Dispatch an untrusted event
return this._dispatchEvent(event, false);
},
//
// See DOMCore §4.4
// XXX: I'll probably need another version of this method for
// internal use, one that does not set isTrusted to false.
// XXX: see Document._dispatchEvent: perhaps that and this could
// call a common internal function with different settings of
// a trusted boolean argument
//
// XXX:
// The spec has changed in how to deal with handlers registered
// on idl or content attributes rather than with addEventListener.
// Used to say that they always ran first. That's how webkit does it
// Spec now says that they run in a position determined by
// when they were first set. FF does it that way. See:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#event-handlers
//
_dispatchEvent: function _dispatchEvent(event, trusted) {
if (typeof trusted !== 'boolean') trusted = false;
function invoke(target, event) {
var type = event.type, phase = event.eventPhase;
event.currentTarget = target;
// If there was an individual handler defined, invoke it first
// XXX: see comment above: this shouldn't always be first.
if (phase !== Event.CAPTURING_PHASE &&
target._handlers && target._handlers[type])
{
var handler = target._handlers[type];
var rv;
if (typeof handler === 'function') {
rv=handler.call(event.currentTarget, event);
}
else {
var f = handler.handleEvent;
if (typeof f !== 'function')
throw new TypeError('handleEvent property of ' +
'event handler object is' +
'not a function.');
rv=f.call(handler, event);
}
switch(event.type) {
case 'mouseover':
if (rv === true) // Historical baggage
event.preventDefault();
break;
case 'beforeunload':
// XXX: eventually we need a special case here
/* falls through */
default:
if (rv === false)
event.preventDefault();
break;
}
}
// Now invoke list list of listeners for this target and type
var list = target._listeners && target._listeners[type];
if (!list) return;
list = list.slice();
for(var i = 0, n = list.length; i < n; i++) {
if (event._immediatePropagationStopped) return;
var l = list[i];
if ((phase === Event.CAPTURING_PHASE && !l.capture) ||
(phase === Event.BUBBLING_PHASE && l.capture))
continue;
if (l.f) {
l.f.call(event.currentTarget, event);
}
else {
var fn = l.listener.handleEvent;
if (typeof fn !== 'function')
throw new TypeError('handleEvent property of event listener object is not a function.');
fn.call(l.listener, event);
}
}
}
if (!event._initialized || event._dispatching) utils.InvalidStateError();
event.isTrusted = trusted;
// Begin dispatching the event now
event._dispatching = true;
event.target = this;
// Build the list of targets for the capturing and bubbling phases
// XXX: we'll eventually have to add Window to this list.
var ancestors = [];
for(var n = this.parentNode; n; n = n.parentNode)
ancestors.push(n);
// Capturing phase
event.eventPhase = Event.CAPTURING_PHASE;
for(var i = ancestors.length-1; i >= 0; i--) {
invoke(ancestors[i], event);
if (event._propagationStopped) break;
}
// At target phase
if (!event._propagationStopped) {
event.eventPhase = Event.AT_TARGET;
invoke(this, event);
}
// Bubbling phase
if (event.bubbles && !event._propagationStopped) {
event.eventPhase = Event.BUBBLING_PHASE;
for(var ii = 0, nn = ancestors.length; ii < nn; ii++) {
invoke(ancestors[ii], event);
if (event._propagationStopped) break;
}
}
event._dispatching = false;
event.eventPhase = Event.AT_TARGET;
event.currentTarget = null;
// Deal with mouse events and figure out when
// a click has happened
if (trusted && !event.defaultPrevented && event instanceof MouseEvent) {
switch(event.type) {
case 'mousedown':
this._armed = {
x: event.clientX,
y: event.clientY,
t: event.timeStamp
};
break;
case 'mouseout':
case 'mouseover':
this._armed = null;
break;
case 'mouseup':
if (this._isClick(event)) this._doClick(event);
this._armed = null;
break;
}
}
return !event.defaultPrevented;
},
// Determine whether a click occurred
// XXX We don't support double clicks for now
_isClick: function(event) {
return (this._armed !== null &&
event.type === 'mouseup' &&
event.isTrusted &&
event.button === 0 &&
event.timeStamp - this._armed.t < 1000 &&
Math.abs(event.clientX - this._armed.x) < 10 &&
Math.abs(event.clientY - this._armed.Y) < 10);
},
// Clicks are handled like this:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#interactive-content-0
//
// Note that this method is similar to the HTMLElement.click() method
// The event argument must be the trusted mouseup event
_doClick: function(event) {
if (this._click_in_progress) return;
this._click_in_progress = true;
// Find the nearest enclosing element that is activatable
// An element is activatable if it has a
// _post_click_activation_steps hook
var activated = this;
while(activated && !activated._post_click_activation_steps)
activated = activated.parentNode;
if (activated && activated._pre_click_activation_steps) {
activated._pre_click_activation_steps();
}
var click = this.ownerDocument.createEvent('MouseEvent');
click.initMouseEvent('click', true, true,
this.ownerDocument.defaultView, 1,
event.screenX, event.screenY,
event.clientX, event.clientY,
event.ctrlKey, event.altKey,
event.shiftKey, event.metaKey,
event.button, null);
var result = this._dispatchEvent(click, true);
if (activated) {
if (result) {
// This is where hyperlinks get followed, for example.
if (activated._post_click_activation_steps)
activated._post_click_activation_steps(click);
}
else {
if (activated._cancelled_activation_steps)
activated._cancelled_activation_steps();
}
}
},
//
// An event handler is like an event listener, but it registered
// by setting an IDL or content attribute like onload or onclick.
// There can only be one of these at a time for any event type.
// This is an internal method for the attribute accessors and
// content attribute handlers that need to register events handlers.
// The type argument is the same as in addEventListener().
// The handler argument is the same as listeners in addEventListener:
// it can be a function or an object. Pass null to remove any existing
// handler. Handlers are always invoked before any listeners of
// the same type. They are not invoked during the capturing phase
// of event dispatch.
//
_setEventHandler: function _setEventHandler(type, handler) {
if (!this._handlers) this._handlers = Object.create(null);
this._handlers[type] = handler;
},
_getEventHandler: function _getEventHandler(type) {
return (this._handlers && this._handlers[type]) || null;
}
};

View File

@@ -0,0 +1,92 @@
"use strict";
module.exports = FilteredElementList;
var Node = require('./Node');
//
// This file defines node list implementation that lazily traverses
// the document tree (or a subtree rooted at any element) and includes
// only those elements for which a specified filter function returns true.
// It is used to implement the
// {Document,Element}.getElementsBy{TagName,ClassName}{,NS} methods.
//
// XXX this should inherit from NodeList
function FilteredElementList(root, filter) {
this.root = root;
this.filter = filter;
this.lastModTime = root.lastModTime;
this.done = false;
this.cache = [];
this.traverse();
}
FilteredElementList.prototype = Object.create(Object.prototype, {
length: { get: function() {
this.checkcache();
if (!this.done) this.traverse();
return this.cache.length;
} },
item: { value: function(n) {
this.checkcache();
if (!this.done && n >= this.cache.length) {
// This can lead to O(N^2) behavior if we stop when we get to n
// and the caller is iterating through the items in order; so
// be sure to do the full traverse here.
this.traverse(/*n*/);
}
return this.cache[n];
} },
checkcache: { value: function() {
if (this.lastModTime !== this.root.lastModTime) {
// subtree has changed, so invalidate cache
for (var i = this.cache.length-1; i>=0; i--) {
this[i] = undefined;
}
this.cache.length = 0;
this.done = false;
this.lastModTime = this.root.lastModTime;
}
} },
// If n is specified, then traverse the tree until we've found the nth
// item (or until we've found all items). If n is not specified,
// traverse until we've found all items.
traverse: { value: function(n) {
// increment n so we can compare to length, and so it is never falsy
if (n !== undefined) n++;
var elt;
while ((elt = this.next()) !== null) {
this[this.cache.length] = elt; //XXX Use proxy instead
this.cache.push(elt);
if (n && this.cache.length === n) return;
}
// no next element, so we've found everything
this.done = true;
} },
// Return the next element under root that matches filter
next: { value: function() {
var start = (this.cache.length === 0) ? this.root // Start at the root or at
: this.cache[this.cache.length-1]; // the last element we found
var elt;
if (start.nodeType === Node.DOCUMENT_NODE)
elt = start.documentElement;
else
elt = start.nextElement(this.root);
while(elt) {
if (this.filter(elt)) {
return elt;
}
elt = elt.nextElement(this.root);
}
return null;
} },
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,37 @@
"use strict";
module.exports = Leaf;
var Node = require('./Node');
var NodeList = require('./NodeList');
var utils = require('./utils');
var HierarchyRequestError = utils.HierarchyRequestError;
var NotFoundError = utils.NotFoundError;
// This class defines common functionality for node subtypes that
// can never have children
function Leaf() {
Node.call(this);
}
Leaf.prototype = Object.create(Node.prototype, {
hasChildNodes: { value: function() { return false; }},
firstChild: { value: null },
lastChild: { value: null },
insertBefore: { value: function(node, child) {
if (!node.nodeType) throw new TypeError('not a node');
HierarchyRequestError();
}},
replaceChild: { value: function(node, child) {
if (!node.nodeType) throw new TypeError('not a node');
HierarchyRequestError();
}},
removeChild: { value: function(node) {
if (!node.nodeType) throw new TypeError('not a node');
NotFoundError();
}},
removeChildren: { value: function() { /* no op */ }},
childNodes: { get: function() {
if (!this._childNodes) this._childNodes = new NodeList();
return this._childNodes;
}}
});

View File

@@ -0,0 +1,44 @@
"use strict";
var utils = require('./utils');
var LinkedList = module.exports = {
// basic validity tests on a circular linked list a
valid: function(a) {
utils.assert(a, "list falsy");
utils.assert(a._previousSibling, "previous falsy");
utils.assert(a._nextSibling, "next falsy");
// xxx check that list is actually circular
return true;
},
// insert a before b
insertBefore: function(a, b) {
utils.assert(LinkedList.valid(a) && LinkedList.valid(b));
var a_first = a, a_last = a._previousSibling;
var b_first = b, b_last = b._previousSibling;
a_first._previousSibling = b_last;
a_last._nextSibling = b_first;
b_last._nextSibling = a_first;
b_first._previousSibling = a_last;
utils.assert(LinkedList.valid(a) && LinkedList.valid(b));
},
// replace a single node a with a list b (which could be null)
replace: function(a, b) {
utils.assert(LinkedList.valid(a) && (b===null || LinkedList.valid(b)));
if (b!==null) {
LinkedList.insertBefore(b, a);
}
LinkedList.remove(a);
utils.assert(LinkedList.valid(a) && (b===null || LinkedList.valid(b)));
},
// remove single node a from its list
remove: function(a) {
utils.assert(LinkedList.valid(a));
var prev = a._previousSibling;
if (prev === a) { return; }
var next = a._nextSibling;
prev._nextSibling = next;
next._previousSibling = prev;
a._previousSibling = a._nextSibling = a;
utils.assert(LinkedList.valid(a));
}
};

View File

@@ -0,0 +1,56 @@
"use strict";
var URL = require('./URL');
var URLUtils = require('./URLUtils');
module.exports = Location;
function Location(window, href) {
this._window = window;
this._href = href;
}
Location.prototype = Object.create(URLUtils.prototype, {
constructor: { value: Location },
// Special behavior when href is set
href: {
get: function() { return this._href; },
set: function(v) { this.assign(v); }
},
assign: { value: function(url) {
// Resolve the new url against the current one
// XXX:
// This is not actually correct. It should be resolved against
// the URL of the document of the script. For now, though, I only
// support a single window and there is only one base url.
// So this is good enough for now.
var current = new URL(this._href);
var newurl = current.resolve(url);
// Save the new url
this._href = newurl;
// Start loading the new document!
// XXX
// This is just something hacked together.
// The real algorithm is: http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#navigate
}},
replace: { value: function(url) {
// XXX
// Since we aren't tracking history yet, replace is the same as assign
this.assign(url);
}},
reload: { value: function() {
// XXX:
// Actually, the spec is a lot more complicated than this
this.assign(this.href);
}},
toString: { value: function() {
return this.href;
}}
});

View File

@@ -0,0 +1,52 @@
"use strict";
var UIEvent = require('./UIEvent');
module.exports = MouseEvent;
function MouseEvent() {
// Just use the superclass constructor to initialize
UIEvent.call(this);
this.screenX = this.screenY = this.clientX = this.clientY = 0;
this.ctrlKey = this.altKey = this.shiftKey = this.metaKey = false;
this.button = 0;
this.buttons = 1;
this.relatedTarget = null;
}
MouseEvent.prototype = Object.create(UIEvent.prototype, {
constructor: { value: MouseEvent },
initMouseEvent: { value: function(type, bubbles, cancelable,
view, detail,
screenX, screenY, clientX, clientY,
ctrlKey, altKey, shiftKey, metaKey,
button, relatedTarget) {
this.initEvent(type, bubbles, cancelable, view, detail);
this.screenX = screenX;
this.screenY = screenY;
this.clientX = clientX;
this.clientY = clientY;
this.ctrlKey = ctrlKey;
this.altKey = altKey;
this.shiftKey = shiftKey;
this.metaKey = metaKey;
this.button = button;
switch(button) {
case 0: this.buttons = 1; break;
case 1: this.buttons = 4; break;
case 2: this.buttons = 2; break;
default: this.buttons = 0; break;
}
this.relatedTarget = relatedTarget;
}},
getModifierState: { value: function(key) {
switch(key) {
case "Alt": return this.altKey;
case "Control": return this.ctrlKey;
case "Shift": return this.shiftKey;
case "Meta": return this.metaKey;
default: return false;
}
}}
});

View File

@@ -0,0 +1,9 @@
"use strict";
module.exports = {
VALUE: 1, // The value of a Text, Comment or PI node changed
ATTR: 2, // A new attribute was added or an attribute value and/or prefix changed
REMOVE_ATTR: 3, // An attribute was removed
REMOVE: 4, // A node was removed
MOVE: 5, // A node was moved
INSERT: 6 // A node (or a subtree of nodes) was inserted
};

View File

@@ -0,0 +1,41 @@
"use strict";
module.exports = NamedNodeMap;
var utils = require('./utils');
/* This is a hacky implementation of NamedNodeMap, intended primarily to
* satisfy clients (like dompurify and the web-platform-tests) which check
* to ensure that Node#attributes instanceof NamedNodeMap. */
function NamedNodeMap(element) {
this.element = element;
}
Object.defineProperties(NamedNodeMap.prototype, {
length: { get: utils.shouldOverride },
item: { value: utils.shouldOverride },
getNamedItem: { value: function getNamedItem(qualifiedName) {
return this.element.getAttributeNode(qualifiedName);
} },
getNamedItemNS: { value: function getNamedItemNS(namespace, localName) {
return this.element.getAttributeNodeNS(namespace, localName);
} },
setNamedItem: { value: utils.nyi },
setNamedItemNS: { value: utils.nyi },
removeNamedItem: { value: function removeNamedItem(qualifiedName) {
var attr = this.element.getAttributeNode(qualifiedName);
if (attr) {
this.element.removeAttribute(qualifiedName);
return attr;
}
utils.NotFoundError();
} },
removeNamedItemNS: { value: function removeNamedItemNS(ns, lname) {
var attr = this.element.getAttributeNodeNS(ns, lname);
if (attr) {
this.element.removeAttributeNS(ns, lname);
return attr;
}
utils.NotFoundError();
} },
});

View File

@@ -0,0 +1,17 @@
"use strict";
// https://html.spec.whatwg.org/multipage/webappapis.html#navigatorid
var NavigatorID = Object.create(null, {
appCodeName: { value: "Mozilla" },
appName: { value: "Netscape" },
appVersion: { value: "4.0" },
platform: { value: "" },
product: { value: "Gecko" },
productSub: { value: "20100101" },
userAgent: { value: "" },
vendor: { value: "" },
vendorSub: { value: "" },
taintEnabled: { value: function() { return false; } }
});
module.exports = NavigatorID;

View File

@@ -0,0 +1,764 @@
"use strict";
module.exports = Node;
var EventTarget = require('./EventTarget');
var LinkedList = require('./LinkedList');
var NodeUtils = require('./NodeUtils');
var utils = require('./utils');
// All nodes have a nodeType and an ownerDocument.
// Once inserted, they also have a parentNode.
// This is an abstract class; all nodes in a document are instances
// of a subtype, so all the properties are defined by more specific
// constructors.
function Node() {
EventTarget.call(this);
this.parentNode = null;
this._nextSibling = this._previousSibling = this;
this._index = undefined;
}
var ELEMENT_NODE = Node.ELEMENT_NODE = 1;
var ATTRIBUTE_NODE = Node.ATTRIBUTE_NODE = 2;
var TEXT_NODE = Node.TEXT_NODE = 3;
var CDATA_SECTION_NODE = Node.CDATA_SECTION_NODE = 4;
var ENTITY_REFERENCE_NODE = Node.ENTITY_REFERENCE_NODE = 5;
var ENTITY_NODE = Node.ENTITY_NODE = 6;
var PROCESSING_INSTRUCTION_NODE = Node.PROCESSING_INSTRUCTION_NODE = 7;
var COMMENT_NODE = Node.COMMENT_NODE = 8;
var DOCUMENT_NODE = Node.DOCUMENT_NODE = 9;
var DOCUMENT_TYPE_NODE = Node.DOCUMENT_TYPE_NODE = 10;
var DOCUMENT_FRAGMENT_NODE = Node.DOCUMENT_FRAGMENT_NODE = 11;
var NOTATION_NODE = Node.NOTATION_NODE = 12;
var DOCUMENT_POSITION_DISCONNECTED = Node.DOCUMENT_POSITION_DISCONNECTED = 0x01;
var DOCUMENT_POSITION_PRECEDING = Node.DOCUMENT_POSITION_PRECEDING = 0x02;
var DOCUMENT_POSITION_FOLLOWING = Node.DOCUMENT_POSITION_FOLLOWING = 0x04;
var DOCUMENT_POSITION_CONTAINS = Node.DOCUMENT_POSITION_CONTAINS = 0x08;
var DOCUMENT_POSITION_CONTAINED_BY = Node.DOCUMENT_POSITION_CONTAINED_BY = 0x10;
var DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
Node.prototype = Object.create(EventTarget.prototype, {
// Node that are not inserted into the tree inherit a null parent
// XXX: the baseURI attribute is defined by dom core, but
// a correct implementation of it requires HTML features, so
// we'll come back to this later.
baseURI: { get: utils.nyi },
parentElement: { get: function() {
return (this.parentNode && this.parentNode.nodeType===ELEMENT_NODE) ? this.parentNode : null;
}},
hasChildNodes: { value: utils.shouldOverride },
firstChild: { get: utils.shouldOverride },
lastChild: { get: utils.shouldOverride },
isConnected: {
get: function () {
let node = this;
while (node != null) {
if (node.nodeType === Node.DOCUMENT_NODE) {
return true;
}
node = node.parentNode;
if (node != null && node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
node = node.host;
}
}
return false;
},
},
previousSibling: { get: function() {
var parent = this.parentNode;
if (!parent) return null;
if (this === parent.firstChild) return null;
return this._previousSibling;
}},
nextSibling: { get: function() {
var parent = this.parentNode, next = this._nextSibling;
if (!parent) return null;
if (next === parent.firstChild) return null;
return next;
}},
textContent: {
// Should override for DocumentFragment/Element/Attr/Text/PI/Comment
get: function() { return null; },
set: function(v) { /* do nothing */ },
},
innerText: {
// Should override for DocumentFragment/Element/Attr/Text/PI/Comment
get: function() { return null; },
set: function(v) { /* do nothing */ },
},
_countChildrenOfType: { value: function(type) {
var sum = 0;
for (var kid = this.firstChild; kid !== null; kid = kid.nextSibling) {
if (kid.nodeType === type) sum++;
}
return sum;
}},
_ensureInsertValid: { value: function _ensureInsertValid(node, child, isPreinsert) {
var parent = this, i, kid;
if (!node.nodeType) throw new TypeError('not a node');
// 1. If parent is not a Document, DocumentFragment, or Element
// node, throw a HierarchyRequestError.
switch (parent.nodeType) {
case DOCUMENT_NODE:
case DOCUMENT_FRAGMENT_NODE:
case ELEMENT_NODE:
break;
default: utils.HierarchyRequestError();
}
// 2. If node is a host-including inclusive ancestor of parent,
// throw a HierarchyRequestError.
if (node.isAncestor(parent)) utils.HierarchyRequestError();
// 3. If child is not null and its parent is not parent, then
// throw a NotFoundError. (replaceChild omits the 'child is not null'
// and throws a TypeError here if child is null.)
if (child !== null || !isPreinsert) {
if (child.parentNode !== parent) utils.NotFoundError();
}
// 4. If node is not a DocumentFragment, DocumentType, Element,
// Text, ProcessingInstruction, or Comment node, throw a
// HierarchyRequestError.
switch (node.nodeType) {
case DOCUMENT_FRAGMENT_NODE:
case DOCUMENT_TYPE_NODE:
case ELEMENT_NODE:
case TEXT_NODE:
case PROCESSING_INSTRUCTION_NODE:
case COMMENT_NODE:
break;
default: utils.HierarchyRequestError();
}
// 5. If either node is a Text node and parent is a document, or
// node is a doctype and parent is not a document, throw a
// HierarchyRequestError.
// 6. If parent is a document, and any of the statements below, switched
// on node, are true, throw a HierarchyRequestError.
if (parent.nodeType === DOCUMENT_NODE) {
switch (node.nodeType) {
case TEXT_NODE:
utils.HierarchyRequestError();
break;
case DOCUMENT_FRAGMENT_NODE:
// 6a1. If node has more than one element child or has a Text
// node child.
if (node._countChildrenOfType(TEXT_NODE) > 0)
utils.HierarchyRequestError();
switch (node._countChildrenOfType(ELEMENT_NODE)) {
case 0:
break;
case 1:
// 6a2. Otherwise, if node has one element child and either
// parent has an element child, child is a doctype, or child
// is not null and a doctype is following child. [preinsert]
// 6a2. Otherwise, if node has one element child and either
// parent has an element child that is not child or a
// doctype is following child. [replaceWith]
if (child !== null /* always true here for replaceWith */) {
if (isPreinsert && child.nodeType === DOCUMENT_TYPE_NODE)
utils.HierarchyRequestError();
for (kid = child.nextSibling; kid !== null; kid = kid.nextSibling) {
if (kid.nodeType === DOCUMENT_TYPE_NODE)
utils.HierarchyRequestError();
}
}
i = parent._countChildrenOfType(ELEMENT_NODE);
if (isPreinsert) {
// "parent has an element child"
if (i > 0)
utils.HierarchyRequestError();
} else {
// "parent has an element child that is not child"
if (i > 1 || (i === 1 && child.nodeType !== ELEMENT_NODE))
utils.HierarchyRequestError();
}
break;
default: // 6a1, continued. (more than one Element child)
utils.HierarchyRequestError();
}
break;
case ELEMENT_NODE:
// 6b. parent has an element child, child is a doctype, or
// child is not null and a doctype is following child. [preinsert]
// 6b. parent has an element child that is not child or a
// doctype is following child. [replaceWith]
if (child !== null /* always true here for replaceWith */) {
if (isPreinsert && child.nodeType === DOCUMENT_TYPE_NODE)
utils.HierarchyRequestError();
for (kid = child.nextSibling; kid !== null; kid = kid.nextSibling) {
if (kid.nodeType === DOCUMENT_TYPE_NODE)
utils.HierarchyRequestError();
}
}
i = parent._countChildrenOfType(ELEMENT_NODE);
if (isPreinsert) {
// "parent has an element child"
if (i > 0)
utils.HierarchyRequestError();
} else {
// "parent has an element child that is not child"
if (i > 1 || (i === 1 && child.nodeType !== ELEMENT_NODE))
utils.HierarchyRequestError();
}
break;
case DOCUMENT_TYPE_NODE:
// 6c. parent has a doctype child, child is non-null and an
// element is preceding child, or child is null and parent has
// an element child. [preinsert]
// 6c. parent has a doctype child that is not child, or an
// element is preceding child. [replaceWith]
if (child === null) {
if (parent._countChildrenOfType(ELEMENT_NODE))
utils.HierarchyRequestError();
} else {
// child is always non-null for [replaceWith] case
for (kid = parent.firstChild; kid !== null; kid = kid.nextSibling) {
if (kid === child) break;
if (kid.nodeType === ELEMENT_NODE)
utils.HierarchyRequestError();
}
}
i = parent._countChildrenOfType(DOCUMENT_TYPE_NODE);
if (isPreinsert) {
// "parent has an doctype child"
if (i > 0)
utils.HierarchyRequestError();
} else {
// "parent has an doctype child that is not child"
if (i > 1 || (i === 1 && child.nodeType !== DOCUMENT_TYPE_NODE))
utils.HierarchyRequestError();
}
break;
}
} else {
// 5, continued: (parent is not a document)
if (node.nodeType === DOCUMENT_TYPE_NODE) utils.HierarchyRequestError();
}
}},
insertBefore: { value: function insertBefore(node, child) {
var parent = this;
// 1. Ensure pre-insertion validity
parent._ensureInsertValid(node, child, true);
// 2. Let reference child be child.
var refChild = child;
// 3. If reference child is node, set it to node's next sibling
if (refChild === node) { refChild = node.nextSibling; }
// 4. Adopt node into parent's node document.
parent.doc.adoptNode(node);
// 5. Insert node into parent before reference child.
node._insertOrReplace(parent, refChild, false);
// 6. Return node
return node;
}},
appendChild: { value: function(child) {
// This invokes _appendChild after doing validity checks.
return this.insertBefore(child, null);
}},
_appendChild: { value: function(child) {
child._insertOrReplace(this, null, false);
}},
removeChild: { value: function removeChild(child) {
var parent = this;
if (!child.nodeType) throw new TypeError('not a node');
if (child.parentNode !== parent) utils.NotFoundError();
child.remove();
return child;
}},
// To replace a `child` with `node` within a `parent` (this)
replaceChild: { value: function replaceChild(node, child) {
var parent = this;
// Ensure validity (slight differences from pre-insertion check)
parent._ensureInsertValid(node, child, false);
// Adopt node into parent's node document.
if (node.doc !== parent.doc) {
// XXX adoptNode has side-effect of removing node from its parent
// and generating a mutation event, thus causing the _insertOrReplace
// to generate two deletes and an insert instead of a 'move'
// event. It looks like the new MutationObserver stuff avoids
// this problem, but for now let's only adopt (ie, remove `node`
// from its parent) here if we need to.
parent.doc.adoptNode(node);
}
// Do the replace.
node._insertOrReplace(parent, child, true);
return child;
}},
// See: http://ejohn.org/blog/comparing-document-position/
contains: { value: function contains(node) {
if (node === null) { return false; }
if (this === node) { return true; /* inclusive descendant */ }
/* jshint bitwise: false */
return (this.compareDocumentPosition(node) &
DOCUMENT_POSITION_CONTAINED_BY) !== 0;
}},
compareDocumentPosition: { value: function compareDocumentPosition(that){
// Basic algorithm for finding the relative position of two nodes.
// Make a list the ancestors of each node, starting with the
// document element and proceeding down to the nodes themselves.
// Then, loop through the lists, looking for the first element
// that differs. The order of those two elements give the
// order of their descendant nodes. Or, if one list is a prefix
// of the other one, then that node contains the other.
if (this === that) return 0;
// If they're not owned by the same document or if one is rooted
// and one is not, then they're disconnected.
if (this.doc !== that.doc ||
this.rooted !== that.rooted)
return (DOCUMENT_POSITION_DISCONNECTED +
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
// Get arrays of ancestors for this and that
var these = [], those = [];
for(var n = this; n !== null; n = n.parentNode) these.push(n);
for(n = that; n !== null; n = n.parentNode) those.push(n);
these.reverse(); // So we start with the outermost
those.reverse();
if (these[0] !== those[0]) // No common ancestor
return (DOCUMENT_POSITION_DISCONNECTED +
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
n = Math.min(these.length, those.length);
for(var i = 1; i < n; i++) {
if (these[i] !== those[i]) {
// We found two different ancestors, so compare
// their positions
if (these[i].index < those[i].index)
return DOCUMENT_POSITION_FOLLOWING;
else
return DOCUMENT_POSITION_PRECEDING;
}
}
// If we get to here, then one of the nodes (the one with the
// shorter list of ancestors) contains the other one.
if (these.length < those.length)
return (DOCUMENT_POSITION_FOLLOWING +
DOCUMENT_POSITION_CONTAINED_BY);
else
return (DOCUMENT_POSITION_PRECEDING +
DOCUMENT_POSITION_CONTAINS);
}},
isSameNode: {value : function isSameNode(node) {
return this === node;
}},
// This method implements the generic parts of node equality testing
// and defers to the (non-recursive) type-specific isEqual() method
// defined by subclasses
isEqualNode: { value: function isEqualNode(node) {
if (!node) return false;
if (node.nodeType !== this.nodeType) return false;
// Check type-specific properties for equality
if (!this.isEqual(node)) return false;
// Now check children for number and equality
for (var c1 = this.firstChild, c2 = node.firstChild;
c1 && c2;
c1 = c1.nextSibling, c2 = c2.nextSibling) {
if (!c1.isEqualNode(c2)) return false;
}
return c1 === null && c2 === null;
}},
// This method delegates shallow cloning to a clone() method
// that each concrete subclass must implement
cloneNode: { value: function(deep) {
// Clone this node
var clone = this.clone();
// Handle the recursive case if necessary
if (deep) {
for (var kid = this.firstChild; kid !== null; kid = kid.nextSibling) {
clone._appendChild(kid.cloneNode(true));
}
}
return clone;
}},
lookupPrefix: { value: function lookupPrefix(ns) {
var e;
if (ns === '' || ns === null || ns === undefined) return null;
switch(this.nodeType) {
case ELEMENT_NODE:
return this._lookupNamespacePrefix(ns, this);
case DOCUMENT_NODE:
e = this.documentElement;
return e ? e.lookupPrefix(ns) : null;
case ENTITY_NODE:
case NOTATION_NODE:
case DOCUMENT_FRAGMENT_NODE:
case DOCUMENT_TYPE_NODE:
return null;
case ATTRIBUTE_NODE:
e = this.ownerElement;
return e ? e.lookupPrefix(ns) : null;
default:
e = this.parentElement;
return e ? e.lookupPrefix(ns) : null;
}
}},
lookupNamespaceURI: {value: function lookupNamespaceURI(prefix) {
if (prefix === '' || prefix === undefined) { prefix = null; }
var e;
switch(this.nodeType) {
case ELEMENT_NODE:
return utils.shouldOverride();
case DOCUMENT_NODE:
e = this.documentElement;
return e ? e.lookupNamespaceURI(prefix) : null;
case ENTITY_NODE:
case NOTATION_NODE:
case DOCUMENT_TYPE_NODE:
case DOCUMENT_FRAGMENT_NODE:
return null;
case ATTRIBUTE_NODE:
e = this.ownerElement;
return e ? e.lookupNamespaceURI(prefix) : null;
default:
e = this.parentElement;
return e ? e.lookupNamespaceURI(prefix) : null;
}
}},
isDefaultNamespace: { value: function isDefaultNamespace(ns) {
if (ns === '' || ns === undefined) { ns = null; }
var defaultNamespace = this.lookupNamespaceURI(null);
return (defaultNamespace === ns);
}},
// Utility methods for nodes. Not part of the DOM
// Return the index of this node in its parent.
// Throw if no parent, or if this node is not a child of its parent
index: { get: function() {
var parent = this.parentNode;
if (this === parent.firstChild) return 0; // fast case
var kids = parent.childNodes;
if (this._index === undefined || kids[this._index] !== this) {
// Ensure that we don't have an O(N^2) blowup if none of the
// kids have defined indices yet and we're traversing via
// nextSibling or previousSibling
for (var i=0; i<kids.length; i++) {
kids[i]._index = i;
}
utils.assert(kids[this._index] === this);
}
return this._index;
}},
// Return true if this node is equal to or is an ancestor of that node
// Note that nodes are considered to be ancestors of themselves
isAncestor: { value: function(that) {
// If they belong to different documents, then they're unrelated.
if (this.doc !== that.doc) return false;
// If one is rooted and one isn't then they're not related
if (this.rooted !== that.rooted) return false;
// Otherwise check by traversing the parentNode chain
for(var e = that; e; e = e.parentNode) {
if (e === this) return true;
}
return false;
}},
// DOMINO Changed the behavior to conform with the specs. See:
// https://groups.google.com/d/topic/mozilla.dev.platform/77sIYcpdDmc/discussion
ensureSameDoc: { value: function(that) {
if (that.ownerDocument === null) {
that.ownerDocument = this.doc;
}
else if(that.ownerDocument !== this.doc) {
utils.WrongDocumentError();
}
}},
removeChildren: { value: utils.shouldOverride },
// Insert this node as a child of parent before the specified child,
// or insert as the last child of parent if specified child is null,
// or replace the specified child with this node, firing mutation events as
// necessary
_insertOrReplace: { value: function _insertOrReplace(parent, before, isReplace) {
var child = this, before_index, i;
if (child.nodeType === DOCUMENT_FRAGMENT_NODE && child.rooted) {
utils.HierarchyRequestError();
}
/* Ensure index of `before` is cached before we (possibly) remove it. */
if (parent._childNodes) {
before_index = (before === null) ? parent._childNodes.length :
before.index; /* ensure _index is cached */
// If we are already a child of the specified parent, then
// the index may have to be adjusted.
if (child.parentNode === parent) {
var child_index = child.index;
// If the child is before the spot it is to be inserted at,
// then when it is removed, the index of that spot will be
// reduced.
if (child_index < before_index) {
before_index--;
}
}
}
// Delete the old child
if (isReplace) {
if (before.rooted) before.doc.mutateRemove(before);
before.parentNode = null;
}
var n = before;
if (n === null) { n = parent.firstChild; }
// If both the child and the parent are rooted, then we want to
// transplant the child without uprooting and rerooting it.
var bothRooted = child.rooted && parent.rooted;
if (child.nodeType === DOCUMENT_FRAGMENT_NODE) {
var spliceArgs = [0, isReplace ? 1 : 0], next;
for (var kid = child.firstChild; kid !== null; kid = next) {
next = kid.nextSibling;
spliceArgs.push(kid);
kid.parentNode = parent;
}
var len = spliceArgs.length;
// Add all nodes to the new parent, overwriting the old child
if (isReplace) {
LinkedList.replace(n, len > 2 ? spliceArgs[2] : null);
} else if (len > 2 && n !== null) {
LinkedList.insertBefore(spliceArgs[2], n);
}
if (parent._childNodes) {
spliceArgs[0] = (before === null) ?
parent._childNodes.length : before._index;
parent._childNodes.splice.apply(parent._childNodes, spliceArgs);
for (i=2; i<len; i++) {
spliceArgs[i]._index = spliceArgs[0] + (i - 2);
}
} else if (parent._firstChild === before) {
if (len > 2) {
parent._firstChild = spliceArgs[2];
} else if (isReplace) {
parent._firstChild = null;
}
}
// Remove all nodes from the document fragment
if (child._childNodes) {
child._childNodes.length = 0;
} else {
child._firstChild = null;
}
// Call the mutation handlers
// Use spliceArgs since the original array has been destroyed. The
// liveness guarantee requires us to clone the array so that
// references to the childNodes of the DocumentFragment will be empty
// when the insertion handlers are called.
if (parent.rooted) {
parent.modify();
for (i = 2; i < len; i++) {
parent.doc.mutateInsert(spliceArgs[i]);
}
}
} else {
if (before === child) { return; }
if (bothRooted) {
// Remove the child from its current position in the tree
// without calling remove(), since we don't want to uproot it.
child._remove();
} else if (child.parentNode) {
child.remove();
}
// Insert it as a child of its new parent
child.parentNode = parent;
if (isReplace) {
LinkedList.replace(n, child);
if (parent._childNodes) {
child._index = before_index;
parent._childNodes[before_index] = child;
} else if (parent._firstChild === before) {
parent._firstChild = child;
}
} else {
if (n !== null) {
LinkedList.insertBefore(child, n);
}
if (parent._childNodes) {
child._index = before_index;
parent._childNodes.splice(before_index, 0, child);
} else if (parent._firstChild === before) {
parent._firstChild = child;
}
}
if (bothRooted) {
parent.modify();
// Generate a move mutation event
parent.doc.mutateMove(child);
} else if (parent.rooted) {
parent.modify();
parent.doc.mutateInsert(child);
}
}
}},
// Return the lastModTime value for this node. (For use as a
// cache invalidation mechanism. If the node does not already
// have one, initialize it from the owner document's modclock
// property. (Note that modclock does not return the actual
// time; it is simply a counter incremented on each document
// modification)
lastModTime: { get: function() {
if (!this._lastModTime) {
this._lastModTime = this.doc.modclock;
}
return this._lastModTime;
}},
// Increment the owner document's modclock and use the new
// value to update the lastModTime value for this node and
// all of its ancestors. Nodes that have never had their
// lastModTime value queried do not need to have a
// lastModTime property set on them since there is no
// previously queried value to ever compare the new value
// against, so only update nodes that already have a
// _lastModTime property.
modify: { value: function() {
if (this.doc.modclock) { // Skip while doc.modclock == 0
var time = ++this.doc.modclock;
for(var n = this; n; n = n.parentElement) {
if (n._lastModTime) {
n._lastModTime = time;
}
}
}
}},
// This attribute is not part of the DOM but is quite helpful.
// It returns the document with which a node is associated. Usually
// this is the ownerDocument. But ownerDocument is null for the
// document object itself, so this is a handy way to get the document
// regardless of the node type
doc: { get: function() {
return this.ownerDocument || this;
}},
// If the node has a nid (node id), then it is rooted in a document
rooted: { get: function() {
return !!this._nid;
}},
normalize: { value: function() {
var next;
for (var child=this.firstChild; child !== null; child=next) {
next = child.nextSibling;
if (child.normalize) {
child.normalize();
}
if (child.nodeType !== Node.TEXT_NODE) {
continue;
}
if (child.nodeValue === "") {
this.removeChild(child);
continue;
}
var prevChild = child.previousSibling;
if (prevChild === null) {
continue;
} else if (prevChild.nodeType === Node.TEXT_NODE) {
// merge this with previous and remove the child
prevChild.appendData(child.nodeValue);
this.removeChild(child);
}
}
}},
// Convert the children of a node to an HTML string.
// This is used by the innerHTML getter
// The serialization spec is at:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments
//
// The serialization logic is intentionally implemented in a separate
// `NodeUtils` helper instead of the more obvious choice of a private
// `_serializeOne()` method on the `Node.prototype` in order to avoid
// the megamorphic `this._serializeOne` property access, which reduces
// performance unnecessarily. If you need specialized behavior for a
// certain subclass, you'll need to implement that in `NodeUtils`.
// See https://github.com/fgnass/domino/pull/142 for more information.
serialize: { value: function() {
if (this._innerHTML) {
return this._innerHTML;
}
var s = '';
for (var kid = this.firstChild; kid !== null; kid = kid.nextSibling) {
s += NodeUtils.serializeOne(kid, this);
}
return s;
}},
// Non-standard, but often useful for debugging.
outerHTML: {
get: function() {
return NodeUtils.serializeOne(this, { nodeType: 0 });
},
set: utils.nyi,
},
// mirror node type properties in the prototype, so they are present
// in instances of Node (and subclasses)
ELEMENT_NODE: { value: ELEMENT_NODE },
ATTRIBUTE_NODE: { value: ATTRIBUTE_NODE },
TEXT_NODE: { value: TEXT_NODE },
CDATA_SECTION_NODE: { value: CDATA_SECTION_NODE },
ENTITY_REFERENCE_NODE: { value: ENTITY_REFERENCE_NODE },
ENTITY_NODE: { value: ENTITY_NODE },
PROCESSING_INSTRUCTION_NODE: { value: PROCESSING_INSTRUCTION_NODE },
COMMENT_NODE: { value: COMMENT_NODE },
DOCUMENT_NODE: { value: DOCUMENT_NODE },
DOCUMENT_TYPE_NODE: { value: DOCUMENT_TYPE_NODE },
DOCUMENT_FRAGMENT_NODE: { value: DOCUMENT_FRAGMENT_NODE },
NOTATION_NODE: { value: NOTATION_NODE },
DOCUMENT_POSITION_DISCONNECTED: { value: DOCUMENT_POSITION_DISCONNECTED },
DOCUMENT_POSITION_PRECEDING: { value: DOCUMENT_POSITION_PRECEDING },
DOCUMENT_POSITION_FOLLOWING: { value: DOCUMENT_POSITION_FOLLOWING },
DOCUMENT_POSITION_CONTAINS: { value: DOCUMENT_POSITION_CONTAINS },
DOCUMENT_POSITION_CONTAINED_BY: { value: DOCUMENT_POSITION_CONTAINED_BY },
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: { value: DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC },
});

View File

@@ -0,0 +1,24 @@
"use strict";
var NodeFilter = {
// Constants for acceptNode()
FILTER_ACCEPT: 1,
FILTER_REJECT: 2,
FILTER_SKIP: 3,
// Constants for whatToShow
SHOW_ALL: 0xFFFFFFFF,
SHOW_ELEMENT: 0x1,
SHOW_ATTRIBUTE: 0x2, // historical
SHOW_TEXT: 0x4,
SHOW_CDATA_SECTION: 0x8, // historical
SHOW_ENTITY_REFERENCE: 0x10, // historical
SHOW_ENTITY: 0x20, // historical
SHOW_PROCESSING_INSTRUCTION: 0x40,
SHOW_COMMENT: 0x80,
SHOW_DOCUMENT: 0x100,
SHOW_DOCUMENT_TYPE: 0x200,
SHOW_DOCUMENT_FRAGMENT: 0x400,
SHOW_NOTATION: 0x800 // historical
};
module.exports = (NodeFilter.constructor = NodeFilter.prototype = NodeFilter);

View File

@@ -0,0 +1,217 @@
"use strict";
module.exports = NodeIterator;
var NodeFilter = require('./NodeFilter');
var NodeTraversal = require('./NodeTraversal');
var utils = require('./utils');
/* Private methods and helpers */
/**
* @based on WebKit's NodeIterator::moveToNext and NodeIterator::moveToPrevious
* https://trac.webkit.org/browser/trunk/Source/WebCore/dom/NodeIterator.cpp?rev=186279#L51
*/
function move(node, stayWithin, directionIsNext) {
if (directionIsNext) {
return NodeTraversal.next(node, stayWithin);
} else {
if (node === stayWithin) {
return null;
}
return NodeTraversal.previous(node, null);
}
}
function isInclusiveAncestor(node, possibleChild) {
for ( ; possibleChild; possibleChild = possibleChild.parentNode) {
if (node === possibleChild) { return true; }
}
return false;
}
/**
* @spec http://www.w3.org/TR/dom/#concept-nodeiterator-traverse
* @method
* @access private
* @param {NodeIterator} ni
* @param {string} direction One of 'next' or 'previous'.
* @return {Node|null}
*/
function traverse(ni, directionIsNext) {
var node, beforeNode;
node = ni._referenceNode;
beforeNode = ni._pointerBeforeReferenceNode;
while (true) {
if (beforeNode === directionIsNext) {
beforeNode = !beforeNode;
} else {
node = move(node, ni._root, directionIsNext);
if (node === null) {
return null;
}
}
var result = ni._internalFilter(node);
if (result === NodeFilter.FILTER_ACCEPT) {
break;
}
}
ni._referenceNode = node;
ni._pointerBeforeReferenceNode = beforeNode;
return node;
}
/* Public API */
/**
* Implemented version: http://www.w3.org/TR/2015/WD-dom-20150618/#nodeiterator
* Latest version: http://www.w3.org/TR/dom/#nodeiterator
*
* @constructor
* @param {Node} root
* @param {number} whatToShow [optional]
* @param {Function|NodeFilter} filter [optional]
* @throws Error
*/
function NodeIterator(root, whatToShow, filter) {
if (!root || !root.nodeType) {
utils.NotSupportedError();
}
// Read-only properties
this._root = root;
this._referenceNode = root;
this._pointerBeforeReferenceNode = true;
this._whatToShow = Number(whatToShow) || 0;
this._filter = filter || null;
this._active = false;
// Record active node iterators in the document, in order to perform
// "node iterator pre-removal steps".
root.doc._attachNodeIterator(this);
}
Object.defineProperties(NodeIterator.prototype, {
root: { get: function root() {
return this._root;
} },
referenceNode: { get: function referenceNode() {
return this._referenceNode;
} },
pointerBeforeReferenceNode: { get: function pointerBeforeReferenceNode() {
return this._pointerBeforeReferenceNode;
} },
whatToShow: { get: function whatToShow() {
return this._whatToShow;
} },
filter: { get: function filter() {
return this._filter;
} },
/**
* @method
* @param {Node} node
* @return {Number} Constant NodeFilter.FILTER_ACCEPT,
* NodeFilter.FILTER_REJECT or NodeFilter.FILTER_SKIP.
*/
_internalFilter: { value: function _internalFilter(node) {
/* jshint bitwise: false */
var result, filter;
if (this._active) {
utils.InvalidStateError();
}
// Maps nodeType to whatToShow
if (!(((1 << (node.nodeType - 1)) & this._whatToShow))) {
return NodeFilter.FILTER_SKIP;
}
filter = this._filter;
if (filter === null) {
result = NodeFilter.FILTER_ACCEPT;
} else {
this._active = true;
try {
if (typeof filter === 'function') {
result = filter(node);
} else {
result = filter.acceptNode(node);
}
} finally {
this._active = false;
}
}
// Note that coercing to a number means that
// `true` becomes `1` (which is NodeFilter.FILTER_ACCEPT)
// `false` becomes `0` (neither accept, reject, or skip)
return (+result);
} },
/**
* @spec https://dom.spec.whatwg.org/#nodeiterator-pre-removing-steps
* @method
* @return void
*/
_preremove: { value: function _preremove(toBeRemovedNode) {
if (isInclusiveAncestor(toBeRemovedNode, this._root)) { return; }
if (!isInclusiveAncestor(toBeRemovedNode, this._referenceNode)) { return; }
if (this._pointerBeforeReferenceNode) {
var next = toBeRemovedNode;
while (next.lastChild) {
next = next.lastChild;
}
next = NodeTraversal.next(next, this.root);
if (next) {
this._referenceNode = next;
return;
}
this._pointerBeforeReferenceNode = false;
// fall through
}
if (toBeRemovedNode.previousSibling === null) {
this._referenceNode = toBeRemovedNode.parentNode;
} else {
this._referenceNode = toBeRemovedNode.previousSibling;
var lastChild;
for (lastChild = this._referenceNode.lastChild;
lastChild;
lastChild = this._referenceNode.lastChild) {
this._referenceNode = lastChild;
}
}
} },
/**
* @spec http://www.w3.org/TR/dom/#dom-nodeiterator-nextnode
* @method
* @return {Node|null}
*/
nextNode: { value: function nextNode() {
return traverse(this, true);
} },
/**
* @spec http://www.w3.org/TR/dom/#dom-nodeiterator-previousnode
* @method
* @return {Node|null}
*/
previousNode: { value: function previousNode() {
return traverse(this, false);
} },
/**
* @spec http://www.w3.org/TR/dom/#dom-nodeiterator-detach
* @method
* @return void
*/
detach: { value: function detach() {
/* "The detach() method must do nothing.
* Its functionality (disabling a NodeIterator object) was removed,
* but the method itself is preserved for compatibility.
*/
} },
/** For compatibility with web-platform-tests. */
toString: { value: function toString() {
return "[object NodeIterator]";
} },
});

View File

@@ -0,0 +1,15 @@
"use strict";
// No support for subclassing array, return an actual Array object.
function item(i) {
/* jshint validthis: true */
return this[i] || null;
}
function NodeList(a) {
if (!a) a = [];
a.item = item;
return a;
}
module.exports = NodeList;

View File

@@ -0,0 +1,12 @@
/* jshint esversion: 6 */
"use strict";
module.exports = class NodeList extends Array {
constructor(a) {
super((a && a.length) || 0);
if (a) {
for (var idx in a) { this[idx] = a[idx]; }
}
}
item(i) { return this[i] || null; }
};

View File

@@ -0,0 +1,13 @@
"use strict";
var NodeList;
try {
// Attempt to use ES6-style Array subclass if possible.
NodeList = require('./NodeList.es6.js');
} catch (e) {
// No support for subclassing array, return an actual Array object.
NodeList = require('./NodeList.es5.js');
}
module.exports = NodeList;

View File

@@ -0,0 +1,87 @@
"use strict";
/* exported NodeTraversal */
var NodeTraversal = module.exports = {
nextSkippingChildren: nextSkippingChildren,
nextAncestorSibling: nextAncestorSibling,
next: next,
previous: previous,
deepLastChild: deepLastChild
};
/**
* @based on WebKit's NodeTraversal::nextSkippingChildren
* https://trac.webkit.org/browser/trunk/Source/WebCore/dom/NodeTraversal.h?rev=179143#L109
*/
function nextSkippingChildren(node, stayWithin) {
if (node === stayWithin) {
return null;
}
if (node.nextSibling !== null) {
return node.nextSibling;
}
return nextAncestorSibling(node, stayWithin);
}
/**
* @based on WebKit's NodeTraversal::nextAncestorSibling
* https://trac.webkit.org/browser/trunk/Source/WebCore/dom/NodeTraversal.cpp?rev=179143#L93
*/
function nextAncestorSibling(node, stayWithin) {
for (node = node.parentNode; node !== null; node = node.parentNode) {
if (node === stayWithin) {
return null;
}
if (node.nextSibling !== null) {
return node.nextSibling;
}
}
return null;
}
/**
* @based on WebKit's NodeTraversal::next
* https://trac.webkit.org/browser/trunk/Source/WebCore/dom/NodeTraversal.h?rev=179143#L99
*/
function next(node, stayWithin) {
var n;
n = node.firstChild;
if (n !== null) {
return n;
}
if (node === stayWithin) {
return null;
}
n = node.nextSibling;
if (n !== null) {
return n;
}
return nextAncestorSibling(node, stayWithin);
}
/**
* @based on WebKit's NodeTraversal::deepLastChild
* https://trac.webkit.org/browser/trunk/Source/WebCore/dom/NodeTraversal.cpp?rev=179143#L116
*/
function deepLastChild(node) {
while (node.lastChild) {
node = node.lastChild;
}
return node;
}
/**
* @based on WebKit's NodeTraversal::previous
* https://trac.webkit.org/browser/trunk/Source/WebCore/dom/NodeTraversal.h?rev=179143#L121
*/
function previous(node, stayWithin) {
var p;
p = node.previousSibling;
if (p !== null) {
return deepLastChild(p);
}
p = node.parentNode;
if (p === stayWithin) {
return null;
}
return p;
}

View File

@@ -0,0 +1,246 @@
"use strict";
module.exports = {
// NOTE: The `serializeOne()` function used to live on the `Node.prototype`
// as a private method `Node#_serializeOne(child)`, however that requires
// a megamorphic property access `this._serializeOne` just to get to the
// method, and this is being done on lots of different `Node` subclasses,
// which puts a lot of pressure on V8's megamorphic stub cache. So by
// moving the helper off of the `Node.prototype` and into a separate
// function in this helper module, we get a monomorphic property access
// `NodeUtils.serializeOne` to get to the function and reduce pressure
// on the megamorphic stub cache.
// See https://github.com/fgnass/domino/pull/142 for more information.
serializeOne: serializeOne,
// Export util functions so that we can run extra test for them.
// Note: we prefix function names with `ɵ`, similar to what we do
// with internal functions in Angular packages.
ɵescapeMatchingClosingTag: escapeMatchingClosingTag,
ɵescapeClosingCommentTag: escapeClosingCommentTag,
ɵescapeProcessingInstructionContent: escapeProcessingInstructionContent
};
var utils = require('./utils');
var NAMESPACE = utils.NAMESPACE;
var hasRawContent = {
STYLE: true,
SCRIPT: true,
XMP: true,
IFRAME: true,
NOEMBED: true,
NOFRAMES: true,
PLAINTEXT: true
};
var emptyElements = {
area: true,
base: true,
basefont: true,
bgsound: true,
br: true,
col: true,
embed: true,
frame: true,
hr: true,
img: true,
input: true,
keygen: true,
link: true,
meta: true,
param: true,
source: true,
track: true,
wbr: true
};
var extraNewLine = {
/* Removed in https://github.com/whatwg/html/issues/944
pre: true,
textarea: true,
listing: true
*/
};
const ESCAPE_REGEXP = /[&<>\u00A0]/g;
const ESCAPE_ATTR_REGEXP = /[&"<>\u00A0]/g;
function escape(s) {
if (!ESCAPE_REGEXP.test(s)) {
// nothing to do, fast path
return s;
}
return s.replace(ESCAPE_REGEXP, (c) => {
switch (c) {
case "&":
return "&amp;";
case "<":
return "&lt;";
case ">":
return "&gt;";
case "\u00A0":
return "&nbsp;";
}
});
}
function escapeAttr(s) {
if (!ESCAPE_ATTR_REGEXP.test(s)) {
// nothing to do, fast path
return s;
}
return s.replace(ESCAPE_ATTR_REGEXP, (c) => {
switch (c) {
case "<":
return "&lt;";
case ">":
return "&gt;";
case "&":
return "&amp;";
case '"':
return "&quot;";
case "\u00A0":
return "&nbsp;";
}
});
}
function attrname(a) {
var ns = a.namespaceURI;
if (!ns)
return a.localName;
if (ns === NAMESPACE.XML)
return 'xml:' + a.localName;
if (ns === NAMESPACE.XLINK)
return 'xlink:' + a.localName;
if (ns === NAMESPACE.XMLNS) {
if (a.localName === 'xmlns') return 'xmlns';
else return 'xmlns:' + a.localName;
}
return a.name;
}
/**
* Escapes matching closing tag in a raw text.
*
* For example, given `<style>#text(</style><script></script>)</style>`,
* the parent tag would by "style" and the raw text is
* "</style><script></script>". If we come across a matching closing tag
* (in out case `</style>`) - replace `<` with `&lt;` to avoid unexpected
* and unsafe behavior after de-serialization.
*/
function escapeMatchingClosingTag(rawText, parentTag) {
const parentClosingTag = '</' + parentTag;
if (!rawText.toLowerCase().includes(parentClosingTag)) {
return rawText; // fast path
}
const result = [...rawText];
const matches = rawText.matchAll(new RegExp(parentClosingTag, 'ig'));
for (const match of matches) {
result[match.index] = '&lt;';
}
return result.join('');
}
const CLOSING_COMMENT_REGEXP = /--!?>/;
/**
* Escapes closing comment tag in a comment content.
*
* For example, given `#comment('-->')`, the content of a comment would be
* updated to `--&gt;` to avoid unexpected and unsafe behavior after
* de-serialization.
*/
function escapeClosingCommentTag(rawContent) {
if (!CLOSING_COMMENT_REGEXP.test(rawContent)) {
return rawContent; // fast path
}
return rawContent.replace(/(--\!?)>/g, '$1&gt;');
}
/**
* Escapes processing instruction content by replacing `>` with `&gt`.
*/
function escapeProcessingInstructionContent(rawContent) {
return rawContent.includes('>')
? rawContent.replaceAll('>', '&gt;')
: rawContent;
}
function serializeOne(kid, parent) {
var s = '';
switch(kid.nodeType) {
case 1: //ELEMENT_NODE
var ns = kid.namespaceURI;
var html = ns === NAMESPACE.HTML;
var tagname = (html || ns === NAMESPACE.SVG || ns === NAMESPACE.MATHML) ? kid.localName : kid.tagName;
s += '<' + tagname;
for(var j = 0, k = kid._numattrs; j < k; j++) {
var a = kid._attr(j);
s += ' ' + attrname(a);
if (a.value !== undefined) s += '="' + escapeAttr(a.value) + '"';
}
s += '>';
if (!(html && emptyElements[tagname])) {
var ss = kid.serialize();
// If an element can have raw content, this content may
// potentially require escaping to avoid XSS.
if (hasRawContent[tagname.toUpperCase()]) {
ss = escapeMatchingClosingTag(ss, tagname);
}
if (html && extraNewLine[tagname] && ss.charAt(0)==='\n') s += '\n';
// Serialize children and add end tag for all others
s += ss;
s += '</' + tagname + '>';
}
break;
case 3: //TEXT_NODE
case 4: //CDATA_SECTION_NODE
var parenttag;
if (parent.nodeType === 1 /*ELEMENT_NODE*/ &&
parent.namespaceURI === NAMESPACE.HTML)
parenttag = parent.tagName;
else
parenttag = '';
if (hasRawContent[parenttag] ||
(parenttag==='NOSCRIPT' && parent.ownerDocument._scripting_enabled)) {
s += kid.data;
} else {
s += escape(kid.data);
}
break;
case 8: //COMMENT_NODE
s += '<!--' + escapeClosingCommentTag(kid.data) + '-->';
break;
case 7: //PROCESSING_INSTRUCTION_NODE
const content = escapeProcessingInstructionContent(kid.data);
s += '<?' + kid.target + ' ' + content + '?>';
break;
case 10: //DOCUMENT_TYPE_NODE
s += '<!DOCTYPE ' + kid.name;
if (false) {
// Latest HTML serialization spec omits the public/system ID
if (kid.publicID) {
s += ' PUBLIC "' + kid.publicId + '"';
}
if (kid.systemId) {
s += ' "' + kid.systemId + '"';
}
}
s += '>';
break;
default:
utils.InvalidStateError();
}
return s;
}

View File

@@ -0,0 +1,26 @@
"use strict";
var Node = require('./Node');
var NonDocumentTypeChildNode = {
nextElementSibling: { get: function() {
if (this.parentNode) {
for (var kid = this.nextSibling; kid !== null; kid = kid.nextSibling) {
if (kid.nodeType === Node.ELEMENT_NODE) return kid;
}
}
return null;
}},
previousElementSibling: { get: function() {
if (this.parentNode) {
for (var kid = this.previousSibling; kid !== null; kid = kid.previousSibling) {
if (kid.nodeType === Node.ELEMENT_NODE) return kid;
}
}
return null;
}}
};
module.exports = NonDocumentTypeChildNode;

View File

@@ -0,0 +1,44 @@
"use strict";
module.exports = ProcessingInstruction;
var Node = require('./Node');
var CharacterData = require('./CharacterData');
function ProcessingInstruction(doc, target, data) {
CharacterData.call(this);
this.nodeType = Node.PROCESSING_INSTRUCTION_NODE;
this.ownerDocument = doc;
this.target = target;
this._data = data;
}
var nodeValue = {
get: function() { return this._data; },
set: function(v) {
if (v === null || v === undefined) { v = ''; } else { v = String(v); }
this._data = v;
if (this.rooted) this.ownerDocument.mutateValue(this);
}
};
ProcessingInstruction.prototype = Object.create(CharacterData.prototype, {
nodeName: { get: function() { return this.target; }},
nodeValue: nodeValue,
textContent: nodeValue,
innerText: nodeValue,
data: {
get: nodeValue.get,
set: function(v) {
nodeValue.set.call(this, v===null ? '' : String(v));
},
},
// Utility methods
clone: { value: function clone() {
return new ProcessingInstruction(this.ownerDocument, this.target, this._data);
}},
isEqual: { value: function isEqual(n) {
return this.target === n.target && this._data === n._data;
}}
});

View File

@@ -0,0 +1,75 @@
"use strict";
module.exports = Text;
var utils = require('./utils');
var Node = require('./Node');
var CharacterData = require('./CharacterData');
function Text(doc, data) {
CharacterData.call(this);
this.nodeType = Node.TEXT_NODE;
this.ownerDocument = doc;
this._data = data;
this._index = undefined;
}
var nodeValue = {
get: function() { return this._data; },
set: function(v) {
if (v === null || v === undefined) { v = ''; } else { v = String(v); }
if (v === this._data) return;
this._data = v;
if (this.rooted)
this.ownerDocument.mutateValue(this);
if (this.parentNode &&
this.parentNode._textchangehook)
this.parentNode._textchangehook(this);
}
};
Text.prototype = Object.create(CharacterData.prototype, {
nodeName: { value: "#text" },
// These three attributes are all the same.
// The data attribute has a [TreatNullAs=EmptyString] but we'll
// implement that at the interface level
nodeValue: nodeValue,
textContent: nodeValue,
innerText: nodeValue,
data: {
get: nodeValue.get,
set: function(v) {
nodeValue.set.call(this, v===null ? '' : String(v));
},
},
splitText: { value: function splitText(offset) {
if (offset > this._data.length || offset < 0) utils.IndexSizeError();
var newdata = this._data.substring(offset),
newnode = this.ownerDocument.createTextNode(newdata);
this.data = this.data.substring(0, offset);
var parent = this.parentNode;
if (parent !== null)
parent.insertBefore(newnode, this.nextSibling);
return newnode;
}},
wholeText: { get: function wholeText() {
var result = this.textContent;
for (var next = this.nextSibling; next; next = next.nextSibling) {
if (next.nodeType !== Node.TEXT_NODE) { break; }
result += next.textContent;
}
return result;
}},
// Obsolete, removed from spec.
replaceWholeText: { value: utils.nyi },
// Utility methods
clone: { value: function clone() {
return new Text(this.ownerDocument, this._data);
}},
});

View File

@@ -0,0 +1,336 @@
"use strict";
module.exports = TreeWalker;
var Node = require('./Node');
var NodeFilter = require('./NodeFilter');
var NodeTraversal = require('./NodeTraversal');
var utils = require('./utils');
var mapChild = {
first: 'firstChild',
last: 'lastChild',
next: 'firstChild',
previous: 'lastChild'
};
var mapSibling = {
first: 'nextSibling',
last: 'previousSibling',
next: 'nextSibling',
previous: 'previousSibling'
};
/* Private methods and helpers */
/**
* @spec https://dom.spec.whatwg.org/#concept-traverse-children
* @method
* @access private
* @param {TreeWalker} tw
* @param {string} type One of 'first' or 'last'.
* @return {Node|null}
*/
function traverseChildren(tw, type) {
var child, node, parent, result, sibling;
node = tw._currentNode[mapChild[type]];
while (node !== null) {
result = tw._internalFilter(node);
if (result === NodeFilter.FILTER_ACCEPT) {
tw._currentNode = node;
return node;
}
if (result === NodeFilter.FILTER_SKIP) {
child = node[mapChild[type]];
if (child !== null) {
node = child;
continue;
}
}
while (node !== null) {
sibling = node[mapSibling[type]];
if (sibling !== null) {
node = sibling;
break;
}
parent = node.parentNode;
if (parent === null || parent === tw.root || parent === tw._currentNode) {
return null;
} else {
node = parent;
}
}
}
return null;
}
/**
* @spec https://dom.spec.whatwg.org/#concept-traverse-siblings
* @method
* @access private
* @param {TreeWalker} tw
* @param {TreeWalker} type One of 'next' or 'previous'.
* @return {Node|nul}
*/
function traverseSiblings(tw, type) {
var node, result, sibling;
node = tw._currentNode;
if (node === tw.root) {
return null;
}
while (true) {
sibling = node[mapSibling[type]];
while (sibling !== null) {
node = sibling;
result = tw._internalFilter(node);
if (result === NodeFilter.FILTER_ACCEPT) {
tw._currentNode = node;
return node;
}
sibling = node[mapChild[type]];
if (result === NodeFilter.FILTER_REJECT || sibling === null) {
sibling = node[mapSibling[type]];
}
}
node = node.parentNode;
if (node === null || node === tw.root) {
return null;
}
if (tw._internalFilter(node) === NodeFilter.FILTER_ACCEPT) {
return null;
}
}
}
/* Public API */
/**
* Latest version: https://dom.spec.whatwg.org/#treewalker
*
* @constructor
* @param {Node} root
* @param {number} whatToShow [optional]
* @param {Function|NodeFilter} filter [optional]
* @throws Error
*/
function TreeWalker(root, whatToShow, filter) {
if (!root || !root.nodeType) {
utils.NotSupportedError();
}
// Read-only properties
this._root = root;
this._whatToShow = Number(whatToShow) || 0;
this._filter = filter || null;
this._active = false;
// Read-write property
this._currentNode = root;
}
Object.defineProperties(TreeWalker.prototype, {
root: { get: function() { return this._root; } },
whatToShow: { get: function() { return this._whatToShow; } },
filter: { get: function() { return this._filter; } },
currentNode: {
get: function currentNode() {
return this._currentNode;
},
set: function setCurrentNode(v) {
if (!(v instanceof Node)) {
throw new TypeError("Not a Node"); // `null` is also not a node
}
this._currentNode = v;
},
},
/**
* @method
* @param {Node} node
* @return {Number} Constant NodeFilter.FILTER_ACCEPT,
* NodeFilter.FILTER_REJECT or NodeFilter.FILTER_SKIP.
*/
_internalFilter: { value: function _internalFilter(node) {
/* jshint bitwise: false */
var result, filter;
if (this._active) {
utils.InvalidStateError();
}
// Maps nodeType to whatToShow
if (!(((1 << (node.nodeType - 1)) & this._whatToShow))) {
return NodeFilter.FILTER_SKIP;
}
filter = this._filter;
if (filter === null) {
result = NodeFilter.FILTER_ACCEPT;
} else {
this._active = true;
try {
if (typeof filter === 'function') {
result = filter(node);
} else {
result = filter.acceptNode(node);
}
} finally {
this._active = false;
}
}
// Note that coercing to a number means that
// `true` becomes `1` (which is NodeFilter.FILTER_ACCEPT)
// `false` becomes `0` (neither accept, reject, or skip)
return (+result);
}},
/**
* @spec https://dom.spec.whatwg.org/#dom-treewalker-parentnode
* @based on WebKit's TreeWalker::parentNode
* https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/dom/TreeWalker.cpp?rev=220453#L50
* @method
* @return {Node|null}
*/
parentNode: { value: function parentNode() {
var node = this._currentNode;
while (node !== this.root) {
node = node.parentNode;
if (node === null) {
return null;
}
if (this._internalFilter(node) === NodeFilter.FILTER_ACCEPT) {
this._currentNode = node;
return node;
}
}
return null;
}},
/**
* @spec https://dom.spec.whatwg.org/#dom-treewalker-firstchild
* @method
* @return {Node|null}
*/
firstChild: { value: function firstChild() {
return traverseChildren(this, 'first');
}},
/**
* @spec https://dom.spec.whatwg.org/#dom-treewalker-lastchild
* @method
* @return {Node|null}
*/
lastChild: { value: function lastChild() {
return traverseChildren(this, 'last');
}},
/**
* @spec http://www.w3.org/TR/dom/#dom-treewalker-previoussibling
* @method
* @return {Node|null}
*/
previousSibling: { value: function previousSibling() {
return traverseSiblings(this, 'previous');
}},
/**
* @spec http://www.w3.org/TR/dom/#dom-treewalker-nextsibling
* @method
* @return {Node|null}
*/
nextSibling: { value: function nextSibling() {
return traverseSiblings(this, 'next');
}},
/**
* @spec https://dom.spec.whatwg.org/#dom-treewalker-previousnode
* @based on WebKit's TreeWalker::previousNode
* https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/dom/TreeWalker.cpp?rev=220453#L181
* @method
* @return {Node|null}
*/
previousNode: { value: function previousNode() {
var node, result, previousSibling, lastChild;
node = this._currentNode;
while (node !== this._root) {
for (previousSibling = node.previousSibling;
previousSibling;
previousSibling = node.previousSibling) {
node = previousSibling;
result = this._internalFilter(node);
if (result === NodeFilter.FILTER_REJECT) {
continue;
}
for (lastChild = node.lastChild;
lastChild;
lastChild = node.lastChild) {
node = lastChild;
result = this._internalFilter(node);
if (result === NodeFilter.FILTER_REJECT) {
break;
}
}
if (result === NodeFilter.FILTER_ACCEPT) {
this._currentNode = node;
return node;
}
}
if (node === this.root || node.parentNode === null) {
return null;
}
node = node.parentNode;
if (this._internalFilter(node) === NodeFilter.FILTER_ACCEPT) {
this._currentNode = node;
return node;
}
}
return null;
}},
/**
* @spec https://dom.spec.whatwg.org/#dom-treewalker-nextnode
* @based on WebKit's TreeWalker::nextNode
* https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/dom/TreeWalker.cpp?rev=220453#L228
* @method
* @return {Node|null}
*/
nextNode: { value: function nextNode() {
var node, result, firstChild, nextSibling;
node = this._currentNode;
result = NodeFilter.FILTER_ACCEPT;
CHILDREN:
while (true) {
for (firstChild = node.firstChild;
firstChild;
firstChild = node.firstChild) {
node = firstChild;
result = this._internalFilter(node);
if (result === NodeFilter.FILTER_ACCEPT) {
this._currentNode = node;
return node;
} else if (result === NodeFilter.FILTER_REJECT) {
break;
}
}
for (nextSibling = NodeTraversal.nextSkippingChildren(node, this.root);
nextSibling;
nextSibling = NodeTraversal.nextSkippingChildren(node, this.root)) {
node = nextSibling;
result = this._internalFilter(node);
if (result === NodeFilter.FILTER_ACCEPT) {
this._currentNode = node;
return node;
} else if (result === NodeFilter.FILTER_SKIP) {
continue CHILDREN;
}
}
return null;
}
}},
/** For compatibility with web-platform-tests. */
toString: { value: function toString() {
return "[object TreeWalker]";
}},
});

View File

@@ -0,0 +1,19 @@
"use strict";
var Event = require('./Event');
module.exports = UIEvent;
function UIEvent() {
// Just use the superclass constructor to initialize
Event.call(this);
this.view = null; // FF uses the current window
this.detail = 0;
}
UIEvent.prototype = Object.create(Event.prototype, {
constructor: { value: UIEvent },
initUIEvent: { value: function(type, bubbles, cancelable, view, detail) {
this.initEvent(type, bubbles, cancelable);
this.view = view;
this.detail = detail;
}}
});

View File

@@ -0,0 +1,194 @@
"use strict";
module.exports = URL;
function URL(url) {
if (!url) return Object.create(URL.prototype);
// Can't use String.trim() since it defines whitespace differently than HTML
this.url = url.replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, "");
// See http://tools.ietf.org/html/rfc3986#appendix-B
// and https://url.spec.whatwg.org/#parsing
var match = URL.pattern.exec(this.url);
if (match) {
if (match[2]) this.scheme = match[2];
if (match[4]) {
// parse username/password
var userinfo = match[4].match(URL.userinfoPattern);
if (userinfo) {
this.username = userinfo[1];
this.password = userinfo[3];
match[4] = match[4].substring(userinfo[0].length);
}
if (match[4].match(URL.portPattern)) {
var pos = match[4].lastIndexOf(':');
this.host = match[4].substring(0, pos);
this.port = match[4].substring(pos+1);
}
else {
this.host = match[4];
}
}
if (match[5]) this.path = match[5];
if (match[6]) this.query = match[7];
if (match[8]) this.fragment = match[9];
}
}
URL.pattern = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/;
URL.userinfoPattern = /^([^@:]*)(:([^@]*))?@/;
URL.portPattern = /:\d+$/;
URL.authorityPattern = /^[^:\/?#]+:\/\//;
URL.hierarchyPattern = /^[^:\/?#]+:\//;
// Return a percentEncoded version of s.
// S should be a single-character string
// XXX: needs to do utf-8 encoding?
URL.percentEncode = function percentEncode(s) {
var c = s.charCodeAt(0);
if (c < 256) return "%" + c.toString(16);
else throw Error("can't percent-encode codepoints > 255 yet");
};
URL.prototype = {
constructor: URL,
// XXX: not sure if this is the precise definition of absolute
isAbsolute: function() { return !!this.scheme; },
isAuthorityBased: function() {
return URL.authorityPattern.test(this.url);
},
isHierarchical: function() {
return URL.hierarchyPattern.test(this.url);
},
toString: function() {
var s = "";
if (this.scheme !== undefined) s += this.scheme + ":";
if (this.isAbsolute()) {
s += '//';
if (this.username || this.password) {
s += this.username || '';
if (this.password) {
s += ':' + this.password;
}
s += '@';
}
if (this.host) {
s += this.host;
}
}
if (this.port !== undefined) s += ":" + this.port;
if (this.path !== undefined) s += this.path;
if (this.query !== undefined) s += "?" + this.query;
if (this.fragment !== undefined) s += "#" + this.fragment;
return s;
},
// See: http://tools.ietf.org/html/rfc3986#section-5.2
// and https://url.spec.whatwg.org/#constructors
resolve: function(relative) {
var base = this; // The base url we're resolving against
var r = new URL(relative); // The relative reference url to resolve
var t = new URL(); // The absolute target url we will return
if (r.scheme !== undefined) {
t.scheme = r.scheme;
t.username = r.username;
t.password = r.password;
t.host = r.host;
t.port = r.port;
t.path = remove_dot_segments(r.path);
t.query = r.query;
}
else {
t.scheme = base.scheme;
if (r.host !== undefined) {
t.username = r.username;
t.password = r.password;
t.host = r.host;
t.port = r.port;
t.path = remove_dot_segments(r.path);
t.query = r.query;
}
else {
t.username = base.username;
t.password = base.password;
t.host = base.host;
t.port = base.port;
if (!r.path) { // undefined or empty
t.path = base.path;
if (r.query !== undefined)
t.query = r.query;
else
t.query = base.query;
}
else {
if (r.path.charAt(0) === "/") {
t.path = remove_dot_segments(r.path);
}
else {
t.path = merge(base.path, r.path);
t.path = remove_dot_segments(t.path);
}
t.query = r.query;
}
}
}
t.fragment = r.fragment;
return t.toString();
function merge(basepath, refpath) {
if (base.host !== undefined && !base.path)
return "/" + refpath;
var lastslash = basepath.lastIndexOf("/");
if (lastslash === -1)
return refpath;
else
return basepath.substring(0, lastslash+1) + refpath;
}
function remove_dot_segments(path) {
if (!path) return path; // For "" or undefined
var output = "";
while(path.length > 0) {
if (path === "." || path === "..") {
path = "";
break;
}
var twochars = path.substring(0,2);
var threechars = path.substring(0,3);
var fourchars = path.substring(0,4);
if (threechars === "../") {
path = path.substring(3);
}
else if (twochars === "./") {
path = path.substring(2);
}
else if (threechars === "/./") {
path = "/" + path.substring(3);
}
else if (twochars === "/." && path.length === 2) {
path = "/";
}
else if (fourchars === "/../" ||
(threechars === "/.." && path.length === 3)) {
path = "/" + path.substring(4);
output = output.replace(/\/?[^\/]*$/, "");
}
else {
var segment = path.match(/(\/?([^\/]*))/)[0];
output += segment;
path = path.substring(segment.length);
}
}
return output;
}
},
};

View File

@@ -0,0 +1,270 @@
"use strict";
var URL = require('./URL');
module.exports = URLUtils;
// Allow the `x == null` pattern. This is eslint's "null: 'ignore'" option,
// but jshint doesn't support this.
/* jshint eqeqeq: false */
// This is an abstract superclass for Location, HTMLAnchorElement and
// other types that have the standard complement of "URL decomposition
// IDL attributes". This is now standardized as URLUtils, see:
// https://url.spec.whatwg.org/#urlutils
// Subclasses must define a getter/setter on href.
// The getter and setter methods parse and rebuild the URL on each
// invocation; there is no attempt to cache the value and be more efficient
function URLUtils() {}
URLUtils.prototype = Object.create(Object.prototype, {
_url: { get: function() {
// XXX: this should do the "Reinitialize url" steps, and "null" should
// be a valid return value.
return new URL(this.href);
} },
protocol: {
get: function() {
var url = this._url;
if (url && url.scheme) return url.scheme + ":";
else return ":";
},
set: function(v) {
var output = this.href;
var url = new URL(output);
if (url.isAbsolute()) {
v = v.replace(/:+$/, "");
v = v.replace(/[^-+\.a-zA-Z0-9]/g, URL.percentEncode);
if (v.length > 0) {
url.scheme = v;
output = url.toString();
}
}
this.href = output;
},
},
host: {
get: function() {
var url = this._url;
if (url.isAbsolute() && url.isAuthorityBased())
return url.host + (url.port ? (":" + url.port) : "");
else
return "";
},
set: function(v) {
var output = this.href;
var url = new URL(output);
if (url.isAbsolute() && url.isAuthorityBased()) {
v = v.replace(/[^-+\._~!$&'()*,;:=a-zA-Z0-9]/g, URL.percentEncode);
if (v.length > 0) {
url.host = v;
delete url.port;
output = url.toString();
}
}
this.href = output;
},
},
hostname: {
get: function() {
var url = this._url;
if (url.isAbsolute() && url.isAuthorityBased())
return url.host;
else
return "";
},
set: function(v) {
var output = this.href;
var url = new URL(output);
if (url.isAbsolute() && url.isAuthorityBased()) {
v = v.replace(/^\/+/, "");
v = v.replace(/[^-+\._~!$&'()*,;:=a-zA-Z0-9]/g, URL.percentEncode);
if (v.length > 0) {
url.host = v;
output = url.toString();
}
}
this.href = output;
},
},
port: {
get: function() {
var url = this._url;
if (url.isAbsolute() && url.isAuthorityBased() && url.port!==undefined)
return url.port;
else
return "";
},
set: function(v) {
var output = this.href;
var url = new URL(output);
if (url.isAbsolute() && url.isAuthorityBased()) {
v = '' + v;
v = v.replace(/[^0-9].*$/, "");
v = v.replace(/^0+/, "");
if (v.length === 0) v = "0";
if (parseInt(v, 10) <= 65535) {
url.port = v;
output = url.toString();
}
}
this.href = output;
},
},
pathname: {
get: function() {
var url = this._url;
if (url.isAbsolute() && url.isHierarchical())
return url.path;
else
return "";
},
set: function(v) {
var output = this.href;
var url = new URL(output);
if (url.isAbsolute() && url.isHierarchical()) {
if (v.charAt(0) !== "/")
v = "/" + v;
v = v.replace(/[^-+\._~!$&'()*,;:=@\/a-zA-Z0-9]/g, URL.percentEncode);
url.path = v;
output = url.toString();
}
this.href = output;
},
},
search: {
get: function() {
var url = this._url;
if (url.isAbsolute() && url.isHierarchical() && url.query!==undefined)
return "?" + url.query;
else
return "";
},
set: function(v) {
var output = this.href;
var url = new URL(output);
if (url.isAbsolute() && url.isHierarchical()) {
if (v.charAt(0) === "?") v = v.substring(1);
v = v.replace(/[^-+\._~!$&'()*,;:=@\/?a-zA-Z0-9]/g, URL.percentEncode);
url.query = v;
output = url.toString();
}
this.href = output;
},
},
hash: {
get: function() {
var url = this._url;
if (url == null || url.fragment == null || url.fragment === '') {
return "";
} else {
return "#" + url.fragment;
}
},
set: function(v) {
var output = this.href;
var url = new URL(output);
if (v.charAt(0) === "#") v = v.substring(1);
v = v.replace(/[^-+\._~!$&'()*,;:=@\/?a-zA-Z0-9]/g, URL.percentEncode);
url.fragment = v;
output = url.toString();
this.href = output;
},
},
username: {
get: function() {
var url = this._url;
return url.username || '';
},
set: function(v) {
var output = this.href;
var url = new URL(output);
if (url.isAbsolute()) {
v = v.replace(/[\x00-\x1F\x7F-\uFFFF "#<>?`\/@\\:]/g, URL.percentEncode);
url.username = v;
output = url.toString();
}
this.href = output;
},
},
password: {
get: function() {
var url = this._url;
return url.password || '';
},
set: function(v) {
var output = this.href;
var url = new URL(output);
if (url.isAbsolute()) {
if (v==='') {
url.password = null;
} else {
v = v.replace(/[\x00-\x1F\x7F-\uFFFF "#<>?`\/@\\]/g, URL.percentEncode);
url.password = v;
}
output = url.toString();
}
this.href = output;
},
},
origin: { get: function() {
var url = this._url;
if (url == null) { return ''; }
var originForPort = function(defaultPort) {
var origin = [url.scheme, url.host, +url.port || defaultPort];
// XXX should be "unicode serialization"
return origin[0] + '://' + origin[1] +
(origin[2] === defaultPort ? '' : (':' + origin[2]));
};
switch (url.scheme) {
case 'ftp':
return originForPort(21);
case 'gopher':
return originForPort(70);
case 'http':
case 'ws':
return originForPort(80);
case 'https':
case 'wss':
return originForPort(443);
default:
// this is what chrome does
return url.scheme + '://';
}
} },
/*
searchParams: {
get: function() {
var url = this._url;
// XXX
},
set: function(v) {
var output = this.href;
var url = new URL(output);
// XXX
this.href = output;
},
},
*/
});
URLUtils._inherit = function(proto) {
// copy getters/setters from URLUtils to o.
Object.getOwnPropertyNames(URLUtils.prototype).forEach(function(p) {
if (p==='constructor' || p==='href') { return; }
var desc = Object.getOwnPropertyDescriptor(URLUtils.prototype, p);
Object.defineProperty(proto, p, desc);
});
};

View File

@@ -0,0 +1,60 @@
"use strict";
var DOMImplementation = require('./DOMImplementation');
var EventTarget = require('./EventTarget');
var Location = require('./Location');
var utils = require('./utils');
module.exports = Window;
function Window(document) {
this.document = document || new DOMImplementation(null).createHTMLDocument("");
this.document._scripting_enabled = true;
this.document.defaultView = this;
this.location = new Location(this, this.document._address || 'about:blank');
}
Window.prototype = Object.create(EventTarget.prototype, {
console: { value: console },
history: { value: {
back: utils.nyi,
forward: utils.nyi,
go: utils.nyi
}},
navigator: { value: require("./NavigatorID") },
// Self-referential properties
window: { get: function() { return this; }},
self: { get: function() { return this; }},
frames: { get: function() { return this; }},
// Self-referential properties for a top-level window
parent: { get: function() { return this; }},
top: { get: function() { return this; }},
// We don't support any other windows for now
length: { value: 0 }, // no frames
frameElement: { value: null }, // not part of a frame
opener: { value: null }, // not opened by another window
// The onload event handler.
// XXX: need to support a bunch of other event types, too,
// and have them interoperate with document.body.
onload: {
get: function() {
return this._getEventHandler("load");
},
set: function(v) {
this._setEventHandler("load", v);
}
},
// XXX This is a completely broken implementation
getComputedStyle: { value: function getComputedStyle(elt) {
return elt.style;
}}
});
utils.expose(require('./WindowTimers'), Window);
utils.expose(require('./impl'), Window);

View File

@@ -0,0 +1,11 @@
"use strict";
// https://html.spec.whatwg.org/multipage/webappapis.html#windowtimers
var WindowTimers = {
setTimeout: setTimeout,
clearTimeout: clearTimeout,
setInterval: setInterval,
clearInterval: clearInterval
};
module.exports = WindowTimers;

View File

@@ -0,0 +1,152 @@
"use strict";
var utils = require('./utils');
exports.property = function(attr) {
if (Array.isArray(attr.type)) {
var valid = Object.create(null);
attr.type.forEach(function(val) {
valid[val.value || val] = val.alias || val;
});
var missingValueDefault = attr.missing;
if (missingValueDefault===undefined) { missingValueDefault = null; }
var invalidValueDefault = attr.invalid;
if (invalidValueDefault===undefined) { invalidValueDefault = missingValueDefault; }
return {
get: function() {
var v = this._getattr(attr.name);
if (v === null) return missingValueDefault;
v = valid[v.toLowerCase()];
if (v !== undefined) return v;
if (invalidValueDefault !== null) return invalidValueDefault;
return v;
},
set: function(v) {
this._setattr(attr.name, v);
}
};
}
else if (attr.type === Boolean) {
return {
get: function() {
return this.hasAttribute(attr.name);
},
set: function(v) {
if (v) {
this._setattr(attr.name, '');
}
else {
this.removeAttribute(attr.name);
}
}
};
}
else if (attr.type === Number ||
attr.type === "long" ||
attr.type === "unsigned long" ||
attr.type === "limited unsigned long with fallback") {
return numberPropDesc(attr);
}
else if (!attr.type || attr.type === String) {
return {
get: function() { return this._getattr(attr.name) || ''; },
set: function(v) {
if (attr.treatNullAsEmptyString && v === null) { v = ''; }
this._setattr(attr.name, v);
}
};
}
else if (typeof attr.type === 'function') {
return attr.type(attr.name, attr);
}
throw new Error('Invalid attribute definition');
};
// See http://www.whatwg.org/specs/web-apps/current-work/#reflect
//
// defval is the default value. If it is a function, then that function
// will be invoked as a method of the element to obtain the default.
// If no default is specified for a given attribute, then the default
// depends on the type of the attribute, but since this function handles
// 4 integer cases, you must specify the default value in each call
//
// min and max define a valid range for getting the attribute.
//
// setmin defines a minimum value when setting. If the value is less
// than that, then throw INDEX_SIZE_ERR.
//
// Conveniently, JavaScript's parseInt function appears to be
// compatible with HTML's 'rules for parsing integers'
function numberPropDesc(a) {
var def;
if(typeof a.default === 'function') {
def = a.default;
}
else if(typeof a.default === 'number') {
def = function() { return a.default; };
}
else {
def = function() { utils.assert(false, typeof a.default); };
}
var unsigned_long = (a.type === 'unsigned long');
var signed_long = (a.type === 'long');
var unsigned_fallback = (a.type === 'limited unsigned long with fallback');
var min = a.min, max = a.max, setmin = a.setmin;
if (min === undefined) {
if (unsigned_long) min = 0;
if (signed_long) min = -0x80000000;
if (unsigned_fallback) min = 1;
}
if (max === undefined) {
if (unsigned_long || signed_long || unsigned_fallback) max = 0x7FFFFFFF;
}
return {
get: function() {
var v = this._getattr(a.name);
var n = a.float ? parseFloat(v) : parseInt(v, 10);
if (v === null || !isFinite(n) || (min !== undefined && n < min) || (max !== undefined && n > max)) {
return def.call(this);
}
if (unsigned_long || signed_long || unsigned_fallback) {
if (!/^[ \t\n\f\r]*[-+]?[0-9]/.test(v)) { return def.call(this); }
n = n|0; // jshint ignore:line
}
return n;
},
set: function(v) {
if (!a.float) { v = Math.floor(v); }
if (setmin !== undefined && v < setmin) {
utils.IndexSizeError(a.name + ' set to ' + v);
}
if (unsigned_long) {
v = (v < 0 || v > 0x7FFFFFFF) ? def.call(this) :
(v|0); // jshint ignore:line
} else if (unsigned_fallback) {
v = (v < 1 || v > 0x7FFFFFFF) ? def.call(this) :
(v|0); // jshint ignore:line
} else if (signed_long) {
v = (v < -0x80000000 || v > 0x7FFFFFFF) ? def.call(this) :
(v|0); // jshint ignore:line
}
this._setattr(a.name, String(v));
}
};
}
// This is a utility function for setting up change handler functions
// for attributes like 'id' that require special handling when they change.
exports.registerChangeHandler = function(c, name, handler) {
var p = c.prototype;
// If p does not already have its own _attributeChangeHandlers
// then create one for it, inheriting from the inherited
// _attributeChangeHandlers. At the top (for the Element class) the
// _attributeChangeHandlers object will be created with a null prototype.
if (!Object.prototype.hasOwnProperty.call(p, '_attributeChangeHandlers')) {
p._attributeChangeHandlers =
Object.create(p._attributeChangeHandlers || null);
}
p._attributeChangeHandlers[name] = handler;
};

View File

@@ -0,0 +1,7 @@
/*
* This file defines Domino behaviour that can be externally configured.
* To change these settings, set the relevant global property *before*
* you call `require("domino")`.
*/
exports.isApiWritable = !globalThis.__domino_frozen__;

View File

@@ -0,0 +1,71 @@
"use strict";
var attributes = require('./attributes');
var isApiWritable = require("./config").isApiWritable;
module.exports = function(spec, defaultConstructor, tagList, tagNameToImpl) {
var c = spec.ctor;
if (c) {
var props = spec.props || {};
if (spec.attributes) {
for (var n in spec.attributes) {
var attr = spec.attributes[n];
if (typeof attr !== 'object' || Array.isArray(attr)) attr = {type: attr};
if (!attr.name) attr.name = n.toLowerCase();
props[n] = attributes.property(attr);
}
}
props.constructor = { value : c, writable: isApiWritable };
c.prototype = Object.create((spec.superclass || defaultConstructor).prototype, props);
if (spec.events) {
addEventHandlers(c, spec.events);
}
tagList[spec.name] = c;
}
else {
c = defaultConstructor;
}
(spec.tags || spec.tag && [spec.tag] || []).forEach(function(tag) {
tagNameToImpl[tag] = c;
});
return c;
};
function EventHandlerBuilder(body, document, form, element) {
this.body = body;
this.document = document;
this.form = form;
this.element = element;
}
EventHandlerBuilder.prototype.build = function () {
return () => {};
};
function EventHandlerChangeHandler(elt, name, oldval, newval) {
var doc = elt.ownerDocument || Object.create(null);
var form = elt.form || Object.create(null);
elt[name] = new EventHandlerBuilder(newval, doc, form, elt).build();
}
function addEventHandlers(c, eventHandlerTypes) {
var p = c.prototype;
eventHandlerTypes.forEach(function(type) {
// Define the event handler registration IDL attribute for this type
Object.defineProperty(p, "on" + type, {
get: function() {
return this._getEventHandler(type);
},
set: function(v) {
this._setEventHandler(type, v);
},
});
// Define special behavior for the content attribute as well
attributes.registerChangeHandler(c, "on" + type, EventHandlerChangeHandler);
});
}

View File

@@ -0,0 +1,7 @@
"use strict";
module.exports = {
Event: require('./Event'),
UIEvent: require('./UIEvent'),
MouseEvent: require('./MouseEvent'),
CustomEvent: require('./CustomEvent')
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
"use strict";
var utils = require('./utils');
exports = module.exports = {
CSSStyleDeclaration: require('./CSSStyleDeclaration'),
CharacterData: require('./CharacterData'),
Comment: require('./Comment'),
DOMException: require('./DOMException'),
DOMImplementation: require('./DOMImplementation'),
DOMTokenList: require('./DOMTokenList'),
Document: require('./Document'),
DocumentFragment: require('./DocumentFragment'),
DocumentType: require('./DocumentType'),
Element: require('./Element'),
HTMLParser: require('./HTMLParser'),
NamedNodeMap: require('./NamedNodeMap'),
Node: require('./Node'),
NodeList: require('./NodeList'),
NodeFilter: require('./NodeFilter'),
ProcessingInstruction: require('./ProcessingInstruction'),
Text: require('./Text'),
Window: require('./Window')
};
utils.merge(exports, require('./events'));
utils.merge(exports, require('./htmlelts').elements);
utils.merge(exports, require('./svg').elements);

View File

@@ -0,0 +1,80 @@
"use strict";
var DOMImplementation = require('./DOMImplementation');
var HTMLParser = require('./HTMLParser');
var Window = require('./Window');
var impl = require('./impl');
exports.createDOMImplementation = function() {
return new DOMImplementation(null);
};
exports.createDocument = function(html, force) {
// Previous API couldn't let you pass '' as a document, and that
// yields a slightly different document than createHTMLDocument('')
// does. The new `force` parameter lets you pass '' if you want to.
if (html || force) {
var parser = new HTMLParser();
parser.parse(html || '', true);
return parser.document();
}
return new DOMImplementation(null).createHTMLDocument("");
};
exports.createIncrementalHTMLParser = function() {
var parser = new HTMLParser();
/** API for incremental parser. */
return {
/** Provide an additional chunk of text to be parsed. */
write: function(s) {
if (s.length > 0) {
parser.parse(s, false, function() { return true; });
}
},
/**
* Signal that we are done providing input text, optionally
* providing one last chunk as a parameter.
*/
end: function(s) {
parser.parse(s || '', true, function() { return true; });
},
/**
* Performs a chunk of parsing work, returning at the end of
* the next token as soon as shouldPauseFunc() returns true.
* Returns true iff there is more work to do.
*
* For example:
* ```
* var incrParser = domino.createIncrementalHTMLParser();
* incrParser.end('...long html document...');
* while (true) {
* // Pause every 10ms
* var start = Date.now();
* var pauseIn10 = function() { return (Date.now() - start) >= 10; };
* if (!incrParser.process(pauseIn10)) {
* break;
* }
* ...yield to other tasks, do other housekeeping, etc...
* }
* ```
*/
process: function(shouldPauseFunc) {
return parser.parse('', false, shouldPauseFunc);
},
/**
* Returns the result of the incremental parse. Valid after
* `this.end()` has been called and `this.process()` has returned
* false.
*/
document: function() {
return parser.document();
},
};
};
exports.createWindow = function(html, address) {
var document = exports.createDocument(html);
if (address !== undefined) { document._address = address; }
return new impl.Window(document);
};
exports.impl = impl;

View File

@@ -0,0 +1,933 @@
"use strict";
/* jshint eqnull: true */
/**
* Zest (https://github.com/chjj/zest)
* A css selector engine.
* Copyright (c) 2011-2012, Christopher Jeffrey. (MIT Licensed)
* Domino version based on Zest v0.1.3 with bugfixes applied.
*/
/**
* Helpers
*/
var window = Object.create(null, {
location: { get: function() {
throw new Error('window.location is not supported.');
} }
});
var compareDocumentPosition = function(a, b) {
return a.compareDocumentPosition(b);
};
var order = function(a, b) {
/* jshint bitwise: false */
return compareDocumentPosition(a, b) & 2 ? 1 : -1;
};
var next = function(el) {
while ((el = el.nextSibling)
&& el.nodeType !== 1);
return el;
};
var prev = function(el) {
while ((el = el.previousSibling)
&& el.nodeType !== 1);
return el;
};
var child = function(el) {
/*jshint -W084 */
if (el = el.firstChild) {
while (el.nodeType !== 1
&& (el = el.nextSibling));
}
return el;
};
var lastChild = function(el) {
/*jshint -W084 */
if (el = el.lastChild) {
while (el.nodeType !== 1
&& (el = el.previousSibling));
}
return el;
};
var parentIsElement = function(n) {
if (!n.parentNode) { return false; }
var nodeType = n.parentNode.nodeType;
// The root `html` element can be a first- or last-child, too.
return nodeType === 1 || nodeType === 9;
};
var unquote = function(str) {
if (!str) return str;
var ch = str[0];
if (ch === '"' || ch === '\'') {
if (str[str.length-1] === ch) {
str = str.slice(1, -1);
} else {
// bad string.
str = str.slice(1);
}
return str.replace(rules.str_escape, function(s) {
var m = /^\\(?:([0-9A-Fa-f]+)|([\r\n\f]+))/.exec(s);
if (!m) { return s.slice(1); }
if (m[2]) { return ''; /* escaped newlines are ignored in strings. */ }
var cp = parseInt(m[1], 16);
return String.fromCodePoint ? String.fromCodePoint(cp) :
// Not all JavaScript implementations have String.fromCodePoint yet.
String.fromCharCode(cp);
});
} else if (rules.ident.test(str)) {
return decodeid(str);
} else {
// NUMBER, PERCENTAGE, DIMENSION, etc
return str;
}
};
var decodeid = function(str) {
return str.replace(rules.escape, function(s) {
var m = /^\\([0-9A-Fa-f]+)/.exec(s);
if (!m) { return s[1]; }
var cp = parseInt(m[1], 16);
return String.fromCodePoint ? String.fromCodePoint(cp) :
// Not all JavaScript implementations have String.fromCodePoint yet.
String.fromCharCode(cp);
});
};
var indexOf = (function() {
if (Array.prototype.indexOf) {
return Array.prototype.indexOf;
}
return function(obj, item) {
var i = this.length;
while (i--) {
if (this[i] === item) return i;
}
return -1;
};
})();
var makeInside = function(start, end) {
var regex = rules.inside.source
.replace(/</g, start)
.replace(/>/g, end);
return new RegExp(regex);
};
var replace = function(regex, name, val) {
regex = regex.source;
regex = regex.replace(name, val.source || val);
return new RegExp(regex);
};
var truncateUrl = function(url, num) {
return url
.replace(/^(?:\w+:\/\/|\/+)/, '')
.replace(/(?:\/+|\/*#.*?)$/, '')
.split('/', num)
.join('/');
};
/**
* Handle `nth` Selectors
*/
var parseNth = function(param_, test) {
var param = param_.replace(/\s+/g, '')
, cap;
if (param === 'even') {
param = '2n+0';
} else if (param === 'odd') {
param = '2n+1';
} else if (param.indexOf('n') === -1) {
param = '0n' + param;
}
cap = /^([+-])?(\d+)?n([+-])?(\d+)?$/.exec(param);
return {
group: cap[1] === '-'
? -(cap[2] || 1)
: +(cap[2] || 1),
offset: cap[4]
? (cap[3] === '-' ? -cap[4] : +cap[4])
: 0
};
};
var nth = function(param_, test, last) {
var param = parseNth(param_)
, group = param.group
, offset = param.offset
, find = !last ? child : lastChild
, advance = !last ? next : prev;
return function(el) {
if (!parentIsElement(el)) return;
var rel = find(el.parentNode)
, pos = 0;
while (rel) {
if (test(rel, el)) pos++;
if (rel === el) {
pos -= offset;
return group && pos
? (pos % group) === 0 && (pos < 0 === group < 0)
: !pos;
}
rel = advance(rel);
}
};
};
/**
* Simple Selectors
*/
var selectors = {
'*': (function() {
if (false/*function() {
var el = document.createElement('div');
el.appendChild(document.createComment(''));
return !!el.getElementsByTagName('*')[0];
}()*/) {
return function(el) {
if (el.nodeType === 1) return true;
};
}
return function() {
return true;
};
})(),
'type': function(type) {
type = type.toLowerCase();
return function(el) {
return el.nodeName.toLowerCase() === type;
};
},
'attr': function(key, op, val, i) {
op = operators[op];
return function(el) {
var attr;
switch (key) {
case 'for':
attr = el.htmlFor;
break;
case 'class':
// className is '' when non-existent
// getAttribute('class') is null
attr = el.className;
if (attr === '' && el.getAttribute('class') == null) {
attr = null;
}
break;
case 'href':
case 'src':
attr = el.getAttribute(key, 2);
break;
case 'title':
// getAttribute('title') can be '' when non-existent sometimes?
attr = el.getAttribute('title') || null;
break;
// careful with attributes with special getter functions
case 'id':
case 'lang':
case 'dir':
case 'accessKey':
case 'hidden':
case 'tabIndex':
case 'style':
if (el.getAttribute) {
attr = el.getAttribute(key);
break;
}
/* falls through */
default:
if (el.hasAttribute && !el.hasAttribute(key)) {
break;
}
attr = el[key] != null
? el[key]
: el.getAttribute && el.getAttribute(key);
break;
}
if (attr == null) return;
attr = attr + '';
if (i) {
attr = attr.toLowerCase();
val = val.toLowerCase();
}
return op(attr, val);
};
},
':first-child': function(el) {
return !prev(el) && parentIsElement(el);
},
':last-child': function(el) {
return !next(el) && parentIsElement(el);
},
':only-child': function(el) {
return !prev(el) && !next(el) && parentIsElement(el);
},
':nth-child': function(param, last) {
return nth(param, function() {
return true;
}, last);
},
':nth-last-child': function(param) {
return selectors[':nth-child'](param, true);
},
':root': function(el) {
return el.ownerDocument.documentElement === el;
},
':empty': function(el) {
return !el.firstChild;
},
':not': function(sel) {
var test = compileGroup(sel);
return function(el) {
return !test(el);
};
},
':first-of-type': function(el) {
if (!parentIsElement(el)) return;
var type = el.nodeName;
/*jshint -W084 */
while (el = prev(el)) {
if (el.nodeName === type) return;
}
return true;
},
':last-of-type': function(el) {
if (!parentIsElement(el)) return;
var type = el.nodeName;
/*jshint -W084 */
while (el = next(el)) {
if (el.nodeName === type) return;
}
return true;
},
':only-of-type': function(el) {
return selectors[':first-of-type'](el)
&& selectors[':last-of-type'](el);
},
':nth-of-type': function(param, last) {
return nth(param, function(rel, el) {
return rel.nodeName === el.nodeName;
}, last);
},
':nth-last-of-type': function(param) {
return selectors[':nth-of-type'](param, true);
},
':checked': function(el) {
return !!(el.checked || el.selected);
},
':indeterminate': function(el) {
return !selectors[':checked'](el);
},
':enabled': function(el) {
return !el.disabled && el.type !== 'hidden';
},
':disabled': function(el) {
return !!el.disabled;
},
':target': function(el) {
return el.id === window.location.hash.substring(1);
},
':focus': function(el) {
return el === el.ownerDocument.activeElement;
},
':is': function(sel) {
return compileGroup(sel);
},
// :matches is an older name for :is; see
// https://github.com/w3c/csswg-drafts/issues/3258
':matches': function(sel) {
return selectors[':is'](sel);
},
':nth-match': function(param, last) {
var args = param.split(/\s*,\s*/)
, arg = args.shift()
, test = compileGroup(args.join(','));
return nth(arg, test, last);
},
':nth-last-match': function(param) {
return selectors[':nth-match'](param, true);
},
':links-here': function(el) {
return el + '' === window.location + '';
},
':lang': function(param) {
return function(el) {
while (el) {
if (el.lang) return el.lang.indexOf(param) === 0;
el = el.parentNode;
}
};
},
':dir': function(param) {
return function(el) {
while (el) {
if (el.dir) return el.dir === param;
el = el.parentNode;
}
};
},
':scope': function(el, con) {
var context = con || el.ownerDocument;
if (context.nodeType === 9) {
return el === context.documentElement;
}
return el === context;
},
':any-link': function(el) {
return typeof el.href === 'string';
},
':local-link': function(el) {
if (el.nodeName) {
return el.href && el.host === window.location.host;
}
var param = +el + 1;
return function(el) {
if (!el.href) return;
var url = window.location + ''
, href = el + '';
return truncateUrl(url, param) === truncateUrl(href, param);
};
},
':default': function(el) {
return !!el.defaultSelected;
},
':valid': function(el) {
return el.willValidate || (el.validity && el.validity.valid);
},
':invalid': function(el) {
return !selectors[':valid'](el);
},
':in-range': function(el) {
return el.value > el.min && el.value <= el.max;
},
':out-of-range': function(el) {
return !selectors[':in-range'](el);
},
':required': function(el) {
return !!el.required;
},
':optional': function(el) {
return !el.required;
},
':read-only': function(el) {
if (el.readOnly) return true;
var attr = el.getAttribute('contenteditable')
, prop = el.contentEditable
, name = el.nodeName.toLowerCase();
name = name !== 'input' && name !== 'textarea';
return (name || el.disabled) && attr == null && prop !== 'true';
},
':read-write': function(el) {
return !selectors[':read-only'](el);
},
':hover': function() {
throw new Error(':hover is not supported.');
},
':active': function() {
throw new Error(':active is not supported.');
},
':link': function() {
throw new Error(':link is not supported.');
},
':visited': function() {
throw new Error(':visited is not supported.');
},
':column': function() {
throw new Error(':column is not supported.');
},
':nth-column': function() {
throw new Error(':nth-column is not supported.');
},
':nth-last-column': function() {
throw new Error(':nth-last-column is not supported.');
},
':current': function() {
throw new Error(':current is not supported.');
},
':past': function() {
throw new Error(':past is not supported.');
},
':future': function() {
throw new Error(':future is not supported.');
},
// Non-standard, for compatibility purposes.
':contains': function(param) {
return function(el) {
var text = el.innerText || el.textContent || el.value || '';
return text.indexOf(param) !== -1;
};
},
':has': function(param) {
return function(el) {
return find(param, el).length > 0;
};
}
// Potentially add more pseudo selectors for
// compatibility with sizzle and most other
// selector engines (?).
};
/**
* Attribute Operators
*/
var operators = {
'-': function() {
return true;
},
'=': function(attr, val) {
return attr === val;
},
'*=': function(attr, val) {
return attr.indexOf(val) !== -1;
},
'~=': function(attr, val) {
var i
, s
, f
, l;
for (s = 0; true; s = i + 1) {
i = attr.indexOf(val, s);
if (i === -1) return false;
f = attr[i - 1];
l = attr[i + val.length];
if ((!f || f === ' ') && (!l || l === ' ')) return true;
}
},
'|=': function(attr, val) {
var i = attr.indexOf(val)
, l;
if (i !== 0) return;
l = attr[i + val.length];
return l === '-' || !l;
},
'^=': function(attr, val) {
return attr.indexOf(val) === 0;
},
'$=': function(attr, val) {
var i = attr.lastIndexOf(val);
return i !== -1 && i + val.length === attr.length;
},
// non-standard
'!=': function(attr, val) {
return attr !== val;
}
};
/**
* Combinator Logic
*/
var combinators = {
' ': function(test) {
return function(el) {
/*jshint -W084 */
while (el = el.parentNode) {
if (test(el)) return el;
}
};
},
'>': function(test) {
return function(el) {
/*jshint -W084 */
if (el = el.parentNode) {
return test(el) && el;
}
};
},
'+': function(test) {
return function(el) {
/*jshint -W084 */
if (el = prev(el)) {
return test(el) && el;
}
};
},
'~': function(test) {
return function(el) {
/*jshint -W084 */
while (el = prev(el)) {
if (test(el)) return el;
}
};
},
'noop': function(test) {
return function(el) {
return test(el) && el;
};
},
'ref': function(test, name) {
var node;
function ref(el) {
var doc = el.ownerDocument
, nodes = doc.getElementsByTagName('*')
, i = nodes.length;
while (i--) {
node = nodes[i];
if (ref.test(el)) {
node = null;
return true;
}
}
node = null;
}
ref.combinator = function(el) {
if (!node || !node.getAttribute) return;
var attr = node.getAttribute(name) || '';
if (attr[0] === '#') attr = attr.substring(1);
if (attr === el.id && test(node)) {
return node;
}
};
return ref;
}
};
/**
* Grammar
*/
var rules = {
escape: /\\(?:[^0-9A-Fa-f\r\n]|[0-9A-Fa-f]{1,6}[\r\n\t ]?)/g,
str_escape: /(escape)|\\(\n|\r\n?|\f)/g,
nonascii: /[\u00A0-\uFFFF]/,
cssid: /(?:(?!-?[0-9])(?:escape|nonascii|[-_a-zA-Z0-9])+)/,
qname: /^ *(cssid|\*)/,
simple: /^(?:([.#]cssid)|pseudo|attr)/,
ref: /^ *\/(cssid)\/ */,
combinator: /^(?: +([^ \w*.#\\]) +|( )+|([^ \w*.#\\]))(?! *$)/,
attr: /^\[(cssid)(?:([^\w]?=)(inside))?\]/,
pseudo: /^(:cssid)(?:\((inside)\))?/,
inside: /(?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|<[^"'>]*>|\\["'>]|[^"'>])*/,
ident: /^(cssid)$/
};
rules.cssid = replace(rules.cssid, 'nonascii', rules.nonascii);
rules.cssid = replace(rules.cssid, 'escape', rules.escape);
rules.qname = replace(rules.qname, 'cssid', rules.cssid);
rules.simple = replace(rules.simple, 'cssid', rules.cssid);
rules.ref = replace(rules.ref, 'cssid', rules.cssid);
rules.attr = replace(rules.attr, 'cssid', rules.cssid);
rules.pseudo = replace(rules.pseudo, 'cssid', rules.cssid);
rules.inside = replace(rules.inside, '[^"\'>]*', rules.inside);
rules.attr = replace(rules.attr, 'inside', makeInside('\\[', '\\]'));
rules.pseudo = replace(rules.pseudo, 'inside', makeInside('\\(', '\\)'));
rules.simple = replace(rules.simple, 'pseudo', rules.pseudo);
rules.simple = replace(rules.simple, 'attr', rules.attr);
rules.ident = replace(rules.ident, 'cssid', rules.cssid);
rules.str_escape = replace(rules.str_escape, 'escape', rules.escape);
/**
* Compiling
*/
var compile = function(sel_) {
var sel = sel_.replace(/^\s+|\s+$/g, '')
, test
, filter = []
, buff = []
, subject
, qname
, cap
, op
, ref;
/*jshint -W084 */
while (sel) {
if (cap = rules.qname.exec(sel)) {
sel = sel.substring(cap[0].length);
qname = decodeid(cap[1]);
buff.push(tok(qname, true));
} else if (cap = rules.simple.exec(sel)) {
sel = sel.substring(cap[0].length);
qname = '*';
buff.push(tok(qname, true));
buff.push(tok(cap));
} else {
throw new SyntaxError('Invalid selector.');
}
while (cap = rules.simple.exec(sel)) {
sel = sel.substring(cap[0].length);
buff.push(tok(cap));
}
if (sel[0] === '!') {
sel = sel.substring(1);
subject = makeSubject();
subject.qname = qname;
buff.push(subject.simple);
}
if (cap = rules.ref.exec(sel)) {
sel = sel.substring(cap[0].length);
ref = combinators.ref(makeSimple(buff), decodeid(cap[1]));
filter.push(ref.combinator);
buff = [];
continue;
}
if (cap = rules.combinator.exec(sel)) {
sel = sel.substring(cap[0].length);
op = cap[1] || cap[2] || cap[3];
if (op === ',') {
filter.push(combinators.noop(makeSimple(buff)));
break;
}
} else {
op = 'noop';
}
if (!combinators[op]) { throw new SyntaxError('Bad combinator.'); }
filter.push(combinators[op](makeSimple(buff)));
buff = [];
}
test = makeTest(filter);
test.qname = qname;
test.sel = sel;
if (subject) {
subject.lname = test.qname;
subject.test = test;
subject.qname = subject.qname;
subject.sel = test.sel;
test = subject;
}
if (ref) {
ref.test = test;
ref.qname = test.qname;
ref.sel = test.sel;
test = ref;
}
return test;
};
var tok = function(cap, qname) {
// qname
if (qname) {
return cap === '*'
? selectors['*']
: selectors.type(cap);
}
// class/id
if (cap[1]) {
return cap[1][0] === '.'
// XXX unescape here? or in attr?
? selectors.attr('class', '~=', decodeid(cap[1].substring(1)), false)
: selectors.attr('id', '=', decodeid(cap[1].substring(1)), false);
}
// pseudo-name
// inside-pseudo
if (cap[2]) {
return cap[3]
? selectors[decodeid(cap[2])](unquote(cap[3]))
: selectors[decodeid(cap[2])];
}
// attr name
// attr op
// attr value
if (cap[4]) {
var value = cap[6];
var i = /["'\s]\s*I$/i.test(value);
if (i) {
value = value.replace(/\s*I$/i, '');
}
return selectors.attr(decodeid(cap[4]), cap[5] || '-', unquote(value), i);
}
throw new SyntaxError('Unknown Selector.');
};
var makeSimple = function(func) {
var l = func.length
, i;
// Potentially make sure
// `el` is truthy.
if (l < 2) return func[0];
return function(el) {
if (!el) return;
for (i = 0; i < l; i++) {
if (!func[i](el)) return;
}
return true;
};
};
var makeTest = function(func) {
if (func.length < 2) {
return function(el) {
return !!func[0](el);
};
}
return function(el) {
var i = func.length;
while (i--) {
if (!(el = func[i](el))) return;
}
return true;
};
};
var makeSubject = function() {
var target;
function subject(el) {
var node = el.ownerDocument
, scope = node.getElementsByTagName(subject.lname)
, i = scope.length;
while (i--) {
if (subject.test(scope[i]) && target === el) {
target = null;
return true;
}
}
target = null;
}
subject.simple = function(el) {
target = el;
return true;
};
return subject;
};
var compileGroup = function(sel) {
var test = compile(sel)
, tests = [ test ];
while (test.sel) {
test = compile(test.sel);
tests.push(test);
}
if (tests.length < 2) return test;
return function(el) {
var l = tests.length
, i = 0;
for (; i < l; i++) {
if (tests[i](el)) return true;
}
};
};
/**
* Selection
*/
var find = function(sel, node) {
var results = []
, test = compile(sel)
, scope = node.getElementsByTagName(test.qname)
, i = 0
, el;
/*jshint -W084 */
while (el = scope[i++]) {
if (test(el)) results.push(el);
}
if (test.sel) {
while (test.sel) {
test = compile(test.sel);
scope = node.getElementsByTagName(test.qname);
i = 0;
/*jshint -W084 */
while (el = scope[i++]) {
if (test(el) && indexOf.call(results, el) === -1) {
results.push(el);
}
}
}
results.sort(order);
}
return results;
};
/**
* Expose
*/
module.exports = exports = function(sel, context) {
/* when context isn't a DocumentFragment and the selector is simple: */
var id, r;
if (context.nodeType !== 11 && sel.indexOf(' ') === -1) {
if (sel[0] === '#' && context.rooted && /^#[A-Z_][-A-Z0-9_]*$/i.test(sel)) {
if (context.doc._hasMultipleElementsWithId) {
id = sel.substring(1);
if (!context.doc._hasMultipleElementsWithId(id)) {
r = context.doc.getElementById(id);
return r ? [r] : [];
}
}
}
if (sel[0] === '.' && /^\.\w+$/.test(sel)) {
return context.getElementsByClassName(sel.substring(1));
}
if (/^\w+$/.test(sel)) {
return context.getElementsByTagName(sel);
}
}
/* do things the hard/slow way */
return find(sel, context);
};
exports.selectors = selectors;
exports.operators = operators;
exports.combinators = combinators;
exports.matches = function(el, sel) {
var test = { sel: sel };
do {
test = compile(test.sel);
if (test(el)) { return true; }
} while (test.sel);
return false;
};

View File

@@ -0,0 +1,106 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// The below is a compiled copy of https://github.com/angular/angular/blob/92e41e9cb417223d9888a4c23b4c0e73188f87d0/packages/compiler/src/render3/view/style_parser.ts
Object.defineProperty(exports, "__esModule", { value: true });
exports.hyphenate = exports.parse = void 0;
/**
* Parses string representation of a style and converts it into object literal.
*
* @param value string representation of style as used in the `style` attribute in HTML.
* Example: `color: red; height: auto`.
* @returns An array of style property name and value pairs, e.g. `['color', 'red', 'height',
* 'auto']`
*/
function parse(value) {
// we use a string array here instead of a string map
// because a string-map is not guaranteed to retain the
// order of the entries whereas a string array can be
// constructed in a [key, value, key, value] format.
const styles = [];
let i = 0;
let parenDepth = 0;
let quote = 0; /* Char.QuoteNone */
let valueStart = 0;
let propStart = 0;
let currentProp = null;
while (i < value.length) {
const token = value.charCodeAt(i++);
switch (token) {
case 40 /* Char.OpenParen */:
parenDepth++;
break;
case 41 /* Char.CloseParen */:
parenDepth--;
break;
case 39 /* Char.QuoteSingle */:
// valueStart needs to be there since prop values don't
// have quotes in CSS
if (quote === 0 /* Char.QuoteNone */) {
quote = 39 /* Char.QuoteSingle */;
} else if (
quote === 39 /* Char.QuoteSingle */ &&
value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */
) {
quote = 0 /* Char.QuoteNone */;
}
break;
case 34 /* Char.QuoteDouble */:
// same logic as above
if (quote === 0 /* Char.QuoteNone */) {
quote = 34 /* Char.QuoteDouble */;
} else if (
quote === 34 /* Char.QuoteDouble */ &&
value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */
) {
quote = 0 /* Char.QuoteNone */;
}
break;
case 58 /* Char.Colon */:
if (
!currentProp &&
parenDepth === 0 &&
quote === 0 /* Char.QuoteNone */
) {
currentProp = hyphenate(value.substring(propStart, i - 1).trim());
valueStart = i;
}
break;
case 59 /* Char.Semicolon */:
if (
currentProp &&
valueStart > 0 &&
parenDepth === 0 &&
quote === 0 /* Char.QuoteNone */
) {
const styleVal = value.substring(valueStart, i - 1).trim();
styles.push(currentProp, styleVal);
propStart = i;
valueStart = 0;
currentProp = null;
}
break;
}
}
if (currentProp && valueStart) {
const styleVal = value.slice(valueStart).trim();
styles.push(currentProp, styleVal);
}
return styles;
}
exports.parse = parse;
function hyphenate(value) {
return value
.replace(/[a-z][A-Z]/g, (v) => {
return v.charAt(0) + "-" + v.charAt(1);
})
.toLowerCase();
}
exports.hyphenate = hyphenate;

View File

@@ -0,0 +1,59 @@
"use strict";
var Element = require('./Element');
var defineElement = require('./defineElement');
var utils = require('./utils');
var CSSStyleDeclaration = require('./CSSStyleDeclaration');
var svgElements = exports.elements = {};
var svgNameToImpl = Object.create(null);
exports.createElement = function(doc, localName, prefix) {
var impl = svgNameToImpl[localName] || SVGElement;
return new impl(doc, localName, prefix);
};
function define(spec) {
return defineElement(spec, SVGElement, svgElements, svgNameToImpl);
}
var SVGElement = define({
superclass: Element,
name: 'SVGElement',
ctor: function SVGElement(doc, localName, prefix) {
Element.call(this, doc, localName, utils.NAMESPACE.SVG, prefix);
},
props: {
style: { get: function() {
if (!this._style)
this._style = new CSSStyleDeclaration(this);
return this._style;
}}
}
});
define({
name: 'SVGSVGElement',
ctor: function SVGSVGElement(doc, localName, prefix) {
SVGElement.call(this, doc, localName, prefix);
},
tag: 'svg',
props: {
createSVGRect: { value: function () {
return exports.createElement(this.ownerDocument, 'rect', null);
} }
}
});
define({
tags: [
'a', 'altGlyph', 'altGlyphDef', 'altGlyphItem', 'animate', 'animateColor', 'animateMotion', 'animateTransform',
'circle', 'clipPath', 'color-profile', 'cursor', 'defs', 'desc', 'ellipse', 'feBlend', 'feColorMatrix',
'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight',
'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode',
'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence', 'filter',
'font', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignObject', 'g',
'glyph', 'glyphRef', 'hkern', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'missing-glyph',
'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'script', 'set', 'stop', 'style',
'switch', 'symbol', 'text', 'textPath', 'title', 'tref', 'tspan', 'use', 'view', 'vkern'
]
});

View File

@@ -0,0 +1,85 @@
"use strict";
var DOMException = require('./DOMException');
var ERR = DOMException;
var isApiWritable = require("./config").isApiWritable;
exports.NAMESPACE = {
HTML: 'http://www.w3.org/1999/xhtml',
XML: 'http://www.w3.org/XML/1998/namespace',
XMLNS: 'http://www.w3.org/2000/xmlns/',
MATHML: 'http://www.w3.org/1998/Math/MathML',
SVG: 'http://www.w3.org/2000/svg',
XLINK: 'http://www.w3.org/1999/xlink'
};
//
// Shortcut functions for throwing errors of various types.
//
exports.IndexSizeError = function() { throw new DOMException(ERR.INDEX_SIZE_ERR); };
exports.HierarchyRequestError = function() { throw new DOMException(ERR.HIERARCHY_REQUEST_ERR); };
exports.WrongDocumentError = function() { throw new DOMException(ERR.WRONG_DOCUMENT_ERR); };
exports.InvalidCharacterError = function() { throw new DOMException(ERR.INVALID_CHARACTER_ERR); };
exports.NoModificationAllowedError = function() { throw new DOMException(ERR.NO_MODIFICATION_ALLOWED_ERR); };
exports.NotFoundError = function() { throw new DOMException(ERR.NOT_FOUND_ERR); };
exports.NotSupportedError = function() { throw new DOMException(ERR.NOT_SUPPORTED_ERR); };
exports.InvalidStateError = function() { throw new DOMException(ERR.INVALID_STATE_ERR); };
exports.SyntaxError = function() { throw new DOMException(ERR.SYNTAX_ERR); };
exports.InvalidModificationError = function() { throw new DOMException(ERR.INVALID_MODIFICATION_ERR); };
exports.NamespaceError = function() { throw new DOMException(ERR.NAMESPACE_ERR); };
exports.InvalidAccessError = function() { throw new DOMException(ERR.INVALID_ACCESS_ERR); };
exports.TypeMismatchError = function() { throw new DOMException(ERR.TYPE_MISMATCH_ERR); };
exports.SecurityError = function() { throw new DOMException(ERR.SECURITY_ERR); };
exports.NetworkError = function() { throw new DOMException(ERR.NETWORK_ERR); };
exports.AbortError = function() { throw new DOMException(ERR.ABORT_ERR); };
exports.UrlMismatchError = function() { throw new DOMException(ERR.URL_MISMATCH_ERR); };
exports.QuotaExceededError = function() { throw new DOMException(ERR.QUOTA_EXCEEDED_ERR); };
exports.TimeoutError = function() { throw new DOMException(ERR.TIMEOUT_ERR); };
exports.InvalidNodeTypeError = function() { throw new DOMException(ERR.INVALID_NODE_TYPE_ERR); };
exports.DataCloneError = function() { throw new DOMException(ERR.DATA_CLONE_ERR); };
exports.nyi = function() {
throw new Error("NotYetImplemented");
};
exports.shouldOverride = function() {
throw new Error("Abstract function; should be overriding in subclass.");
};
exports.assert = function(expr, msg) {
if (!expr) {
throw new Error("Assertion failed: " + (msg || "") + "\n" + new Error().stack);
}
};
exports.expose = function(src, c) {
for (var n in src) {
Object.defineProperty(c.prototype, n, { value: src[n], writable: isApiWritable });
}
};
exports.merge = function(a, b) {
for (var n in b) {
a[n] = b[n];
}
};
// Compare two nodes based on their document order. This function is intended
// to be passed to sort(). Assumes that the array being sorted does not
// contain duplicates. And that all nodes are connected and comparable.
// Clever code by ppk via jeresig.
exports.documentOrder = function(n,m) {
/* jshint bitwise: false */
return 3 - (n.compareDocumentPosition(m) & 6);
};
exports.toASCIILowerCase = function(s) {
return s.replace(/[A-Z]+/g, function(c) {
return c.toLowerCase();
});
};
exports.toASCIIUpperCase = function(s) {
return s.replace(/[a-z]+/g, function(c) {
return c.toUpperCase();
});
};

View File

@@ -0,0 +1,91 @@
"use strict";
// This grammar is from the XML and XML Namespace specs. It specifies whether
// a string (such as an element or attribute name) is a valid Name or QName.
//
// Name ::= NameStartChar (NameChar)*
// NameStartChar ::= ":" | [A-Z] | "_" | [a-z] |
// [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] |
// [#x370-#x37D] | [#x37F-#x1FFF] |
// [#x200C-#x200D] | [#x2070-#x218F] |
// [#x2C00-#x2FEF] | [#x3001-#xD7FF] |
// [#xF900-#xFDCF] | [#xFDF0-#xFFFD] |
// [#x10000-#xEFFFF]
//
// NameChar ::= NameStartChar | "-" | "." | [0-9] |
// #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
//
// QName ::= PrefixedName| UnprefixedName
// PrefixedName ::= Prefix ':' LocalPart
// UnprefixedName ::= LocalPart
// Prefix ::= NCName
// LocalPart ::= NCName
// NCName ::= Name - (Char* ':' Char*)
// # An XML Name, minus the ":"
//
exports.isValidName = isValidName;
exports.isValidQName = isValidQName;
// Most names will be ASCII only. Try matching against simple regexps first
var simplename = /^[_:A-Za-z][-.:\w]+$/;
var simpleqname = /^([_A-Za-z][-.\w]+|[_A-Za-z][-.\w]+:[_A-Za-z][-.\w]+)$/;
// If the regular expressions above fail, try more complex ones that work
// for any identifiers using codepoints from the Unicode BMP
var ncnamestartchars = "_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02ff\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD";
var ncnamechars = "-._A-Za-z0-9\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02ff\u0300-\u037D\u037F-\u1FFF\u200C\u200D\u203f\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD";
var ncname = "[" + ncnamestartchars + "][" + ncnamechars + "]*";
var namestartchars = ncnamestartchars + ":";
var namechars = ncnamechars + ":";
var name = new RegExp("^[" + namestartchars + "]" + "[" + namechars + "]*$");
var qname = new RegExp("^(" + ncname + "|" + ncname + ":" + ncname + ")$");
// XML says that these characters are also legal:
// [#x10000-#xEFFFF]. So if the patterns above fail, and the
// target string includes surrogates, then try the following
// patterns that allow surrogates and then run an extra validation
// step to make sure that the surrogates are in valid pairs and in
// the right range. Note that since the characters \uf0000 to \u1f0000
// are not allowed, it means that the high surrogate can only go up to
// \uDB7f instead of \uDBFF.
var hassurrogates = /[\uD800-\uDB7F\uDC00-\uDFFF]/;
var surrogatechars = /[\uD800-\uDB7F\uDC00-\uDFFF]/g;
var surrogatepairs = /[\uD800-\uDB7F][\uDC00-\uDFFF]/g;
// Modify the variables above to allow surrogates
ncnamestartchars += "\uD800-\uDB7F\uDC00-\uDFFF";
ncnamechars += "\uD800-\uDB7F\uDC00-\uDFFF";
ncname = "[" + ncnamestartchars + "][" + ncnamechars + "]*";
namestartchars = ncnamestartchars + ":";
namechars = ncnamechars + ":";
// Build another set of regexps that include surrogates
var surrogatename = new RegExp("^[" + namestartchars + "]" + "[" + namechars + "]*$");
var surrogateqname = new RegExp("^(" + ncname + "|" + ncname + ":" + ncname + ")$");
function isValidName(s) {
if (simplename.test(s)) return true; // Plain ASCII
if (name.test(s)) return true; // Unicode BMP
// Maybe the tests above failed because s includes surrogate pairs
// Most likely, though, they failed for some more basic syntax problem
if (!hassurrogates.test(s)) return false;
// Is the string a valid name if we allow surrogates?
if (!surrogatename.test(s)) return false;
// Finally, are the surrogates all correctly paired up?
var chars = s.match(surrogatechars), pairs = s.match(surrogatepairs);
return pairs !== null && 2*pairs.length === chars.length;
}
function isValidQName(s) {
if (simpleqname.test(s)) return true; // Plain ASCII
if (qname.test(s)) return true; // Unicode BMP
if (!hassurrogates.test(s)) return false;
if (!surrogateqname.test(s)) return false;
var chars = s.match(surrogatechars), pairs = s.match(surrogatepairs);
return pairs !== null && 2*pairs.length === chars.length;
}

View File

@@ -0,0 +1,22 @@
{
"name": "@mixmark-io/domino",
"version": "2.2.0",
"license": "BSD-2-Clause",
"author": "Felix Gnass <fgnass@gmail.com>",
"description": "Server-side DOM implementation based on Mozilla's dom.js",
"main": "./lib",
"repository": {
"type": "git",
"url": "https://github.com/mixmark-io/domino.git"
},
"scripts": {
"test": "mocha"
},
"types": "lib/index.d.ts",
"devDependencies": {
"jquery": "^3.5.1",
"mocha": "^6.2.3",
"puppeteer": "^21.3.5",
"should": "^13.2.3"
}
}

Binary file not shown.

View File

@@ -0,0 +1,55 @@
'use strict';
const { promisify } = require('util');
const { isUint8Array } = require('util/types');
function load() {
try {
return require('../build/Release/zstd.node');
} catch {
// Webpack will fail when just returning the require, so we need to wrap
// in a try/catch and rethrow.
/* eslint no-useless-catch: 0 */
try {
return require('../build/Debug/zstd.node');
} catch (error) {
throw error;
}
}
}
const zstd = load();
const _compress = promisify(zstd.compress);
const _decompress = promisify(zstd.decompress);
// Error objects created via napi don't have JS stacks; wrap them so .stack is present
// https://github.com/nodejs/node/issues/25318#issuecomment-451068073
exports.compress = async function compress(data, compressionLevel) {
if (!isUint8Array(data)) {
throw new TypeError(`parameter 'data' must be a Uint8Array.`);
}
if (compressionLevel != null && typeof compressionLevel !== 'number') {
throw new TypeError(`parameter 'compressionLevel' must be a number.`);
}
try {
return await _compress(data, compressionLevel ?? 3);
} catch (e) {
throw new Error(`zstd: ${e.message}`);
}
};
exports.decompress = async function decompress(data) {
if (!isUint8Array(data)) {
throw new TypeError(`parameter 'data' must be a Uint8Array.`);
}
try {
return await _decompress(data);
} catch (e) {
throw new Error(`zstd: ${e.message}`);
}
};
/** used for testing */
exports.getDefinedNapiVersion = zstd.getDefinedNapiVersion;

View File

@@ -0,0 +1,51 @@
{
"name": "@mongodb-js/zstd",
"version": "7.0.0",
"main": "lib/index.js",
"types": "index.d.ts",
"repository": "https://github.com/mongodb-js/zstd",
"files": [
"index.d.ts",
"lib/index.js",
"addon/*",
"binding.gyp"
],
"dependencies": {
"node-addon-api": "^8.5.0",
"prebuild-install": "^7.1.3"
},
"license": "Apache-2.0",
"devDependencies": {
"@mongodb-js/zstd": "^1.2.0",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@wasm-fmt/clang-format": "^21.1.4",
"chai": "^4.5.0",
"eslint": "^9.37.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.4",
"mocha": "^11.7.4",
"node-gyp": "^11.4.2",
"prebuild": "^13.0.1",
"prettier": "^3.6.2"
},
"engines": {
"node": ">= 20.19.0"
},
"scripts": {
"install": "prebuild-install --runtime napi || npm run clean-install",
"clean-install": "npm run install-zstd && npm run compile",
"compile": "node-gyp rebuild",
"test": "mocha test/*.js",
"install-zstd": "bash etc/install-zstd.sh",
"check:eslint": "ESLINT_USE_FLAT_CONFIG=false eslint *ts lib/*.js test/*.js .*.json",
"clang-format": "clang-format --style=file:.clang-format --Werror -i addon/*",
"check:clang-format": "clang-format --style=file:.clang-format --dry-run --Werror addon/*",
"prebuild": "prebuild --runtime napi --strip --verbose --all"
},
"binary": {
"napi_versions": [
9
]
},
"mongodb:zstd_version": "1.5.6"
}

View File

@@ -0,0 +1,54 @@
export const balanced = (a, b, str) => {
const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
const mb = b instanceof RegExp ? maybeMatch(b, str) : b;
const r = ma !== null && mb != null && range(ma, mb, str);
return (r && {
start: r[0],
end: r[1],
pre: str.slice(0, r[0]),
body: str.slice(r[0] + ma.length, r[1]),
post: str.slice(r[1] + mb.length),
});
};
const maybeMatch = (reg, str) => {
const m = str.match(reg);
return m ? m[0] : null;
};
export const range = (a, b, str) => {
let begs, beg, left, right = undefined, result;
let ai = str.indexOf(a);
let bi = str.indexOf(b, ai + 1);
let i = ai;
if (ai >= 0 && bi > 0) {
if (a === b) {
return [ai, bi];
}
begs = [];
left = str.length;
while (i >= 0 && !result) {
if (i === ai) {
begs.push(i);
ai = str.indexOf(a, i + 1);
}
else if (begs.length === 1) {
const r = begs.pop();
if (r !== undefined)
result = [r, bi];
}
else {
beg = begs.pop();
if (beg !== undefined && beg < left) {
left = beg;
right = bi;
}
bi = str.indexOf(b, i + 1);
}
i = ai < bi && ai >= 0 ? ai : bi;
}
if (begs.length && right !== undefined) {
result = [left, right];
}
}
return result;
};
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,3 @@
{
"type": "module"
}

View File

@@ -0,0 +1,68 @@
{
"name": "balanced-match",
"description": "Match balanced character pairs, like \"{\" and \"}\"",
"version": "4.0.4",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/balanced-match.git"
},
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/commonjs/index.d.ts",
"default": "./dist/commonjs/index.js"
}
}
},
"type": "module",
"scripts": {
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"prepare": "tshy",
"pretest": "npm run prepare",
"presnap": "npm run prepare",
"test": "tap",
"snap": "tap",
"format": "prettier --write .",
"benchmark": "node benchmark/index.js",
"typedoc": "typedoc --tsconfig .tshy/esm.json ./src/*.ts"
},
"devDependencies": {
"@types/brace-expansion": "^1.1.2",
"@types/node": "^25.2.1",
"mkdirp": "^3.0.1",
"prettier": "^3.3.2",
"tap": "^21.6.2",
"tshy": "^3.0.2",
"typedoc": "^0.28.5"
},
"keywords": [
"match",
"regexp",
"test",
"balanced",
"parse"
],
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
},
"tshy": {
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
}
},
"main": "./dist/commonjs/index.js",
"types": "./dist/commonjs/index.d.ts",
"module": "./dist/esm/index.js"
}

View File

@@ -0,0 +1,207 @@
import { balanced } from 'balanced-match';
const escSlash = '\0SLASH' + Math.random() + '\0';
const escOpen = '\0OPEN' + Math.random() + '\0';
const escClose = '\0CLOSE' + Math.random() + '\0';
const escComma = '\0COMMA' + Math.random() + '\0';
const escPeriod = '\0PERIOD' + Math.random() + '\0';
const escSlashPattern = new RegExp(escSlash, 'g');
const escOpenPattern = new RegExp(escOpen, 'g');
const escClosePattern = new RegExp(escClose, 'g');
const escCommaPattern = new RegExp(escComma, 'g');
const escPeriodPattern = new RegExp(escPeriod, 'g');
const slashPattern = /\\\\/g;
const openPattern = /\\{/g;
const closePattern = /\\}/g;
const commaPattern = /\\,/g;
const periodPattern = /\\\./g;
export const EXPANSION_MAX = 100_000;
function numeric(str) {
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
}
function escapeBraces(str) {
return str
.replace(slashPattern, escSlash)
.replace(openPattern, escOpen)
.replace(closePattern, escClose)
.replace(commaPattern, escComma)
.replace(periodPattern, escPeriod);
}
function unescapeBraces(str) {
return str
.replace(escSlashPattern, '\\')
.replace(escOpenPattern, '{')
.replace(escClosePattern, '}')
.replace(escCommaPattern, ',')
.replace(escPeriodPattern, '.');
}
/**
* Basically just str.split(","), but handling cases
* where we have nested braced sections, which should be
* treated as individual members, like {a,{b,c},d}
*/
function parseCommaParts(str) {
if (!str) {
return [''];
}
const parts = [];
const m = balanced('{', '}', str);
if (!m) {
return str.split(',');
}
const { pre, body, post } = m;
const p = pre.split(',');
p[p.length - 1] += '{' + body + '}';
const postParts = parseCommaParts(post);
if (post.length) {
;
p[p.length - 1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
export function expand(str, options = {}) {
if (!str) {
return [];
}
const { max = EXPANSION_MAX } = options;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.slice(0, 2) === '{}') {
str = '\\{\\}' + str.slice(2);
}
return expand_(escapeBraces(str), max, true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand_(str, max, isTop) {
/** @type {string[]} */
const expansions = [];
// The `{a},b}` rewrite below restarts expansion on a rewritten string with
// the same `max` and `isTop = true`. Loop instead of recursing so a long run
// of non-expanding `{}` groups can't exhaust the call stack.
for (;;) {
const m = balanced('{', '}', str);
if (!m)
return [str];
// no need to expand pre, since it is guaranteed to be free of brace-sets
const pre = m.pre;
if (/\$$/.test(m.pre)) {
const post = m.post.length ? expand_(m.post, max, false) : [''];
for (let k = 0; k < post.length && k < max; k++) {
const expansion = pre + '{' + m.body + '}' + post[k];
expansions.push(expansion);
}
return expansions;
}
const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
const isSequence = isNumericSequence || isAlphaSequence;
const isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
isTop = true;
continue;
}
return [str];
}
// Only expand post once we know this brace set actually expands. Computing
// it before the early returns above expanded post a second time on every
// non-expanding `{}`, which is what made inputs like `a{},{},{}...` blow up
// exponentially.
const post = m.post.length ? expand_(m.post, max, false) : [''];
let n;
if (isSequence) {
n = m.body.split(/\.\./);
}
else {
n = parseCommaParts(m.body);
if (n.length === 1 && n[0] !== undefined) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand_(n[0], max, false).map(embrace);
//XXX is this necessary? Can't seem to hit it in tests.
/* c8 ignore start */
if (n.length === 1) {
return post.map(p => m.pre + n[0] + p);
}
/* c8 ignore stop */
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
let N;
if (isSequence && n[0] !== undefined && n[1] !== undefined) {
const x = numeric(n[0]);
const y = numeric(n[1]);
const width = Math.max(n[0].length, n[1].length);
let incr = n.length === 3 && n[2] !== undefined ?
Math.max(Math.abs(numeric(n[2])), 1)
: 1;
let test = lte;
const reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
const pad = n.some(isPadded);
N = [];
for (let i = x; test(i, y) && N.length < max; i += incr) {
let c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\') {
c = '';
}
}
else {
c = String(i);
if (pad) {
const need = width - c.length;
if (need > 0) {
const z = new Array(need + 1).join('0');
if (i < 0) {
c = '-' + z + c.slice(1);
}
else {
c = z + c;
}
}
}
}
N.push(c);
}
}
else {
N = [];
for (let j = 0; j < n.length; j++) {
N.push.apply(N, expand_(n[j], max, false));
}
}
for (let j = 0; j < N.length; j++) {
for (let k = 0; k < post.length && expansions.length < max; k++) {
const expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion) {
expansions.push(expansion);
}
}
}
return expansions;
}
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,3 @@
{
"type": "module"
}

View File

@@ -0,0 +1,64 @@
{
"name": "brace-expansion",
"description": "Brace expansion as known from sh/bash",
"version": "5.0.7",
"files": [
"dist"
],
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/commonjs/index.d.ts",
"default": "./dist/commonjs/index.js"
}
}
},
"type": "module",
"scripts": {
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"prepare": "tshy",
"pretest": "npm run prepare",
"presnap": "npm run prepare",
"test": "tap",
"snap": "tap",
"format": "prettier --write .",
"benchmark": "node benchmark/index.js",
"typedoc": "typedoc --tsconfig .tshy/esm.json ./src/*.ts"
},
"devDependencies": {
"@types/brace-expansion": "^1.1.2",
"@types/node": "^25.2.1",
"mkdirp": "^3.0.1",
"prettier": "^3.3.2",
"tap": "^21.6.2",
"tshy": "^3.0.2",
"typedoc": "^0.28.5"
},
"dependencies": {
"balanced-match": "^4.0.2"
},
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
},
"tshy": {
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
}
},
"main": "./dist/commonjs/index.js",
"types": "./dist/commonjs/index.d.ts",
"module": "./dist/esm/index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/juliangruber/brace-expansion.git"
}
}

21
.output/server/node_modules/diff/libesm/convert/dmp.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
/**
* converts a list of change objects to the format returned by Google's [diff-match-patch](https://github.com/google/diff-match-patch) library
*/
export function convertChangesToDMP(changes) {
const ret = [];
let change, operation;
for (let i = 0; i < changes.length; i++) {
change = changes[i];
if (change.added) {
operation = 1;
}
else if (change.removed) {
operation = -1;
}
else {
operation = 0;
}
ret.push([operation, change.value]);
}
return ret;
}

31
.output/server/node_modules/diff/libesm/convert/xml.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
/**
* converts a list of change objects to a serialized XML format
*/
export function convertChangesToXML(changes) {
const ret = [];
for (let i = 0; i < changes.length; i++) {
const change = changes[i];
if (change.added) {
ret.push('<ins>');
}
else if (change.removed) {
ret.push('<del>');
}
ret.push(escapeHTML(change.value));
if (change.added) {
ret.push('</ins>');
}
else if (change.removed) {
ret.push('</del>');
}
}
return ret.join('');
}
function escapeHTML(s) {
let n = s;
n = n.replace(/&/g, '&amp;');
n = n.replace(/</g, '&lt;');
n = n.replace(/>/g, '&gt;');
n = n.replace(/"/g, '&quot;');
return n;
}

16
.output/server/node_modules/diff/libesm/diff/array.js generated vendored Normal file
View File

@@ -0,0 +1,16 @@
import Diff from './base.js';
class ArrayDiff extends Diff {
tokenize(value) {
return value.slice();
}
join(value) {
return value;
}
removeEmpty(value) {
return value;
}
}
export const arrayDiff = new ArrayDiff();
export function diffArrays(oldArr, newArr, options) {
return arrayDiff.diff(oldArr, newArr, options);
}

253
.output/server/node_modules/diff/libesm/diff/base.js generated vendored Normal file
View File

@@ -0,0 +1,253 @@
export default class Diff {
diff(oldStr, newStr,
// Type below is not accurate/complete - see above for full possibilities - but it compiles
options = {}) {
let callback;
if (typeof options === 'function') {
callback = options;
options = {};
}
else if ('callback' in options) {
callback = options.callback;
}
// Allow subclasses to massage the input prior to running
const oldString = this.castInput(oldStr, options);
const newString = this.castInput(newStr, options);
const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
const newTokens = this.removeEmpty(this.tokenize(newString, options));
return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
}
diffWithOptionsObj(oldTokens, newTokens, options, callback) {
var _a;
const done = (value) => {
value = this.postProcess(value, options);
if (callback) {
setTimeout(function () { callback(value); }, 0);
return undefined;
}
else {
return value;
}
};
const newLen = newTokens.length, oldLen = oldTokens.length;
let editLength = 1;
let maxEditLength = newLen + oldLen;
if (options.maxEditLength != null) {
maxEditLength = Math.min(maxEditLength, options.maxEditLength);
}
const maxExecutionTime = (_a = options.timeout) !== null && _a !== void 0 ? _a : Infinity;
const abortAfterTimestamp = Date.now() + maxExecutionTime;
const bestPath = [{ oldPos: -1, lastComponent: undefined }];
// Seed editLength = 0, i.e. the content starts with the same values
let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
// Identity per the equality and tokenizer
return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
}
// Once we hit the right edge of the edit graph on some diagonal k, we can
// definitely reach the end of the edit graph in no more than k edits, so
// there's no point in considering any moves to diagonal k+1 any more (from
// which we're guaranteed to need at least k+1 more edits).
// Similarly, once we've reached the bottom of the edit graph, there's no
// point considering moves to lower diagonals.
// We record this fact by setting minDiagonalToConsider and
// maxDiagonalToConsider to some finite value once we've hit the edge of
// the edit graph.
// This optimization is not faithful to the original algorithm presented in
// Myers's paper, which instead pointlessly extends D-paths off the end of
// the edit graph - see page 7 of Myers's paper which notes this point
// explicitly and illustrates it with a diagram. This has major performance
// implications for some common scenarios. For instance, to compute a diff
// where the new text simply appends d characters on the end of the
// original text of length n, the true Myers algorithm will take O(n+d^2)
// time while this optimization needs only O(n+d) time.
let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
// Main worker method. checks all permutations of a given edit length for acceptance.
const execEditLength = () => {
for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
let basePath;
const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
if (removePath) {
// No one else is going to attempt to use this value, clear it
// @ts-expect-error - perf optimisation. This type-violating value will never be read.
bestPath[diagonalPath - 1] = undefined;
}
let canAdd = false;
if (addPath) {
// what newPos will be after we do an insertion:
const addPathNewPos = addPath.oldPos - diagonalPath;
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
}
const canRemove = removePath && removePath.oldPos + 1 < oldLen;
if (!canAdd && !canRemove) {
// If this path is a terminal then prune
// @ts-expect-error - perf optimisation. This type-violating value will never be read.
bestPath[diagonalPath] = undefined;
continue;
}
// Select the diagonal that we want to branch from. We select the prior
// path whose position in the old string is the farthest from the origin
// and does not pass the bounds of the diff graph
if (!canRemove || (canAdd && removePath.oldPos < addPath.oldPos)) {
basePath = this.addToPath(addPath, true, false, 0, options);
}
else {
basePath = this.addToPath(removePath, false, true, 1, options);
}
newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
// If we have hit the end of both strings, then we are done
return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
}
else {
bestPath[diagonalPath] = basePath;
if (basePath.oldPos + 1 >= oldLen) {
maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
}
if (newPos + 1 >= newLen) {
minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
}
}
}
editLength++;
};
// Performs the length of edit iteration. Is a bit fugly as this has to support the
// sync and async mode which is never fun. Loops over execEditLength until a value
// is produced, or until the edit length exceeds options.maxEditLength (if given),
// in which case it will return undefined.
if (callback) {
(function exec() {
setTimeout(function () {
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
return callback(undefined);
}
if (!execEditLength()) {
exec();
}
}, 0);
}());
}
else {
while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
const ret = execEditLength();
if (ret) {
return ret;
}
}
}
}
addToPath(path, added, removed, oldPosInc, options) {
const last = path.lastComponent;
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
return {
oldPos: path.oldPos + oldPosInc,
lastComponent: { count: last.count + 1, added: added, removed: removed, previousComponent: last.previousComponent }
};
}
else {
return {
oldPos: path.oldPos + oldPosInc,
lastComponent: { count: 1, added: added, removed: removed, previousComponent: last }
};
}
}
extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
const newLen = newTokens.length, oldLen = oldTokens.length;
let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
newPos++;
oldPos++;
commonCount++;
if (options.oneChangePerToken) {
basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
}
}
if (commonCount && !options.oneChangePerToken) {
basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
}
basePath.oldPos = oldPos;
return newPos;
}
equals(left, right, options) {
if (options.comparator) {
return options.comparator(left, right);
}
else {
return left === right
|| (!!options.ignoreCase && left.toLowerCase() === right.toLowerCase());
}
}
removeEmpty(array) {
const ret = [];
for (let i = 0; i < array.length; i++) {
if (array[i]) {
ret.push(array[i]);
}
}
return ret;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
castInput(value, options) {
return value;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
tokenize(value, options) {
return Array.from(value);
}
join(chars) {
// Assumes ValueT is string, which is the case for most subclasses.
// When it's false, e.g. in diffArrays, this method needs to be overridden (e.g. with a no-op)
// Yes, the casts are verbose and ugly, because this pattern - of having the base class SORT OF
// assume tokens and values are strings, but not completely - is weird and janky.
return chars.join('');
}
postProcess(changeObjects,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
options) {
return changeObjects;
}
get useLongestToken() {
return false;
}
buildValues(lastComponent, newTokens, oldTokens) {
// First we convert our linked list of components in reverse order to an
// array in the right order:
const components = [];
let nextComponent;
while (lastComponent) {
components.push(lastComponent);
nextComponent = lastComponent.previousComponent;
delete lastComponent.previousComponent;
lastComponent = nextComponent;
}
components.reverse();
const componentLen = components.length;
let componentPos = 0, newPos = 0, oldPos = 0;
for (; componentPos < componentLen; componentPos++) {
const component = components[componentPos];
if (!component.removed) {
if (!component.added && this.useLongestToken) {
let value = newTokens.slice(newPos, newPos + component.count);
value = value.map(function (value, i) {
const oldValue = oldTokens[oldPos + i];
return oldValue.length > value.length ? oldValue : value;
});
component.value = this.join(value);
}
else {
component.value = this.join(newTokens.slice(newPos, newPos + component.count));
}
newPos += component.count;
// Common case
if (!component.added) {
oldPos += component.count;
}
}
else {
component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
oldPos += component.count;
}
}
return components;
}
}

Some files were not shown because too many files have changed in this diff Show More