Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions napi/parser/bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -379,4 +379,5 @@ module.exports.ImportNameKind = nativeBinding.ImportNameKind
module.exports.parseAsync = nativeBinding.parseAsync
module.exports.parseSync = nativeBinding.parseSync
module.exports.parseSyncRaw = nativeBinding.parseSyncRaw
module.exports.rawTransferSupported = nativeBinding.rawTransferSupported
module.exports.Severity = nativeBinding.Severity
3 changes: 3 additions & 0 deletions napi/parser/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ export declare function parseSync(filename: string, sourceText: string, options?
*/
export declare function parseSyncRaw(filename: string, buffer: Uint8Array, sourceLen: number, options?: ParserOptions | undefined | null): void

/** Returns `true` if raw transfer is supported on this platform. */
export declare function rawTransferSupported(): boolean

export declare const enum Severity {
Error = 'Error',
Warning = 'Warning',
Expand Down
15 changes: 15 additions & 0 deletions napi/parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ module.exports.parseSync = function parseSync(filename, sourceText, options) {
let buffer, encoder;

function parseSyncRaw(filename, sourceText, options) {
if (!rawTransferSupported()) {
throw new Error('`experimentalRawTransfer` option is not supported on 32-bit or big-endian systems');
}

// Delete `experimentalRawTransfer` option
let experimentalRawTransfer;
({ experimentalRawTransfer, ...options } = options);
Expand Down Expand Up @@ -138,3 +142,14 @@ function createBuffer() {
const offset = bindings.getBufferOffset(new Uint8Array(arrayBuffer));
return new Uint8Array(arrayBuffer, offset, TWO_GIB);
}

let rawTransferIsSupported = null;

// Returns `true` if `experimentalRawTransfer` is option is supported.
// Raw transfer is only available on 64-bit little-endian systems.
function rawTransferSupported() {
if (rawTransferIsSupported === null) rawTransferIsSupported = bindings.rawTransferSupported();
return rawTransferIsSupported;
}

module.exports.rawTransferSupported = rawTransferSupported;
2 changes: 1 addition & 1 deletion napi/parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mod convert;
mod raw_transfer;
mod raw_transfer_types;
mod types;
pub use raw_transfer::{get_buffer_offset, parse_sync_raw};
pub use raw_transfer::{get_buffer_offset, parse_sync_raw, raw_transfer_supported};
pub use types::{Comment, EcmaScriptModule, ParseResult, ParserOptions};

mod generated {
Expand Down
20 changes: 17 additions & 3 deletions napi/parser/src/raw_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ use crate::{
raw_transfer_types::{EcmaScriptModule, Error, RawTransferData},
};

// Only 64-bit little-endian platforms are supported at present.
const IS_SUPPORTED_PLATFORM: bool =
cfg!(all(target_pointer_width = "64", target_endian = "little"));

// For raw transfer, use a buffer 4 GiB in size, with 4 GiB alignment.
// This ensures that all 64-bit pointers have the same value in upper 32 bits,
// so JS only needs to read the lower 32 bits to get an offset into the buffer.
Expand All @@ -26,7 +30,9 @@ use crate::{
// so this enables using `>>` bitshift operator in JS, rather than the more expensive `>>>`,
// without offsets being interpreted as negative.
const TWO_GIB: usize = 1 << 31;
const FOUR_GIB: usize = 1 << 32;
// `1 << 32`.
// We use `IS_SUPPORTED_PLATFORM as usize * 32` to avoid compilation failure on 32-bit platforms.
const FOUR_GIB: usize = 1 << (IS_SUPPORTED_PLATFORM as usize * 32);

const BUFFER_SIZE: usize = TWO_GIB;
const BUFFER_ALIGN: usize = FOUR_GIB;
Expand Down Expand Up @@ -75,8 +81,10 @@ pub unsafe fn parse_sync_raw(
source_len: u32,
options: Option<ParserOptions>,
) {
// 32-bit systems are not supported
const { assert!(std::mem::size_of::<usize>() >= 8) };
assert!(
IS_SUPPORTED_PLATFORM,
"Raw transfer is only supported on 64-bit little-endian platforms"
);

// Check buffer has expected size and alignment
let buffer = &mut *buffer;
Expand Down Expand Up @@ -176,6 +184,12 @@ pub unsafe fn parse_sync_raw(
}
}

/// Returns `true` if raw transfer is supported on this platform.
#[napi]
pub fn raw_transfer_supported() -> bool {
IS_SUPPORTED_PLATFORM
}

/// Returns `true` if `n` is a multiple of `divisor`.
const fn is_multiple_of(n: usize, divisor: usize) -> bool {
n % divisor == 0
Expand Down
Loading