@@ -240,7 +240,9 @@ impl Compiler {
240240 }
241241
242242 /// Compiles the `source` into bytecode.
243- pub fn compile ( & self , source : impl AsRef < [ u8 ] > ) -> Vec < u8 > {
243+ ///
244+ /// Returns `Error::SyntaxError` if the source code is invalid.
245+ pub fn compile ( & self , source : impl AsRef < [ u8 ] > ) -> Result < Vec < u8 > > {
244246 use std:: os:: raw:: c_int;
245247 use std:: ptr;
246248
@@ -274,7 +276,7 @@ impl Compiler {
274276 vec2cstring_ptr ! ( mutable_globals, mutable_globals_ptr) ;
275277 vec2cstring_ptr ! ( userdata_types, userdata_types_ptr) ;
276278
277- unsafe {
279+ let bytecode = unsafe {
278280 let mut options = ffi:: lua_CompileOptions:: default ( ) ;
279281 options. optimizationLevel = self . optimization_level as c_int ;
280282 options. debugLevel = self . debug_level as c_int ;
@@ -286,7 +288,19 @@ impl Compiler {
286288 options. mutableGlobals = mutable_globals_ptr;
287289 options. userdataTypes = userdata_types_ptr;
288290 ffi:: luau_compile ( source. as_ref ( ) , options)
291+ } ;
292+
293+ if bytecode. first ( ) == Some ( & 0 ) {
294+ // The rest of the bytecode is the error message starting with `:`
295+ // See https://github.com/luau-lang/luau/blob/0.640/Compiler/src/Compiler.cpp#L4336
296+ let message = String :: from_utf8_lossy ( & bytecode[ 2 ..] ) . to_string ( ) ;
297+ return Err ( Error :: SyntaxError {
298+ incomplete_input : message. ends_with ( "<eof>" ) ,
299+ message,
300+ } ) ;
289301 }
302+
303+ Ok ( bytecode)
290304 }
291305}
292306
@@ -443,13 +457,12 @@ impl<'a> Chunk<'a> {
443457
444458 /// Compiles the chunk and changes mode to binary.
445459 ///
446- /// It does nothing if the chunk is already binary.
460+ /// It does nothing if the chunk is already binary or invalid .
447461 fn compile ( & mut self ) {
448462 if let Ok ( ref source) = self . source {
449463 if self . detect_mode ( ) == ChunkMode :: Text {
450464 #[ cfg( feature = "luau" ) ]
451- {
452- let data = self . compiler . get_or_insert_with ( Default :: default) . compile ( source) ;
465+ if let Ok ( data) = self . compiler . get_or_insert_with ( Default :: default) . compile ( source) {
453466 self . source = Ok ( Cow :: Owned ( data) ) ;
454467 self . mode = Some ( ChunkMode :: Binary ) ;
455468 }
@@ -516,6 +529,7 @@ impl<'a> Chunk<'a> {
516529 . compiler
517530 . as_ref ( )
518531 . map ( |c| c. compile ( & source) )
532+ . transpose ( ) ?
519533 . unwrap_or ( source) ;
520534
521535 let name = Self :: convert_name ( self . name . clone ( ) ) ?;
0 commit comments