mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-13 22:46:06 +09:00
new filesystem impl wip
This commit is contained in:
@@ -65,20 +65,42 @@ Object.freeze(_TVDOS);
|
|||||||
_TVDOS.DRV.FS = {}
|
_TVDOS.DRV.FS = {}
|
||||||
|
|
||||||
class TVDOSFileDescriptor {
|
class TVDOSFileDescriptor {
|
||||||
constructor(path, driverString) {
|
|
||||||
path = path.replaceAll("\\", "/")
|
constructor(path0, driverID) {
|
||||||
|
let p = path0.replaceAll("/", "\\")
|
||||||
// oh well...
|
// oh well...
|
||||||
while (path.endsWith("/")) {
|
while (p.endsWith("\\")) {
|
||||||
path = path.substring(0, path.length - 1)
|
p = p.substring(0, p.length - 1)
|
||||||
}
|
}
|
||||||
this.path = path
|
serial.println(`TVDOSFileDescriptor input path: ${path0}, p = ${p}`)
|
||||||
this.driverString = driverString
|
this._driveLetter = p[0]
|
||||||
this.driver = _TVDOS.DRV.FS[driverString]
|
this._path = p.substring(2) // detaches A:
|
||||||
this.driveLetter = path[0]
|
this._driverID = driverID
|
||||||
|
this._driver = _TVDOS.DRV.FS[driverID]
|
||||||
}
|
}
|
||||||
|
|
||||||
get size() {
|
get size() {
|
||||||
return this.driver.getFileLen()
|
return this.driver.getFileLen(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
get path() {
|
||||||
|
return this._path
|
||||||
|
}
|
||||||
|
|
||||||
|
get driverID() {
|
||||||
|
return this._driverID
|
||||||
|
}
|
||||||
|
|
||||||
|
get driver() {
|
||||||
|
return this._driver
|
||||||
|
}
|
||||||
|
|
||||||
|
get driveLetter() {
|
||||||
|
return this._driveLetter
|
||||||
|
}
|
||||||
|
|
||||||
|
get fullPath() {
|
||||||
|
return `${this._driveLetter}:${this._path}`
|
||||||
}
|
}
|
||||||
|
|
||||||
/** reads the file bytewise and puts it to the specified memory address
|
/** reads the file bytewise and puts it to the specified memory address
|
||||||
@@ -125,11 +147,16 @@ class TVDOSFileDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get name() {
|
get name() {
|
||||||
return this.split("/").last()
|
return this.path.split("\\").last()
|
||||||
|
}
|
||||||
|
get parentPath() {
|
||||||
|
// return this.path.split("\\").init().join("\\")
|
||||||
|
let li = this.path.lastIndexOf("\\")
|
||||||
|
return this.path.substring(0, li)
|
||||||
}
|
}
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
if (!this.isDirectory()) throw Error(`File is not a directory: ${this.path}`)
|
if (!this.isDirectory) throw Error(`File is not a directory: ${this.path}`)
|
||||||
return this.driver.listFiles(this)
|
return this.driver.listFiles(this)
|
||||||
}
|
}
|
||||||
/** When the file does not exist, mkfile() will be called; if you want to make a directory, use mkdir() */
|
/** When the file does not exist, mkfile() will be called; if you want to make a directory, use mkdir() */
|
||||||
@@ -153,6 +180,8 @@ class TVDOSFileDescriptor {
|
|||||||
|
|
||||||
|
|
||||||
_TVDOS.DRV.FS.SERIAL = {}
|
_TVDOS.DRV.FS.SERIAL = {}
|
||||||
|
_TVDOS.DRV.FS.ROMFS = {}
|
||||||
|
_TVDOS.DRV.FS.DEVFS = {} // \dev\null zero full random lp fb0..fb3 mem pmem0..pmem7 com1..com4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -166,6 +195,27 @@ _TVDOS.DRV.FS.SERIAL._toPorts = (driveLetter) => {
|
|||||||
}
|
}
|
||||||
return port
|
return port
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_TVDOS.DRV.FS.SERIAL._openr = (fd) => {
|
||||||
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
|
_TVDOS.DRV.FS.SERIAL._flush(port[0]);_TVDOS.DRV.FS.SERIAL._close(port[0])
|
||||||
|
com.sendMessage(port[0], "OPENR"+'"'+fd.path+'",'+port[1])
|
||||||
|
return com.getStatusCode(port[0])
|
||||||
|
}
|
||||||
|
_TVDOS.DRV.FS.SERIAL._openw = (fd) => {
|
||||||
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
|
_TVDOS.DRV.FS.SERIAL._flush(port[0]);_TVDOS.DRV.FS.SERIAL._close(port[0])
|
||||||
|
com.sendMessage(port[0], "OPENW"+'"'+fd.path+'",'+port[1])
|
||||||
|
return com.getStatusCode(port[0])
|
||||||
|
}
|
||||||
|
_TVDOS.DRV.FS.SERIAL._opena = (fd) => {
|
||||||
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
|
_TVDOS.DRV.FS.SERIAL._flush(port[0]);_TVDOS.DRV.FS.SERIAL._close(port[0])
|
||||||
|
com.sendMessage(port[0], "OPENA"+'"'+fd.path+'",'+port[1])
|
||||||
|
return com.getStatusCode(port[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_TVDOS.DRV.FS.SERIAL._close = (portNo) => {
|
_TVDOS.DRV.FS.SERIAL._close = (portNo) => {
|
||||||
com.sendMessage(portNo, "CLOSE")
|
com.sendMessage(portNo, "CLOSE")
|
||||||
}
|
}
|
||||||
@@ -181,8 +231,10 @@ _TVDOS.DRV.FS.SERIAL.flush = (fd) => {
|
|||||||
com.sendMessage(portNo, "FLUSH")
|
com.sendMessage(portNo, "FLUSH")
|
||||||
}
|
}
|
||||||
|
|
||||||
_TVDOS.DRV.FS.SERIAL.getFileLen = (driveLetter) => {
|
_TVDOS.DRV.FS.SERIAL.getFileLen = (fd) => {
|
||||||
let port = _TVDOS.DRV.FS.SERIAL._toPorts(driveLetter)
|
if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.path}`)
|
||||||
|
|
||||||
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
com.sendMessage(port[0], "GETLEN")
|
com.sendMessage(port[0], "GETLEN")
|
||||||
var response = com.getStatusCode(port[0])
|
var response = com.getStatusCode(port[0])
|
||||||
if (135 == response) {
|
if (135 == response) {
|
||||||
@@ -196,6 +248,8 @@ _TVDOS.DRV.FS.SERIAL.getFileLen = (driveLetter) => {
|
|||||||
// TODO pread replaces DMA.comToRam
|
// TODO pread replaces DMA.comToRam
|
||||||
// TODO pwrite replaces DMA.ramToCom
|
// TODO pwrite replaces DMA.ramToCom
|
||||||
_TVDOS.DRV.FS.SERIAL.sread = (fd) => {
|
_TVDOS.DRV.FS.SERIAL.sread = (fd) => {
|
||||||
|
if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.path}`)
|
||||||
|
|
||||||
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
com.sendMessage(port[0], "READ")
|
com.sendMessage(port[0], "READ")
|
||||||
let response = com.getStatusCode(port[0])
|
let response = com.getStatusCode(port[0])
|
||||||
@@ -208,6 +262,8 @@ _TVDOS.DRV.FS.SERIAL.sread = (fd) => {
|
|||||||
return com.pullMessage(port[0])
|
return com.pullMessage(port[0])
|
||||||
}
|
}
|
||||||
_TVDOS.DRV.FS.SERIAL.swrite = (fd, str) => {
|
_TVDOS.DRV.FS.SERIAL.swrite = (fd, str) => {
|
||||||
|
let rrrr = _TVDOS.DRV.FS.SERIAL._openw(fd); if (rrrr != 0) throw Error("Writing a file failed with "+rrrr)
|
||||||
|
|
||||||
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
com.sendMessage(port[0], "WRITE"+string.length)
|
com.sendMessage(port[0], "WRITE"+string.length)
|
||||||
let response = com.getStatusCode(port[0])
|
let response = com.getStatusCode(port[0])
|
||||||
@@ -221,7 +277,7 @@ _TVDOS.DRV.FS.SERIAL.swrite = (fd, str) => {
|
|||||||
_TVDOS.DRV.FS.SERIAL._flush(port[0]);_TVDOS.DRV.FS.SERIAL._close(port[0])
|
_TVDOS.DRV.FS.SERIAL._flush(port[0]);_TVDOS.DRV.FS.SERIAL._close(port[0])
|
||||||
}
|
}
|
||||||
_TVDOS.DRV.FS.SERIAL.bread = (fd) => {
|
_TVDOS.DRV.FS.SERIAL.bread = (fd) => {
|
||||||
let str = _TVDOS.DRV.FS.SERIAL.readAll(fd.driveLetter)
|
let str = _TVDOS.DRV.FS.SERIAL.sread(fd.driveLetter)
|
||||||
let bytes = new Uint8Array(str.length)
|
let bytes = new Uint8Array(str.length)
|
||||||
for (let i = 0; i < str.length; i++) {
|
for (let i = 0; i < str.length; i++) {
|
||||||
bytes[i] = str.charCodeAt(i)
|
bytes[i] = str.charCodeAt(i)
|
||||||
@@ -233,21 +289,41 @@ _TVDOS.DRV.FS.SERIAL.bwrite = (fd, bytes) => { // pwrite replaces DMA.ramToCom
|
|||||||
_TVDOS.DRV.FS.SERIAL.swrite(fd, string)
|
_TVDOS.DRV.FS.SERIAL.swrite(fd, string)
|
||||||
}
|
}
|
||||||
_TVDOS.DRV.FS.SERIAL.isDirectory = (fd) => {
|
_TVDOS.DRV.FS.SERIAL.isDirectory = (fd) => {
|
||||||
|
if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.path}`)
|
||||||
|
|
||||||
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
com.sendMessage(port[0], "LISTFILES")
|
com.sendMessage(port[0], "LISTFILES")
|
||||||
let response = com.getStatusCode(port[0])
|
let response = com.getStatusCode(port[0])
|
||||||
return (response === 0)
|
return (response === 0)
|
||||||
}
|
}
|
||||||
_TVDOS.DRV.FS.SERIAL.listFiles = (fd) => {
|
_TVDOS.DRV.FS.SERIAL.listFiles = (fd) => {
|
||||||
TODO()
|
if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.path}`)
|
||||||
|
|
||||||
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
|
com.sendMessage(port[0], "LISTFILES")
|
||||||
|
let response = com.getStatusCode(port[0])
|
||||||
|
if (response !== 0) return undefined
|
||||||
|
let rawStr = com.pullMessage(port[0]) // {\x11 | \x12} <name> [ \x1E {\x11 | \x12} <name> ] \x17
|
||||||
|
let fdsInDir = []
|
||||||
|
let parentPath = fd.fullPath
|
||||||
|
rawStr.substring(0, rawStr.length).split('\x1E').forEach(it => {
|
||||||
|
let filename = it.substring(1)
|
||||||
|
let newfd = new TVDOSFileDescriptor(`${parentPath}/${filename}`, "SERIAL")
|
||||||
|
fdsInDir.push(newfd)
|
||||||
|
})
|
||||||
|
return fdsInDir
|
||||||
}
|
}
|
||||||
_TVDOS.DRV.FS.SERIAL.touch = (fd) => {
|
_TVDOS.DRV.FS.SERIAL.touch = (fd) => {
|
||||||
|
let rrrr = _TVDOS.DRV.FS.SERIAL._openw(fd); if (rrrr != 0) throw Error("Touching a file failed with "+rrrr)
|
||||||
|
|
||||||
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
com.sendMessage(port[0], "TOUCH")
|
com.sendMessage(port[0], "TOUCH")
|
||||||
let response = com.getStatusCode(port[0])
|
let response = com.getStatusCode(port[0])
|
||||||
return (response === 0)
|
return (response === 0)
|
||||||
}
|
}
|
||||||
_TVDOS.DRV.FS.SERIAL.mkDir = (fd) => {
|
_TVDOS.DRV.FS.SERIAL.mkDir = (fd) => {
|
||||||
|
let rrrr = _TVDOS.DRV.FS.SERIAL._openw(fd); if (rrrr != 0) throw Error("Mkdir a file failed with "+rrrr)
|
||||||
|
|
||||||
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
com.sendMessage(port[0], "MKDIR")
|
com.sendMessage(port[0], "MKDIR")
|
||||||
let response = com.getStatusCode(port[0])
|
let response = com.getStatusCode(port[0])
|
||||||
@@ -259,12 +335,16 @@ _TVDOS.DRV.FS.SERIAL.mkDir = (fd) => {
|
|||||||
return (response === 0) // possible status codes: 0 (success), 1 (fail)
|
return (response === 0) // possible status codes: 0 (success), 1 (fail)
|
||||||
}
|
}
|
||||||
_TVDOS.DRV.FS.SERIAL.mkFile = (fd) => {
|
_TVDOS.DRV.FS.SERIAL.mkFile = (fd) => {
|
||||||
|
let rrrr = _TVDOS.DRV.FS.SERIAL._openw(fd); if (rrrr != 0) throw Error("Mkfile failed with "+rrrr)
|
||||||
|
|
||||||
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
com.sendMessage(port[0], "MKFILE")
|
com.sendMessage(port[0], "MKFILE")
|
||||||
let response = com.getStatusCode(port[0])
|
let response = com.getStatusCode(port[0])
|
||||||
return (response === 0)
|
return (response === 0)
|
||||||
}
|
}
|
||||||
_TVDOS.DRV.FS.SERIAL.delete = (fd) => {
|
_TVDOS.DRV.FS.SERIAL.delete = (fd) => {
|
||||||
|
let rrrr = _TVDOS.DRV.FS.SERIAL._openw(fd); if (rrrr != 0) throw Error("Writing a file failed with "+rrrr)
|
||||||
|
|
||||||
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter)
|
||||||
com.sendMessage(port[0], "DELETE")
|
com.sendMessage(port[0], "DELETE")
|
||||||
let response = com.getStatusCode(port[0])
|
let response = com.getStatusCode(port[0])
|
||||||
@@ -272,6 +352,8 @@ _TVDOS.DRV.FS.SERIAL.delete = (fd) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object.freeze(_TVDOS.DRV.FS.SERIAL)
|
Object.freeze(_TVDOS.DRV.FS.SERIAL)
|
||||||
|
Object.freeze(_TVDOS.DRV.FS.ROMFS)
|
||||||
|
Object.freeze(_TVDOS.DRV.FS.DEVFS)
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -404,7 +486,7 @@ const files = {}
|
|||||||
|
|
||||||
/** This function only creates a file descriptor; will not actually interact with the drives yet. */
|
/** This function only creates a file descriptor; will not actually interact with the drives yet. */
|
||||||
files.open = (fullpath) => {
|
files.open = (fullpath) => {
|
||||||
if (fullpath[1] != '/' && fullpath[1] != '\\') throw Error("Expected full path with drive letter")
|
if (fullpath[2] != '/' && fullpath[2] != '\\') throw Error("Expected full path with drive letter")
|
||||||
let driveLetter = fullpath[0].toUpperCase()
|
let driveLetter = fullpath[0].toUpperCase()
|
||||||
let driver = _TVDOS.DRIVEFS[driveLetter]
|
let driver = _TVDOS.DRIVEFS[driveLetter]
|
||||||
return new TVDOSFileDescriptor(fullpath, driver)
|
return new TVDOSFileDescriptor(fullpath, driver)
|
||||||
@@ -629,12 +711,13 @@ let injectIntChk = (s, n) => {
|
|||||||
// @param args arguments for the program, must be Array, and args[0] is always the name of the program, e.g.
|
// @param args arguments for the program, must be Array, and args[0] is always the name of the program, e.g.
|
||||||
// for command line 'echo foo bar', args[0] must be 'echo'
|
// for command line 'echo foo bar', args[0] must be 'echo'
|
||||||
// @return status returned by the program
|
// @return status returned by the program
|
||||||
var execApp = (cmdsrc, args) => {
|
var execApp = (cmdsrc, args, appname) => {
|
||||||
|
appname = (appname) ? `_${appname}` : "_appStub"
|
||||||
var intchkFunName = `tvdosSIGTERM_${generateRandomHashStr(16)}`;
|
var intchkFunName = `tvdosSIGTERM_${generateRandomHashStr(16)}`;
|
||||||
var execAppPrg = eval(
|
var execAppPrg = eval(
|
||||||
`var ${intchkFunName} = function(){ ${checkTerm} };` +
|
`var ${intchkFunName} = function(){ ${checkTerm} };` +
|
||||||
`var _appStub=function(exec_args){${injectIntChk(cmdsrc, intchkFunName)}\n};` +
|
`var ${appname}=function(exec_args){${injectIntChk(cmdsrc, intchkFunName)}\n};` +
|
||||||
`_appStub`); // making 'exec_args' a app-level global
|
`${appname}`); // making 'exec_args' a app-level global
|
||||||
|
|
||||||
execAppPrg(args);
|
execAppPrg(args);
|
||||||
}
|
}
|
||||||
@@ -645,5 +728,5 @@ var execApp = (cmdsrc, args) => {
|
|||||||
serial.println("TVDOS.SYS initialised, running boot script...");
|
serial.println("TVDOS.SYS initialised, running boot script...");
|
||||||
var _G = {};
|
var _G = {};
|
||||||
filesystem.open("A", "tvdos/bin/command.js", "R");
|
filesystem.open("A", "tvdos/bin/command.js", "R");
|
||||||
eval(`var _appStub=function(exec_args){${filesystem.readAll("A")}\n};` +
|
eval(`var _AUTOEXEC=function(exec_args){${filesystem.readAll("A")}\n};` +
|
||||||
`_appStub`)(["", "/c", "\\AUTOEXEC.BAT"])
|
`_AUTOEXEC`)(["", "/c", "\\AUTOEXEC.BAT"])
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function print_prompt_text() {
|
|||||||
con.color_pair(161,253);
|
con.color_pair(161,253);
|
||||||
con.addch(16);con.curs_right();
|
con.addch(16);con.curs_right();
|
||||||
con.color_pair(0,253);
|
con.color_pair(0,253);
|
||||||
print(" /"+shell_pwd.join("/").substring(1)+" ");
|
print(" \\"+shell_pwd.join("\\").substring(1)+" ");
|
||||||
if (errorlevel != 0) {
|
if (errorlevel != 0) {
|
||||||
con.color_pair(166,253);
|
con.color_pair(166,253);
|
||||||
print("["+errorlevel+"] ");
|
print("["+errorlevel+"] ");
|
||||||
@@ -44,9 +44,9 @@ function print_prompt_text() {
|
|||||||
else {
|
else {
|
||||||
// con.color_pair(253,255);
|
// con.color_pair(253,255);
|
||||||
if (errorlevel != 0)
|
if (errorlevel != 0)
|
||||||
print(CURRENT_DRIVE + ":/" + shell_pwd.join("/") + " [" + errorlevel + "]" + PROMPT_TEXT);
|
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + " [" + errorlevel + "]" + PROMPT_TEXT);
|
||||||
else
|
else
|
||||||
print(CURRENT_DRIVE + ":/" + shell_pwd.join("/") + PROMPT_TEXT);
|
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,17 +541,19 @@ shell.execute = function(line) {
|
|||||||
else
|
else
|
||||||
pathExt.push(""); // final empty extension
|
pathExt.push(""); // final empty extension
|
||||||
|
|
||||||
|
var searchPath = ""
|
||||||
|
|
||||||
searchLoop:
|
searchLoop:
|
||||||
for (var i = 0; i < searchDir.length; i++) {
|
for (var i = 0; i < searchDir.length; i++) {
|
||||||
for (var j = 0; j < pathExt.length; j++) {
|
for (var j = 0; j < pathExt.length; j++) {
|
||||||
var search = searchDir[i]; if (!search.endsWith('\\')) search += '\\';
|
var search = searchDir[i]; if (!search.endsWith('\\')) search += '\\';
|
||||||
var path = trimStartRevSlash(search + cmd + pathExt[j]);
|
searchPath = trimStartRevSlash(search + cmd + pathExt[j]);
|
||||||
|
|
||||||
if (DEBUG_PRINT) {
|
if (DEBUG_PRINT) {
|
||||||
serial.println("[command.js > shell.execute] file search path: "+path);
|
serial.println("[command.js > shell.execute] file search path: "+searchPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == filesystem.open(CURRENT_DRIVE, path, "R")) {
|
if (0 == filesystem.open(CURRENT_DRIVE, searchPath, "R")) {
|
||||||
fileExists = true;
|
fileExists = true;
|
||||||
break searchLoop;
|
break searchLoop;
|
||||||
}
|
}
|
||||||
@@ -588,7 +590,7 @@ shell.execute = function(line) {
|
|||||||
sendLcdMsg(_G.shellProgramTitles[_G.shellProgramTitles.length - 1]);
|
sendLcdMsg(_G.shellProgramTitles[_G.shellProgramTitles.length - 1]);
|
||||||
//serial.println(_G.shellProgramTitles);
|
//serial.println(_G.shellProgramTitles);
|
||||||
|
|
||||||
errorlevel = execApp(programCode, tokens); // return value of undefined will cast into 0
|
errorlevel = execApp(programCode, tokens, `tvdosExec$${cmd}$` + searchPath.replaceAll(/[^A-Za-z0-9_]/g, "$")); // return value of undefined will cast into 0
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
gotError = true;
|
gotError = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user