Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

walt-link

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

walt-link - npm Package Compare versions

Comparing version 0.2.0 to 0.2.1

13

package.json
{
"name": "walt-link",
"version": "0.2.0",
"version": "0.2.1",
"description": "Links .walt WebAssembly programs",

@@ -18,2 +18,5 @@ "main": "src/index.js",

"license": "MIT",
"dependencies": {
"invariant": "^2.2.4"
},
"devDependencies": {

@@ -24,7 +27,4 @@ "ava": "^0.25.0",

"prettier": "^1.12.0",
"walt-compiler": "^0.5.0"
"walt-buildtools": "^0.0.2"
},
"peerDependencies": {
"walt-compiler": "^0.5.0"
},
"prettier": {

@@ -46,6 +46,3 @@ "trailingComma": "es5"

"powerAssert": false
},
"dependencies": {
"invariant": "^2.2.4"
}
}
const test = require("ava");
const { link, buildTree, assemble, mergeStatics, parseImports } = require("..");
const link = require("..");
const path = require("path");
const fs = require("fs");
const { stringDecoder } = require("walt-compiler");
const compiler = require("walt-compiler");
const decodeText = (view, ptr) => {
const decoder = stringDecoder(view, ptr);
const decoder = compiler.stringDecoder(view, ptr);
let iterator = decoder.next();

@@ -19,5 +19,28 @@ let text = "";

const resolve = (file, parent) => {
if (parent != null) {
return path.resolve(
path.dirname(parent),
file.slice(-5) === ".walt" ? file : file + ".walt"
);
}
return path.resolve(__dirname, file);
};
const getFileContents = (file, parent, mode) => {
if (parent != null) {
return fs.readFileSync(resolve(file, parent), mode);
}
return fs.readFileSync(resolve(file, null), mode);
};
test("returns (src: string) => (importsObj) => Promise<Wasm>", async t => {
const memory = new WebAssembly.Memory({ initial: 1 });
const factory = link(path.resolve(__dirname, "./index.walt"));
const factory = link("./index.walt", null, {
...compiler,
getFileContents,
resolve,
});
t.is(typeof factory === "function", true, "linker returns a factory");

@@ -24,0 +47,0 @@ const wasm = await factory({

@@ -11,181 +11,8 @@ /**

const compiler = require("walt-compiler");
const buildTools = require("walt-buildtools");
const fs = require("fs");
const path = require("path");
const fs = require("fs");
const waltCompiler = require("walt-compiler");
const { inferImportTypes } = require("./patches");
const invariant = require("invariant");
function mergeStatics(tree = {}) {
let statics = {};
Object.values(tree.modules).forEach(mod => {
const localStatics = mod.ast.meta.AST_METADATA.statics;
Object.assign(statics, localStatics);
});
return statics;
}
// Parse imports out of an ast
function parseImports(ast, compiler) {
const imports = {};
compiler.walkNode({
Import(node, _) {
// Import nodes consist of field and a string literal node
const [fields, module] = node.params;
if (imports[module.value] == null) {
imports[module.value] = [];
}
compiler.walkNode({
Pair(pair, __) {
// Import pairs consist of identifier and type
const [identifier] = pair.params;
imports[module.value] = Array.from(
new Set(imports[module.value].concat(identifier.value))
);
},
})(fields);
},
})(ast);
return imports;
}
// Build a dependency tree of ASTs given a root module
function buildTree(index, compiler) {
const modules = {};
const dependency = (module, resolve) => {
const filepath = resolve(module);
if (modules[filepath] != null) {
return modules[filepath];
}
const src = fs.readFileSync(filepath, "utf8");
const basic = compiler.parser(src);
const nestedImports = parseImports(basic, compiler);
const deps = {};
Object.keys(nestedImports).forEach(mod => {
if (mod.indexOf(".") === 0) {
const dep = dependency(mod, file =>
path.resolve(
path.dirname(filepath),
file.slice(-5) === ".walt" ? file : file + ".walt"
)
);
deps[mod] = dep;
}
});
const patched = inferImportTypes(basic, deps, compiler);
const ast = compiler.semantics(patched);
compiler.validate(ast, {
lines: src.split("\n"),
filename: module.split("/").pop(),
});
const result = {
ast,
deps,
filepath,
};
modules[filepath] = result;
return result;
};
const root = dependency(index, file => file);
return {
root,
modules,
};
}
// Assemble all AST into opcodes/instructions
function assemble(tree, options, compiler) {
return Object.entries(tree.modules).reduce((opcodes, [filepath, mod]) => {
// If the child does not define any static data then we should not attempt to
// generate any. Even if there are GLOBAL data sections.
let statics = mod.ast.meta.AST_METADATA.statics;
if (Object.keys(statics).length > 0) {
// Use global statics object
statics = options.linker.statics;
}
const instructions = compiler.generator(
mod.ast,
Object.assign({}, options, { linker: { statics } })
);
return Object.assign({}, opcodes, {
[filepath]: instructions,
});
}, {});
}
function compile(filepath, compiler) {
const filename = filepath.split("/").pop();
const options = {
version: 0x1,
filename,
filepath,
};
const tree = buildTree(filepath, compiler);
const statics = mergeStatics(tree);
const opcodes = assemble(
tree,
Object.assign({}, options, { linker: { statics } }),
compiler
);
return Object.assign(tree, {
statics,
opcodes,
options,
});
}
// Build the final binary Module set
function build(importsObj, tree, compiler) {
const modules = {};
const instantiate = filepath => {
if (modules[filepath] != null) {
return modules[filepath];
}
const mod = tree.modules[filepath];
return Promise.all(
Object.entries(mod.deps).map(([key, dep]) => {
return instantiate(dep.filepath).then(result => [key, result]);
})
)
.then(importsMap => {
const imports = importsMap.reduce((acc, [key, module]) => {
acc[key] = module.instance.exports;
return acc;
}, {});
return WebAssembly.instantiate(
compiler.emitter(tree.opcodes[filepath], tree.options).buffer(),
Object.assign({}, imports, importsObj)
);
})
.catch(e => {
// TODO: do some logging here
throw e;
});
};
modules[tree.root.filepath] = instantiate(tree.root.filepath);
return modules[tree.root.filepath];
}
/**

@@ -196,3 +23,3 @@ * Link Walt programs together.

* @param {Object} options Reserved
* @param {Object} compiler Custom compiler. Is the node module by default.
* @param {Object} api Custom compiler. Is the node module by default.
*

@@ -207,11 +34,29 @@ * This is here to allow for the compiler to test itself

*/
function link(
filepath,
options = { logger: console },
compiler = waltCompiler
) {
const tree = compile(filepath, compiler);
const resolve = (dirname = __dirname) => (file, parent) => {
const root = parent ? path.dirname(parent) : dirname;
return path.resolve(root, file.slice(-5) === ".walt" ? file : file + ".walt");
};
const getFileContents = resolver => (file, parent, mode) => {
return fs.readFileSync(resolver(file, parent), mode);
};
function link(file, options = { logger: console }, api = compiler) {
invariant(api, "An API needs to be provided to the linker.");
if (api.resolve == null) {
api = Object.assign(
{
resolve: resolve(path.dirname(file)),
getFileContents: getFileContents(resolve(path.dirname(file))),
},
api
);
}
const tree = buildTools.compile(file, api);
function walt(importsObj = {}) {
return build(importsObj, tree, compiler);
return buildTools.build(importsObj, tree, api);
}

@@ -224,9 +69,2 @@

module.exports = {
link,
parseImports,
compile,
buildTree,
mergeStatics,
assemble,
};
module.exports = link;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc