diff --git a/lib/read-wasm-browser.js b/lib/read-wasm-browser.js deleted file mode 100644 index a4fb29c2..00000000 --- a/lib/read-wasm-browser.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; - -let mappingsWasm = null; - -module.exports = function readWasm() { - if (typeof mappingsWasm === "string") { - return fetch(mappingsWasm).then(response => response.arrayBuffer()); - } - if (mappingsWasm instanceof ArrayBuffer) { - return Promise.resolve(mappingsWasm); - } - - throw new Error( - "You must provide the string URL or ArrayBuffer contents " + - "of lib/mappings.wasm by calling " + - "SourceMapConsumer.initialize({ 'lib/mappings.wasm': ... }) " + - "before using SourceMapConsumer" - ); -}; - -module.exports.initialize = input => { - mappingsWasm = input; -}; diff --git a/lib/read-wasm.js b/lib/read-wasm.js deleted file mode 100644 index 2ce01a75..00000000 --- a/lib/read-wasm.js +++ /dev/null @@ -1,27 +0,0 @@ -"use strict"; - -// Note: This file is replaced with "read-wasm-browser.js" when this module is -// bundled with a packager that takes package.json#browser fields into account. - -const fs = require("fs"); -const path = require("path"); - -module.exports = function readWasm() { - return new Promise((resolve, reject) => { - const wasmPath = path.join(__dirname, "mappings.wasm"); - fs.readFile(wasmPath, null, (error, data) => { - if (error) { - reject(error); - return; - } - - resolve(data.buffer); - }); - }); -}; - -module.exports.initialize = _ => { - console.debug( - "SourceMapConsumer.initialize is a no-op when running in node.js" - ); -}; diff --git a/lib/source-map-consumer.js b/lib/source-map-consumer.js index aa3357d7..465f97f5 100644 --- a/lib/source-map-consumer.js +++ b/lib/source-map-consumer.js @@ -9,7 +9,6 @@ const util = require("./util"); const binarySearch = require("./binary-search"); const ArraySet = require("./array-set").ArraySet; const base64VLQ = require("./base64-vlq"); // eslint-disable-line no-unused-vars -const readWasm = require("../lib/read-wasm"); const wasm = require("./wasm"); const INTERNAL = Symbol("smcInternal"); diff --git a/lib/wasm.js b/lib/wasm.js index 3091d9ee..7c0b25ed 100644 --- a/lib/wasm.js +++ b/lib/wasm.js @@ -1,4 +1,33 @@ -const readWasm = require("../lib/read-wasm"); +let cachedWasm = null; + +module.exports = async function wasm() { + if (cachedWasm) { + return cachedWasm; + } + + let wasmExports; + + // Once we support Es Modules is Workers in Firefox, + // we can migrate all modules from CommonJS to ES Modules, especially the current module + // and import the wasm mjs from the top level and no longar have to be async here! + // + // => This mean that we will no longer require to be async in this library, at least on nodejs + const wasm = await import("../wasm-mappings/source-map-mappings-wasm-api/source_map_mappings_wasm_api.mjs"); + if (true /* IS NODE */) { + const path = require('path').join(__dirname, '../wasm-mappings/source-map-mappings-wasm-api/source_map_mappings_wasm_api_bg.wasm'); + const bytes = require('fs').readFileSync(path); + const wasmModule = new WebAssembly.Module(bytes); + wasmExports = wasm.initSync(wasmModule); + } else { /* IS BROWSER */ + wasmExports = await wasm.default("../wasm-mappings/source-map-mappings-wasm-api/source_map_mappings_wasm_api.wasm"); + } + + cachedWasm = { + exports: wasmExports, + withMappingCallback, + }; + return cachedWasm; +}; /** * Provide the JIT with a nice shape / hidden class. @@ -13,126 +42,54 @@ function Mapping() { this.name = null; } -let cachedWasm = null; +const callbackStack = []; -module.exports = function wasm() { - if (cachedWasm) { - return cachedWasm; +function withMappingCallback(mappingCallback, f) { + callbackStack.push(mappingCallback); + try { + f(); + } finally { + callbackStack.pop(); } +} - const callbackStack = []; - - cachedWasm = readWasm() - .then(buffer => { - return WebAssembly.instantiate(buffer, { - env: { - mapping_callback( - generatedLine, - generatedColumn, - - hasLastGeneratedColumn, - lastGeneratedColumn, - - hasOriginal, - source, - originalLine, - originalColumn, - - hasName, - name - ) { - const mapping = new Mapping(); - // JS uses 1-based line numbers, wasm uses 0-based. - mapping.generatedLine = generatedLine + 1; - mapping.generatedColumn = generatedColumn; - - if (hasLastGeneratedColumn) { - // JS uses inclusive last generated column, wasm uses exclusive. - mapping.lastGeneratedColumn = lastGeneratedColumn - 1; - } - - if (hasOriginal) { - mapping.source = source; - // JS uses 1-based line numbers, wasm uses 0-based. - mapping.originalLine = originalLine + 1; - mapping.originalColumn = originalColumn; - - if (hasName) { - mapping.name = name; - } - } - - callbackStack[callbackStack.length - 1](mapping); - }, - - start_all_generated_locations_for() { - console.time("all_generated_locations_for"); - }, - end_all_generated_locations_for() { - console.timeEnd("all_generated_locations_for"); - }, - - start_compute_column_spans() { - console.time("compute_column_spans"); - }, - end_compute_column_spans() { - console.timeEnd("compute_column_spans"); - }, - - start_generated_location_for() { - console.time("generated_location_for"); - }, - end_generated_location_for() { - console.timeEnd("generated_location_for"); - }, - - start_original_location_for() { - console.time("original_location_for"); - }, - end_original_location_for() { - console.timeEnd("original_location_for"); - }, - - start_parse_mappings() { - console.time("parse_mappings"); - }, - end_parse_mappings() { - console.timeEnd("parse_mappings"); - }, - - start_sort_by_generated_location() { - console.time("sort_by_generated_location"); - }, - end_sort_by_generated_location() { - console.timeEnd("sort_by_generated_location"); - }, - - start_sort_by_original_location() { - console.time("sort_by_original_location"); - }, - end_sort_by_original_location() { - console.timeEnd("sort_by_original_location"); - }, - }, - }); - }) - .then(Wasm => { - return { - exports: Wasm.instance.exports, - withMappingCallback: (mappingCallback, f) => { - callbackStack.push(mappingCallback); - try { - f(); - } finally { - callbackStack.pop(); - } - }, - }; - }) - .then(null, e => { - cachedWasm = null; - throw e; - }); - - return cachedWasm; -}; +// Expose this method to WASM/Rust +module.exports.mapping_callback = + ( + generatedLine, + generatedColumn, + + hasLastGeneratedColumn, + lastGeneratedColumn, + + hasOriginal, + source, + originalLine, + originalColumn, + + hasName, + name + ) => { + const mapping = new Mapping(); + // JS uses 1-based line numbers, wasm uses 0-based. + mapping.generatedLine = generatedLine + 1; + mapping.generatedColumn = generatedColumn; + + if (hasLastGeneratedColumn) { + // JS uses inclusive last generated column, wasm uses exclusive. + mapping.lastGeneratedColumn = lastGeneratedColumn - 1; + } + + if (hasOriginal) { + mapping.source = source; + // JS uses 1-based line numbers, wasm uses 0-based. + mapping.originalLine = originalLine + 1; + mapping.originalColumn = originalColumn; + + if (hasName) { + mapping.name = name; + } + } + + callbackStack[callbackStack.length - 1](mapping); + }; diff --git a/package.json b/package.json index 00077059..3c697b68 100644 --- a/package.json +++ b/package.json @@ -49,8 +49,7 @@ "main": "./source-map.js", "types": "./source-map.d.ts", "browser": { - "./lib/url.js": "./lib/url-browser.js", - "./lib/read-wasm.js": "./lib/read-wasm-browser.js" + "./lib/url.js": "./lib/url-browser.js" }, "files": [ "source-map.js", diff --git a/wasm-mappings/Cargo.toml b/wasm-mappings/Cargo.toml index 6e075f37..eff301e5 100644 --- a/wasm-mappings/Cargo.toml +++ b/wasm-mappings/Cargo.toml @@ -21,7 +21,8 @@ repository = "https://github.com/mozilla/source-map" version = "0.5.0" [dependencies] -rand = "0.4.1" +rand = "0.8.5" +getrandom = { version = "0.2.8", features = ["js"] } vlq = "0.5.1" [dev-dependencies] diff --git a/wasm-mappings/source-map-mappings-wasm-api/Cargo.toml b/wasm-mappings/source-map-mappings-wasm-api/Cargo.toml index 43683b01..81bcbd56 100644 --- a/wasm-mappings/source-map-mappings-wasm-api/Cargo.toml +++ b/wasm-mappings/source-map-mappings-wasm-api/Cargo.toml @@ -9,6 +9,7 @@ version = "0.5.0" [dependencies] source-map-mappings = { version = "0.5.0", path = ".." } +wasm-bindgen = { version ="0.2.83" } [features] profiling = [] diff --git a/wasm-mappings/source-map-mappings-wasm-api/build-wasm-bindgen.sh b/wasm-mappings/source-map-mappings-wasm-api/build-wasm-bindgen.sh new file mode 100755 index 00000000..d5530d35 --- /dev/null +++ b/wasm-mappings/source-map-mappings-wasm-api/build-wasm-bindgen.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +cargo build --target=wasm32-unknown-unknown +wasm-bindgen target/wasm32-unknown-unknown/debug/source_map_mappings_wasm_api.wasm --out-dir . --target web --no-typescript +mv source_map_mappings_wasm_api.js source_map_mappings_wasm_api.mjs diff --git a/wasm-mappings/source-map-mappings-wasm-api/build.py b/wasm-mappings/source-map-mappings-wasm-api/build.py deleted file mode 100755 index 7ff2aab1..00000000 --- a/wasm-mappings/source-map-mappings-wasm-api/build.py +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import re -import subprocess -import sys - -DESC = """ - -Build, trim, and optimize the `.wasm` file for inclusion in the -`mozilla/source-map` library. - -Requires: - -- wasm-nm: https://github.com/fitzgen/wasm-nm -- wasm-gc: https://github.com/alexcrichton/wasm-gc -- wasm-snip: https://github.com/fitzgen/wasm-snip -- wasm-opt: https://github.com/WebAssembly/binaryen - -""" - -parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description=DESC) - -parser.add_argument( - "-g", - "--debug", - action="store_true", - help="Include debug info (the \"name\" section) in the final `.wasm` file.") - -parser.add_argument( - "-p", - "--profiling", - action="store_true", - help="Enable the `profiling` cargo feature.") - -parser.add_argument( - "-o", - "--output", - type=str, - default=None, - help="The path to write the output `.wasm` file to. If not supplied, the `.wasm` file is written to `stdout`.") - -parser.add_argument( - "--no-wasm-opt", - dest="wasm_opt", - action="store_false", - help="Do not run `wasm-opt`.") - -parser.add_argument( - "--no-wasm-gc", - dest="wasm_gc", - action="store_false", - help="Do not run `wasm-gc`.") - -parser.add_argument( - "--no-wasm-snip", - dest="wasm_snip", - action="store_false", - help="Do not run `wasm-snip`.") - -def decode(f): - return f.decode(encoding="utf-8", errors="ignore") - -def run(cmd, **kwargs): - sys.stderr.write(str(cmd) + "\n") - - if "stdout" not in kwargs: - kwargs["stdout"] = subprocess.PIPE - child = subprocess.run(cmd, **kwargs) - if child.returncode != 0: - raise Exception("{} did not exit OK".format(str(cmd))) - return decode(child.stdout) - -def add_path_ext_prefix(path, prefix): - (root, ext) = os.path.splitext(path) - return root + "." + prefix + ext - -def build(args): - cmd = ["cargo", "build", "--release", "--target", "wasm32-unknown-unknown"] - if args.profiling: - cmd.extend(["--features", "profiling"]) - run(cmd) - return "./target/wasm32-unknown-unknown/release/source_map_mappings_wasm_api.wasm" - -def wasm_gc(args, wasm_path): - if not args.wasm_gc: - return wasm_path - - out_path = add_path_ext_prefix(wasm_path, "gc") - run(["wasm-gc", wasm_path, out_path]) - return out_path - -SHOULD_SNIP = [ - re.compile(r".*(std|core)(9|::)panicking.*"), - re.compile(r".*(std|core)(3|::)fmt.*"), - re.compile(r".*core(6|::)option(13|::)expect_failed.*"), - re.compile(r".*core(5|::)slice(\d+|::)slice_index_.*_fail.*"), - re.compile(r".*core(3|::)str(\d+|::)slice_.*_fail.*"), - re.compile(r".*core(6|::)result(13|::)unwrap_failed.*"), - re.compile(r".*std(6|::)thread(5|::)local.*"), - re.compile(r".*std(2|::)io(5|::).*"), - re.compile(r"__.*2"), - re.compile(r".*(std|core)(5|::)error.*"), - re.compile(r".*(std|core)(3|::)any(3|::)Any.*"), -] - -def wasm_snip(args, wasm_path): - if not args.wasm_snip: - return wasm_path - - out_path = add_path_ext_prefix(wasm_path, "snip") - - private_functions = run(["wasm-nm", "-j", wasm_path]).splitlines() - - snip_functions = set() - for snip in SHOULD_SNIP: - snip_functions.update(filter(lambda f: re.match(snip, f), - private_functions)) - - run(["wasm-snip", "-o", out_path, wasm_path, *snip_functions]), - return out_path - -def wasm_opt(args, wasm_path): - if not args.wasm_opt: - return wasm_path - - out_path = add_path_ext_prefix(wasm_path, "opt") - - cmd = [ - "wasm-opt", - "-O3", - "-Oz", - "--duplicate-function-elimination", - "-o", out_path, - wasm_path - ] - if args.debug: - cmd.append("-g") - run(cmd) - return out_path - -def main(): - args = parser.parse_args() - os.chdir(os.path.dirname(sys.argv[0])) - - wasm_path = build(args) - wasm_path = wasm_gc(args, wasm_path) - wasm_path = wasm_snip(args, wasm_path) - # GC again after snipping. - wasm_path = wasm_gc(args, wasm_path) - wasm_path = wasm_opt(args, wasm_path) - - if args.output: - run(["cp", wasm_path, args.output]) - else: - run(["cat", wasm_path], stdout=subprocess.STDOUT) - -if __name__ == "__main__": - main() diff --git a/wasm-mappings/source-map-mappings-wasm-api/source_map_mappings_wasm_api.mjs b/wasm-mappings/source-map-mappings-wasm-api/source_map_mappings_wasm_api.mjs new file mode 100644 index 00000000..10ef384a --- /dev/null +++ b/wasm-mappings/source-map-mappings-wasm-api/source_map_mappings_wasm_api.mjs @@ -0,0 +1,242 @@ +import { mapping_callback } from '../../lib/wasm.js'; + +let wasm; + +const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); + +cachedTextDecoder.decode(); + +let cachedUint8Memory0 = new Uint8Array(); + +function getUint8Memory0() { + if (cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} +/** +* Get the last error's error code, or 0 if there was none. +* +* See `source_map_mappings::Error` for the error code definitions. +* @returns {number} +*/ +export function get_last_error() { + const ret = wasm.get_last_error(); + return ret >>> 0; +} + +/** +* Allocate space for a mappings string of the given size (in bytes). +* +* It is the JS callers responsibility to initialize the resulting buffer by +* copying the JS `String` holding the source map's "mappings" into it (encoded +* in ascii). +* @param {number} size +* @returns {number} +*/ +export function allocate_mappings(size) { + const ret = wasm.allocate_mappings(size); + return ret; +} + +/** +* Parse the given initialized mappings string into a `Mappings` structure. +* +* Returns `NULL` on failure, or a pointer to the parsed `Mappings` structure +* on success. +* +* In the case of failure, the error can be retrieved with `get_last_error`. +* +* In the case of success, the caller takes ownership of the result, and must +* call `free_mappings` to destroy it when finished. +* +* In both the success or failure cases, the caller gives up ownership of the +* input mappings string and must not use it again. +* @param {number} mappings +* @returns {number} +*/ +export function parse_mappings(mappings) { + const ret = wasm.parse_mappings(mappings); + return ret; +} + +/** +* Destroy the given `Mappings` structure. +* +* The caller gives up ownership of the mappings and must not use them again. +* @param {number} mappings +*/ +export function free_mappings(mappings) { + wasm.free_mappings(mappings); +} + +/** +* Invoke the `mapping_callback` on each mapping in the given `Mappings` +* structure, in order of generated location. +* @param {number} mappings +*/ +export function by_generated_location(mappings) { + wasm.by_generated_location(mappings); +} + +/** +* Compute column spans for the given mappings. +* @param {number} mappings +*/ +export function compute_column_spans(mappings) { + wasm.compute_column_spans(mappings); +} + +/** +* Invoke the `mapping_callback` on each mapping in the given `Mappings` +* structure that has original location information, in order of original +* location. +* @param {number} mappings +*/ +export function by_original_location(mappings) { + wasm.by_original_location(mappings); +} + +/** +* Find the mapping for the given generated location, if any exists. +* +* If a mapping is found, the `mapping_callback` is invoked with it +* once. Otherwise, the `mapping_callback` is not invoked at all. +* @param {number} mappings +* @param {number} generated_line +* @param {number} generated_column +* @param {number} bias +*/ +export function original_location_for(mappings, generated_line, generated_column, bias) { + wasm.original_location_for(mappings, generated_line, generated_column, bias); +} + +/** +* Find the mapping for the given original location, if any exists. +* +* If a mapping is found, the `mapping_callback` is invoked with it +* once. Otherwise, the `mapping_callback` is not invoked at all. +* @param {number} mappings +* @param {number} source +* @param {number} original_line +* @param {number} original_column +* @param {number} bias +*/ +export function generated_location_for(mappings, source, original_line, original_column, bias) { + wasm.generated_location_for(mappings, source, original_line, original_column, bias); +} + +/** +* Find all mappings for the given original location, and invoke the +* `mapping_callback` on each of them. +* +* If `has_original_column` is `true`, then the `mapping_callback` is only +* invoked with mappings with matching source and original line **and** +* original column is equal to `original_column`. If `has_original_column` is +* `false`, then the `original_column` argument is ignored, and the +* `mapping_callback` is invoked on all mappings with matching source and +* original line. +* @param {number} mappings +* @param {number} source +* @param {number} original_line +* @param {boolean} has_original_column +* @param {number} original_column +*/ +export function all_generated_locations_for(mappings, source, original_line, has_original_column, original_column) { + wasm.all_generated_locations_for(mappings, source, original_line, has_original_column, original_column); +} + +async function load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function getImports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbg_mappingcallback_af4710b7a58d26dd = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + mapping_callback(arg0 >>> 0, arg1 >>> 0, arg2 !== 0, arg3 >>> 0, arg4 !== 0, arg5 >>> 0, arg6 >>> 0, arg7 >>> 0, arg8 !== 0, arg9 >>> 0); + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + + return imports; +} + +function initMemory(imports, maybe_memory) { + +} + +function finalizeInit(instance, module) { + wasm = instance.exports; + init.__wbindgen_wasm_module = module; + cachedUint8Memory0 = new Uint8Array(); + + + return wasm; +} + +function initSync(module) { + const imports = getImports(); + + initMemory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return finalizeInit(instance, module); +} + +async function init(input) { + if (typeof input === 'undefined') { + input = new URL('source_map_mappings_wasm_api_bg.wasm', import.meta.url); + } + const imports = getImports(); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + initMemory(imports); + + const { instance, module } = await load(await input, imports); + + return finalizeInit(instance, module); +} + +export { initSync } +export default init; diff --git a/wasm-mappings/source-map-mappings-wasm-api/source_map_mappings_wasm_api_bg.wasm b/wasm-mappings/source-map-mappings-wasm-api/source_map_mappings_wasm_api_bg.wasm new file mode 100644 index 00000000..2089c62a Binary files /dev/null and b/wasm-mappings/source-map-mappings-wasm-api/source_map_mappings_wasm_api_bg.wasm differ diff --git a/wasm-mappings/source-map-mappings-wasm-api/src/lib.rs b/wasm-mappings/source-map-mappings-wasm-api/src/lib.rs index d91ed381..3a7242e2 100644 --- a/wasm-mappings/source-map-mappings-wasm-api/src/lib.rs +++ b/wasm-mappings/source-map-mappings-wasm-api/src/lib.rs @@ -19,12 +19,14 @@ //! 6. When finished with `Mappings` structure, dispose of it with //! `free_mappings`. -// NB: every exported function must be `#[no_mangle]` and `pub extern "C"`. - #![deny(missing_docs)] extern crate source_map_mappings; +extern crate wasm_bindgen; +use wasm_bindgen::prelude::*; + + use source_map_mappings::{Bias, Error, Mapping, Mappings}; use std::mem; use std::ptr; @@ -125,8 +127,8 @@ static mut LAST_ERROR: Option = None; /// Get the last error's error code, or 0 if there was none. /// /// See `source_map_mappings::Error` for the error code definitions. -#[no_mangle] -pub extern "C" fn get_last_error() -> u32 { +#[wasm_bindgen] +pub fn get_last_error() -> u32 { unsafe { match LAST_ERROR { None => 0, @@ -145,8 +147,8 @@ fn assert_pointer_is_word_aligned(p: *mut u8) { /// It is the JS callers responsibility to initialize the resulting buffer by /// copying the JS `String` holding the source map's "mappings" into it (encoded /// in ascii). -#[no_mangle] -pub extern "C" fn allocate_mappings(size: usize) -> *mut u8 { +#[wasm_bindgen] +pub fn allocate_mappings(size: usize) -> *mut u8 { // Make sure that we don't lose any bytes from size in the remainder. let size_in_units_of_usize = (size + mem::size_of::() - 1) / mem::size_of::(); @@ -191,8 +193,8 @@ where /// /// In both the success or failure cases, the caller gives up ownership of the /// input mappings string and must not use it again. -#[no_mangle] -pub extern "C" fn parse_mappings(mappings: *mut u8) -> *mut Mappings { +#[wasm_bindgen] +pub fn parse_mappings(mappings: *mut u8) -> *mut Mappings { assert_pointer_is_word_aligned(mappings); let mappings = mappings as *mut usize; @@ -236,8 +238,8 @@ pub extern "C" fn parse_mappings(mappings: *mut u8) -> *mut Mappings { /// Destroy the given `Mappings` structure. /// /// The caller gives up ownership of the mappings and must not use them again. -#[no_mangle] -pub extern "C" fn free_mappings(mappings: *mut Mappings) { +#[wasm_bindgen] +pub fn free_mappings(mappings: *mut Mappings) { unsafe { Box::from_raw(mappings); } @@ -251,6 +253,7 @@ unsafe fn mappings_mut<'a>( mappings.as_mut().unwrap() } +#[wasm_bindgen(raw_module = "../../lib/wasm.js")] extern "C" { fn mapping_callback( // These two parameters are always valid. @@ -323,8 +326,8 @@ unsafe fn invoke_mapping_callback(mapping: &Mapping) { /// Invoke the `mapping_callback` on each mapping in the given `Mappings` /// structure, in order of generated location. -#[no_mangle] -pub extern "C" fn by_generated_location(mappings: *mut Mappings) { +#[wasm_bindgen] +pub fn by_generated_location(mappings: *mut Mappings) { let this_scope = (); let mappings = unsafe { mappings_mut(&this_scope, mappings) }; @@ -337,8 +340,8 @@ pub extern "C" fn by_generated_location(mappings: *mut Mappings) { } /// Compute column spans for the given mappings. -#[no_mangle] -pub extern "C" fn compute_column_spans(mappings: *mut Mappings) { +#[wasm_bindgen] +pub fn compute_column_spans(mappings: *mut Mappings) { let this_scope = (); let mappings = unsafe { mappings_mut(&this_scope, mappings) }; @@ -348,8 +351,8 @@ pub extern "C" fn compute_column_spans(mappings: *mut Mappings) { /// Invoke the `mapping_callback` on each mapping in the given `Mappings` /// structure that has original location information, in order of original /// location. -#[no_mangle] -pub extern "C" fn by_original_location(mappings: *mut Mappings) { +#[wasm_bindgen] +pub fn by_original_location(mappings: *mut Mappings) { let this_scope = (); let mappings = unsafe { mappings_mut(&this_scope, mappings) }; @@ -381,8 +384,8 @@ fn u32_to_bias(bias: u32) -> Bias { /// /// If a mapping is found, the `mapping_callback` is invoked with it /// once. Otherwise, the `mapping_callback` is not invoked at all. -#[no_mangle] -pub extern "C" fn original_location_for( +#[wasm_bindgen] +pub fn original_location_for( mappings: *mut Mappings, generated_line: u32, generated_column: u32, @@ -403,8 +406,8 @@ pub extern "C" fn original_location_for( /// /// If a mapping is found, the `mapping_callback` is invoked with it /// once. Otherwise, the `mapping_callback` is not invoked at all. -#[no_mangle] -pub extern "C" fn generated_location_for( +#[wasm_bindgen] +pub fn generated_location_for( mappings: *mut Mappings, source: u32, original_line: u32, @@ -431,8 +434,8 @@ pub extern "C" fn generated_location_for( /// `false`, then the `original_column` argument is ignored, and the /// `mapping_callback` is invoked on all mappings with matching source and /// original line. -#[no_mangle] -pub extern "C" fn all_generated_locations_for( +#[wasm_bindgen] +pub fn all_generated_locations_for( mappings: *mut Mappings, source: u32, original_line: u32,