@@ -240,7 +240,9 @@ impl Compiler {
240
240
}
241
241
242
242
/// 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 > > {
244
246
use std:: os:: raw:: c_int;
245
247
use std:: ptr;
246
248
@@ -274,7 +276,7 @@ impl Compiler {
274
276
vec2cstring_ptr ! ( mutable_globals, mutable_globals_ptr) ;
275
277
vec2cstring_ptr ! ( userdata_types, userdata_types_ptr) ;
276
278
277
- unsafe {
279
+ let bytecode = unsafe {
278
280
let mut options = ffi:: lua_CompileOptions:: default ( ) ;
279
281
options. optimizationLevel = self . optimization_level as c_int ;
280
282
options. debugLevel = self . debug_level as c_int ;
@@ -286,7 +288,19 @@ impl Compiler {
286
288
options. mutableGlobals = mutable_globals_ptr;
287
289
options. userdataTypes = userdata_types_ptr;
288
290
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
+ } ) ;
289
301
}
302
+
303
+ Ok ( bytecode)
290
304
}
291
305
}
292
306
@@ -443,13 +457,12 @@ impl<'a> Chunk<'a> {
443
457
444
458
/// Compiles the chunk and changes mode to binary.
445
459
///
446
- /// It does nothing if the chunk is already binary.
460
+ /// It does nothing if the chunk is already binary or invalid .
447
461
fn compile ( & mut self ) {
448
462
if let Ok ( ref source) = self . source {
449
463
if self . detect_mode ( ) == ChunkMode :: Text {
450
464
#[ 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) {
453
466
self . source = Ok ( Cow :: Owned ( data) ) ;
454
467
self . mode = Some ( ChunkMode :: Binary ) ;
455
468
}
@@ -516,6 +529,7 @@ impl<'a> Chunk<'a> {
516
529
. compiler
517
530
. as_ref ( )
518
531
. map ( |c| c. compile ( & source) )
532
+ . transpose ( ) ?
519
533
. unwrap_or ( source) ;
520
534
521
535
let name = Self :: convert_name ( self . name . clone ( ) ) ?;
0 commit comments