microvium
Version:
A compact, embeddable scripting engine for microcontrollers for executing small scripts written in a subset of JavaScript.
123 lines • 5.67 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _TestResults_results;
Object.defineProperty(exports, "__esModule", { value: true });
exports.compileJs = exports.assertSameCode = exports.TestResults = exports.bufferToHexString = void 0;
const fs = __importStar(require("fs-extra"));
const chai_1 = require("chai");
const path = __importStar(require("path"));
const os = __importStar(require("os"));
const utils_1 = require("../lib/utils");
const virtual_machine_friendly_1 = require("../lib/virtual-machine-friendly");
const lib_1 = require("../lib");
;
function bufferToHexString(b) {
// Hex string with spaces between bytes
return b.toString('hex').replace(/([0-9a-fA-F]{2})/g, (_, v) => v + ' ').trim();
}
exports.bufferToHexString = bufferToHexString;
// This class allows tests to do all their checks at the end, while accumulating
// the results incrementally. The reason this is useful is that all the outputs
// for the test are generated before the first failure is encountered.
class TestResults {
constructor() {
_TestResults_results.set(this, new Array());
}
push(output, filenames) {
if (!fs.pathExistsSync(path.dirname(filenames.output))) {
fs.emptyDirSync(path.dirname(filenames.output));
}
if (!fs.pathExistsSync(path.dirname(filenames.expected))) {
fs.emptyDirSync(path.dirname(filenames.expected));
}
const encoding = typeof output === 'string' ? 'utf8' : null;
if (encoding === 'utf8' && typeof output === 'string') {
output = output.replace(/\r?\n/g, os.EOL);
}
fs.writeFileSync(filenames.output, output, encoding);
__classPrivateFieldGet(this, _TestResults_results, "f").push({ output, filenames, encoding });
}
checkAll() {
for (const { output, filenames, encoding } of __classPrivateFieldGet(this, _TestResults_results, "f")) {
const expected = fs.readFileSync(filenames.expected, encoding);
if (encoding === 'utf8') {
assertSameCode(output, expected);
}
else {
chai_1.assert.deepEqual(output, expected);
}
}
}
}
exports.TestResults = TestResults;
_TestResults_results = new WeakMap();
/**
* Compares code but normalizes the indentation first
*/
function assertSameCode(actual, expected) {
function normalizeIndentation(code) {
// The rest of this function doesn't work well with empty strings
if (/^\s*$/.test(code)) {
return '';
}
code = code.replace(/\t/g, ' '); // Replace tabs
code = code.replace(/^(\s*\n)+/, ''); // replace leading blank lines
code = code.replace(/(\s*\n)+$/, ''); // replace trailing blank lines
code = code.replace(/(\s*\n\s*\n)+/g, '\n'); // replace all other blank lines
code = code.trimRight();
const lines = code.split('\n');
const indentOf = (line) => line.match(/^ */)[0].length;
const nonBlankLines = lines.filter(l => !(/^\s*$/g).test(l));
const minIndent = ' '.repeat(Math.min.apply(Math, nonBlankLines.map(indentOf)));
const matchIndent = new RegExp('^' + minIndent, 'gm');
const normalized = code.replace(matchIndent, '');
return normalized;
}
;
function normalizeLineEndings(code) {
return code.replace(/(\r\n)|(\n\r)/g, '\n');
}
function normalize(code) {
return normalizeIndentation(normalizeLineEndings(code));
}
const normalizedActual = normalize(actual);
const normalizedExpected = normalize(expected);
chai_1.assert.deepEqual(normalizedActual, normalizedExpected);
}
exports.assertSameCode = assertSameCode;
function compileJs(src) {
src.length === 1 || (0, utils_1.unexpected)();
const vm = virtual_machine_friendly_1.VirtualMachineFriendly.create();
(0, lib_1.addDefaultGlobals)(vm);
vm.evaluateModule({ sourceText: src[0] });
return vm.createSnapshot();
}
exports.compileJs = compileJs;
//# sourceMappingURL=common.js.map