removing logs, moving parse function to bottom

This commit is contained in:
metacryst
2024-04-08 20:19:22 -05:00
parent c9ae021c6b
commit 95e90568db
4 changed files with 396 additions and 235 deletions

View File

@@ -39,10 +39,13 @@ window.testSuites.push( class testObservedObject {
} }
} }
// throw some sort of warning if a global OO is accessed without "this"
NotExtensible() { NotExtensible() {
return "not done" return "not done"
} }
// MustInitAllFields() { // MustInitAllFields() {
// class Form extends ObservedObject { // class Form extends ObservedObject {
// id // id

View File

@@ -1,152 +1,198 @@
window.testSuites.push( class testParse { window.testSuites.push( class testParse {
testParseConstructor() { testParseConstructor() {
class Space extends Shadow { class Space extends Shadow {
form form
contents = [] contents = []
constructor(...params) { constructor(...params) {
super(...params) super(...params)
}
} }
}
let newClass = window.Registry.parseConstructor(Space)
if(!newClass.prototype.constructor.toString().includes("window.Registry.construct(")) {
return "'window.Registry.construct(' not detected!"
}
}
testParseConstructorIfNoneProvided() {
class Space extends Shadow {
$form
}
let newClass = window.Registry.parseConstructor(Space)
if(!newClass.prototype.constructor.toString().includes("window.Registry.construct(")) {
return "'window.Registry.construct(' not detected!"
}
}
testParseConstructorFailsIfNoSuper() {
class Space extends Shadow {
form
contents = []
constructor() {
}
}
try {
let newClass = window.Registry.parseConstructor(Space) let newClass = window.Registry.parseConstructor(Space)
return "No error thrown!" if(!newClass.prototype.constructor.toString().includes("window.Registry.construct(")) {
} catch(e) { return "'window.Registry.construct(' not detected!"
}
}
testParseClassFieldsWithNoDefault() {
class Space extends Shadow {
form
contents = []
constructor(...params) {
super(...params)
} }
} }
const fields = window.Registry.parseClassFields(Space); testParseConstructorIfNoneProvided() {
if(!(JSON.stringify(fields) === JSON.stringify(["form", "contents"]))) { class Space extends Shadow {
return `Fields don't match` $form
} }
}
testParseClassFieldsWithEqualityCheck() { let newClass = window.Registry.parseConstructor(Space)
class Space extends Shadow { if(!newClass.prototype.constructor.toString().includes("window.Registry.construct(")) {
form = Forms.observe(window.location.pathname, this) return "'window.Registry.construct(' not detected!"
contents = [
...this.form.children.map(form => {
switch(form.type) {
case "file" === "file":
return File(form)
case "space":
return ChildSpace(form)
case "link":
return Link()
}
})
]
constructor(...params) {
super(...params)
} }
} }
const fields = window.Registry.parseClassFields(Space); testParseConstructorFailsIfNoSuper() {
if(!(JSON.stringify(fields) === JSON.stringify(["form", "contents"]))) { class Space extends Shadow {
return `Fields don't match` form
} contents = []
}
constructor() {
}
}
testParseClassFieldsWithInnerFunctionVariable() { try {
class Space extends Shadow { let newClass = window.Registry.parseConstructor(Space)
form = Forms.observe(window.location.pathname, this) return "No error thrown!"
} catch(e) {
contents = [
...this.form.children.map(form => { }
let file; }
file = "hey"
switch(form.type) { testParseClassFieldsWithNoDefault() {
case "file" === "file": class Space extends Shadow {
return File(form) form
case "space": contents = []
return ChildSpace(form)
case "link": constructor(...params) {
return Link() super(...params)
} }
}) }
]
const fields = window.Registry.parseClassFields(Space);
constructor(...params) { if(!(JSON.stringify(fields) === JSON.stringify(["form", "contents"]))) {
super(...params) return `Fields don't match`
} }
} }
const fields = window.Registry.parseClassFields(Space); testParseClassFieldsWithEqualityCheck() {
if(!(JSON.stringify(fields) === JSON.stringify(["form", "contents"]))) { class Space extends Shadow {
return `Fields don't match` form = Forms.observe(window.location.pathname, this)
}
} contents = [
...this.form.children.map(form => {
switch(form.type) {
case "file" === "file":
return File(form)
case "space":
return ChildSpace(form)
case "link":
return Link()
}
})
]
constructor(...params) {
super(...params)
}
}
ParseConstructorWithFunctionsBelow() { const fields = window.Registry.parseClassFields(Space);
class Space extends Shadow { if(!(JSON.stringify(fields) === JSON.stringify(["form", "contents"]))) {
$$form = Forms.observe(window.location.pathname, this) return `Fields don't match`
render = () => {
ForEach(this.form.children, (form) => {
switch(form.type) {
case "file":
File(form)
break
case "space":
ChildSpace(form)
break
case "link":
Link()
break
}
})
}
constructor() {
super()
}
connectedCallback() {
} }
} }
window.Registry.parseConstructor(Space) testParseClassFieldsWithInnerFunctionVariable() {
} class Space extends Shadow {
form = Forms.observe(window.location.pathname, this)
contents = [
...this.form.children.map(form => {
let file;
file = "hey"
switch(form.type) {
case "file" === "file":
return File(form)
case "space":
return ChildSpace(form)
case "link":
return Link()
}
})
]
constructor(...params) {
super(...params)
}
}
const fields = window.Registry.parseClassFields(Space);
if(!(JSON.stringify(fields) === JSON.stringify(["form", "contents"]))) {
return `Fields don't match`
}
}
ParseConstructorWithFunctionsBelow() {
class Space extends Shadow {
$$form = Forms.observe(window.location.pathname, this)
render = () => {
ForEach(this.form.children, (form) => {
switch(form.type) {
case "file":
File(form)
break
case "space":
ChildSpace(form)
break
case "link":
Link()
break
}
})
}
constructor() {
super()
}
connectedCallback() {
}
}
window.Registry.parseConstructor(Space)
}
ParseRender() {
class Sidebar extends Shadow {
$$windowState = windowState
$$form = Forms.observe(window.location.pathname)
$sidebarPos = -200
render = () => {
VStack(() => {
ForEach(this.form.children, (form) => {
switch(form.constructor.name) {
case "File":
SidebarFile(form)
break
case "Space":
SidebarSpace(form)
break
}
})
})
.background("black")
.positionType("absolute")
.x(this.windowState.sidebarOut ? 0 : -200)
.y(0)
.width(200, "px")
.height(100, "vh")
}
}
let result = Registry.parseRender(Sidebar)
console.log(result)
let expectedOutput = "[[VStack.ForEach, form.children], [VStack.x, windowState.sidebarOut]]"
if(JSON.stringify(result) !== JSON.stringify(expectedOutput)) {
return "Result does not match expected array!"
}
}
CopyTo() {
let str = "render=()=>{VStack(()=>{"
let ret = str.copyTo("{")
console.log(ret)
if(ret !== "render=()=>") return "Copy 1 failed!"
}
}) })

