Skip to content

Commit eb01b7b

Browse files
committed
[[ LCB ]] Added explicit error throwing to MCScriptEnsureModuleIsUsable.
1 parent fa52f62 commit eb01b7b

1 file changed

Lines changed: 87 additions & 25 deletions

File tree

libscript/src/script-module.cpp

Lines changed: 87 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,31 @@ static uindex_t s_context_slot_count;
203203

204204
////////////////////////////////////////////////////////////////////////////////
205205

206+
static MCStringRef __MCScriptDefinitionKindToString(MCScriptDefinitionKind p_kind)
207+
{
208+
switch(p_kind)
209+
{
210+
case kMCScriptDefinitionKindNone: return MCSTR("unknown");
211+
case kMCScriptDefinitionKindExternal: return MCSTR("external");
212+
case kMCScriptDefinitionKindType: return MCSTR("type");
213+
case kMCScriptDefinitionKindConstant: return MCSTR("constant");
214+
case kMCScriptDefinitionKindVariable: return MCSTR("variable");
215+
case kMCScriptDefinitionKindHandler: return MCSTR("handler");
216+
case kMCScriptDefinitionKindForeignHandler: return MCSTR("handler");
217+
case kMCScriptDefinitionKindProperty: return MCSTR("property");
218+
case kMCScriptDefinitionKindEvent: return MCSTR("event");
219+
case kMCScriptDefinitionKindSyntax: return MCSTR("syntax");
220+
case kMCScriptDefinitionKindDefinitionGroup: return MCSTR("group");
221+
case kMCScriptDefinitionKindContextVariable: return MCSTR("context variable");
222+
default:
223+
return MCSTR("unknown");
224+
}
225+
226+
return kMCEmptyString;
227+
}
228+
229+
////////////////////////////////////////////////////////////////////////////////
230+
206231
void MCScriptDestroyModule(MCScriptModuleRef self)
207232
{
208233
__MCScriptValidateObjectAndKind__(self, kMCScriptObjectKindModule);
@@ -268,7 +293,7 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
268293
if (t_index == UINDEX_MAX)
269294
{
270295
if (!MCMemoryResizeArray(s_context_slot_count + 1, s_context_slot_owners, s_context_slot_count))
271-
return false;
296+
return false; // oom
272297

273298
t_index = s_context_slot_count - 1;
274299
}
@@ -301,7 +326,7 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
301326
case kMCScriptBytecodeOpJump:
302327
// jump <offset>
303328
if (t_arity != 1)
304-
return false;
329+
goto invalid_bytecode_error;
305330

306331
// check resolved address is within handler
307332
break;
@@ -310,23 +335,23 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
310335
// jumpiftrue <register>, <offset>
311336
// jumpiffalse <register>, <offset>
312337
if (t_arity != 2)
313-
return false;
338+
goto invalid_bytecode_error;
314339

315340
// check resolved address is within handler
316341
t_temporary_count = MCMax(t_temporary_count, t_operands[0] + 1);
317342
break;
318343
case kMCScriptBytecodeOpAssignConstant:
319344
// assignconst <dst>, <index>
320345
if (t_arity != 2)
321-
return false;
346+
goto invalid_bytecode_error;
322347

323348
// check index argument is within value pool range
324349
t_temporary_count = MCMax(t_temporary_count, t_operands[0] + 1);
325350
break;
326351
case kMCScriptBytecodeOpAssign:
327352
// assign <dst>, <src>
328353
if (t_arity != 2)
329-
return false;
354+
goto invalid_bytecode_error;
330355

331356
t_temporary_count = MCMax(t_temporary_count, t_operands[0] + 1);
332357
t_temporary_count = MCMax(t_temporary_count, t_operands[1] + 1);
@@ -335,15 +360,15 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
335360
// return
336361
// return <value>
337362
if (t_arity != 0 && t_arity != 1)
338-
return false;
363+
goto invalid_bytecode_error;
339364

340365
if (t_arity == 1)
341366
t_temporary_count = MCMax(t_temporary_count, t_operands[0] + 1);
342367
break;
343368
case kMCScriptBytecodeOpInvoke:
344369
// invoke <index>, <result>, [ <arg_1>, ..., <arg_n> ]
345370
if (t_arity < 2)
346-
return false;
371+
goto invalid_bytecode_error;
347372

348373
// check index operand is within definition range
349374
// check definition[index] is handler or definition group
@@ -354,7 +379,7 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
354379
case kMCScriptBytecodeOpInvokeIndirect:
355380
// invoke *<src>, <result>, [ <arg_1>, ..., <arg_n> ]
356381
if (t_arity < 2)
357-
return false;
382+
goto invalid_bytecode_error;
358383

359384
for(uindex_t i = 0; i < t_arity; i++)
360385
t_temporary_count = MCMax(t_temporary_count, t_operands[i] + 1);
@@ -364,7 +389,7 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
364389
// fetch <dst>, <index>
365390
// store <src>, <index>
366391
if (t_arity != 2)
367-
return false;
392+
goto invalid_bytecode_error;
368393

369394
// check definition[index] is variable or handler
370395
// check level is appropriate.
@@ -373,7 +398,7 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
373398
case kMCScriptBytecodeOpAssignList:
374399
// assignlist <dst>, [ <elem_1>, ..., <elem_n> ]
375400
if (t_arity < 1)
376-
return false;
401+
goto invalid_bytecode_error;
377402

378403
for(uindex_t i = 0; i < t_arity; i++)
379404
t_temporary_count = MCMax(t_temporary_count, t_operands[i] + 1);
@@ -385,7 +410,7 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
385410

386411
// If we didn't reach the limit, the bytecode is malformed.
387412
if (t_bytecode != t_bytecode_limit)
388-
return false;
413+
goto invalid_bytecode_error;
389414

390415
// The total number of slots we need is params (inc result) + temps.
391416
MCTypeInfoRef t_signature;
@@ -396,6 +421,11 @@ bool MCScriptValidateModule(MCScriptModuleRef self)
396421
// If the module has context
397422

398423
return true;
424+
425+
invalid_bytecode_error:
426+
return MCErrorThrowGenericWithMessage(MCSTR("%{name} is not valid - malformed bytecode"),
427+
"name", self -> name,
428+
nil);
399429
}
400430

