const op = {}; const Hash = require('./hash.js'); const core = require('./core.js'); const AnsiToHtml = require('ansi-to-html'); const NQPObject = require('./nqp-object.js'); const NQPException = require('./nqp-exception.js'); const BOOT = require('./BOOT.js'); exports.op = op; // allows running code bundles as for browser use outside of the browser const maybeWindow = typeof window === 'undefined' ? {} : window; class BufferedConsole extends NQPObject { constructor(output) { super(); this.buffered = []; this.output = output; } $$writefh(buf) { const buffer = core.toRawBuffer(buf); this.$$write(buffer.toString()); } $$write(str) { const lines = str.split(/\n/); if (lines.length === 0) return; for (let i = 0; i < lines.length-1; i++) { if (i === 0) { this.output(this.buffered.join('') + lines[0]); this.buffered.length = 0; } else { this.output(lines[i]); } } if (lines[lines.length - 1] !== '') { this.buffered.push(lines[lines.length - 1]); } } $$isttyfh() { return 1; } $$setbuffersizefh(size) { return this; } } class BrowserStdin extends NQPObject { $$isttyfh() { return 1; } } const converter = new AnsiToHtml({escapeXML: true, stream: true}); class HijackedConsole extends NQPObject { constructor(hijack) { super(); this.hijack = hijack; } $$writefh(buf) { const buffer = core.toRawBuffer(buf); this.$$write(buffer.toString()); } $$write(str) { this.hijack(converter.toHtml(str)); } $$isttyfh() { return 1; } } let STDOUT; if (maybeWindow.NQP_STDOUT) { STDOUT = new HijackedConsole(maybeWindow.NQP_STDOUT); } else if (maybeWindow.__karma__) { const TapConsole = require('./tap-console.js'); STDOUT = new TapConsole(); } else { STDOUT = new BufferedConsole(output => console.log(output)); } if (maybeWindow.__karma__) { if (!maybeWindow.__rakudo__) { maybeWindow.__rakudo__ = {}; } maybeWindow.__rakudo__.startTime = new Date().getTime(); maybeWindow.__rakudo__.waitForStart = []; maybeWindow.__rakudo__.results = []; maybeWindow.__rakudo__.resultCount = 0; maybeWindow.__karma__.start = /*async*/ function(results) { STDOUT.karmaResults = results; for (const code of maybeWindow.__rakudo__.waitForStart) { /*await*/ code(); } maybeWindow.__karma__.info({total: maybeWindow.__rakudo__.resultCount}); for (const result of maybeWindow.__rakudo__.results) { maybeWindow.__karma__.result(result); } maybeWindow.__karma__.complete({ coverage: maybeWindow.__coverage__, }); }; } const STDERR = new BufferedConsole(output => console.error(output)); const STDIN = new BrowserStdin(); op.say = function(arg) { STDOUT.$$write(arg + '\n'); return arg; }; op.print = function(arg) { STDOUT.$$write(arg); return arg; }; op.getstdin = function(arg) { return STDIN; }; op.getstdout = function(arg) { return STDOUT; }; op.getstderr = function(arg) { return STDERR; }; op.getenvhash = function() { return new Hash(); }; const pid = core.fakePid(); op.getpid = function() { return pid; }; op.getppid = function() { return -1; }; op.cwd = function() { return '?'; }; op.stat = function(file, code) { const EXISTS = 0; if (code == EXISTS && (file === '/etc/os-release' || file === '/bin/uname' || file === '/usr/bin/uname')) { return 0; } else { throw new NQPException('nqp::stat is not supported in the browser'); } }; class Exit { constructor(code) { this.code = code; } }; exports.Exit = Exit; op.exit = function(code) { throw new exports.Exit(code); }; op.gethostname = function() { return 'unknown'; }; op.uname = function() { let sysname = 'unknown'; let release = 'unknown'; let version = 'unknown'; let machine = 'unknown'; const stable = BOOT.StrArray.$$STable; return stable.REPR.allocateFromArray(stable, [sysname, release, version, machine]); };