View File

@@ -2,9 +2,9 @@ console.log("Tests initializing.")
window.testSuites = []; window.testSuites = [];
await import ("./parse.test.js") await import ("./parse.test.js")
await import ("./init.test.js") // await import ("./init.test.js")
await import ("./render.test.js") // await import ("./render.test.js")
await import ("./observedobject.test.js") // await import ("./observedobject.test.js")
window.randomName = function randomName(prefix) { window.randomName = function randomName(prefix) {
const sanitizedPrefix = prefix.toLowerCase().replace(/[^a-z0-9]/g, ''); const sanitizedPrefix = prefix.toLowerCase().replace(/[^a-z0-9]/g, '');
@@ -75,13 +75,13 @@ window.test = async function() {
console.log("") console.log("")
let elapsed = new Date() - start; let elapsed = new Date() - start;
if(failed === 0) { if(failed === 0) {
console.log(`%cRan ${failed+success} tests in ${elapsed}ms`, 'background: #222; color: #00FF00'); console.log(`%cRan ${failed+success} tests in ${elapsed}ms`, 'color: #00FF00');
console.log(`%c ${success} passed`, 'background: #222; color: #00FF00'); console.log(`%c ${success} passed`, 'color: #00FF00');
console.log(`%c ${failed} failed`, 'background: #222;'); console.log(`%c ${failed} failed`);
} else { } else {
console.log(`%cRan ${failed+success} tests in ${elapsed}ms`, 'background: #222; color: rgb(254, 62, 43)'); console.log(`%cRan ${failed+success} tests in ${elapsed}ms`, 'color: rgb(254, 62, 43)');
console.log(`%c ${success} `, 'background: #222; color: #00FF00', "passed"); console.log(`%c ${success} `, 'color: #00FF00', "passed");
console.log(`%c ${failed} failed`, 'background: #222; color: rgb(254, 62, 43)'); console.log(`%c ${failed} failed`, 'color: rgb(254, 62, 43)');
} }
} }

302
index.js
View File

@@ -308,7 +308,7 @@ window.Registry = class Registry {
if(!objName) return; if(!objName) return;
let valueCheck = parent[objName][objField] let valueCheck = parent[objName][objField]
if(valueCheck && valueCheck === value) { if(valueCheck !== undefined && valueCheck === value) {
if(!parent[objName]._observers[objField].get(elem)) { if(!parent[objName]._observers[objField].get(elem)) {
parent[objName]._observers[objField].set(elem, []) parent[objName]._observers[objField].set(elem, [])
} }
@@ -380,14 +380,14 @@ window.Registry = class Registry {
Object.defineProperty(elem, name, { Object.defineProperty(elem, name, {
set: function(newValue) { set: function(newValue) {
elem[backingFieldName] = newValue; // Use the backing field to store the value elem[backingFieldName] = newValue;
elem.setAttribute(name, typeof newValue === "object" ? "{..}" : newValue); elem.setAttribute(name, typeof newValue === "object" ? "{..}" : newValue);
for (let [observer, properties] of elem._observers[name]) { for (let [element, properties] of elem._observers[name]) {
for (let property of properties) { for (let property of properties) {
if(Array.isArray(property)) { if(Array.isArray(property)) {
observer[property[0]][property[1]] = newValue; element[property[0]][property[1]] = newValue;
} else { } else {
observer[property] = newValue; element[property] = newValue;
} }
} }
} }
@@ -495,95 +495,6 @@ window.Registry = class Registry {
return elIncarnate return elIncarnate
} }
} }
static parseClassFields(classObject) {
let str = classObject.toString();
const lines = str.split('\n');
const fields = [];
let braceDepth = 0; // Tracks the depth of curly braces to identify when we're inside a function/method
for (let line of lines) {
const trimmedLine = line.trim();
// Update braceDepth based on the current line
braceDepth += (trimmedLine.match(/{/g) || []).length;
braceDepth -= (trimmedLine.match(/}/g) || []).length;
// Check if the line is outside any function/method (top-level within the class)
if (braceDepth === 1) {
// Attempt to match a class field declaration with or without initialization
const fieldMatch = trimmedLine.match(/^([a-zA-Z_$][0-9a-zA-Z_$]*)\s*(=|;|\n|$)/);
if (fieldMatch) {
fields.push(fieldMatch[1]);
}
}
// If we encounter the constructor, stop the parsing as we're only interested in fields above it
if (trimmedLine.startsWith('constructor')) {
break;
}
}
return fields;
}
static parseConstructor(classObject) {
let str = classObject.toString();
const lines = str.split('\n');
let modifiedLines = [];
let braceDepth = 0;
let constructorFound = false
let superCallFound = false;
let constructorEndFound = false;
for (let i = 0; i < lines.length; i++) {
let line = lines[i];
const trimmedLine = line.trim();
modifiedLines.push(line);
braceDepth += (trimmedLine.match(/{/g) || []).length;
braceDepth -= (trimmedLine.match(/}/g) || []).length;
if (trimmedLine.startsWith('constructor(')) {
constructorFound = true;
}
if (constructorFound && trimmedLine.startsWith('super(') && !superCallFound) {
superCallFound = true;
modifiedLines.push(` window.Registry.construct(this);`);
}
if (constructorFound && braceDepth === 1 && superCallFound && !constructorEndFound) {
modifiedLines.splice(modifiedLines.length - 1, 0, ' Object.preventExtensions(this);');
modifiedLines.splice(modifiedLines.length - 1, 0, ' window.Registry.testInitialized(this);');
constructorEndFound = true
}
}
if(superCallFound) {
let modifiedStr = modifiedLines.join('\n');
modifiedStr = '(' + modifiedStr + ')'
modifiedStr += `//# sourceURL=${classObject.prototype.constructor.name}.shadow`
return eval(modifiedStr);
}
if(constructorFound) {
throw new Error("Quill: Constructor must have super()! " + lines[0])
} else {
let constructorString = `
constructor(...params) {
super(...params)
window.Registry.construct(this)
Object.preventExtensions(this);
window.Registry.testInitialized(this);
}
`
let closingBracket = str.lastIndexOf("}");
str = str.slice(0, closingBracket - 1) + constructorString + "\n}"
return eval('(' + str + `) //# sourceURL=${classObject.prototype.constructor.name}.shadow`);
}
}
} }
/* DEFAULT WRAPPERS */ /* DEFAULT WRAPPERS */
@@ -843,5 +754,206 @@ HTMLElement.prototype.onHover = function(cb) {
return this return this
} }
/* PARSE */
Registry.parseClassFields = function(classObject) {
let str = classObject.toString();
const lines = str.split('\n');
const fields = [];
let braceDepth = 0; // Tracks the depth of curly braces to identify when we're inside a function/method
for (let line of lines) {
const trimmedLine = line.trim();
// Update braceDepth based on the current line
braceDepth += (trimmedLine.match(/{/g) || []).length;
braceDepth -= (trimmedLine.match(/}/g) || []).length;
// Check if the line is outside any function/method (top-level within the class)
if (braceDepth === 1) {
// Attempt to match a class field declaration with or without initialization
const fieldMatch = trimmedLine.match(/^([a-zA-Z_$][0-9a-zA-Z_$]*)\s*(=|;|\n|$)/);
if (fieldMatch) {
fields.push(fieldMatch[1]);
}
}
// If we encounter the constructor, stop the parsing as we're only interested in fields above it
if (trimmedLine.startsWith('constructor')) {
break;
}
}
return fields;
}
Registry.parseConstructor = function(classObject) {
let str = classObject.toString();
const lines = str.split('\n');
let modifiedLines = [];
let braceDepth = 0;
let constructorFound = false
let superCallFound = false;
let constructorEndFound = false;
for (let i = 0; i < lines.length; i++) {
let line = lines[i];
const trimmedLine = line.trim();
modifiedLines.push(line);
braceDepth += (trimmedLine.match(/{/g) || []).length;
braceDepth -= (trimmedLine.match(/}/g) || []).length;
if (trimmedLine.startsWith('constructor(')) {
constructorFound = true;
}
if (constructorFound && trimmedLine.startsWith('super(') && !superCallFound) {
superCallFound = true;
modifiedLines.push(` window.Registry.construct(this);`);
}
if (constructorFound && braceDepth === 1 && superCallFound && !constructorEndFound) {
modifiedLines.splice(modifiedLines.length - 1, 0, ' Object.preventExtensions(this);');
modifiedLines.splice(modifiedLines.length - 1, 0, ' window.Registry.testInitialized(this);');
constructorEndFound = true
}
}
if(superCallFound) {
let modifiedStr = modifiedLines.join('\n');
modifiedStr = '(' + modifiedStr + ')'
modifiedStr += `//# sourceURL=${classObject.prototype.constructor.name}.shadow`
return eval(modifiedStr);
}
if(constructorFound) {
throw new Error("Quill: Constructor must have super()! " + lines[0])
} else {
let constructorString = `
constructor(...params) {
super(...params)
window.Registry.construct(this)
Object.preventExtensions(this);
window.Registry.testInitialized(this);
}
`
let closingBracket = str.lastIndexOf("}");
str = str.slice(0, closingBracket - 1) + constructorString + "\n}"
return eval('(' + str + `) //# sourceURL=${classObject.prototype.constructor.name}.shadow`);
}
}
Registry.getRender = function(classObject) {
const classString = classObject.toString();
const regular = /render\s*\(\s*\)\s*\{/;
const arrow = /render\s*=\s*\(\s*\)\s*=>\s*\{/;
const matches = classString.match(regular) || classString.match(arrow);
if(matches && matches.length === 1) {
return classString.substring(matches.index)
} else {
console.error("Quill: render funcion not defined properly!")
}
}
Registry.parseRender = function(classObject) {
let str = Registry.getRender(classObject.toString()).replace(/\s/g, "");
console.log(str)
let functionStack = []
let i = str.indexOf("{");
let firstEl = str.copyTo("(", i)
if(!firstEl) {
console.log("Empty render function")
return
} else {
i += firstEl.length + 1
}
if(firstEl.includes("Stack")) {
parseArrowFunction(str, i)
}
return usage;
}
function parseArrowFunction(str, i) {
i += str.copyTo("{", i).length + 1
console.log(str[i])
let firstEl = str.copyTo("(", i)
console.log(firstEl)
}
function firstParam(str, i) {
console.log(str[i])
switch(str[i]) {
case "(":
console.log("function")
break;
case "\"":
console.log("string")
break;
default:
if (!isNaN(input)) {
console.log("Number");
} else {
console.log("Variable");
}
}
}
String.prototype.copyTo = function(char, i=0) {
let copied = ""
while(this[i]) {
if(this[i] === char) {
break;
}
copied += this[i]
i++
}
return copied
}
window.register = Registry.register window.register = Registry.register
window.rendering = [] window.rendering = []
// const usage = [];
// const lines = renderFunctionToClassEnd.split('\n');
// let currentFunction = null;
// let currentFunctionChain = []; // To keep track of nested function names
// for (const line of lines) {
// const functionMatch = line.match(/^\s*([a-zA-Z_$][0-9a-zA-Z_$]*)\s*=\s*\(\s*\)\s*=>\s*{/);
// if (functionMatch) {
// currentFunction = functionMatch[1];
// currentFunctionChain.push(currentFunction);
// }
// if (line.includes('this')) {
// if (currentFunction) {
// const thisUsage = line.match(/this\.[a-zA-Z_$][0-9a-zA-Z_$]*(?:\.[a-zA-Z_$][0-9a-zA-Z_$]*)*/g);
// if (thisUsage) {
// for (const usageItem of thisUsage) {
// const propertyChain = usageItem.replace('this.', '');
// const completeChain = [...currentFunctionChain, propertyChain];
// usage.push(completeChain);
// }
// }
// } else {
// const thisUsage = line.match(/this\.[a-zA-Z_$][0-9a-zA-Z_$]*/g);
// if (thisUsage) {
// for (const usageItem of thisUsage) {
// const propertyChain = usageItem.replace('this.', '');
// usage.push([propertyChain]);
// }
// }
// }
// }
// }