Skip to content

Commit

Permalink
✨ feat: Add exception to transpile
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed Mar 8, 2024
1 parent ba8382f commit e80dd78
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 41 deletions.
File renamed without changes.
23 changes: 13 additions & 10 deletions rust/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,26 @@ use crate::{options, outputs};

const VERSION: &'static str = "0.1.0";

pub fn transpile<'local>(code: String, options: options::TranspileOptions) -> Option<outputs::TranspileOutput> {
pub fn transpile<'local>(code: String, options: options::TranspileOptions) -> Result<outputs::TranspileOutput, String> {
let url = ModuleSpecifier::parse(&format!("file:///{}", options.file_name)).unwrap();
let parsed_source = parse_module(ParseParams {
match parse_module(ParseParams {
specifier: url.to_string(),
text_info: SourceTextInfo::from_string(code.to_string()),
media_type: options.media_type,
capture_tokens: false,
maybe_syntax: None,
scope_analysis: false,
})
.unwrap();
let transpiled_js_code = parsed_source.transpile(&EmitOptions::default()).unwrap();
Some(outputs::TranspileOutput {
code: transpiled_js_code.text,
module: parsed_source.is_module(),
source_map: transpiled_js_code.source_map,
})
}) {
Ok(parsed_source) => match parsed_source.transpile(&EmitOptions::default()) {
Ok(transpiled_js_code) => Ok(outputs::TranspileOutput {
code: transpiled_js_code.text,
module: parsed_source.is_module(),
source_map: transpiled_js_code.source_map,
}),
Err(e) => Err(e.to_string()),
},
Err(e) => Err(e.to_string()),
}
}

pub fn get_version<'local>() -> &'local str {
Expand Down
75 changes: 75 additions & 0 deletions rust/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2024. caoccao.com Sam Cao
* All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use jni::objects::{GlobalRef, JStaticMethodID, JThrowable};
use jni::signature::ReturnType;
use jni::sys::{jvalue};
use jni::JNIEnv;

use crate::converter;

struct JniCalls {
pub jclass_core_exception: GlobalRef,
pub jmethod_id_core_exception_transpile_error: JStaticMethodID,
}
unsafe impl Send for JniCalls {}
unsafe impl Sync for JniCalls {}

static mut JNI_CALLS: Option<JniCalls> = None;

pub fn init<'local>(env: &mut JNIEnv<'local>) {
let jclass_core_exception = env
.find_class("com/caoccao/javet/swc4j/exceptions/Swc4jCoreException")
.expect("Couldn't find class Swc4jCoreException");
let jclass_core_exception = env
.new_global_ref(jclass_core_exception)
.expect("Couldn't globalize class Swc4jCoreException");
let jmethod_id_core_exception_transpile_error = env
.get_static_method_id(
&jclass_core_exception,
"transpileError",
"(Ljava/lang/String;)Lcom/caoccao/javet/swc4j/exceptions/Swc4jCoreException;",
)
.expect("Couldn't find static method Swc4jCoreException.transpileError");
unsafe {
JNI_CALLS = Some(JniCalls {
jclass_core_exception,
jmethod_id_core_exception_transpile_error,
});
}
}

pub fn throw_transpile_error<'local, 'a>(env: &mut JNIEnv<'local>, message: &'a str) {
let message = jvalue {
l: converter::string_to_jstring(env, message),
};
let exception = unsafe {
JThrowable::from_raw(
env
.call_static_method_unchecked(
&JNI_CALLS.as_ref().unwrap().jclass_core_exception,
&JNI_CALLS.as_ref().unwrap().jmethod_id_core_exception_transpile_error,
ReturnType::Object,
&[message],
)
.expect("Couldn't create transpile error")
.as_jni()
.l,
)
};
let _ = env.throw(exception);
}
15 changes: 10 additions & 5 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ use outputs::ToJniType;
use std::ffi::c_void;
use std::ptr::null_mut;

pub mod converter;
pub mod core;
pub mod error;
pub mod options;
pub mod outputs;
pub mod utils;

#[no_mangle]
pub extern "system" fn JNI_OnLoad<'local>(java_vm: JavaVM, _: c_void) -> jint {
debug_println!("JNI_OnLoad()");
let mut env = java_vm.get_env().expect("Cannot get JNI env");
error::init(&mut env);
options::init(&mut env);
outputs::init(&mut env);
JNI_VERSION_1_8
Expand All @@ -44,7 +46,7 @@ pub extern "system" fn Java_com_caoccao_javet_swc4j_Swc4jNative_coreGetVersion<'
env: JNIEnv<'local>,
_: JClass<'local>,
) -> jstring {
utils::converter::string_to_jstring(&env, core::get_version())
converter::string_to_jstring(&env, core::get_version())
}