401431
////////////////////////////////////////////////////////////////////////////////
@@ -508,19 +538,32 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
508538
/* If the module is already marked as being checked for usability,
509539
* then there must be a cyclic module dependency. */
510540
if (self -> is_in_usable_check)
511-
return false;
541+
return MCErrorThrowGeneric(MCSTR("cyclic module dependency"));
542+
512543
self -> is_in_usable_check = true;
513544

514545
// First ensure we can resolve all its external dependencies.
515546
for(uindex_t i = 0; i < self -> dependency_count; i++)
516547
{
517548
MCScriptModuleRef t_module;
518549
if (!MCScriptLookupModule(self -> dependencies[i] . name, t_module))
550+
{
551+
MCErrorThrowGenericWithMessage(MCSTR("%{name} not usable - dependent module not found %{dependency}"),
552+
"name", self -> name,
553+
"dependency", self -> dependencies[i] . name,
554+
nil);
519555
goto error_cleanup;
556+
}
520557

521558
// A used module must not be a widget.
522559
if (t_module -> module_kind == kMCScriptModuleKindWidget)
560+
{
561+
MCErrorThrowGenericWithMessage(MCSTR("%{name} not usable - depends on widget module %{dependency}"),
562+
"name", self -> name,
563+
"dependency", self -> dependencies[i] . name,
564+
nil);
523565
goto error_cleanup;
566+
}
524567

525568
// A used module must be usable - do this before resolving imports so
526569
// chained imports work.
@@ -537,7 +580,14 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
537580

538581
MCScriptDefinition *t_def;
539582
if (!MCScriptLookupDefinitionInModule(t_module, t_import_def -> name, t_def))
583+
{
584+
MCErrorThrowGenericWithMessage(MCSTR("%{name} not usable - %{dependency}.%{definition} not found"),
585+
"name", self -> name,
586+
"dependency", self -> dependencies[i] . name,
587+
"definition", t_import_def -> name,
588+
nil);
540589
goto error_cleanup;
590+
}
541591

542592
MCScriptModuleRef t_mod;
543593
if (t_def -> kind == kMCScriptDefinitionKindExternal)
@@ -554,7 +604,16 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
554604
{
555605
if (t_import_def -> kind != kMCScriptDefinitionKindHandler ||
556606
t_def -> kind != kMCScriptDefinitionKindForeignHandler)
557-
goto error_cleanup;
607+
{
608+
MCErrorThrowGenericWithMessage(MCSTR("%{name} not usable - %{dependency}.%{definition} expected to be %{expected}, but is %{actual}"),
609+
"name", self -> name,
610+
"dependency", self -> dependencies[i] . name,
611+
"definition", t_import_def -> name,
612+
"expected", __MCScriptDefinitionKindToString(t_import_def -> kind),
613+
"actual", __MCScriptDefinitionKindToString(t_def -> kind),
614+
nil);
615+
goto error_cleanup;
616+
}
558617
}
559618

560619
// Check that signatures match.
@@ -563,7 +622,7 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
563622
t_import_def -> resolved_module = t_mod;
564623
}
565624

