forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			163 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			163 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright (C)2005-2019 Haxe Foundation
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Permission is hereby granted, free of charge, to any person obtaining a
							 | 
						||
| 
								 | 
							
								 * copy of this software and associated documentation files (the "Software"),
							 | 
						||
| 
								 | 
							
								 * to deal in the Software without restriction, including without limitation
							 | 
						||
| 
								 | 
							
								 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
							 | 
						||
| 
								 | 
							
								 * and/or sell copies of the Software, and to permit persons to whom the
							 | 
						||
| 
								 | 
							
								 * Software is furnished to do so, subject to the following conditions:
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The above copyright notice and this permission notice shall be included in
							 | 
						||
| 
								 | 
							
								 * all copies or substantial portions of the Software.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
							 | 
						||
| 
								 | 
							
								 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
							 | 
						||
| 
								 | 
							
								 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
							 | 
						||
| 
								 | 
							
								 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
							 | 
						||
| 
								 | 
							
								 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
							 | 
						||
| 
								 | 
							
								 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
							 | 
						||
| 
								 | 
							
								 * DEALINGS IN THE SOFTWARE.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								package neko.vm;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
									The Neko object that implements the loader.
							 | 
						||
| 
								 | 
							
								**/
							 | 
						||
| 
								 | 
							
								@:callable
							 | 
						||
| 
								 | 
							
								@:coreType
							 | 
						||
| 
								 | 
							
								abstract LoaderHandle {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
									Loaders can be used to dynamically load Neko primitives stored in NDLL libraries.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Loaders can be used to dynamically load other Neko modules (.n bytecode files).
							 | 
						||
| 
								 | 
							
									Modules are referenced by names. To lookup the corresponding bytecode file, the
							 | 
						||
| 
								 | 
							
									default loader first look in its cache, then eventually adds the .n extension
							 | 
						||
| 
								 | 
							
									to the name and lookup the bytecode in its path.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Loaders can be used for sandbox security. When a Module is loaded with a given
							 | 
						||
| 
								 | 
							
									Loader, this loader can manager the module security by filtering which
							 | 
						||
| 
								 | 
							
									primitives can be loaded by this module or by rewrapping them at loading-time
							 | 
						||
| 
								 | 
							
									with custom secured versions. Loaders are inherited in loaded submodules.
							 | 
						||
| 
								 | 
							
								**/
							 | 
						||
| 
								 | 
							
								class Loader {
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										The abstract handle.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public var l:LoaderHandle;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function new(l) {
							 | 
						||
| 
								 | 
							
										this.l = l;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										The default loader contains a search path in its `path` field. It's a
							 | 
						||
| 
								 | 
							
										linked list of Neko strings that is a parsed version of the `NEKOPATH`.
							 | 
						||
| 
								 | 
							
										This path is used to lookup for modules and libraries.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function getPath() {
							 | 
						||
| 
								 | 
							
										var p = untyped l.path;
							 | 
						||
| 
								 | 
							
										var path = new Array<String>();
							 | 
						||
| 
								 | 
							
										while (p != null) {
							 | 
						||
| 
								 | 
							
											path.push(new String(p[0]));
							 | 
						||
| 
								 | 
							
											p = cast p[1];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return path;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Adds a directory to the search path. See `getPath`.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function addPath(s:String) {
							 | 
						||
| 
								 | 
							
										untyped l.path = __dollar__array(s.__s, l.path);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										The default loader contains a cache of already loaded modules. It's
							 | 
						||
| 
								 | 
							
										ensuring that the same module does not get loaded twice when circular
							 | 
						||
| 
								 | 
							
										references are occurring. The same module can eventually be loaded twice
							 | 
						||
| 
								 | 
							
										but with different names, for example with two relative paths representing
							 | 
						||
| 
								 | 
							
										the same file, since the cache is done on a by-name basic.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function getCache():Map<String, Module> {
							 | 
						||
| 
								 | 
							
										var h = new haxe.ds.StringMap<Module>();
							 | 
						||
| 
								 | 
							
										var cache = untyped l.cache;
							 | 
						||
| 
								 | 
							
										for (f in Reflect.fields(cache))
							 | 
						||
| 
								 | 
							
											h.set(f, new Module(Reflect.field(cache, f)));
							 | 
						||
| 
								 | 
							
										return h;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Set a module in the loader cache.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function setCache(name:String, m:Module) {
							 | 
						||
| 
								 | 
							
										if (m == null)
							 | 
						||
| 
								 | 
							
											Reflect.deleteField(untyped l.cache, name);
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											Reflect.setField(untyped l.cache, name, m.m);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Change the cache value and returns the old value. This can be used
							 | 
						||
| 
								 | 
							
										to backup the loader cache and restore it later.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function backupCache(c:Dynamic):Dynamic {
							 | 
						||
| 
								 | 
							
										var old = untyped l.cache;
							 | 
						||
| 
								 | 
							
										untyped l.cache = c;
							 | 
						||
| 
								 | 
							
										return old;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function __compare(other:Loader) {
							 | 
						||
| 
								 | 
							
										return untyped __dollar__compare(this.l, other.l);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Loads a neko primitive. By default, the name is of the form `[library@method]`.
							 | 
						||
| 
								 | 
							
										The primitive might not be used directly in Haxe since some of the Neko values
							 | 
						||
| 
								 | 
							
										needs an object wrapper in Haxe.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function loadPrimitive(prim:String, nargs:Int):Dynamic {
							 | 
						||
| 
								 | 
							
										return untyped l.loadprim(prim.__s, nargs);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Loads a Module with the given name. If `loader` is defined, this will be
							 | 
						||
| 
								 | 
							
										this Module loader, else this loader will be inherited. When loaded this
							 | 
						||
| 
								 | 
							
										way, the module is directly executed.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function loadModule(modName:String, ?loader:Loader):Module {
							 | 
						||
| 
								 | 
							
										var exp = untyped l.loadmodule(modName.__s, if (loader == null) l else loader.l);
							 | 
						||
| 
								 | 
							
										return new Module(exp.__module);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns the local Loader. This is the loader that was used to load the
							 | 
						||
| 
								 | 
							
										module in which the code is defined.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public static function local() {
							 | 
						||
| 
								 | 
							
										return new Loader(untyped __dollar__loader);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Creates a loader using two methods. This loader will not have an accessible cache or path,
							 | 
						||
| 
								 | 
							
										although you can implement such mechanism in the methods body.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public static function make(loadPrim:String->Int->Dynamic, loadModule:String->Loader->Module) {
							 | 
						||
| 
								 | 
							
										var l = {
							 | 
						||
| 
								 | 
							
											loadprim: function(prim, nargs) {
							 | 
						||
| 
								 | 
							
												return loadPrim(new String(prim), nargs);
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
											loadmodule: function(mname, loader) {
							 | 
						||
| 
								 | 
							
												return loadModule(new String(mname), new Loader(loader)).exportsTable();
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
											args: untyped __dollar__amake(0),
							 | 
						||
| 
								 | 
							
											cache: {},
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
										return new Loader(cast l);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |