diff --git a/src/core/org/luaj/lib/PackageLib.java b/src/core/org/luaj/lib/PackageLib.java index d3fa2bc2..7519e1b9 100644 --- a/src/core/org/luaj/lib/PackageLib.java +++ b/src/core/org/luaj/lib/PackageLib.java @@ -309,13 +309,13 @@ public class PackageLib extends LFunction { vm.call( 1, 1 ); /* run loaded module */ if ( ! vm.isnil(-1) ) /* non-nil return? */ LOADED.luaSetTable(vm, LOADED, name, vm.topointer(-1) ); /* _LOADED[name] = returned value */ - vm.resettop(); LOADED.luaGetTable(vm, LOADED, name); if ( vm.topointer(-1) == _SENTINEL ) { /* module did not set a value? */ LOADED.luaSetTable(vm, LOADED, name, LBoolean.TRUE ); /* _LOADED[name] = true */ - vm.resettop(); vm.pushboolean(true); } + vm.insert(1); + vm.settop(1); } public static void loadlib( LuaState vm ) { @@ -371,21 +371,25 @@ public class PackageLib extends LFunction { if ( ! vm.isstring(-1) ) vm.error("package."+pname+" must be a string"); String path = vm.tostring(-1); - int te = -1; + int e = -1; int n = path.length(); StringBuffer sb = null; - while ( te < n ) { + name = name.replace('.','/'); + while ( e < n ) { // find next template - int tb = te+1; - te = path.indexOf(';',tb); - if ( te < 0 ) - te = path.length(); - String template = path.substring(tb,te); + int b = e+1; + e = path.indexOf(';',b); + if ( e < 0 ) + e = path.length(); + String template = path.substring(b,e); // create filename - int ques = template.indexOf('?'); - String filename = (ques<0? template: template.substring(0,ques)+name+template.substring(ques+1)); + int q = template.indexOf('?'); + String filename = template; + if ( q >= 0 ) { + filename = template.substring(0,q) + name + template.substring(q+1); + } // try opening the file InputStream is = p.openFile(filename); diff --git a/src/test/java/org/luaj/vm/require/RequireSampleClassCastExcep.java b/src/test/java/org/luaj/vm/require/RequireSampleClassCastExcep.java new file mode 100644 index 00000000..8c17f3ad --- /dev/null +++ b/src/test/java/org/luaj/vm/require/RequireSampleClassCastExcep.java @@ -0,0 +1,19 @@ +package org.luaj.vm.require; + +import org.luaj.vm.LuaState; + +/** + * This should fail while trying to load via "require() because it is not an LFunction" + * + */ +public class RequireSampleClassCastExcep { + + public RequireSampleClassCastExcep() { + } + + public boolean luaStackCall( LuaState vm ) { + System.out.println("called "+this.getClass().getName()+" with vm.topointer(1)=="+vm.topointer(1) ); + vm.resettop(); + return false; + } +} diff --git a/src/test/java/org/luaj/vm/require/RequireSampleLoadLuaError.java b/src/test/java/org/luaj/vm/require/RequireSampleLoadLuaError.java new file mode 100644 index 00000000..7bf7b311 --- /dev/null +++ b/src/test/java/org/luaj/vm/require/RequireSampleLoadLuaError.java @@ -0,0 +1,20 @@ +package org.luaj.vm.require; + +import org.luaj.vm.LFunction; +import org.luaj.vm.LuaState; + +/** + * This should fail while trying to load via "require()" because it throws a LuaError + * + */ +public class RequireSampleLoadLuaError extends LFunction { + + public RequireSampleLoadLuaError() { + } + + public boolean luaStackCall( LuaState vm ) { + System.out.println("called "+this.getClass().getName()+" with vm.topointer(1)=="+vm.topointer(1) ); + vm.error("lua error thrown by "+this.getClass().getName()); + return false; + } +} diff --git a/src/test/java/org/luaj/vm/require/RequireSampleLoadRuntimeExcep.java b/src/test/java/org/luaj/vm/require/RequireSampleLoadRuntimeExcep.java new file mode 100644 index 00000000..cc4fc402 --- /dev/null +++ b/src/test/java/org/luaj/vm/require/RequireSampleLoadRuntimeExcep.java @@ -0,0 +1,19 @@ +package org.luaj.vm.require; + +import org.luaj.vm.LFunction; +import org.luaj.vm.LuaState; + +/** +* This should fail while trying to load via "require()" because it throws a RuntimeException + * + */ +public class RequireSampleLoadRuntimeExcep extends LFunction { + + public RequireSampleLoadRuntimeExcep() { + } + + public boolean luaStackCall( LuaState vm ) { + System.out.println("called "+this.getClass().getName()+" with vm.topointer(1)=="+vm.topointer(1) ); + throw new RuntimeException("error thrown by "+this.getClass().getName()); + } +} diff --git a/src/test/java/org/luaj/vm/require/RequireSampleSuccess.java b/src/test/java/org/luaj/vm/require/RequireSampleSuccess.java new file mode 100644 index 00000000..66307079 --- /dev/null +++ b/src/test/java/org/luaj/vm/require/RequireSampleSuccess.java @@ -0,0 +1,20 @@ +package org.luaj.vm.require; + +import org.luaj.vm.LFunction; +import org.luaj.vm.LuaState; + +/** + * This should succeed as a library that can be loaded dynmaically via "require()" + * + */ +public class RequireSampleSuccess extends LFunction { + + public RequireSampleSuccess() { + } + + public boolean luaStackCall( LuaState vm ) { + System.out.println("called "+this.getClass().getName()+" with vm.topointer(1)=="+vm.topointer(1) ); + vm.resettop(); + return false; + } +} diff --git a/src/test/res/req/subsample.lua b/src/test/res/req/subsample.lua new file mode 100644 index 00000000..111fc695 --- /dev/null +++ b/src/test/res/req/subsample.lua @@ -0,0 +1,8 @@ +-- helper file for require() tests +module( 'req.subsample', package.seeall ) +function h() + print 'in subsample.h' +end +print 'loading subsample.lua' +return 'return value from subsample', 'second return value from subsample' + diff --git a/src/test/res/require.lua b/src/test/res/require.lua index f7e0e610..00faa91f 100644 --- a/src/test/res/require.lua +++ b/src/test/res/require.lua @@ -2,7 +2,7 @@ local ids = {} local ti = table.insert local function id(obj) - if not obj or type(obj) == 'number' or type(obj) == 'string' then + if not obj or type(obj) == 'number' or type(obj) == 'string' or type(obj) == 'boolean' then return obj end local v = ids[obj] @@ -28,13 +28,16 @@ function f( name ) end end f('sample') -print( 'main', id(sample), id(bogus), id(custom) ); +print( 'main', id(sample), id(bogus), id(custom), id(req) ); f('sample') -print( 'main', id(sample), id(bogus), id(custom) ); +print( 'main', id(sample), id(bogus), id(custom), id(req) ); f('bogus') -print( 'main', id(sample), id(bogus), id(custom) ); +print( 'main', id(sample), id(bogus), id(custom), id(req) ); +f( 'req.subsample' ) +print( 'main', id(sample), id(bogus), id(custom), id(req) ); -- custom loader chain +local pl = package.loaders for i=1,3 do print( i,id(package.loaders[i]) ) end @@ -63,6 +66,46 @@ function loader3( ... ) end package.loaders = { loader1, loader2, loader3 } f( 'bogus' ) -print( 'main', id(sample), id(bogus), id(custom) ); +print( 'main', id(sample), id(bogus), id(custom), id(src) ); f( 'custom' ) -print( 'main', id(sample), id(bogus), id(custom) ); +print( 'main', id(sample), id(bogus), id(custom), id(src) ); + +-- good, and bad lua samples +function g(name) + print( name, pcall(f,name) ) +end +package.loaders = { function(...) + print( 'in success loader', ... ) + return function(...) + print( 'in success chunk', ... ) + end +end } +pcall( g, 'require-sample-succeed' ) +package.loaders = { function(...) + print( 'in loader-error loader', ... ) + error( 'sample error thrown by loader-error loader') + return function(...) + print( 'in loader-error chunk', ... ) + end +end } +pcall( g, 'require-sample-loader-error' ) +package.loaders = { function(...) + print( 'in chunk-error loader', ... ) + return function(...) + error( 'sample error thrown by chunk-error function') + print( 'in chunk-error chunk', ... ) + end +end } +pcall( g, 'require-sample-chunk-error' ) + +-- good, and bad java samples +package.loaders = pl +function g(name) + print( name, pcall(f,name) ) + print( 'main', id(org) ); +end +pcall( g, 'org.luaj.vm.require.RequireSampleClassCastExcep') +pcall( g, 'org.luaj.vm.require.RequireSampleLoadLuaError') +pcall( g, 'org.luaj.vm.require.RequireSampleLoadRuntimeExcep') +pcall( g, 'org.luaj.vm.require.RequireSampleSuccess') +pcall( g, 'org.luaj.vm.require.RequireSampleSuccess')