566-
// Now create the instance we need.
625+
// Now create the instance we need - if this fails its due to out of memory.
567626
if (!MCScriptCreateInstanceOfModule(t_module, self -> dependencies[i] . instance))
568627
goto error_cleanup;
569628
}
@@ -599,11 +658,12 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
599658
{
600659
MCAutoStringRef t_name_string;
601660
if (!MCStringFormat(&t_name_string, "%@.%@", self -> name, t_public_name))
602-
goto error_cleanup;
661+
goto error_cleanup; // oom
603662

604663
MCNewAutoNameRef t_name;
605664
if (!MCNameCreate(*t_name_string, &t_name))
606-
goto error_cleanup;
665+
goto error_cleanup; // oom
666+
607667
// If the target type is an alias, named type or optional type then
608668
// we just create an alias. Otherwise it must be a record, foreign,
609669
// handler type - this means it must be named.
@@ -614,21 +674,21 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
614674
MCTypeInfoIsOptional(t_target_type))
615675
{
616676
if (!MCAliasTypeInfoCreate(*t_name, t_target_type, &t_typeinfo))
617-
goto error_cleanup;
677+
goto error_cleanup; // oom
618678
}
619679
else
620680
{
621681
if (!MCNamedTypeInfoCreate(*t_name, &t_typeinfo))
622-
goto error_cleanup;
682+
goto error_cleanup; // oom
623683

624684
if (!MCNamedTypeInfoBind(*t_typeinfo, t_target_type))
625-
goto error_cleanup;
685+
goto error_cleanup; // oom
626686
}
627687
}
628688
else
629689
{
630690
if (!MCAliasTypeInfoCreate(kMCEmptyName, self -> types[t_type_def -> type] -> typeinfo, &t_typeinfo))
631-
goto error_cleanup;
691+
goto error_cleanup; // oom
632692
}
633693
}
634694
else if (t_def -> kind == kMCScriptDefinitionKindExternal)
@@ -652,7 +712,7 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
652712
MCScriptOptionalType *t_type;
653713
t_type = static_cast<MCScriptOptionalType *>(self -> types[i]);
654714
if (!MCOptionalTypeInfoCreate(self -> types[t_type -> type] -> typeinfo, &t_typeinfo))
655-
goto error_cleanup;
715+
goto error_cleanup; // oom
656716
}
657717
break;
658718
case kMCScriptTypeKindForeign:
@@ -668,7 +728,9 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
668728
#endif
669729
if (t_symbol == nil)
670730
{
671-
MCLog("Unable to resolve foreign type '%@'", t_type -> binding);
731+
MCErrorThrowGenericWithMessage(MCSTR("%{name} not usable - unable to resolve foreign type '%{type}'"),
732+
"type", t_type -> binding,
733+
nil);
672734
goto error_cleanup;
673735
}
674736

@@ -687,11 +749,11 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
687749
t_field . name = t_type -> fields[i] . name;
688750
t_field . type = self -> types[t_type -> fields[i] . type] -> typeinfo;
689751
if (!t_fields . Push(t_field))
690-
goto error_cleanup;
752+
goto error_cleanup; // oom
691753
}
692754

693755
if (!MCRecordTypeInfoCreate(t_fields . Ptr(), t_type -> field_count, self -> types[t_type -> base_type] -> typeinfo, &t_typeinfo))
694-
goto error_cleanup;
756+
goto error_cleanup; // oom
695757
}
696758
break;
697759
case kMCScriptTypeKindHandler:
@@ -710,7 +772,7 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
710772
}
711773

712774
if (!MCHandlerTypeInfoCreate(t_parameters . Ptr(), t_type -> parameter_count, self -> types[t_type -> return_type] -> typeinfo, &t_typeinfo))
713-
goto error_cleanup;
775+
goto error_cleanup; // oom
714776
}
715777
break;
716778
}

0 commit comments

Comments
 (0)