1use crate::enums::feedback_vector_slot_kind::FeedbackVectorSlotKind;
2use crate::enums::lua_status::lua_Status;
3use crate::functions::lua_a_toobject::luaA_toobject;
4use crate::functions::lua_c_barrierback::lua_c_barrierback;
5use crate::functions::lua_d_pcall::luaD_pcall;
6use crate::functions::lua_f_new_lclosure::lua_f_new_lclosure;
7use crate::functions::lua_f_newproto::lua_f_newproto;
8use crate::functions::lua_gettop::lua_gettop;
9use crate::functions::lua_h_new::lua_h_new;
10use crate::functions::lua_h_set::luaH_set;
11use crate::functions::lua_h_setstr::lua_h_setstr;
12use crate::functions::lua_o_chunkid::lua_o_chunkid;
13use crate::functions::lua_pushlstring::lua_pushlstring;
14use crate::functions::lua_r_newclass::lua_r_newclass;
15use crate::functions::lua_s_newlstr::luaS_newlstr;
16use crate::functions::read::read;
17use crate::functions::read_string::read_string;
18use crate::functions::read_var_int::read_var_int;
19use crate::functions::read_var_int_64::read_var_int_64;
20use crate::functions::remap_userdata_types::remap_userdata_types;
21use crate::macros::getstr::getstr;
22use crate::macros::hvalue::hvalue;
23use crate::macros::incr_top::incr_top;
24use crate::macros::isblack::isblack;
25use crate::macros::lua_c_barriert::luaC_barriert;
26use crate::macros::lua_idsize::LUA_IDSIZE;
27use crate::macros::lua_m_newarray::luaM_newarray;
28use crate::macros::lua_s_new::luaS_new;
29use crate::macros::lua_s_updateatom::luaS_updateatom;
30use crate::macros::savestack::savestack;
31use crate::macros::setbvalue::setbvalue;
32use crate::macros::setclassvalue::setclassvalue;
33use crate::macros::setclvalue::setclvalue;
34use crate::macros::sethvalue::sethvalue;
35use crate::macros::setlvalue::setlvalue;
36use crate::macros::setnilvalue::setnilvalue;
37use crate::macros::setnvalue::setnvalue;
38use crate::macros::setobj::setobj;
39use crate::macros::setobj_2_t::setobj2t;
40use crate::macros::setsvalue::setsvalue;
41use crate::macros::setvvalue::setvvalue;
42use crate::macros::tsvalue::tsvalue;
43use crate::macros::ttisnil::ttisnil;
44use crate::macros::ttisstring::ttisstring;
45use crate::records::feedback_vector_slot::FeedbackVectorSlot;
46use crate::records::gc_object::GCObject;
47use crate::records::loc_var::LocVar;
48use crate::records::proto::Proto;
49use crate::records::resolve_import::ResolveImport;
50use crate::records::t_string::TString;
51use crate::records::temp_buffer::TempBuffer;
52use crate::type_aliases::instruction::Instruction;
53use crate::type_aliases::lua_state::lua_State;
54use crate::type_aliases::lua_table::LuaTable;
55use crate::type_aliases::t_value::TValue;
56use core::ffi::{c_char, c_int};
57use luaur_common::enums::luau_bytecode_tag::{
58 LBC_CONSTANT_BOOLEAN, LBC_CONSTANT_CLASS_SHAPE, LBC_CONSTANT_CLOSURE, LBC_CONSTANT_IMPORT,
59 LBC_CONSTANT_INTEGER, LBC_CONSTANT_NIL, LBC_CONSTANT_NUMBER, LBC_CONSTANT_STRING,
60 LBC_CONSTANT_TABLE, LBC_CONSTANT_TABLE_WITH_CONSTANTS, LBC_CONSTANT_VECTOR,
61 LBC_TYPE_VERSION_MAX, LBC_TYPE_VERSION_MIN, LBC_VERSION_MAX, LBC_VERSION_MIN,
62};
63use luaur_common::enums::luau_bytecode_type::{
64 LBC_TYPE_FUNCTION, LBC_TYPE_TAGGED_USERDATA_BASE, LBC_TYPE_TAGGED_USERDATA_END,
65 LBC_TYPE_USERDATA,
66};
67use luaur_common::enums::luau_feedback_type::LuauFeedbackType;
68use luaur_common::enums::luau_opcode::LuauOpcode;
69use luaur_common::functions::get_op_length::getOpLength;
70use luaur_common::macros::luau_assert::LUAU_ASSERT;
71use luaur_common::macros::luau_insn_op::LUAU_INSN_OP;
72
73const LBC_CONSTANT_NIL_U8: u8 = LBC_CONSTANT_NIL.0 as u8;
74const LBC_CONSTANT_BOOLEAN_U8: u8 = LBC_CONSTANT_BOOLEAN.0 as u8;
75const LBC_CONSTANT_NUMBER_U8: u8 = LBC_CONSTANT_NUMBER.0 as u8;
76const LBC_CONSTANT_STRING_U8: u8 = LBC_CONSTANT_STRING.0 as u8;
77const LBC_CONSTANT_IMPORT_U8: u8 = LBC_CONSTANT_IMPORT.0 as u8;
78const LBC_CONSTANT_TABLE_U8: u8 = LBC_CONSTANT_TABLE.0 as u8;
79const LBC_CONSTANT_CLOSURE_U8: u8 = LBC_CONSTANT_CLOSURE.0 as u8;
80const LBC_CONSTANT_VECTOR_U8: u8 = LBC_CONSTANT_VECTOR.0 as u8;
81const LBC_CONSTANT_TABLE_WITH_CONSTANTS_U8: u8 = LBC_CONSTANT_TABLE_WITH_CONSTANTS.0 as u8;
82const LBC_CONSTANT_INTEGER_U8: u8 = LBC_CONSTANT_INTEGER.0 as u8;
83const LBC_CONSTANT_CLASS_SHAPE_U8: u8 = LBC_CONSTANT_CLASS_SHAPE.0 as u8;
84const USERDATA_TYPE_LIMIT: usize =
85 (LBC_TYPE_TAGGED_USERDATA_END.0 - LBC_TYPE_TAGGED_USERDATA_BASE.0) as usize;
86
87#[allow(non_snake_case)]
88pub unsafe fn loadsafe(
89 L: *mut lua_State,
90 strings: &mut TempBuffer<*mut TString>,
91 protos: &mut TempBuffer<*mut Proto>,
92 chunkname: *const c_char,
93 data: *const c_char,
94 size: usize,
95 env: c_int,
96) -> c_int {
97 let mut offset: usize = 0;
98
99 let version: u8 = read(data, size, &mut offset);
100
101 if version == 0 {
103 let mut chunkbuf = [0 as c_char; LUA_IDSIZE as usize];
104 let chunkid = lua_o_chunkid(
105 chunkbuf.as_mut_ptr(),
106 chunkbuf.len(),
107 chunkname,
108 c_strlen(chunkname),
109 );
110 push_chunk_prefixed_slice(L, chunkid, data.add(offset), size - offset);
111 return 1;
112 }
113
114 if version < LBC_VERSION_MIN.0 as u8 || version > LBC_VERSION_MAX.0 as u8 {
115 let mut chunkbuf = [0 as c_char; LUA_IDSIZE as usize];
116 let chunkid = lua_o_chunkid(
117 chunkbuf.as_mut_ptr(),
118 chunkbuf.len(),
119 chunkname,
120 c_strlen(chunkname),
121 );
122 let message = format!(
123 "{}: bytecode version mismatch (expected [{}..{}], got {})",
124 c_string_lossy(chunkid),
125 LBC_VERSION_MIN.0,
126 LBC_VERSION_MAX.0,
127 version
128 );
129 push_rust_string(L, &message);
130 return 1;
131 }
132
133 let mut typesversion: u8 = 0;
134
135 if version >= 4 {
136 typesversion = read(data, size, &mut offset);
137
138 if typesversion < LBC_TYPE_VERSION_MIN.0 as u8
139 || typesversion > LBC_TYPE_VERSION_MAX.0 as u8
140 {
141 let mut chunkbuf = [0 as c_char; LUA_IDSIZE as usize];
142 let chunkid = lua_o_chunkid(
143 chunkbuf.as_mut_ptr(),
144 chunkbuf.len(),
145 chunkname,
146 c_strlen(chunkname),
147 );
148 let message = format!(
149 "{}: bytecode type version mismatch (expected [{}..{}], got {})",
150 c_string_lossy(chunkid),
151 LBC_TYPE_VERSION_MIN.0,
152 LBC_TYPE_VERSION_MAX.0,
153 typesversion
154 );
155 push_rust_string(L, &message);
156 return 1;
157 }
158 }
159
160 let envt: *mut LuaTable = if env == 0 {
162 (*L).gt
163 } else {
164 hvalue!(luaA_toobject(L, env))
165 };
166
167 let source: *mut TString = luaS_new(L, chunkname);
168
169 let string_count = read_var_int(data, size, &mut offset);
171 strings.allocate(L, string_count as usize);
172
173 for i in 0..string_count {
174 let length = read_var_int(data, size, &mut offset);
175
176 *strings.data.add(i as usize) = luaS_newlstr(L, data.add(offset), length as usize);
177 offset += length as usize;
178 }
179
180 let mut userdata_remapping = [LBC_TYPE_USERDATA.0 as u8; USERDATA_TYPE_LIMIT];
183
184 if typesversion == 3 {
185 let mut index: u8 = read(data, size, &mut offset);
186
187 while index != 0 {
188 let name = read_string(strings, data, size, &mut offset);
189
190 if ((index - 1) as usize) < USERDATA_TYPE_LIMIT {
191 if let Some(cb) = (*(*L).global).ecb.gettypemapping {
192 userdata_remapping[(index - 1) as usize] =
193 cb(L, getstr(name), (*name).len as usize);
194 }
195 }
196
197 index = read(data, size, &mut offset);
198 }
199 }
200
201 let proto_count = read_var_int(data, size, &mut offset);
203 protos.allocate(L, proto_count as usize);
204
205 for i in 0..proto_count {
206 let p = lua_f_newproto(L);
207 (*p).source = source;
208 (*p).bytecodeid = i as c_int;
209 (*p).funid = if (*(*L).global).lastprotoid == 0 {
210 0
211 } else {
212 let id = (*(*L).global).lastprotoid;
213 (*(*L).global).lastprotoid = (*(*L).global).lastprotoid.wrapping_add(1);
214 id
215 };
216
217 (*p).maxstacksize = read(data, size, &mut offset);
218 (*p).numparams = read(data, size, &mut offset);
219 (*p).nups = read(data, size, &mut offset);
220 (*p).is_vararg = read(data, size, &mut offset);
221
222 if version >= 4 {
223 (*p).flags = read(data, size, &mut offset);
224
225 if typesversion == 1 {
226 let typesize = read_var_int(data, size, &mut offset);
227
228 if typesize != 0 {
229 let types = data.add(offset) as *mut u8;
230
231 LUAU_ASSERT!(typesize == 2 + (*p).numparams as u32);
232 LUAU_ASSERT!(*types.add(0) == LBC_TYPE_FUNCTION.0 as u8);
233 LUAU_ASSERT!(*types.add(1) == (*p).numparams);
234
235 let headersize = if typesize > 127 { 4usize } else { 3usize };
237
238 (*p).typeinfo =
239 luaM_newarray!(L, headersize + typesize as usize, u8, (*p).hdr.memcat);
240 (*p).sizetypeinfo = (headersize + typesize as usize) as c_int;
241
242 if headersize == 4 {
243 *(*p).typeinfo.add(0) = ((typesize & 127) | (1 << 7)) as u8;
244 *(*p).typeinfo.add(1) = (typesize >> 7) as u8;
245 *(*p).typeinfo.add(2) = 0;
246 *(*p).typeinfo.add(3) = 0;
247 } else {
248 *(*p).typeinfo.add(0) = typesize as u8;
249 *(*p).typeinfo.add(1) = 0;
250 *(*p).typeinfo.add(2) = 0;
251 }
252
253 core::ptr::copy_nonoverlapping(
254 types,
255 (*p).typeinfo.add(headersize),
256 typesize as usize,
257 );
258 }
259
260 offset += typesize as usize;
261 } else if typesversion == 2 || typesversion == 3 {
262 let typesize = read_var_int(data, size, &mut offset);
263
264 if typesize != 0 {
265 let types = data.add(offset) as *mut u8;
266
267 (*p).typeinfo = luaM_newarray!(L, typesize as usize, u8, (*p).hdr.memcat);
268 (*p).sizetypeinfo = typesize as c_int;
269 core::ptr::copy_nonoverlapping(types, (*p).typeinfo, typesize as usize);
270 offset += typesize as usize;
271
272 if typesversion == 3 {
273 remap_userdata_types(
274 (*p).typeinfo as *mut c_char,
275 (*p).sizetypeinfo as usize,
276 userdata_remapping.as_mut_ptr(),
277 USERDATA_TYPE_LIMIT as u32,
278 );
279 }
280 }
281 }
282 }
283
284 let sizecode = read_var_int(data, size, &mut offset) as c_int;
285 (*p).code = luaM_newarray!(L, sizecode as usize, Instruction, (*p).hdr.memcat);
286 (*p).sizecode = sizecode;
287
288 for j in 0..(*p).sizecode {
289 *(*p).code.add(j as usize) = read::<u32>(data, size, &mut offset);
290 }
291
292 (*p).codeentry = (*p).code;
293
294 let sizek = read_var_int(data, size, &mut offset) as c_int;
295 (*p).k = luaM_newarray!(L, sizek as usize, TValue, (*p).hdr.memcat);
296 (*p).sizek = sizek;
297
298 for j in 0..(*p).sizek {
302 setnilvalue!((*p).k.add(j as usize));
303 }
304
305 for j in 0..(*p).sizek {
306 let k = (*p).k.add(j as usize);
307
308 match read::<u8>(data, size, &mut offset) {
309 LBC_CONSTANT_NIL_U8 => {
310 }
312
313 LBC_CONSTANT_BOOLEAN_U8 => {
314 let v: u8 = read(data, size, &mut offset);
315 setbvalue!(k, v);
316 }
317
318 LBC_CONSTANT_NUMBER_U8 => {
319 let v: f64 = read(data, size, &mut offset);
320 setnvalue!(k, v);
321 }
322
323 LBC_CONSTANT_VECTOR_U8 => {
324 let x: f32 = read(data, size, &mut offset);
325 let y: f32 = read(data, size, &mut offset);
326 let z: f32 = read(data, size, &mut offset);
327 let w: f32 = read(data, size, &mut offset);
328 setvvalue!(k, x, y, z, w);
329 }
330
331 LBC_CONSTANT_STRING_U8 => {
332 let v = read_string(strings, data, size, &mut offset);
333 setsvalue!(L, k, v);
334 }
335
336 LBC_CONSTANT_IMPORT_U8 => {
337 let iid: u32 = read(data, size, &mut offset);
338 resolve_import_safe(L, envt, (*p).k, iid);
339 setobj!(L, k, (*L).top.sub(1));
340 (*L).top = (*L).top.sub(1);
341 }
342
343 LBC_CONSTANT_TABLE_U8 => {
344 let keys = read_var_int(data, size, &mut offset) as c_int;
345 let h = lua_h_new(L, 0, keys);
346 for _ in 0..keys {
347 let key = read_var_int(data, size, &mut offset) as c_int;
348 let val = luaH_set(L, h, (*p).k.add(key as usize) as *const TValue);
349 setnvalue!(val, 0.0);
350 }
351 sethvalue!(L, k, h);
352 }
353
354 LBC_CONSTANT_TABLE_WITH_CONSTANTS_U8 => {
355 let keys = read_var_int(data, size, &mut offset);
356 let h = lua_h_new(L, 0, keys as c_int);
357
358 let mut nil_keys: TempBuffer<i32> = TempBuffer::temp_buffer();
359 nil_keys.allocate(L, keys as usize);
360 let mut nil_keys_size: usize = 0;
361
362 for _ in 0..keys {
363 let key = read_var_int(data, size, &mut offset) as i32;
364 let val = luaH_set(L, h, (*p).k.add(key as usize) as *const TValue);
365 let constant_idx: i32 = read(data, size, &mut offset);
366 if constant_idx >= 0 {
367 let constant = (*p).k.add(constant_idx as usize);
368 if ttisnil!(constant) {
369 *nil_keys.data.add(nil_keys_size) = key;
370 nil_keys_size += 1;
371 } else {
372 setobj2t!(L, val, constant);
373 luaC_barriert!(L, h, constant);
374 continue;
375 }
376 }
377 setnvalue!(val, 0.0);
378 }
379
380 for idx in 0..nil_keys_size {
381 let key = *nil_keys.data.add(idx);
382 let val = luaH_set(L, h, (*p).k.add(key as usize) as *const TValue);
383 setnilvalue!(val);
384 }
385
386 sethvalue!(L, k, h);
387 }
388
389 LBC_CONSTANT_CLOSURE_U8 => {
390 let fid = read_var_int(data, size, &mut offset);
391 let proto = *protos.data.add(fid as usize);
392 let cl = lua_f_new_lclosure(L, (*proto).nups as c_int, envt, proto);
393 (*cl).preload = if (*cl).nupvalues > 0 { 1 } else { 0 };
394 setclvalue!(L, k, cl);
395 }
396
397 LBC_CONSTANT_CLASS_SHAPE_U8 => {
398 let cnid = read_var_int(data, size, &mut offset);
399 let classname = (*p).k.add(cnid as usize);
400 LUAU_ASSERT!(ttisstring!(classname));
401 let num_properties = read_var_int(data, size, &mut offset);
402 let num_methods = read_var_int(data, size, &mut offset);
403 let num_members = num_methods + num_properties;
404 let offset_to_member =
405 luaM_newarray!(L, num_members as usize, *mut TString, (*L).activememcat);
406 let members_to_offset = lua_h_new(L, 0, num_members as c_int);
407
408 for idx in 0..num_members {
409 let mid = read_var_int(data, size, &mut offset);
410 let member_name = (*p).k.add(mid as usize);
411 LUAU_ASSERT!(ttisstring!(member_name));
412 *offset_to_member.add(idx as usize) = tsvalue!(member_name) as *mut TString;
413 let val = lua_h_setstr(
414 L,
415 members_to_offset,
416 tsvalue!(member_name) as *mut TString,
417 );
418 setnvalue!(val, idx as f64);
419 }
420
421 (*members_to_offset).readonly = 1;
422
423 let lco = lua_r_newclass(
424 L,
425 tsvalue!(classname) as *mut TString,
426 members_to_offset,
427 offset_to_member,
428 num_properties as c_int,
429 num_methods as c_int,
430 );
431 setclassvalue!(L, k, lco);
432 }
433
434 LBC_CONSTANT_INTEGER_U8 => {
435 let is_negative: u8 = read(data, size, &mut offset);
436 let magnitude = read_var_int_64(data, size, &mut offset);
437 let value = if is_negative != 0 {
438 (!magnitude).wrapping_add(1) as i64
439 } else {
440 magnitude as i64
441 };
442 setlvalue!(k, value);
443 }
444
445 _ => {
446 LUAU_ASSERT!(false);
447 }
448 }
449 }
450
451 if luaur_common::FFlag::LuauUdataDirectAccess6.get() {
452 let mut instruction = (*p).code;
453 let end = (*p).code.add((*p).sizecode as usize);
454
455 while (instruction as usize) < (end as usize) {
456 let mut target_op = -1i32;
457
458 match LuauOpcode::from(LUAU_INSN_OP(*instruction) as u8) {
459 LuauOpcode::LOP_GETTABLEKS => {
460 target_op = LuauOpcode::LOP_GETUDATAKS as u8 as i32;
461 }
462
463 LuauOpcode::LOP_SETTABLEKS => {
464 target_op = LuauOpcode::LOP_SETUDATAKS as u8 as i32;
465 }
466
467 LuauOpcode::LOP_NAMECALL => {
468 target_op = LuauOpcode::LOP_NAMECALLUDATA as u8 as i32;
469 }
470
471 _ => {}
472 }
473
474 if target_op != -1 {
475 LUAU_ASSERT!(*instruction.add(1) < sizek as u32);
476
477 if *instruction.add(1) < 0x10000 {
479 let k = (*p).k.add(*instruction.add(1) as usize);
480 let s = tsvalue!(k) as *mut TString;
481
482 luaS_updateatom!(L, s);
483
484 if (*s).atom >= 0 {
485 *instruction = (*instruction & 0xffffff00) | target_op as u32;
486 }
487 }
488 }
489
490 instruction = instruction
491 .add(getOpLength(LuauOpcode::from(LUAU_INSN_OP(*instruction) as u8)) as usize);
492 }
493 }
494
495 let sizep = read_var_int(data, size, &mut offset) as c_int;
496 (*p).p = luaM_newarray!(L, sizep as usize, *mut Proto, (*p).hdr.memcat);
497 (*p).sizep = sizep;
498
499 for j in 0..(*p).sizep {
500 let fid = read_var_int(data, size, &mut offset);
501 *(*p).p.add(j as usize) = *protos.data.add(fid as usize);
502 }
503
504 (*p).linedefined = read_var_int(data, size, &mut offset) as c_int;
505 (*p).debugname = read_string(strings, data, size, &mut offset);
506
507 let lineinfo: u8 = read(data, size, &mut offset);
508
509 if lineinfo != 0 {
510 (*p).linegaplog2 = read::<u8>(data, size, &mut offset) as c_int;
511
512 let intervals = (((*p).sizecode - 1) >> (*p).linegaplog2) + 1;
513 let absoffset = ((*p).sizecode + 3) & !3;
514
515 let sizelineinfo = absoffset + intervals * core::mem::size_of::<c_int>() as c_int;
516 (*p).lineinfo = luaM_newarray!(L, sizelineinfo as usize, u8, (*p).hdr.memcat);
517 (*p).sizelineinfo = sizelineinfo;
518
519 (*p).abslineinfo = (*p).lineinfo.add(absoffset as usize) as *mut c_int;
520
521 let mut lastoffset: u8 = 0;
522 for j in 0..(*p).sizecode {
523 lastoffset = lastoffset.wrapping_add(read::<u8>(data, size, &mut offset));
524 *(*p).lineinfo.add(j as usize) = lastoffset;
525 }
526
527 let mut lastline: c_int = 0;
528 for j in 0..intervals {
529 lastline = lastline.wrapping_add(read::<i32>(data, size, &mut offset));
530 *(*p).abslineinfo.add(j as usize) = lastline;
531 }
532 }
533
534 let debuginfo: u8 = read(data, size, &mut offset);
535
536 if debuginfo != 0 {
537 let sizelocvars = read_var_int(data, size, &mut offset) as c_int;
538 (*p).locvars = luaM_newarray!(L, sizelocvars as usize, LocVar, (*p).hdr.memcat);
539 (*p).sizelocvars = sizelocvars;
540
541 for j in 0..(*p).sizelocvars {
542 let locvar = (*p).locvars.add(j as usize);
543 (*locvar).varname = read_string(strings, data, size, &mut offset);
544 (*locvar).startpc = read_var_int(data, size, &mut offset) as c_int;
545 (*locvar).endpc = read_var_int(data, size, &mut offset) as c_int;
546 (*locvar).reg = read(data, size, &mut offset);
547 }
548
549 let sizeupvalues = read_var_int(data, size, &mut offset) as c_int;
550 LUAU_ASSERT!(sizeupvalues == (*p).nups as c_int);
551
552 (*p).upvalues = luaM_newarray!(L, sizeupvalues as usize, *mut TString, (*p).hdr.memcat);
553 (*p).sizeupvalues = sizeupvalues;
554
555 for j in 0..(*p).sizeupvalues {
556 *(*p).upvalues.add(j as usize) = read_string(strings, data, size, &mut offset);
557 }
558 }
559
560 if version >= 11 {
561 LUAU_ASSERT!(luaur_common::FFlag::LuauCallFeedback.get());
562 (*p).feedbackvecsize = read_var_int(data, size, &mut offset);
563
564 if (*p).feedbackvecsize > 0 {
565 (*p).feedbackvec = luaM_newarray!(
566 L,
567 (*p).feedbackvecsize as usize,
568 FeedbackVectorSlot,
569 (*p).hdr.memcat
570 );
571 }
572 for j in 0..(*p).feedbackvecsize {
573 let slottype: u8 = read(data, size, &mut offset);
574 LUAU_ASSERT!(slottype == LuauFeedbackType::LFT_CALLTARGET as u8);
575 let slot = (*p).feedbackvec.add(j as usize);
576 (*slot).kind = FeedbackVectorSlotKind::CALL_TARGET;
577 (*slot).data.call_target.pc = read_var_int(data, size, &mut offset);
578 (*slot).data.call_target.proto = 0;
579 (*slot).data.call_target.hits = 0;
580 }
581 }
582
583 *protos.data.add(i as usize) = p;
584 }
585
586 let mainid = read_var_int(data, size, &mut offset);
588 let main = *protos.data.add(mainid as usize);
589
590 let thread_obj = L as *mut GCObject;
591 if isblack!(thread_obj) {
592 lua_c_barrierback(L, thread_obj, &mut (*L).gclist);
593 }
594
595 let cl = lua_f_new_lclosure(L, 0, envt, main);
596 setclvalue!(L, (*L).top, cl);
597 incr_top!(L);
598
599 0
600}
601
602unsafe fn resolve_import_safe(L: *mut lua_State, _env: *mut LuaTable, k: *mut TValue, id: u32) {
603 let mut ri = ResolveImport { k, id };
604
605 if (*(*L).gt).safeenv != 0 {
606 let old_top = lua_gettop(L);
608 let status = luaD_pcall(
609 L,
610 Some(ResolveImport::run),
611 &mut ri as *mut ResolveImport as *mut core::ffi::c_void,
612 savestack!(L, (*L).top) as isize,
613 0,
614 );
615 LUAU_ASSERT!(old_top + 1 == lua_gettop(L)); if status != lua_Status::LUA_OK as c_int {
618 setnilvalue!((*L).top.sub(1));
620 }
621 } else {
622 setnilvalue!((*L).top);
623 (*L).top = (*L).top.add(1);
624 }
625}
626
627unsafe fn c_strlen(s: *const c_char) -> usize {
628 let mut len = 0usize;
629 while *s.add(len) != 0 {
630 len += 1;
631 }
632 len
633}
634
635unsafe fn c_string_lossy(s: *const c_char) -> String {
636 String::from_utf8_lossy(core::slice::from_raw_parts(s as *const u8, c_strlen(s))).into_owned()
637}
638
639unsafe fn push_chunk_prefixed_slice(
640 L: *mut lua_State,
641 chunkid: *const c_char,
642 bytes: *const c_char,
643 len: usize,
644) {
645 let prefix = core::slice::from_raw_parts(chunkid as *const u8, c_strlen(chunkid));
646 let payload = core::slice::from_raw_parts(bytes as *const u8, len);
647 let mut message = Vec::with_capacity(prefix.len() + payload.len());
648 message.extend_from_slice(prefix);
649 message.extend_from_slice(payload);
650 lua_pushlstring(L, message.as_ptr() as *const c_char, message.len());
651}
652
653unsafe fn push_rust_string(L: *mut lua_State, message: &str) {
654 lua_pushlstring(L, message.as_ptr() as *const c_char, message.len());
655}