From 265cf4c5802982b1d727f804e6278368f6d6a49e Mon Sep 17 00:00:00 2001 From: Jerome Wu Date: Tue, 3 Nov 2020 15:36:44 +0800 Subject: [PATCH] Complete major refactor --- src/browser/defaultOptions.js | 10 +- src/browser/fetchFile.js | 13 +- .../{getModule.js => getCreateFFmpegCore.js} | 13 +- src/browser/index.js | 4 +- src/config.js | 52 +++++ src/constants/defaultArgs.js | 5 - src/constants/defaultOptions.js | 5 - src/createFFmpeg.js | 188 ++++++++++-------- src/index.js | 30 +++ src/node/defaultOptions.js | 4 +- src/node/fetchFile.js | 9 +- src/node/getCreateFFmpegCore.js | 7 + src/node/getModule.js | 6 - src/node/index.js | 4 +- src/utils/getEnvironment.js | 21 -- src/utils/log.js | 23 ++- src/utils/parseArgs.js | 58 +----- src/utils/parseProgress.js | 3 +- src/utils/resolvePaths.js | 12 -- src/utils/string2pointer.js | 8 - src/utils/stringList2pointer.js | 12 -- 21 files changed, 248 insertions(+), 239 deletions(-) rename src/browser/{getModule.js => getCreateFFmpegCore.js} (76%) create mode 100644 src/config.js delete mode 100755 src/constants/defaultArgs.js delete mode 100644 src/constants/defaultOptions.js create mode 100644 src/node/getCreateFFmpegCore.js delete mode 100644 src/node/getModule.js delete mode 100644 src/utils/getEnvironment.js delete mode 100644 src/utils/resolvePaths.js delete mode 100644 src/utils/string2pointer.js delete mode 100644 src/utils/stringList2pointer.js diff --git a/src/browser/defaultOptions.js b/src/browser/defaultOptions.js index 1d9db84..12ce80e 100644 --- a/src/browser/defaultOptions.js +++ b/src/browser/defaultOptions.js @@ -1,13 +1,11 @@ const resolveURL = require('resolve-url'); -const { dependencies } = require('../../package.json'); -const defaultOptions = require('../constants/defaultOptions'); +const { devDependencies } = require('../../package.json'); /* - * Default options for browser worker + * Default options for browser environment */ module.exports = { - ...defaultOptions, corePath: (typeof process !== 'undefined' && process.env.FFMPEG_ENV === 'development') - ? resolveURL('/node_modules/@ffmpeg/core/ffmpeg-core.js') - : `https://unpkg.com/@ffmpeg/core@v${dependencies['@ffmpeg/core'].substring(1)}/ffmpeg-core.js`, + ? resolveURL('/node_modules/@ffmpeg/core/dist/ffmpeg-core.js') + : `https://unpkg.com/@ffmpeg/core@v${devDependencies['@ffmpeg/core'].substring(1)}/ffmpeg-core.js`, }; diff --git a/src/browser/fetchFile.js b/src/browser/fetchFile.js index 823aa45..74dcb7d 100644 --- a/src/browser/fetchFile.js +++ b/src/browser/fetchFile.js @@ -1,12 +1,5 @@ const resolveURL = require('resolve-url'); -/** - * readFromBlobOrFile - * - * @name readFromBlobOrFile - * @function - * @access private - */ const readFromBlobOrFile = (blob) => ( new Promise((resolve, reject) => { const fileReader = new FileReader(); @@ -23,19 +16,21 @@ const readFromBlobOrFile = (blob) => ( module.exports = async (_data) => { let data = _data; if (typeof _data === 'undefined') { - return 'undefined'; + return new Uint8Array(); } if (typeof _data === 'string') { - // Base64 _data + /* From base64 format */ if (/data:_data\/([a-zA-Z]*);base64,([^"]*)/.test(_data)) { data = atob(_data.split(',')[1]) .split('') .map((c) => c.charCodeAt(0)); + /* From remote server/URL */ } else { const res = await fetch(resolveURL(_data)); data = await res.arrayBuffer(); } + /* From Blob or File */ } else if (_data instanceof File || _data instanceof Blob) { data = await readFromBlobOrFile(_data); } diff --git a/src/browser/getModule.js b/src/browser/getCreateFFmpegCore.js similarity index 76% rename from src/browser/getModule.js rename to src/browser/getCreateFFmpegCore.js index 896e3a9..725b1fe 100644 --- a/src/browser/getModule.js +++ b/src/browser/getCreateFFmpegCore.js @@ -1,8 +1,10 @@ +const resolveURL = require('resolve-url'); const { log } = require('../utils/log'); -module.exports = async ({ corePath }) => { - if (typeof window.Module === 'undefined') { +module.exports = async ({ corePath: _corePath }) => { + if (typeof window.createFFmpegCore === 'undefined') { log('info', 'fetch ffmpeg-core.worker.js script'); + const corePath = resolveURL(_corePath); const workerBlob = await (await fetch(corePath.replace('ffmpeg-core.js', 'ffmpeg-core.worker.js'))).blob(); window.FFMPEG_CORE_WORKER_SCRIPT = URL.createObjectURL(workerBlob); log('info', `worker object URL=${window.FFMPEG_CORE_WORKER_SCRIPT}`); @@ -12,10 +14,7 @@ module.exports = async ({ corePath }) => { const eventHandler = () => { script.removeEventListener('load', eventHandler); log('info', 'initialize ffmpeg-core'); - window.Module.onRuntimeInitialized = () => { - log('info', 'ffmpeg-core initialized'); - resolve(window.Module); - }; + resolve(window.createFFmpegCore); }; script.src = corePath; script.type = 'text/javascript'; @@ -24,5 +23,5 @@ module.exports = async ({ corePath }) => { }); } log('info', 'ffmpeg-core is loaded already'); - return Promise.resolve(window.Module); + return Promise.resolve(window.createFFmpegCore); }; diff --git a/src/browser/index.js b/src/browser/index.js index 85ade1f..e73bfaa 100644 --- a/src/browser/index.js +++ b/src/browser/index.js @@ -1,9 +1,9 @@ const defaultOptions = require('./defaultOptions'); -const getModule = require('./getModule'); +const getCreateFFmpegCore = require('./getCreateFFmpegCore'); const fetchFile = require('./fetchFile'); module.exports = { defaultOptions, - getModule, + getCreateFFmpegCore, fetchFile, }; diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..88120fe --- /dev/null +++ b/src/config.js @@ -0,0 +1,52 @@ +module.exports = { + defaultArgs: [ + /* args[0] is always the binary path */ + './ffmpeg', + /* Disable interaction mode */ + '-nostdin', + /* Force to override output file */ + '-y', + /* Not to output banner */ + '-hide_banner', + ], + baseOptions: { + /* Flag to turn on/off log messages in console */ + log: false, + /* + * Custom logger to get ffmpeg.wasm output messages. + * a sample logger looks like this: + * + * ``` + * logger = ({ type, message }) => { + * console.log(type, message); + * } + * ``` + * + * type can be one of following: + * + * info: internal workflow debug messages + * fferr: ffmpeg native stderr output + * ffout: ffmpeg native stdout output + */ + logger: () => {}, + /* + * Progress handler to get current progress of ffmpeg command. + * a sample progress handler looks like this: + * + * ``` + * progress = ({ ratio }) => { + * console.log(ratio); + * } + * ``` + * + * ratio is a float number between 0 to 1. + */ + progress: () => {}, + /* + * Path to find/download ffmpeg.wasm-core, + * this value should be overwriten by `defaultOptions` in + * each environment. + */ + corePath: '', + }, +}; diff --git a/src/constants/defaultArgs.js b/src/constants/defaultArgs.js deleted file mode 100755 index 196b8e0..0000000 --- a/src/constants/defaultArgs.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = [ - './ffmpeg', // args[0] is always binary path - '-nostdin', // Disable interaction mode - '-hide_banner', // Not to output banner -]; diff --git a/src/constants/defaultOptions.js b/src/constants/defaultOptions.js deleted file mode 100644 index f1732fe..0000000 --- a/src/constants/defaultOptions.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - log: false, - logger: () => {}, - progress: () => {}, -}; diff --git a/src/createFFmpeg.js b/src/createFFmpeg.js index 6db4183..4d66ce4 100644 --- a/src/createFFmpeg.js +++ b/src/createFFmpeg.js @@ -1,21 +1,14 @@ -const defaultArgs = require('./constants/defaultArgs'); -const { setLogging, log } = require('./utils/log'); -const resolvePaths = require('./utils/resolvePaths'); +const { defaultArgs, baseOptions } = require('./config'); +const { setLogging, setCustomLogger, log } = require('./utils/log'); const parseProgress = require('./utils/parseProgress'); -const stringList2pointer = require('./utils/stringList2pointer'); const parseArgs = require('./utils/parseArgs'); -const { - defaultOptions, - getModule, - fetchFile, -} = require('./node'); +const { defaultOptions, getCreateFFmpegCore } = require('./node'); -const NO_LOAD = Error('FFmpeg.js is not ready, make sure you have completed load().'); -const NO_MULTIPLE_RUN = Error('FFmpeg.js can only run one command at a time'); -let Module = null; -let ffmpeg = null; +const NO_LOAD = Error('ffmpeg.wasm is not ready, make sure you have completed load().'); module.exports = (_options = {}) => { + let Core = null; + let ffmpeg = null; let runResolve = null; let running = false; const { @@ -23,109 +16,134 @@ module.exports = (_options = {}) => { logger, progress, ...options - } = resolvePaths({ + } = { + ...baseOptions, ...defaultOptions, ..._options, - }); - const detectCompletion = ({ message, type }) => { - if (type === 'ffmpeg-stdout' - && message === 'FFMPEG_END' - && runResolve !== null) { + }; + const detectCompletion = (message) => { + if (message === 'FFMPEG_END' && runResolve !== null) { runResolve(); runResolve = null; running = false; } }; + const parseMessage = ({ type, message }) => { + log(type, message); + parseProgress(message, progress); + detectCompletion(message); + }; - setLogging(logging); - + /* + * Load ffmpeg.wasm-core script. + * In browser environment, the ffmpeg.wasm-core script is fetch from + * CDN and can be assign to a local path by assigning `corePath`. + * In node environment, we use dynamic require and the default `corePath` + * is `$ffmpeg/core`. + * + * Typically the load() func might take few seconds to minutes to complete, + * better to do it as early as possible. + * + */ const load = async () => { - if (Module === null) { - log('info', 'load ffmpeg-core'); - Module = await getModule(options); - Module.setLogger((_log) => { - detectCompletion(_log); - parseProgress(_log, progress); - logger(_log); - log(_log.type, _log.message); + log('info', 'load ffmpeg-core'); + if (Core === null) { + log('info', 'loading ffmpeg-core'); + const createFFmpegCore = await getCreateFFmpegCore(options); + Core = await createFFmpegCore({ + printErr: (message) => parseMessage({ type: 'fferr', message }), + print: (message) => parseMessage({ type: 'ffout', message }), }); - if (ffmpeg === null) { - ffmpeg = Module.cwrap('proxy_main', 'number', ['number', 'number']); - } + ffmpeg = Core.cwrap('proxy_main', 'number', ['number', 'number']); log('info', 'ffmpeg-core loaded'); - } - }; - - const FS = (method, args) => { - if (Module === null) { - throw NO_LOAD; } else { - log('info', `FS.${method} ${args[0]}`); - return Module.FS[method](...args); + throw Error('ffmpeg.wasm was loaded, you should not load it again, use ffmpeg.isLoaded() to check next time.'); } }; - const write = async (path, data) => ( - FS('writeFile', [path, await fetchFile(data)]) - ); - const writeText = (path, text) => ( - FS('writeFile', [path, text]) - ); + /* + * Determine whether the Core is loaded. + */ + const isLoaded = () => Core !== null; - const read = (path) => ( - FS('readFile', [path]) - ); - - const remove = (path) => ( - FS('unlink', [path]) - ); - - const ls = (path) => ( - FS('readdir', [path]) - ); - - const run = (_args) => { - if (ffmpeg === null) { + /* + * Run ffmpeg command. + * This is the major function in ffmpeg.wasm, you can just imagine it + * as ffmpeg native cli and what you need to pass is the same. + * + * For example, you can convert native command below: + * + * ``` + * $ ffmpeg -i video.avi -c:v libx264 video.mp4 + * ``` + * + * To + * + * ``` + * await ffmpeg.run('-i', 'video.avi', '-c:v', 'libx264', 'video.mp4'); + * ``` + * + */ + const run = (..._args) => { + log('info', `run ffmpeg command: ${_args.join(' ')}`); + if (Core === null) { throw NO_LOAD; } else if (running) { - throw NO_MULTIPLE_RUN; + throw Error('ffmpeg.wasm can only run one command at a time'); } else { running = true; return new Promise((resolve) => { - const args = [...defaultArgs, ...parseArgs(_args)].filter((s) => s.length !== 0); - log('info', `ffmpeg command: ${args.join(' ')}`); + const args = [...defaultArgs, ..._args].filter((s) => s.length !== 0); runResolve = resolve; - ffmpeg(args.length, stringList2pointer(Module, args)); + ffmpeg(...parseArgs(Core, args)); }); } }; - const transcode = (input, output, opts = '') => ( - run(`-i ${input} ${opts} ${output}`) - ); - - const trim = (input, output, from, to, opts = '') => ( - run(`-i ${input} -ss ${from} -to ${to} ${opts} ${output}`) - ); - - const concatDemuxer = (input, output, opts = '') => { - const text = input.reduce((acc, path) => `${acc}\nfile ${path}`, ''); - writeText('concat_list.txt', text); - return run(`-f concat -safe 0 -i concat_list.txt ${opts} ${output}`); + /* + * Run FS operations. + * For input/output file of ffmpeg.wasm, it is required to save them to MEMFS + * first so that ffmpeg.wasm is able to consume them. Here we rely on the FS + * methods provided by Emscripten. + * + * Common methods to use are: + * ffmpeg.FS('writeFile', 'video.avi', new Uint8Array(...)): writeFile writes + * data to MEMFS. You need to use Uint8Array for binary data. + * ffmpeg.FS('readFile', 'video.mp4'): readFile from MEMFS. + * ffmpeg.FS('unlink', 'video.map'): delete file from MEMFS. + * + * For more info, check https://emscripten.org/docs/api_reference/Filesystem-API.html + * + */ + const FS = (method, ...args) => { + log('info', `run FS.${method} ${args.map((arg) => (typeof arg === 'string' ? arg : `<${arg.length} bytes binary file>`)).join(' ')}`); + if (Core === null) { + throw NO_LOAD; + } else { + let ret = null; + try { + ret = Core.FS[method](...args); + } catch (e) { + if (method === 'readdir') { + throw Error(`ffmpeg.FS('readdir', '${args[0]}') error. Check if the path exists, ex: ffmpeg.FS('readdir', '/')`); + } else if (method === 'readFile') { + throw Error(`ffmpeg.FS('readFile', '${args[0]}') error. Check if the path exists`); + } else { + throw Error('Oops, something went wrong in FS operation.'); + } + } + return ret; + } }; + setLogging(logging); + setCustomLogger(logger); + return { load, - FS, - write, - writeText, - read, - remove, - ls, + isLoaded, run, - transcode, - trim, - concatDemuxer, + FS, }; }; diff --git a/src/index.js b/src/index.js index 36f717e..8c69a5b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,36 @@ require('regenerator-runtime/runtime'); const createFFmpeg = require('./createFFmpeg'); +const { fetchFile } = require('./node'); module.exports = { + /* + * Create ffmpeg instance. + * Each ffmpeg instance owns an isolated MEMFS and works + * independently. + * + * For example: + * + * ``` + * const ffmpeg = createFFmpeg({ + * log: true, + * logger: () => {}, + * progress: () => {}, + * corePath: '', + * }) + * ``` + * + * For the usage of these four arguments, check config.js + * + */ createFFmpeg, + /* + * Helper function for fetching files from various resource. + * Sometimes the video/audio file you want to process may located + * in a remote URL and somewhere in your local file system. + * + * This helper function helps you to fetch to file and return an + * Uint8Array variable for ffmpeg.wasm to consume. + * + */ + fetchFile, }; diff --git a/src/node/defaultOptions.js b/src/node/defaultOptions.js index b3d3568..5b22e73 100644 --- a/src/node/defaultOptions.js +++ b/src/node/defaultOptions.js @@ -1,8 +1,6 @@ -const defaultOptions = require('../constants/defaultOptions'); - /* * Default options for node environment */ module.exports = { - ...defaultOptions, + corePath: '@ffmpeg/core', }; diff --git a/src/node/fetchFile.js b/src/node/fetchFile.js index ad94150..9c181bf 100644 --- a/src/node/fetchFile.js +++ b/src/node/fetchFile.js @@ -10,14 +10,21 @@ module.exports = async (_data) => { } if (typeof _data === 'string') { - if (isURL(_data) || _data.startsWith('chrome-extension://') || _data.startsWith('file://')) { + /* From remote URL/server */ + if (isURL(_data) + || _data.startsWith('moz-extension://') + || _data.startsWith('chrome-extension://') + || _data.startsWith('file://')) { const res = await fetch(_data); data = await res.arrayBuffer(); + /* From base64 format */ } else if (/data:_data\/([a-zA-Z]*);base64,([^"]*)/.test(_data)) { data = Buffer.from(_data.split(',')[1], 'base64'); + /* From local file path */ } else { data = await util.promisify(fs.readFile)(_data); } + /* From Buffer */ } else if (Buffer.isBuffer(_data)) { data = _data; } diff --git a/src/node/getCreateFFmpegCore.js b/src/node/getCreateFFmpegCore.js new file mode 100644 index 0000000..49b536f --- /dev/null +++ b/src/node/getCreateFFmpegCore.js @@ -0,0 +1,7 @@ +const { log } = require('../utils/log'); + +module.exports = ({ corePath }) => new Promise((resolve) => { + log('info', `fetch ffmpeg.wasm-core script from ${corePath}`); + // eslint-disable-next-line import/no-dynamic-require + resolve(require(corePath)); +}); diff --git a/src/node/getModule.js b/src/node/getModule.js deleted file mode 100644 index 51f54fa..0000000 --- a/src/node/getModule.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = () => new Promise((resolve) => { - const Module = require('@ffmpeg/core'); - Module.onRuntimeInitialized = () => { - resolve(Module); - }; -}); diff --git a/src/node/index.js b/src/node/index.js index 85ade1f..e73bfaa 100644 --- a/src/node/index.js +++ b/src/node/index.js @@ -1,9 +1,9 @@ const defaultOptions = require('./defaultOptions'); -const getModule = require('./getModule'); +const getCreateFFmpegCore = require('./getCreateFFmpegCore'); const fetchFile = require('./fetchFile'); module.exports = { defaultOptions, - getModule, + getCreateFFmpegCore, fetchFile, }; diff --git a/src/utils/getEnvironment.js b/src/utils/getEnvironment.js deleted file mode 100644 index 3b4f100..0000000 --- a/src/utils/getEnvironment.js +++ /dev/null @@ -1,21 +0,0 @@ -const isElectron = require('is-electron'); - -module.exports = (key) => { - const env = {}; - - if (isElectron()) { - env.type = 'electron'; - } else if (typeof window === 'object') { - env.type = 'browser'; - } else if (typeof importScripts === 'function') { - env.type = 'webworker'; - } else if (typeof process === 'object' && typeof require === 'function') { - env.type = 'node'; - } - - if (typeof key === 'undefined') { - return env; - } - - return env[key]; -}; diff --git a/src/utils/log.js b/src/utils/log.js index 34ef0ce..bb2f0fb 100644 --- a/src/utils/log.js +++ b/src/utils/log.js @@ -1,9 +1,24 @@ let logging = false; +let customLogger = () => {}; -exports.logging = logging; - -exports.setLogging = (_logging) => { +const setLogging = (_logging) => { logging = _logging; }; -exports.log = (type, message) => (logging ? console.log(`[${type}] ${message}`) : null); +const setCustomLogger = (logger) => { + customLogger = logger; +}; + +const log = (type, message) => { + customLogger({ type, message }); + if (logging) { + console.log(`[${type}] ${message}`); + } +}; + +module.exports = { + logging, + setLogging, + setCustomLogger, + log, +}; diff --git a/src/utils/parseArgs.js b/src/utils/parseArgs.js index 27cc81b..94e7e6a 100644 --- a/src/utils/parseArgs.js +++ b/src/utils/parseArgs.js @@ -1,51 +1,9 @@ -module.exports = (cmd) => { - const args = []; - let nextDelimiter = 0; - let prevDelimiter = 0; - // eslint-disable-next-line no-cond-assign - while ((nextDelimiter = cmd.indexOf(' ', prevDelimiter)) >= 0) { - let arg = cmd.substring(prevDelimiter, nextDelimiter); - let quoteIdx = arg.indexOf('\''); - let dblQuoteIdx = arg.indexOf('"'); - - if (quoteIdx === 0 || dblQuoteIdx === 0) { - /* The argument has a quote at the start i.e, 'id=0,streams=0 id=1,streams=1' */ - const delimiter = arg[0]; - const endDelimiter = cmd.indexOf(delimiter, prevDelimiter + 1); - - if (endDelimiter < 0) { - throw new Error(`Bad command escape sequence ${delimiter} near ${nextDelimiter}`); - } - - arg = cmd.substring(prevDelimiter + 1, endDelimiter); - prevDelimiter = endDelimiter + 2; - args.push(arg); - } else if (quoteIdx > 0 || dblQuoteIdx > 0) { - /* The argument has a quote in it, it must be ended correctly i,e. title='test' */ - if (quoteIdx === -1) quoteIdx = Infinity; - if (dblQuoteIdx === -1) dblQuoteIdx = Infinity; - const delimiter = (quoteIdx < dblQuoteIdx) ? '\'' : '"'; - const quoteOffset = Math.min(quoteIdx, dblQuoteIdx); - const endDelimiter = cmd.indexOf(delimiter, prevDelimiter + quoteOffset + 1); - - if (endDelimiter < 0) { - throw new Error(`Bad command escape sequence ${delimiter} near ${nextDelimiter}`); - } - - arg = cmd.substring(prevDelimiter, endDelimiter + 1); - prevDelimiter = endDelimiter + 2; - args.push(arg); - } else if (arg !== '') { - args.push(arg); - prevDelimiter = nextDelimiter + 1; - } else { - prevDelimiter = nextDelimiter + 1; - } - } - - if (prevDelimiter !== cmd.length) { - args.push(cmd.substring(prevDelimiter)); - } - - return args; +module.exports = (Core, args) => { + const argsPtr = Core._malloc(args.length * Uint32Array.BYTES_PER_ELEMENT); + args.forEach((s, idx) => { + const buf = Core._malloc(s.length + 1); + Core.writeAsciiToMemory(s, buf); + Core.setValue(argsPtr + (Uint32Array.BYTES_PER_ELEMENT * idx), buf, 'i32'); + }); + return [args.length, argsPtr]; }; diff --git a/src/utils/parseProgress.js b/src/utils/parseProgress.js index 20fc521..93fdd8a 100644 --- a/src/utils/parseProgress.js +++ b/src/utils/parseProgress.js @@ -5,7 +5,7 @@ const ts2sec = (ts) => { return (parseFloat(h) * 60 * 60) + (parseFloat(m) * 60) + parseFloat(s); }; -module.exports = ({ message }, progress) => { +module.exports = (message, progress) => { if (typeof message === 'string') { if (message.startsWith(' Duration')) { const ts = message.split(', ')[0].split(': ')[1]; @@ -19,6 +19,7 @@ module.exports = ({ message }, progress) => { progress({ ratio: t / duration }); } else if (message.startsWith('video:')) { progress({ ratio: 1 }); + duration = 0; } } }; diff --git a/src/utils/resolvePaths.js b/src/utils/resolvePaths.js deleted file mode 100644 index 717d9fc..0000000 --- a/src/utils/resolvePaths.js +++ /dev/null @@ -1,12 +0,0 @@ -const isBrowser = require('./getEnvironment')('type') === 'browser'; -const resolveURL = isBrowser ? require('resolve-url') : s => s; // eslint-disable-line - -module.exports = (options) => { - const opts = { ...options }; - ['corePath'].forEach((key) => { - if (typeof options[key] !== 'undefined') { - opts[key] = resolveURL(opts[key]); - } - }); - return opts; -}; diff --git a/src/utils/string2pointer.js b/src/utils/string2pointer.js deleted file mode 100644 index f8e1198..0000000 --- a/src/utils/string2pointer.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = (Module, s) => { - const ptr = Module._malloc((s.length + 1) * Uint8Array.BYTES_PER_ELEMENT); - for (let i = 0; i < s.length; i += 1) { - Module.setValue(ptr + i, s.charCodeAt(i), 'i8'); - } - Module.setValue(ptr + s.length, 0, 'i8'); - return ptr; -}; diff --git a/src/utils/stringList2pointer.js b/src/utils/stringList2pointer.js deleted file mode 100644 index d9523cb..0000000 --- a/src/utils/stringList2pointer.js +++ /dev/null @@ -1,12 +0,0 @@ -const string2pointer = require('./string2pointer'); - -module.exports = (Module, strList) => { - const listPtr = Module._malloc(strList.length * Uint32Array.BYTES_PER_ELEMENT); - - strList.forEach((s, idx) => { - const strPtr = string2pointer(Module, s); - Module.setValue(listPtr + (4 * idx), strPtr, 'i32'); - }); - - return listPtr; -};