Merge remote-tracking branch 'pmp-p/patch-8' into pmpp_test
This commit is contained in:
commit
4a1d1cbd81
@ -48,6 +48,15 @@ CFLAGS += $(OPTIM) -DNDEBUG -D__EMSCRIPTEN__ -DLV_CONF_INCLUDE_SIMPLE
|
||||
CFLAGS += -fdata-sections -ffunction-sections
|
||||
CFLAGS += $(CFLAGS_MOD)
|
||||
|
||||
ifdef FROZEN_MPY_DIR
|
||||
CFLAGS += -DFROZEN_MPY_DIR=$(FROZEN_MPY_DIR)
|
||||
|
||||
# //for qstr.c
|
||||
CFLAGS +=-DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
|
||||
|
||||
# //for build/genhdr/qstr.i.last
|
||||
QSTR_GEN_EXTRA_CFLAGS=-DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
|
||||
endif
|
||||
|
||||
SRC_LIB = $(addprefix lib/,\
|
||||
utils/interrupt_char.c \
|
||||
|
||||
165
ports/javascript/docs/wasm_file_api.js
Normal file
165
ports/javascript/docs/wasm_file_api.js
Normal file
@ -0,0 +1,165 @@
|
||||
// ============================== FILE I/O (sync => bad) =================================
|
||||
window.urls = {"name":"webcache","id":-1, "index": "/index.html"}
|
||||
|
||||
|
||||
function awfull_get(url) {
|
||||
function updateProgress (oEvent) {
|
||||
if (oEvent.lengthComputable) {
|
||||
var percentComplete = oEvent.loaded / oEvent.total;
|
||||
} else {
|
||||
// Unable to compute progress information since the total size is unknown
|
||||
// on binary XHR
|
||||
}
|
||||
}
|
||||
|
||||
function transferFailed(evt) {
|
||||
console.log("callfs: An error occurred while transferring the file '"+window.currentTransfer+"'");
|
||||
}
|
||||
|
||||
function transferCanceled(evt) {
|
||||
console.log("callfs: transfer '"+window.currentTransfer+"' has been canceled by the user.");
|
||||
}
|
||||
|
||||
var oReq = new XMLHttpRequest();
|
||||
|
||||
function transferComplete(evt) {
|
||||
if (oReq.status==404){
|
||||
console.log("callfs: File not found : "+ url );
|
||||
window.currentTransferSize = -1 ;
|
||||
|
||||
} else {
|
||||
window.currentTransferSize = oReq.response.length;
|
||||
console.log("callfs: Transfer is complete saving : "+window.currentTransferSize);
|
||||
}
|
||||
}
|
||||
|
||||
oReq.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
oReq.addEventListener("progress", updateProgress);
|
||||
oReq.addEventListener("load", transferComplete);
|
||||
oReq.addEventListener("error", transferFailed);
|
||||
oReq.addEventListener("abort", transferCanceled);
|
||||
oReq.open("GET",url ,false);
|
||||
oReq.send();
|
||||
return oReq.response
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function wasm_file_open(url, cachefile){
|
||||
var dirpath = ""
|
||||
if ( url == cachefile ) {
|
||||
//we need to build the target path, it could be a module import.
|
||||
|
||||
//transform to relative path to /
|
||||
while (cachefile.startswith("/"))
|
||||
cachefile = cachefile.substring(1)
|
||||
|
||||
while (url.startswith("/"))
|
||||
url = url.substring(1)
|
||||
|
||||
// is it still a path with at least a one char folder ?
|
||||
if (cachefile.indexOf('/')>0) {
|
||||
var path = cachefile.split('/')
|
||||
|
||||
// last elem is the filename
|
||||
while (path.length>1) {
|
||||
var current_folder = path.shift()
|
||||
try {
|
||||
FS.createFolder(dirpath, current_folder, true, true)
|
||||
//FS.createPath('/', dirname, true, true)
|
||||
} catch (err) {
|
||||
if (err.code !== 'EEXIST') throw err
|
||||
}
|
||||
dirpath = dirpath + "/" + current_folder
|
||||
}
|
||||
console.log("+dir: "+dirpath+" +file: " + path.shift())
|
||||
} else {
|
||||
// this is a root folder, abort
|
||||
if (url.indexOf(".") <1 )
|
||||
return -1
|
||||
}
|
||||
cachefile = "/" + url
|
||||
console.log("in / +" + cachefile)
|
||||
}
|
||||
|
||||
try {
|
||||
if (url[0]==":")
|
||||
url = url.substr(1)
|
||||
else {
|
||||
// [TODO:do some tests there for your CORS integration]
|
||||
if (window.urls.cors)
|
||||
url = window.urls.cors(url)
|
||||
}
|
||||
|
||||
var ab = awfull_get(url)
|
||||
var ret = ab.length
|
||||
|
||||
window.urls.id += 1
|
||||
if (!cachefile){
|
||||
cachefile = "cache_"+window.urls.id
|
||||
ret = window.urls.id
|
||||
}
|
||||
FS.createDataFile("/", cachefile, ab, true, true);
|
||||
return ret
|
||||
} catch (x) {
|
||||
console.log("wasm_file_open :"+x)
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function wasm_file_exists(url, need_dot) {
|
||||
// need_dot reminds we can't check for directory on webserver
|
||||
// but we can check for a know file (probaby with a dot) under it
|
||||
// -1 not found , 1 is a file on server , 2 is a directory
|
||||
|
||||
function url_exists(url,code) {
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.open('HEAD', url, false)
|
||||
xhr.send()
|
||||
if (xhr.status == 200 )
|
||||
return code
|
||||
return -1
|
||||
}
|
||||
|
||||
// we know those are all MEMFS local files.
|
||||
// and yes it's the same folder name as in another OS apps
|
||||
if (url.startswith('assets/'))
|
||||
return -1
|
||||
|
||||
if (url.endswith('.mpy'))
|
||||
return -1
|
||||
|
||||
// are we possibly doing folder checking ?
|
||||
if (need_dot) {
|
||||
// .mpy is blacklisted for now
|
||||
// so if it's not .py then it's a folder check.
|
||||
if (!url.endswith('.py')) {
|
||||
var found = -1
|
||||
|
||||
// package search
|
||||
found = url_exists( url + '/__init__.py' , 2 )
|
||||
//console.log("wasm_([dir]/file)_exists ? :"+url+ ' --> ' + '/__init__.py => '+found)
|
||||
if (found>0) return found
|
||||
|
||||
//namespace search
|
||||
found = url_exists( url + window.urls.index , 2 )
|
||||
//console.log("wasm_([dir]/file)_exists ? :"+url+ ' --> ' + window.urls.index + " => "+found)
|
||||
if (found>0) return found
|
||||
}
|
||||
|
||||
// if name has no dot then it was a folder check
|
||||
//console.log("wasm_(dir/[file])_exists ? :"+url)
|
||||
need_dot = url.split('.').pop()
|
||||
if (need_dot==url) {
|
||||
console.log("wasm_file_exists not-a-file :"+url)
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
// default is a file search
|
||||
return url_exists(url, 1)
|
||||
}
|
||||
|
||||
@ -30,169 +30,8 @@ given some restrictions.
|
||||
|
||||
|
||||
|
||||
|
||||
You will need to provide two functions in your js loader.
|
||||
These are provided as examples and only cover some usefull cases.
|
||||
|
||||
window.urls = {}
|
||||
window.urls.index = 0
|
||||
|
||||
|
||||
function awfull_get(url) {
|
||||
function updateProgress (oEvent) {
|
||||
if (oEvent.lengthComputable) {
|
||||
var percentComplete = oEvent.loaded / oEvent.total;
|
||||
} else {
|
||||
// Unable to compute progress information since the total size is unknown
|
||||
// on binary XHR
|
||||
}
|
||||
}
|
||||
|
||||
function transferFailed(evt) {
|
||||
console.log("callfs: An error occurred while transferring the file '"+window.currentTransfer+"'");
|
||||
}
|
||||
|
||||
function transferCanceled(evt) {
|
||||
console.log("callfs: transfer '"+window.currentTransfer+"' has been canceled by the user.");
|
||||
}
|
||||
|
||||
var oReq = new XMLHttpRequest();
|
||||
|
||||
function transferComplete(evt) {
|
||||
if (oReq.status==404){
|
||||
console.log("callfs: File not found : "+ url );
|
||||
window.currentTransferSize = -1 ;
|
||||
|
||||
} else {
|
||||
window.currentTransferSize = oReq.response.length;
|
||||
console.log("callfs: Transfer is complete saving : "+window.currentTransferSize);
|
||||
}
|
||||
}
|
||||
|
||||
oReq.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
oReq.addEventListener("progress", updateProgress);
|
||||
oReq.addEventListener("load", transferComplete);
|
||||
oReq.addEventListener("error", transferFailed);
|
||||
oReq.addEventListener("abort", transferCanceled);
|
||||
oReq.open("GET",url ,false);
|
||||
oReq.send();
|
||||
return oReq.response
|
||||
}
|
||||
|
||||
|
||||
|
||||
function wasm_file_open(url, cachefile){
|
||||
var dirpath = ""
|
||||
if ( url == cachefile ) {
|
||||
//we need to build the target path, it could be a module import.
|
||||
|
||||
//transform to relative path to /
|
||||
while (cachefile.startswith("/"))
|
||||
cachefile = cachefile.substring(1)
|
||||
|
||||
while (url.startswith("/"))
|
||||
url = url.substring(1)
|
||||
|
||||
// is it still a path with at least a one char folder ?
|
||||
if (cachefile.indexOf('/')>0) {
|
||||
var path = cachefile.split('/')
|
||||
|
||||
// last elem is the filename
|
||||
while (path.length>1) {
|
||||
var current_folder = path.shift()
|
||||
try {
|
||||
FS.createFolder(dirpath, current_folder, true, true)
|
||||
//FS.createPath('/', dirname, true, true)
|
||||
} catch (err) {
|
||||
if (err.code !== 'EEXIST') throw err
|
||||
}
|
||||
dirpath = dirpath + "/" + current_folder
|
||||
}
|
||||
console.log("+dir: "+dirpath+" +file: " + path.shift())
|
||||
} else {
|
||||
// this is a root folder, abort
|
||||
if (url.indexOf(".") <1 )
|
||||
return -1
|
||||
}
|
||||
cachefile = "/" + url
|
||||
console.log("in / +" + cachefile)
|
||||
}
|
||||
|
||||
try {
|
||||
if (url[0]==":")
|
||||
url = url.substr(1)
|
||||
else {
|
||||
// [TODO:do some tests there for your CORS integration]
|
||||
}
|
||||
|
||||
var ab = awfull_get(url)
|
||||
var ret = ab.length
|
||||
|
||||
window.urls.index += 1
|
||||
if (!cachefile){
|
||||
cachefile = "cache_"+window.urls.index
|
||||
ret = window.urls.index
|
||||
}
|
||||
FS.createDataFile("/", cachefile, ab, true, true);
|
||||
return ret
|
||||
} catch (x) {
|
||||
console.log("wasm_file_open :"+x)
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
window.USE_DIR_INDEX = "/index.html"
|
||||
|
||||
function wasm_file_exists(url, need_dot) {
|
||||
// need_dot reminds we can't check for directory on webserver
|
||||
// but we can check for a know file (probaby with a dot) under it
|
||||
// -1 not found , 1 is a file on server , 2 is a directory
|
||||
|
||||
function url_exists(url,code) {
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.open('HEAD', url, false)
|
||||
xhr.send()
|
||||
if (xhr.status == 200 )
|
||||
return code
|
||||
return -1
|
||||
}
|
||||
|
||||
// we know those are all MEMFS local files.
|
||||
// and yes it's the same folder name as in another OS apps
|
||||
if (url.startswith('assets/'))
|
||||
return -1
|
||||
|
||||
if (url.endswith('.mpy'))
|
||||
return -1
|
||||
|
||||
// are we possibly doing folder checking ?
|
||||
if (need_dot) {
|
||||
// .mpy is blacklisted for now
|
||||
// so if it's not .py then it's a folder check.
|
||||
if (!url.endswith('.py')) {
|
||||
var found = -1
|
||||
|
||||
// package search
|
||||
found = url_exists( url + '/__init__.py' , 2 )
|
||||
console.log("wasm_([dir]/file)_exists ? :"+url+ ' --> ' + '/__init__.py => '+found)
|
||||
if (found>0) return found
|
||||
|
||||
//namespace search
|
||||
found = url_exists( url + USE_DIR_INDEX , 2 )
|
||||
console.log("wasm_([dir]/file)_exists ? :"+url+ ' --> ' + USE_DIR_INDEX+" => "+found)
|
||||
if (found>0) return found
|
||||
}
|
||||
|
||||
// if name has no dot then it was a folder check
|
||||
console.log("wasm_(dir/[file])_exists ? :"+url)
|
||||
need_dot = url.split('.').pop()
|
||||
if (need_dot==url) {
|
||||
console.log("wasm_file_exists not-a-file :"+url)
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
// default is a file search
|
||||
return url_exists(url, 1)
|
||||
}
|
||||
see docs/wasm_file_api.js for a dumb implementation using MEMFS as a cache.
|
||||
|
||||
|
||||
BIN
ports/javascript/favicon.ico
Normal file
BIN
ports/javascript/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@ -132,7 +132,7 @@ STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_inpu
|
||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
||||
nlr_raise(obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
nlr_pop();
|
||||
return 0;
|
||||
@ -212,7 +212,7 @@ void mp_js_init(int heap_size) {
|
||||
#endif
|
||||
|
||||
mp_init();
|
||||
|
||||
|
||||
mp_obj_list_init(mp_sys_path, 0);
|
||||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_));
|
||||
mp_obj_list_init(mp_sys_argv, 0);
|
||||
@ -251,7 +251,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
||||
#endif
|
||||
#else
|
||||
#pragma message "file.c will require external WASM_FILE_API functions"
|
||||
#pragma message "see wasm_file_api.txt"
|
||||
#pragma message "see docs/wasm_file_api.txt"
|
||||
#endif
|
||||
|
||||
void nlr_jump_fail(void *val) {
|
||||
|
||||
142
ports/javascript/repl.html
Normal file
142
ports/javascript/repl.html
Normal file
@ -0,0 +1,142 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name=viewport content='width=device-width,initial-scale=1'>
|
||||
|
||||
<style>
|
||||
body {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
a { white-space: nowrap; }
|
||||
#vt100,#mp_js_stdout {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#canvas {
|
||||
border: 4px black solid;
|
||||
border-radius: 4px;
|
||||
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/xterm.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/xterm.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/addons/fit/fit.min.js"></script>
|
||||
|
||||
<script src="lvgl_mp.js"></script>
|
||||
<script src="docs/wasm_file_api.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
<h1>MicroPython javascript port + lvgl</h1>
|
||||
|
||||
<pre id="url"></pre>
|
||||
|
||||
<pre id="test"></pre>
|
||||
|
||||
<pre id="log"></pre>
|
||||
|
||||
<div id='mp_js_stdout'></div>
|
||||
|
||||
<canvas id="canvas" width="240" height="320" oncontextmenu="event.preventDefault()" tabindex="-1"></canvas>
|
||||
|
||||
<p>
|
||||
|
||||
<script type="text/µpython">
|
||||
if 1:
|
||||
print("hello World")
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<script defer>
|
||||
window.vt100 = mp_js_stdout
|
||||
|
||||
Module.canvas = canvas
|
||||
|
||||
// Ctrl+L is mandatory ! need xterm.js 3.14+
|
||||
function xterm_helper(term, key) {
|
||||
function ESC(data) {
|
||||
return String.fromCharCode(27)+data
|
||||
}
|
||||
if ( key.charCodeAt(0)==12 ) {
|
||||
var cy = 0+term.buffer.cursorY
|
||||
if ( cy > 0) {
|
||||
if (cy <= term.rows) {
|
||||
term.write( ESC("[B") )
|
||||
term.write( ESC("[J") )
|
||||
term.write( ESC("[A") )
|
||||
}
|
||||
|
||||
term.write( ESC("[A") )
|
||||
term.write( ESC("[K") )
|
||||
term.write( ESC("[1J"))
|
||||
|
||||
for (var i=1;i<cy;i++) {
|
||||
term.write( ESC("[A") )
|
||||
term.write( ESC("[M") )
|
||||
}
|
||||
term.write( ESC("[M") )
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
Terminal.applyAddon(fit);
|
||||
var term = new Terminal({
|
||||
cols : 132,
|
||||
rows : 33,
|
||||
tabStopWidth : 8,
|
||||
cursorBlink : true,
|
||||
cursorStyle : 'block',
|
||||
applicationCursor : true,
|
||||
});
|
||||
term.open(vt100)
|
||||
|
||||
vt100.addEventListener('print', function(e) {
|
||||
text = e.data;
|
||||
term.write(text);
|
||||
}, false);
|
||||
|
||||
mp_js_init(512 * 1024);
|
||||
mp_js_init_repl()
|
||||
|
||||
window.stdin = ""
|
||||
|
||||
term.on('data', function(key, e) {
|
||||
if ( xterm_helper(term, key) ) {
|
||||
const kc = key.charCodeAt(0)
|
||||
if (kc <=27)
|
||||
console.log("KBD : "+kc+ " len= "+key.length)
|
||||
|
||||
if (0) {
|
||||
// canonical term - bug
|
||||
term.write(key)
|
||||
|
||||
if (kc==13) {
|
||||
mp_js_do_str(window.stdin + "\r\n")
|
||||
window.stdin =""
|
||||
} else window.stdin += key
|
||||
|
||||
} else {
|
||||
// raw
|
||||
for (var i = 0; i < key.length; i++) {
|
||||
mp_js_process_char(key.charCodeAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user