refactor: runtimes into xurfer/runtime + better URI errorhandling + added lua runtime
13
README.md
|
|
@ -10,7 +10,7 @@ Developers can run it via [Lua](https://lua.org), [LÖVR](https://lovr.org) or [
|
||||||
$ cd xurfer
|
$ cd xurfer
|
||||||
$ love . <url_or_file> [..] # if you have LÖVE2D installed (>v12)
|
$ love . <url_or_file> [..] # if you have LÖVE2D installed (>v12)
|
||||||
$ lovr . <url_or_file> [..] # if you have LÖVR installed
|
$ lovr . <url_or_file> [..] # if you have LÖVR installed
|
||||||
$ lua main.lua <url_or_file> [..] # if you have lua installed
|
$ ./main.lua <url_or_file> [..] # if you have lua installed
|
||||||
```
|
```
|
||||||
|
|
||||||
**Example**: lovr xurfer <a href="https://snips.sh/f/_U5-XctEVE?r=1">https://snips.sh/f/_U5-XctEVE?r=1</a>
|
**Example**: lovr xurfer <a href="https://snips.sh/f/_U5-XctEVE?r=1">https://snips.sh/f/_U5-XctEVE?r=1</a>
|
||||||
|
|
@ -39,8 +39,9 @@ The aim of this project is providing **a [XR Hypermedia browser](https://xrhf.is
|
||||||
|
|
||||||
## very hackable extensions
|
## very hackable extensions
|
||||||
|
|
||||||
* XURFER does everything via browser extensions.<br>
|
* XURFER does everything via browser extensions.
|
||||||
* XURFER is the total sum of browser extensions.<br>
|
* XURFER is the total sum of browser extensions.
|
||||||
|
* XURFER can proxy missing api-calls to cli-cmds (like [wget/curl](xurfer/runtime/lua/main.lua) via the [unixy](xurfer/ext/unixy/main.lua) extension)
|
||||||
|
|
||||||
So you can strip/bloat however you want, or build one yourself:
|
So you can strip/bloat however you want, or build one yourself:
|
||||||
|
|
||||||
|
|
@ -51,3 +52,9 @@ $ ./lovr xurfer
|
||||||
[i] loading 'myextension'
|
[i] loading 'myextension'
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Instead of the traditional sandbox-in-a-browser-model (Chromium/Firefox e.g.), we suggest running XURFER via [bubblewrap](https://github.com/meta-quest/bubblewrap)
|
||||||
|
|
||||||
|
> TODO: suggest cli flags
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
-- sync lovr/love positional cli arguments
|
-- sync lovr/love positional cli arguments
|
||||||
if arg[0] == nil and arg[1] ~= nil then arg[0] = arg[1] end
|
if arg[0] == nil and arg[1] ~= nil then arg[0] = arg[1] end
|
||||||
|
|
||||||
runtime = ""
|
package.path = package.path .. ';' ..
|
||||||
|
'?.lua;' ..
|
||||||
|
'?/init.lua;' ..
|
||||||
|
'lib/?.lua;'
|
||||||
|
|
||||||
if lovr ~= nil then runtime = "lovr" end
|
local runtime = require("runtime/detect")
|
||||||
if love ~= nil then runtime = "love" end
|
|
||||||
|
|
||||||
package.path = package.path .. ';' ..
|
package.path = package.path .. ';' ..
|
||||||
arg[0] .. '/' .. runtime .. '/?.lua;' ..
|
arg[0] .. '/' .. runtime.path .. '/?.lua;' ..
|
||||||
arg[0] .. '/' .. runtime .. '/?/init.lua;' ..
|
arg[0] .. '/' .. runtime.path .. '/?/init.lua;' ..
|
||||||
arg[0] .. '/lib/?.lua'
|
arg[0] .. '/lib/?.lua'
|
||||||
|
|
||||||
require( runtime .. "/conf")
|
require( runtime.path .. "/conf")
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
local ecs = require("tiny-ecs")
|
local ecs = require("tiny-ecs")
|
||||||
|
|
||||||
ecs.init = function()
|
ecs.init = function(api)
|
||||||
print("[i] loading ecs")
|
print("[i] loading ecs")
|
||||||
baseEntify = ecs.processingSystem()
|
baseEntify = ecs.processingSystem()
|
||||||
baseEntify.filter = ecs.rejectAll('commit')
|
baseEntify.filter = ecs.rejectAll('commit')
|
||||||
|
|
@ -24,6 +24,7 @@ ecs.init = function()
|
||||||
end
|
end
|
||||||
|
|
||||||
ecs.clear = function()
|
ecs.clear = function()
|
||||||
|
trace("[ecs] ecs.clear() scene")
|
||||||
api.ext.exec("onClear")
|
api.ext.exec("onClear")
|
||||||
api.ecs.clearEntities( api.world )
|
api.ecs.clearEntities( api.world )
|
||||||
api.world.commit()
|
api.world.commit()
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ return {
|
||||||
api.ecs.add( api.world, obj )
|
api.ecs.add( api.world, obj )
|
||||||
obj.commit('on3DFile') -- notify systems
|
obj.commit('on3DFile') -- notify systems
|
||||||
else
|
else
|
||||||
print("[3DFile] error: could not load " .. obj.URL.string )
|
print("[3DFile] error: could not load " .. obj.URL.string .. ": " .. obj.URLResponse.data )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ http = {
|
||||||
req.headers = headers
|
req.headers = headers
|
||||||
channel:pop() -- remove last
|
channel:pop() -- remove last
|
||||||
channel:push(req) -- re-push but with status (which thread ignores)
|
channel:push(req) -- re-push but with status (which thread ignores)
|
||||||
lovr.timer.sleep(.1)
|
|
||||||
end
|
end
|
||||||
|
lovr.timer.sleep(.1)
|
||||||
end
|
end
|
||||||
]]
|
]]
|
||||||
http.channel = lovr.thread.getChannel('http')
|
http.channel = lovr.thread.getChannel('http')
|
||||||
|
|
@ -57,14 +57,19 @@ http = {
|
||||||
|
|
||||||
local msg
|
local msg
|
||||||
local res, present = http.channel:peek()
|
local res, present = http.channel:peek()
|
||||||
if present and res.status ~= nil then
|
if present then
|
||||||
msg = http.channel:pop()
|
if res.status == nil and res.data == "Could not connect to server" then
|
||||||
-- we got our urlrequest response
|
res.status = 503 -- service unavailable
|
||||||
if http.cache[ msg.url ] then
|
end
|
||||||
http.cache[ msg.url ].cb( msg.status, msg.data, msg.headers )
|
if res.status ~= nil then
|
||||||
http.cache[ msg.url ] = nil
|
msg = http.channel:pop()
|
||||||
else
|
-- we got our urlrequest response
|
||||||
error("msg-object was not found in cache")
|
if http.cache[ msg.url ] then
|
||||||
|
http.cache[ msg.url ].cb( msg.status, msg.data, msg.headers )
|
||||||
|
http.cache[ msg.url ] = nil
|
||||||
|
else
|
||||||
|
error("msg-object was not found in cache")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,11 @@ return {
|
||||||
|
|
||||||
sample.load({
|
sample.load({
|
||||||
gameSunsetImage = lovr.graphics.newTexture(
|
gameSunsetImage = lovr.graphics.newTexture(
|
||||||
"lovr/sample/assets/game-sunset.png", {}
|
"runtime/lovr/sample/assets/game-sunset.png", {}
|
||||||
),
|
),
|
||||||
nineSliceImage = {
|
nineSliceImage = {
|
||||||
image = lovr.graphics.newTexture(
|
image = lovr.graphics.newTexture(
|
||||||
"lovr/sample/assets/ui-box-slice.png", { mipmaps = false }
|
"runtime/lovr/sample/assets/ui-box-slice.png", { mipmaps = false }
|
||||||
),
|
),
|
||||||
l = 8,
|
l = 8,
|
||||||
t = 8,
|
t = 8,
|
||||||
|
|
@ -40,14 +40,14 @@ return {
|
||||||
smileMSDFLayeredImage = {
|
smileMSDFLayeredImage = {
|
||||||
{
|
{
|
||||||
image = lovr.graphics.newTexture(
|
image = lovr.graphics.newTexture(
|
||||||
"lovr/sample/assets/smile-bg.png",
|
"runtime/lovr/sample/assets/smile-bg.png",
|
||||||
{ linear = true, mipmaps = false }
|
{ linear = true, mipmaps = false }
|
||||||
),
|
),
|
||||||
color = iui.newColor(0.944, 0.794, 0.468)
|
color = iui.newColor(0.944, 0.794, 0.468)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
image = lovr.graphics.newTexture(
|
image = lovr.graphics.newTexture(
|
||||||
"lovr/sample/assets/smile-fg.png",
|
"runtime/lovr/sample/assets/smile-fg.png",
|
||||||
{ linear = true, mipmaps = false }
|
{ linear = true, mipmaps = false }
|
||||||
),
|
),
|
||||||
color = iui.newColor(0.157, 0.157, 0.157)
|
color = iui.newColor(0.157, 0.157, 0.157)
|
||||||
|
|
@ -57,7 +57,7 @@ return {
|
||||||
{
|
{
|
||||||
image = {
|
image = {
|
||||||
image = lovr.graphics.newTexture(
|
image = lovr.graphics.newTexture(
|
||||||
"lovr/sample/assets/nine-slice-interior.png",
|
"runtime/lovr/sample/assets/nine-slice-interior.png",
|
||||||
{ linear = true, mipmaps = false }
|
{ linear = true, mipmaps = false }
|
||||||
),
|
),
|
||||||
l = 16,
|
l = 16,
|
||||||
|
|
@ -70,7 +70,7 @@ return {
|
||||||
{
|
{
|
||||||
image = {
|
image = {
|
||||||
image = lovr.graphics.newTexture(
|
image = lovr.graphics.newTexture(
|
||||||
"lovr/sample/assets/nine-slice-frame.png",
|
"runtime/lovr/sample/assets/nine-slice-frame.png",
|
||||||
{ linear = true, mipmaps = false }
|
{ linear = true, mipmaps = false }
|
||||||
),
|
),
|
||||||
l = 16,
|
l = 16,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ return {
|
||||||
|
|
||||||
load = function()
|
load = function()
|
||||||
--if api.iui.idiom == "vr" then
|
--if api.iui.idiom == "vr" then
|
||||||
envTex = api.graphics.newTexture("lovr/assets/img/env.png", {})
|
envTex = api.graphics.newTexture("runtime/lovr/assets/img/env.png", {})
|
||||||
api.world.skybox = api.graphics.newTexture({
|
api.world.skybox = api.graphics.newTexture({
|
||||||
px = 'ext/startupscene/skybox/Dayright.jpg', -- 'px.png',
|
px = 'ext/startupscene/skybox/Dayright.jpg', -- 'px.png',
|
||||||
nx = 'ext/startupscene/skybox/Dayleft.jpg', -- 'nx.png',
|
nx = 'ext/startupscene/skybox/Dayleft.jpg', -- 'nx.png',
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,15 @@ unixy = {
|
||||||
init = function()
|
init = function()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
proxyCLI = function( cmdfunc, callback )
|
proxyCLI = function( cmd, cmdfunc, callback )
|
||||||
return function(...)
|
if api.util.cmdExist(cmd) then
|
||||||
return unixy.addjob( cmdfunc, callback, ...)
|
print("[i] attaching ".. cmd .. " cli-cmd to api")
|
||||||
|
return function(...)
|
||||||
|
return unixy.addjob( cmdfunc, callback, ...)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("[!] could not attach ".. cmd .. " cli-cmd to api: not found")
|
||||||
|
return function()end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
|
@ -79,7 +85,6 @@ unixy = {
|
||||||
callback = callback
|
callback = callback
|
||||||
})
|
})
|
||||||
trace("[unixy] start job with pid " .. pid .. " => 1> " .. stdout_file .. " 2> " .. stderr_file)
|
trace("[unixy] start job with pid " .. pid .. " => 1> " .. stdout_file .. " 2> " .. stderr_file)
|
||||||
print_r(unixy.jobs)
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
check_jobs = function()
|
check_jobs = function()
|
||||||
|
|
@ -98,7 +103,7 @@ unixy = {
|
||||||
-- Clean up
|
-- Clean up
|
||||||
os.remove(job.stdout_file)
|
os.remove(job.stdout_file)
|
||||||
os.remove(job.stderr_file)
|
os.remove(job.stderr_file)
|
||||||
job.callback(stdout, stderr, retcode, unpack(job.args) )
|
job.callback(stdout, stderr, retcode, table.unpack(job.args) )
|
||||||
table.remove(unixy.jobs, i)
|
table.remove(unixy.jobs, i)
|
||||||
else
|
else
|
||||||
io.write(".")
|
io.write(".")
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ end
|
||||||
|
|
||||||
-- utility function to traverse recursive table
|
-- utility function to traverse recursive table
|
||||||
xrf.traverse = function(arr, cb, key)
|
xrf.traverse = function(arr, cb, key)
|
||||||
|
if arr == nil then return end
|
||||||
if key == nil then key = 'children' end
|
if key == nil then key = 'children' end
|
||||||
for k, child in pairs(arr) do
|
for k, child in pairs(arr) do
|
||||||
if type(child) == 'table' then
|
if type(child) == 'table' then
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
module(..., package.seeall)
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------
|
||||||
---------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
|
|
|
||||||
28
xurfer/main.lua
Normal file → Executable file
|
|
@ -1,3 +1,4 @@
|
||||||
|
#!/usr/bin/env lua
|
||||||
-- -- GLB URLS
|
-- -- GLB URLS
|
||||||
-- ./lovr xurfer https://coderofsalvation.codeberg.page/xrfragment-haxe/example/assets/example.glb?bar=1&f=2#foo'
|
-- ./lovr xurfer https://coderofsalvation.codeberg.page/xrfragment-haxe/example/assets/example.glb?bar=1&f=2#foo'
|
||||||
-- ./lovr xurfer https://codeberg.org/coderofsalvation/xrfragment/raw/branch/main/assets/template/website/website.glb'
|
-- ./lovr xurfer https://codeberg.org/coderofsalvation/xrfragment/raw/branch/main/assets/template/website/website.glb'
|
||||||
|
|
@ -9,23 +10,18 @@
|
||||||
-- ./lovr xurfer https://snips.sh/f/rHFLg-cewi?r=1' -- cube
|
-- ./lovr xurfer https://snips.sh/f/rHFLg-cewi?r=1' -- cube
|
||||||
-- ./lovr xurfer https://snips.sh/f/_U5-XctEVE?r=1' -- cube, monkey, scene
|
-- ./lovr xurfer https://snips.sh/f/_U5-XctEVE?r=1' -- cube, monkey, scene
|
||||||
|
|
||||||
local runtime = nil
|
print("\n X U R F Ξ R")
|
||||||
|
print(" ⠭ ⠥ ⠗ ⠋ ⠑ ⠗\n")
|
||||||
|
|
||||||
if lovr ~= nil then
|
package.path = package.path .. ';' .. '?.lua;'
|
||||||
runtime = { path = "lovr", api = lovr }
|
require('conf')
|
||||||
elseif love ~= nil then
|
|
||||||
runtime = { path = "love", api = love };
|
|
||||||
end
|
|
||||||
|
|
||||||
if runtime == nil then
|
local runtime = require("runtime/detect")
|
||||||
package.path = package.path .. ';' .. 'xurfer/?.lua'
|
local util = require("util")
|
||||||
require('conf')
|
local ecs = require("ecs")
|
||||||
end
|
|
||||||
|
|
||||||
local util = require("util")
|
|
||||||
local ecs = require("ecs")
|
|
||||||
|
|
||||||
api = {
|
api = {
|
||||||
|
runtime = runtime,
|
||||||
parser = {
|
parser = {
|
||||||
json = require("json"),
|
json = require("json"),
|
||||||
xml = require("xmlSimple"),
|
xml = require("xmlSimple"),
|
||||||
|
|
@ -46,7 +42,8 @@ require( runtime.path .. "/main")
|
||||||
|
|
||||||
util.loaddir( "ext", api, api.ext )
|
util.loaddir( "ext", api, api.ext )
|
||||||
util.loaddir( "media", api, api.media )
|
util.loaddir( "media", api, api.media )
|
||||||
ecs.init()
|
|
||||||
|
ecs.init(api)
|
||||||
api.ext.exec('init')
|
api.ext.exec('init')
|
||||||
|
|
||||||
-- load urls passed on the cli
|
-- load urls passed on the cli
|
||||||
|
|
@ -55,3 +52,6 @@ foreach( arg, function(k,uri)
|
||||||
api.ecs.add( api.world, { URI = { url = uri, method = 'GET', target = '_top' } })
|
api.ecs.add( api.world, { URI = { url = uri, method = 'GET', target = '_top' } })
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- for runtimes (runtime/lua) which dont automatically run an update-loop (like love/lovr)
|
||||||
|
api.ext.exec('main')
|
||||||
|
|
|
||||||
17
xurfer/runtime/detect.lua
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
local runtime = nil
|
||||||
|
-- determine runtime
|
||||||
|
if lovr ~= nil then
|
||||||
|
runtime = { name = "lovr", path = "runtime/lovr", api = lovr }
|
||||||
|
elseif love ~= nil then
|
||||||
|
runtime = { name = "lua", path = "runtime/love", api = love }
|
||||||
|
else
|
||||||
|
runtime = { name = "lua", path = "runtime/lua", api = require("runtime/lua/api") }
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
runtime.os = "unixy"
|
||||||
|
if package.config:sub(1,1) == "\\" then
|
||||||
|
runtime.os = "windows"
|
||||||
|
end
|
||||||
|
|
||||||
|
return runtime
|
||||||
|
Before Width: | Height: | Size: 175 KiB After Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 599 B After Width: | Height: | Size: 599 B |
|
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 232 B |
|
Before Width: | Height: | Size: 405 B After Width: | Height: | Size: 405 B |
|
Before Width: | Height: | Size: 628 B After Width: | Height: | Size: 628 B |
|
Before Width: | Height: | Size: 617 B After Width: | Height: | Size: 617 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
|
@ -9,8 +9,8 @@ local iui = require "lib.iui"
|
||||||
local backend = require "lib.lovr-iui"
|
local backend = require "lib.lovr-iui"
|
||||||
|
|
||||||
-- modify for nested lovr path for api
|
-- modify for nested lovr path for api
|
||||||
iui.resourcePath = "lovr/" .. iui.resourcePath
|
iui.resourcePath = "runtime/lovr/" .. iui.resourcePath
|
||||||
backend.resourcePath = "lovr/" .. backend.resourcePath
|
backend.resourcePath = "runtime/lovr/" .. backend.resourcePath
|
||||||
api.iui = iui
|
api.iui = iui
|
||||||
api.backend = backend
|
api.backend = backend
|
||||||
-- decorate api
|
-- decorate api
|
||||||
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 636 B After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 191 B After Width: | Height: | Size: 191 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 919 B After Width: | Height: | Size: 919 B |