| 297 | } |
| 298 | |
| 299 | tsn_value tsn_require(tsn_vm* ctx, tsn_atom module_name) { |
| 300 | auto global = ValueRef(ctx, JS_GetGlobalObject(ctx)); |
| 301 | TSN_CHECK_EXCEPTION(global); |
| 302 | |
| 303 | auto modules = ValueRef(ctx, JS_GetPropertyStr(ctx, *global, "__modules__")); |
| 304 | TSN_CHECK_EXCEPTION(modules); |
| 305 | |
| 306 | if (tsn_is_undefined(ctx, *modules)) { |
| 307 | modules = JS_NewObject(ctx); |
| 308 | TSN_CHECK_EXCEPTION(modules); |
| 309 | |
| 310 | if (tsn_set_property_str(ctx, *global, "__modules__", *modules) < 0) { |
| 311 | return tsn_exception(ctx); |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | // don't use prop cache in the GetProperty call because module_name is not fixed |
| 316 | auto alreadyLoadedModule = ValueRef(ctx, JS_GetProperty(ctx, *modules, module_name)); |
| 317 | if (!tsn_is_undefined(ctx, *alreadyLoadedModule)) { |
| 318 | return alreadyLoadedModule.release(); |
| 319 | } |
| 320 | |
| 321 | auto moduleInitFunc = ValueRef(ctx, tsn_load_module(ctx, JS_AtomToCString(ctx, module_name))); |
| 322 | TSN_CHECK_EXCEPTION(moduleInitFunc); |
| 323 | |
| 324 | auto moduleVar = ValueRef(ctx, JS_NewObject(ctx)); |
| 325 | TSN_CHECK_EXCEPTION(moduleVar); |
| 326 | auto exportsVar = ValueRef(ctx, JS_NewObject(ctx)); |
| 327 | TSN_CHECK_EXCEPTION(exportsVar); |
| 328 | auto requireFunc = ValueRef(ctx, JS_NewCFunctionData(ctx, &tsn_require_relative, 0, 0, 1, &moduleVar.get())); |
| 329 | TSN_CHECK_EXCEPTION(exportsVar); |
| 330 | |
| 331 | auto pathVar = ValueRef(ctx, JS_AtomToValue(ctx, module_name)); |
| 332 | TSN_CHECK_EXCEPTION(exportsVar); |
| 333 | |
| 334 | if (tsn_set_property_str(ctx, *moduleVar, "path", *pathVar) < 0) { |
| 335 | return tsn_exception(ctx); |
| 336 | } |
| 337 | |
| 338 | if (tsn_set_property_str(ctx, *moduleVar, "exports", *exportsVar) < 0) { |
| 339 | return tsn_exception(ctx); |
| 340 | } |
| 341 | |
| 342 | if (tsn_set_property(ctx, &modules.get(), module_name, &exportsVar.get()) < 0) { |
| 343 | return tsn_exception(ctx); |
| 344 | } |
| 345 | |
| 346 | // Now load the module |
| 347 | |
| 348 | auto loadedModule = ValueRef(ctx, |
| 349 | JS_CallInternal_tsn(ctx, |
| 350 | *moduleInitFunc, |
| 351 | tsn_undefined(ctx), |
| 352 | tsn_undefined(ctx), |
| 353 | 3, |
| 354 | (tsn_value[]){*requireFunc, *moduleVar, *exportsVar}, |
| 355 | 0)); |
| 356 | if (tsn_is_exception(ctx, *loadedModule)) { |
no test coverage detected