bool SavedStacks::insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle<SavedFrame*> frame) { if (iter.done()) { frame.set(nullptr); return true; } ScriptFrameIter thisFrame(iter); Rooted<SavedFrame*> parentFrame(cx); if (!insertFrames(cx, ++iter, &parentFrame)) return false; RootedScript script(cx, thisFrame.script()); RootedFunction callee(cx, thisFrame.maybeCallee()); const char *filename = script->filename(); RootedAtom source(cx, Atomize(cx, filename, strlen(filename))); if (!source) return false; uint32_t column; uint32_t line = PCToLineNumber(script, thisFrame.pc(), &column); SavedFrame::Lookup lookup(source, line, column, callee ? callee->displayAtom() : nullptr, parentFrame, thisFrame.compartment()->principals); frame.set(getOrCreateSavedFrame(cx, lookup)); return frame.address() != nullptr; }
bool js::XDRScriptRegExpObject(XDRState<mode>* xdr, MutableHandle<RegExpObject*> objp) { /* NB: Keep this in sync with CloneScriptRegExpObject. */ RootedAtom source(xdr->cx()); uint32_t flagsword = 0; if (mode == XDR_ENCODE) { MOZ_ASSERT(objp); RegExpObject& reobj = *objp; source = reobj.getSource(); flagsword = reobj.getFlags(); } if (!XDRAtom(xdr, &source) || !xdr->codeUint32(&flagsword)) return false; if (mode == XDR_DECODE) { RegExpFlag flags = RegExpFlag(flagsword); RegExpObject* reobj = RegExpObject::createNoStatics(xdr->cx(), source, flags, nullptr, xdr->cx()->tempLifoAlloc()); if (!reobj) return false; objp.set(reobj); } return true; }
static bool GetSharedTypedArray(JSContext* cx, HandleValue v, MutableHandle<SharedTypedArrayObject*> viewp) { if (!v.isObject()) return ReportBadArrayType(cx); if (!v.toObject().is<SharedTypedArrayObject>()) return ReportBadArrayType(cx); viewp.set(&v.toObject().as<SharedTypedArrayObject>()); return true; }
bool SavedStacks::insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle<SavedFrame*> frame) { if (iter.done()) { frame.set(nullptr); return true; } // Don't report the over-recursion error because if we are blowing the stack // here, we already blew the stack in JS, reported it, and we are creating // the saved stack for the over-recursion error object. We do this check // here, rather than inside saveCurrentStack, because in some cases we will // pass the check there, despite later failing the check here (for example, // in js/src/jit-test/tests/saved-stacks/bug-1006876-too-much-recursion.js). JS_CHECK_RECURSION_DONT_REPORT(cx, return false); ScriptFrameIter thisFrame(iter); Rooted<SavedFrame*> parentFrame(cx); if (!insertFrames(cx, ++iter, &parentFrame)) return false; RootedScript script(cx, thisFrame.script()); RootedFunction callee(cx, thisFrame.maybeCallee()); const char *filename = script->filename(); RootedAtom source(cx, Atomize(cx, filename, strlen(filename))); if (!source) return false; uint32_t column; uint32_t line = PCToLineNumber(script, thisFrame.pc(), &column); SavedFrame::Lookup lookup(source, line, column, callee ? callee->displayAtom() : nullptr, parentFrame, thisFrame.compartment()->principals); frame.set(getOrCreateSavedFrame(cx, lookup)); return frame.get() != nullptr; }
static bool CloneModule(JSContext* cx, MutableHandle<AsmJSModuleObject*> moduleObj) { ScopedJSDeletePtr<AsmJSModule> module; if (!moduleObj->module().clone(cx, &module)) return false; AsmJSModuleObject* newModuleObj = AsmJSModuleObject::create(cx, &module); if (!newModuleObj) return false; moduleObj.set(newModuleObj); return true; }
bool GetRenderTargetProperty( JSContext *cx, Handle<JSObject *> object, Handle<jsid> id, MutableHandle<Value> value ) { RootedValue val(cx); JS_IdToValue( cx, id, MutableHandleValue(&val) ); JSString *propertyString = val.toString(); const char *propertyName=JS_EncodeString(cx, propertyString); //printf("GetRenderTargetProperty: %s\n", propertyName ); RenderTarget *target=(RenderTarget *) JS_GetPrivate( object ); if ( !strcmp( propertyName, "w" ) ) { value.set( INT_TO_JSVAL( target->w ) ); } else if ( !strcmp( propertyName, "h" ) ) { value.set( INT_TO_JSVAL( target->h ) ); } else if ( !strcmp( propertyName, "autoResize" ) ) { value.set( BOOLEAN_TO_JSVAL( target->autoResize ) ); } else if ( !strcmp( propertyName, "main" ) ) { value.set( BOOLEAN_TO_JSVAL( target->main ) ); } return true; }
static bool DecodeMemory(JSContext* cx, Decoder& d, ModuleGenerator& mg, MutableHandle<ArrayBufferObject*> heap) { uint32_t sectionStart; if (!d.startSection(MemoryId, §ionStart)) return Fail(cx, d, "failed to start section"); if (sectionStart == Decoder::NotStarted) return true; uint32_t initialSizePages; if (!d.readVarU32(&initialSizePages)) return Fail(cx, d, "expected initial memory size"); CheckedInt<int32_t> initialSize = initialSizePages; initialSize *= PageSize; if (!initialSize.isValid()) return Fail(cx, d, "initial memory size too big"); uint32_t maxSizePages; if (!d.readVarU32(&maxSizePages)) return Fail(cx, d, "expected initial memory size"); CheckedInt<int32_t> maxSize = maxSizePages; maxSize *= PageSize; if (!maxSize.isValid()) return Fail(cx, d, "initial memory size too big"); uint8_t exported; if (!d.readFixedU8(&exported)) return Fail(cx, d, "expected exported byte"); if (exported) { UniqueChars fieldName = DuplicateString("memory"); if (!fieldName || !mg.addMemoryExport(Move(fieldName))) return false; } if (!d.finishSection(sectionStart)) return Fail(cx, d, "memory section byte size mismatch"); bool signalsForOOB = CompileArgs(cx).useSignalHandlersForOOB; heap.set(ArrayBufferObject::createForWasm(cx, initialSize.value(), signalsForOOB)); if (!heap) return false; mg.initHeapUsage(HeapUsage::Unshared); return true; }
static bool DecodeMemorySection(JSContext* cx, Decoder& d, ModuleGenerator& mg, MutableHandle<ArrayBufferObject*> heap) { if (!d.readCStringIf(MemoryLabel)) return true; uint32_t sectionStart; if (!d.startSection(§ionStart)) return Fail(cx, d, "expected memory section byte size"); if (!d.readCStringIf(InitialLabel)) return Fail(cx, d, "expected memory section initial field"); uint32_t initialHeapSize; if (!d.readVarU32(&initialHeapSize)) return Fail(cx, d, "expected initial memory size"); if (initialHeapSize < PageSize || initialHeapSize % PageSize != 0) return Fail(cx, d, "initial memory size not a multiple of 0x10000"); if (initialHeapSize > INT32_MAX) return Fail(cx, d, "initial memory size too big"); if (!d.readCStringIf(EndLabel)) return Fail(cx, d, "expected end field of memory section"); if (!d.finishSection(sectionStart)) return Fail(cx, d, "memory section byte size mismatch"); bool signalsForOOB = CompileArgs(cx).useSignalHandlersForOOB; heap.set(ArrayBufferObject::createForWasm(cx, initialHeapSize, signalsForOOB)); if (!heap) return false; mg.initHeapUsage(HeapUsage::Unshared); return true; }
bool js::GetProperty(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> receiver, Handle<PropertyId> pid, unsigned resolveFlags, MutableHandle<Value> vp) { NEW_OBJECT_REPRESENTATION_ONLY(); MOZ_ASSERT(receiver); Rooted<ObjectImpl*> current(cx, obj); do { MOZ_ASSERT(obj); if (Downcast(current)->isProxy()) { MOZ_NOT_REACHED("NYI: proxy [[GetP]]"); return false; } PropDesc desc; PropDesc::AutoRooter rootDesc(cx, &desc); if (!GetOwnProperty(cx, current, pid, resolveFlags, &desc)) return false; /* No property? Recur or bottom out. */ if (desc.isUndefined()) { current = current->getProto(); if (current) continue; vp.setUndefined(); return true; } /* If it's a data property, return the value. */ if (desc.isDataDescriptor()) { vp.set(desc.value()); return true; } /* If it's an accessor property, call its [[Get]] with the receiver. */ if (desc.isAccessorDescriptor()) { Rooted<Value> get(cx, desc.getterValue()); if (get.isUndefined()) { vp.setUndefined(); return true; } InvokeArgsGuard args; if (!cx->stack.pushInvokeArgs(cx, 0, &args)) return false; args.setCallee(get); args.setThis(ObjectValue(*receiver)); bool ok = Invoke(cx, args); vp.set(args.rval()); return ok; } /* Otherwise it's a PropertyOp-based property. XXX handle this! */ MOZ_NOT_REACHED("NYI: handle PropertyOp'd properties here"); return false; } while (false); MOZ_NOT_REACHED("buggy control flow"); return false; }
// ES6 (5 April 2014) 9.5.5 Proxy.[[GetOwnProperty]](P) bool ScriptedDirectProxyHandler::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id, MutableHandle<PropertyDescriptor> desc) const { // step 2 RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 3 if (!handler) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED); return false; } // step 4 RootedObject target(cx, proxy->as<ProxyObject>().target()); // step 5-6 RootedValue trap(cx); if (!GetProperty(cx, handler, handler, cx->names().getOwnPropertyDescriptor, &trap)) return false; // step 7 if (trap.isUndefined()) return GetOwnPropertyDescriptor(cx, target, id, desc); // step 8-9 RootedValue propKey(cx); if (!IdToStringOrSymbol(cx, id, &propKey)) return false; Value argv[] = { ObjectValue(*target), propKey }; RootedValue trapResult(cx); if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult)) return false; // step 10 if (!trapResult.isUndefined() && !trapResult.isObject()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_GETOWN_OBJORUNDEF); return false; } //step 11-12 Rooted<PropertyDescriptor> targetDesc(cx); if (!GetOwnPropertyDescriptor(cx, target, id, &targetDesc)) return false; // step 13 if (trapResult.isUndefined()) { // substep a if (!targetDesc.object()) { desc.object().set(nullptr); return true; } // substep b if (!targetDesc.configurable()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_REPORT_NC_AS_NE); return false; } // substep c-e bool extensibleTarget; if (!IsExtensible(cx, target, &extensibleTarget)) return false; if (!extensibleTarget) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_REPORT_E_AS_NE); return false; } // substep f desc.object().set(nullptr); return true; } // step 14-15 bool extensibleTarget; if (!IsExtensible(cx, target, &extensibleTarget)) return false; // step 16-17 Rooted<PropertyDescriptor> resultDesc(cx); if (!ToPropertyDescriptor(cx, trapResult, true, &resultDesc)) return false; // step 18 CompletePropertyDescriptor(&resultDesc); // step 19 bool valid; if (!ValidatePropertyDescriptor(cx, extensibleTarget, resultDesc, targetDesc, &valid)) return false; // step 20 if (!valid) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_REPORT_INVALID); return false; } // step 21 if (!resultDesc.configurable()) { if (!targetDesc.object()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_REPORT_NE_AS_NC); return false; } if (targetDesc.configurable()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_REPORT_C_AS_NC); return false; } } // step 22 desc.set(resultDesc); desc.object().set(proxy); return true; }
static bool DecodeModule(JSContext* cx, UniqueChars filename, const uint8_t* bytes, uint32_t length, ImportNameVector* importNames, ExportMap* exportMap, MutableHandle<WasmModuleObject*> moduleObj) { Decoder d(bytes, bytes + length); uint32_t u32; if (!d.readU32(&u32) || u32 != MagicNumber) return Fail(cx, d, "failed to match magic number"); if (!d.readU32(&u32) || u32 != EncodingVersion) return Fail(cx, d, "failed to match binary version"); UniqueModuleGeneratorData init = MakeUnique<ModuleGeneratorData>(); if (!init) return false; if (!DecodeSignatureSection(cx, d, init.get())) return false; if (!DecodeDeclarationSection(cx, d, init.get())) return false; if (!DecodeImportSection(cx, d, init.get(), importNames)) return false; ModuleGenerator mg(cx); if (!mg.init(Move(init))) return false; if (!DecodeExportsSection(cx, d, mg, exportMap)) return false; HeapUsage heapUsage = HeapUsage::None; if (!DecodeCodeSection(cx, d, mg)) return false; CacheableCharsVector funcNames; while (!d.readCStringIf(EndSection)) { if (!DecodeUnknownSection(cx, d)) return false; } if (!d.done()) return Fail(cx, d, "failed to consume all bytes of module"); UniqueModuleData module; UniqueStaticLinkData link; SlowFunctionVector slowFuncs(cx); if (!mg.finish(heapUsage, Move(filename), Move(funcNames), &module, &link, &slowFuncs)) return false; moduleObj.set(WasmModuleObject::create(cx)); if (!moduleObj) return false; if (!moduleObj->init(cx->new_<Module>(Move(module)))) return false; return moduleObj->module().staticallyLink(cx, *link); }
static bool DecodeModule(JSContext* cx, UniqueChars file, const uint8_t* bytes, uint32_t length, ImportNameVector* importNames, UniqueExportMap* exportMap, MutableHandle<ArrayBufferObject*> heap, MutableHandle<WasmModuleObject*> moduleObj) { Decoder d(bytes, bytes + length); uint32_t u32; if (!d.readFixedU32(&u32) || u32 != MagicNumber) return Fail(cx, d, "failed to match magic number"); if (!d.readFixedU32(&u32) || u32 != EncodingVersion) return Fail(cx, d, "failed to match binary version"); UniqueModuleGeneratorData init = js::MakeUnique<ModuleGeneratorData>(cx); if (!init) return false; if (!DecodeSignatures(cx, d, init.get())) return false; if (!DecodeImportTable(cx, d, init.get(), importNames)) return false; if (!DecodeFunctionSignatures(cx, d, init.get())) return false; if (!DecodeFunctionTable(cx, d, init.get())) return false; ModuleGenerator mg(cx); if (!mg.init(Move(init), Move(file))) return false; if (!DecodeMemory(cx, d, mg, heap)) return false; if (!DecodeExportTable(cx, d, mg)) return false; if (!DecodeFunctionBodies(cx, d, mg)) return false; if (!DecodeDataSegments(cx, d, heap)) return false; CacheableCharsVector funcNames; while (!d.done()) { if (!d.skipSection()) return Fail(cx, d, "failed to skip unknown section at end"); } UniqueModuleData module; UniqueStaticLinkData staticLink; SlowFunctionVector slowFuncs(cx); if (!mg.finish(Move(funcNames), &module, &staticLink, exportMap, &slowFuncs)) return false; moduleObj.set(WasmModuleObject::create(cx)); if (!moduleObj) return false; if (!moduleObj->init(cx->new_<Module>(Move(module)))) return false; return moduleObj->module().staticallyLink(cx, *staticLink); }
// ES8 rev 0c1bd3004329336774cbc90de727cd0cf5f11e93 9.5.5 Proxy.[[GetOwnProperty]](P) bool ScriptedProxyHandler::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id, MutableHandle<PropertyDescriptor> desc) const { // Steps 2-4. RootedObject handler(cx, ScriptedProxyHandler::handlerObject(proxy)); if (!handler) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED); return false; } // Step 5. RootedObject target(cx, proxy->as<ProxyObject>().target()); MOZ_ASSERT(target); // Step 6. RootedValue trap(cx); if (!GetProxyTrap(cx, handler, cx->names().getOwnPropertyDescriptor, &trap)) return false; // Step 7. if (trap.isUndefined()) return GetOwnPropertyDescriptor(cx, target, id, desc); // Step 8. RootedValue propKey(cx); if (!IdToStringOrSymbol(cx, id, &propKey)) return false; RootedValue trapResult(cx); RootedValue targetVal(cx, ObjectValue(*target)); if (!Call(cx, trap, handler, targetVal, propKey, &trapResult)) return false; // Step 9. if (!trapResult.isUndefined() && !trapResult.isObject()) return js::Throw(cx, id, JSMSG_PROXY_GETOWN_OBJORUNDEF); // Step 10. Rooted<PropertyDescriptor> targetDesc(cx); if (!GetOwnPropertyDescriptor(cx, target, id, &targetDesc)) return false; // Step 11. if (trapResult.isUndefined()) { // Step 11a. if (!targetDesc.object()) { desc.object().set(nullptr); return true; } // Step 11b. if (!targetDesc.configurable()) return js::Throw(cx, id, JSMSG_CANT_REPORT_NC_AS_NE); // Steps 11c-d. bool extensibleTarget; if (!IsExtensible(cx, target, &extensibleTarget)) return false; // Step 11e. if (!extensibleTarget) return js::Throw(cx, id, JSMSG_CANT_REPORT_E_AS_NE); // Step 11f. desc.object().set(nullptr); return true; } // Step 12. bool extensibleTarget; if (!IsExtensible(cx, target, &extensibleTarget)) return false; // Step 13. Rooted<PropertyDescriptor> resultDesc(cx); if (!ToPropertyDescriptor(cx, trapResult, true, &resultDesc)) return false; // Step 14. CompletePropertyDescriptor(&resultDesc); // Step 15. const char* errorDetails = nullptr; if (!IsCompatiblePropertyDescriptor(cx, extensibleTarget, resultDesc, targetDesc, &errorDetails)) return false; // Step 16. if (errorDetails) return js::Throw(cx, id, JSMSG_CANT_REPORT_INVALID, errorDetails); // Step 17. if (!resultDesc.configurable()) { if (!targetDesc.object()) return js::Throw(cx, id, JSMSG_CANT_REPORT_NE_AS_NC); if (targetDesc.configurable()) return js::Throw(cx, id, JSMSG_CANT_REPORT_C_AS_NC); } // Step 18. desc.set(resultDesc); desc.object().set(proxy); return true; }