#[no_mangle]
Expand All @@ -54,10 +56,13 @@ pub extern "system" fn Java_com_caoccao_javet_swc4j_Swc4jNative_coreTranspile<'l
code: jstring,
options: jobject,
) -> jobject {
let code = utils::converter::jstring_to_string(&mut env, code);
let code = converter::jstring_to_string(&mut env, code);
let options = options::TranspileOptions::from_jni_type(&mut env, options);
match core::transpile(code, options) {
Some(output) => output.to_jni_type(&mut env),
None => null_mut(),
Ok(output) => output.to_jni_type(&mut env),
Err(message) => {
error::throw_transpile_error(&mut env, message.as_str());
null_mut()
},
}
}
6 changes: 3 additions & 3 deletions rust/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use jni::JNIEnv;

use deno_ast::MediaType;

use crate::utils;
use crate::converter;

struct JniCalls {
pub jmethod_id_transpile_options_get_file_name: JMethodID,
Expand Down Expand Up @@ -85,7 +85,7 @@ impl FromJniType for TranspileOptions {
)
};
let file_name = unsafe { file_name.unwrap().as_jni().l };
let file_name = utils::converter::jstring_to_string(env, file_name);
let file_name = converter::jstring_to_string(env, file_name);
// media_type
let media_type = unsafe {
env.call_method_unchecked(
Expand All @@ -105,7 +105,7 @@ impl FromJniType for TranspileOptions {
)
};
let media_type = unsafe { media_type.unwrap().as_jni().i };
let media_type = utils::converter::media_type_id_to_media_type(media_type);
let media_type = converter::media_type_id_to_media_type(media_type);
// construct
TranspileOptions { file_name, media_type }
}
Expand Down
6 changes: 3 additions & 3 deletions rust/src/outputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use jni::JNIEnv;

use std::ptr::null_mut;

use crate::utils;
use crate::converter;

struct JniCalls {
pub jclass_transpile_output: GlobalRef,
Expand Down Expand Up @@ -64,14 +64,14 @@ pub struct TranspileOutput {
impl ToJniType for TranspileOutput {
fn to_jni_type<'local>(&self, env: &mut JNIEnv<'local>) -> jobject {
let code = jvalue {
l: utils::converter::string_to_jstring(env, &self.code),
l: converter::string_to_jstring(env, &self.code),
};
let module = jvalue {
z: if self.module { 1u8 } else { 0u8 },
};
let source_map = jvalue {
l: match &self.source_map {
Some(s) => utils::converter::string_to_jstring(env, &s),
Some(s) => converter::string_to_jstring(env, &s),
None => null_mut(),
},
};
Expand Down
18 changes: 0 additions & 18 deletions rust/src/utils.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,15 @@ private Swc4jCoreException(String message, Throwable cause) {
public static Swc4jCoreException featureNotSupported(String feature) {
return new Swc4jCoreException(MessageFormat.format("Feature {0} is not supported", feature));
}

/**
* Transpile error.
*
* @param message the message
* @return the swc4j core exception
* @since 0.1.0
*/
public static Swc4jCoreException transpileError(String message) {
return new Swc4jCoreException(message);
}
}
21 changes: 19 additions & 2 deletions src/test/java/com/caoccao/javet/swc4j/TestSwc4j.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void testGetVersion() {
}

@Test
public void testTranspile() throws Swc4jCoreException {
public void testTranspileTypeScriptInlineSourceMap() throws Swc4jCoreException {
String code = "function add(a:number, b:number) { return a+b; }";
String expectedCode = "function add(a, b) {\n" +
" return a + b;\n" +
Expand All @@ -48,7 +48,6 @@ public void testTranspile() throws Swc4jCoreException {
.setFileName(fileName)
.setMediaType(Swc4jMediaType.TypeScript);
Swc4jTranspileOutput output = swc4j.transpile(code, options);
System.out.println(output.getCode());
assertNotNull(output);
assertEquals(expectedCode, output.getCode().substring(0, expectedCode.length()));
assertEquals(
Expand All @@ -58,4 +57,22 @@ public void testTranspile() throws Swc4jCoreException {
expectedCode.length() + expectedMapPrefix.length()));
assertNull(output.getSourceMap());
}

@Test
public void testTranspileWrongMediaType() {
String code = "function add(a:number, b:number) { return a+b; }";
String fileName = "abc.ts";
Swc4jTranspileOptions options = new Swc4jTranspileOptions()
.setFileName(fileName)
.setMediaType(Swc4jMediaType.JavaScript);
assertEquals(
"Expected ',', got ':' at file:///abc.ts:1:15\n" +
"\n" +
" function add(a:number, b:number) { return a+b; }\n" +
" ~",
assertThrows(
Swc4jCoreException.class,
() -> swc4j.transpile(code, options))
.getMessage());
}
}

0 comments on commit e80dd78

Please sign in to comment.