ArrayBuffer.cpp阅读

对象继承关系

JavascriptArrayBuffer:
ArrayBuffer:
ArrayBufferBase:
DynamicObject:
RecyclableObject:
FinalizableObject
template<> TypedArray<Typed>
TypedArray
TypedArrayBase
ArrayBufferParent
ArrayObject
DynamicObject
RecyclableObject
FinalizableObject

FinalizableObject类

抽象类FinalizableObject,所有Object类的基类

class FinalizableObject
{
public:
virtual void Finalize(bool isShutdown) = 0;
virtual void Dispose(bool isShutdown) = 0;
virtual void Mark(Recycler * recycler) = 0;
virtual void OnMark() {}
};

RecyclableObject类

//TO DO

RecyclableObject类涉及到内存管理相关的操作

   class RecyclableObject : public FinalizableObject
{ friend class JavascriptOperators; protected:
Field(Type *) type;
DEFINE_VTABLE_CTOR_NOBASE(RecyclableObject); virtual RecyclableObject* GetPrototypeSpecial(); public:
static bool Is(Var aValue);//static方法,传入地址判断是否为RecyclableObject对象
static RecyclableObject* FromVar(Var varValue);//static方法,传入地址返回对象
RecyclableObject(Type * type);//构造函数 ScriptContext* GetScriptContext() const;//返回ScriptContext
TypeId GetTypeId() const;//返回TypeId
RecyclableObject* GetPrototype() const;//return prototype;
JavascriptMethod GetEntryPoint() const;//return entryPoint;
JavascriptLibrary* GetLibrary() const;// return javascriptLibrary;
Recycler* GetRecycler() const;// return recycler;
void SetIsPrototype(); // Is this object known to have only writable data properties
// (i.e. no accessors or non-writable properties)?
bool HasOnlyWritableDataProperties();//查询访问属性 void ClearWritableDataOnlyDetectionBit();//删除只读属性 propertyTypes &= ~PropertyTypesWritableDataOnlyDetection;
bool IsWritableDataOnlyDetectionBitSet(); inline Type * GetType() const { return type; } // In order to avoid a branch, every object has an entry point if it gets called like a
// function - however, if it can't be called like a function, it's set to DefaultEntryPoint
// which will emit an error.
static Var DefaultEntryPoint(RecyclableObject* function, CallInfo callInfo, ...); BOOL HasItem(uint32 index);
BOOL HasProperty(PropertyId propertyId);
BOOL GetProperty(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);
BOOL GetProperty(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);
BOOL GetPropertyReference(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);
BOOL GetItem(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext);
BOOL GetItemReference(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext); virtual PropertyId GetPropertyId(PropertyIndex index) { return Constants::NoProperty; }
virtual PropertyId GetPropertyId(BigPropertyIndex index) { return Constants::NoProperty; }
virtual PropertyIndex GetPropertyIndex(PropertyId propertyId) { return Constants::NoSlot; }
virtual int GetPropertyCount() { return 0; }
virtual PropertyQueryFlags HasPropertyQuery(PropertyId propertyId);
virtual BOOL HasOwnProperty( PropertyId propertyId);
virtual BOOL HasOwnPropertyNoHostObject( PropertyId propertyId);
virtual BOOL HasOwnPropertyCheckNoRedecl( PropertyId propertyId) { Assert(FALSE); return FALSE; }
virtual BOOL UseDynamicObjectForNoHostObjectAccess() { return FALSE; }
virtual DescriptorFlags GetSetter(PropertyId propertyId, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) { return None; }
virtual DescriptorFlags GetSetter(JavascriptString* propertyNameString, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) { return None; }
virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);
virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);
virtual BOOL GetInternalProperty(Var instance, PropertyId internalPropertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);
virtual BOOL GetAccessors(PropertyId propertyId, Var* getter, Var* setter, ScriptContext * requestContext);
virtual PropertyQueryFlags GetPropertyReferenceQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);
virtual BOOL SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info);
virtual BOOL SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info);
virtual BOOL SetInternalProperty(PropertyId internalPropertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info);
virtual BOOL InitProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags = PropertyOperation_None, PropertyValueInfo* info = NULL);
virtual BOOL EnsureProperty(PropertyId propertyId);
virtual BOOL EnsureNoRedeclProperty(PropertyId propertyId);
virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any);
virtual BOOL InitPropertyScoped(PropertyId propertyId, Var value);
virtual BOOL InitFuncScoped(PropertyId propertyId, Var value);
virtual BOOL DeleteProperty(PropertyId propertyId, PropertyOperationFlags flags);
virtual BOOL DeleteProperty(JavascriptString *propertyNameString, PropertyOperationFlags flags);
virtual BOOL IsFixedProperty(PropertyId propertyId);
virtual PropertyQueryFlags HasItemQuery(uint32 index);
virtual BOOL HasOwnItem(uint32 index);
virtual PropertyQueryFlags GetItemQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext);
virtual PropertyQueryFlags GetItemReferenceQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext);
virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) { return None; }
virtual BOOL SetItem(uint32 index, Var value, PropertyOperationFlags flags);
virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags);
virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, ForInCache * forInCache = nullptr);
virtual BOOL ToPrimitive(JavascriptHint hint, Var* value, ScriptContext * requestContext);
virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags = PropertyOperation_None);
virtual BOOL Equals(__in Var other, __out BOOL* value, ScriptContext* requestContext);
virtual BOOL StrictEquals(__in Var other, __out BOOL* value, ScriptContext* requestContext);
virtual BOOL IsWritable(PropertyId propertyId) { return false; }
virtual BOOL IsConfigurable(PropertyId propertyId) { return false; }
virtual BOOL IsEnumerable(PropertyId propertyId) { return false; }
virtual BOOL IsExtensible() { return false; }
virtual BOOL IsProtoImmutable() const { return false; }
virtual BOOL PreventExtensions() { return false; }; // Sets [[Extensible]] flag of instance to false
virtual void ThrowIfCannotDefineProperty(PropertyId propId, const PropertyDescriptor& descriptor);
virtual void ThrowIfCannotGetOwnPropertyDescriptor(PropertyId propId) {}
virtual BOOL GetDefaultPropertyDescriptor(PropertyDescriptor& descriptor);
virtual BOOL Seal() { return false; } // Seals the instance, no additional property can be added or deleted
virtual BOOL Freeze() { return false; } // Freezes the instance, no additional property can be added or deleted or written
virtual BOOL IsSealed() { return false; }
virtual BOOL IsFrozen() { return false; }
virtual BOOL SetWritable(PropertyId propertyId, BOOL value) { return false; }
virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) { return false; }
virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) { return false; }
virtual BOOL SetAttributes(PropertyId propertyId, PropertyAttributes attributes) { return false; } virtual BOOL GetSpecialPropertyName(uint32 index, JavascriptString ** propertyName, ScriptContext * requestContext) { return false; }
virtual uint GetSpecialPropertyCount() const { return 0; }
virtual PropertyId const * GetSpecialPropertyIds() const { return nullptr; }
virtual RecyclableObject* GetThisObjectOrUnWrap(); // Due to the withScope object there are times we need to unwrap virtual BOOL HasInstance(Var instance, ScriptContext* scriptContext, IsInstInlineCache* inlineCache = NULL); BOOL SkipsPrototype() const;
BOOL CanHaveInterceptors() const;
BOOL IsExternal() const;
// Used only in JsVarToExtension where it may be during dispose and the type is not available
virtual BOOL IsExternalVirtual() const { return FALSE; } virtual RecyclableObject* GetConfigurablePrototype(ScriptContext * requestContext) { return GetPrototype(); }
virtual Js::JavascriptString* GetClassName(ScriptContext * requestContext);
virtual RecyclableObject* GetProxiedObjectForHeapEnum(); virtual void RemoveFromPrototype(ScriptContext * requestContext) { AssertMsg(false, "Shouldn't call this implementation."); }
virtual void AddToPrototype(ScriptContext * requestContext) { AssertMsg(false, "Shouldn't call this implementation."); }
virtual void SetPrototype(RecyclableObject* newPrototype) { AssertMsg(false, "Shouldn't call this implementation."); } virtual BOOL ToString(Js::Var* value, Js::ScriptContext* scriptContext) { AssertMsg(FALSE, "Do not use this function."); return false; } // don't need cross-site: in HostDispatch it's IDispatchEx based; in CustomExternalObject we have marshalling code explicitly.
virtual Var GetNamespaceParent(Js::Var aChild) { return nullptr; }
virtual HRESULT QueryObjectInterface(REFIID riid, void **ppvObj); virtual BOOL GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext);
virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext);
virtual RecyclableObject* ToObject(ScriptContext * requestContext);
virtual Var GetTypeOfString(ScriptContext* requestContext); // don't need cross-site: only supported in HostDispatch.
virtual Var InvokePut(Arguments args);
virtual BOOL GetRemoteTypeId(TypeId* typeId); // Only implemented by the HostDispatch object for cross-thread support
// Only supports a subset of entry points to be called remotely.
// For a list of supported entry points see the BuiltInOperation enum defined in JscriptInfo.idl
virtual BOOL InvokeBuiltInOperationRemotely(JavascriptMethod entryPoint, Arguments args, Var* result) { return FALSE; }; // don't need cross-site: only supported in HostDispatch.
virtual DynamicObject* GetRemoteObject(); // don't need cross-site: get the HostDispatch for global object/module root. don't need marshalling.
virtual Var GetHostDispatchVar(); virtual RecyclableObject * CloneToScriptContext(ScriptContext* requestContext); // If dtor is called, that means that OOM happened (mostly), then the vtable might not be initialized
// to the base class', so we can't assert.
virtual void Finalize(bool isShutdown) override { }
virtual void Dispose(bool isShutdown) override { }
virtual void Mark(Recycler *recycler) override { AssertMsg(false, "Mark called on object that isn't TrackableObject"); } static uint32 GetOffsetOfType() { return offsetof(RecyclableObject, type); } virtual void InvalidateCachedScope() { return; }
virtual BOOL HasDeferredTypeHandler() const { return false; } private: bool dtorCalled;
#endif
friend class LowererMD;
friend class LowererMDArch;
friend struct InlineCache; private:
UINT m_heapEnumValidationCookie;
public:
void SetHeapEnumValidationCookie(int cookie ) { m_heapEnumValidationCookie = cookie; }
int GetHeapEnumValidationCookie() { return m_heapEnumValidationCookie; }
#endif
};

ArrayBufferBase类

ArrayBufferBase类包含一系列关于ArrayBuffer的重要操作,但是这是个抽象类,方法并未实现。

GetByteLength //获取buffer size

GetBuffer //获取buffer地址

IsArrayBuffer //判断类型

IsSharedArrayBuffer //判断类型

比较重要的是提供了static方法AllocWrapper,负责分配VirtualBuffer内存

class ArrayBufferBase : public DynamicObject
{
protected:
#define MAX_ASMJS_ARRAYBUFFER_LENGTH 0x100000000 // 4GB //这个static函数会以函数指针作为参数传递,与malloc做选择
template<size_t MaxVirtualSize = MAX_ASMJS_ARRAYBUFFER_LENGTH>
static void* __cdecl AllocWrapper(DECLSPEC_GUARD_OVERFLOW size_t length);
//VirtualFree
static void FreeMemAlloc(Var ptr); public:
virtual void MarshalToScriptContext(Js::ScriptContext * scriptContext) = 0;//pure virtual
//构造函数,设置isDetached=0
ArrayBufferBase(DynamicType *type) : DynamicObject(type), isDetached(false) { }
bool IsDetached() { return isDetached; } virtual bool IsArrayBuffer() = 0;//pure virtual
virtual bool IsSharedArrayBuffer() = 0;//pure virtual
virtual bool IsWebAssemblyArrayBuffer() { return false; }
virtual ArrayBuffer * GetAsArrayBuffer() = 0;//pure virtual
virtual SharedArrayBuffer * GetAsSharedArrayBuffer() { return nullptr; }
virtual void AddParent(ArrayBufferParent* parent) { }//not defined
virtual uint32 GetByteLength() const = 0;//pure virtual
virtual BYTE* GetBuffer() const = 0;//pure virtual
virtual bool IsValidVirtualBufferLength(uint length) const { return false; };//说明Base类是基类,不可直接使用 //通用的static接口
static bool Is(Var value);//static 判断类型
static ArrayBufferBase* FromVar(Var value);//static 类型转换
// #define offsetof(s,m) ((size_t)&reinterpret_cast<char const volatile&>((((s*)0)->m)))
static int GetIsDetachedOffset() { return offsetof(ArrayBufferBase, isDetached); } protected:
Field(bool) isDetached;
};

ArrayBufferBase内存结构,此对象只有一个isDetached成员

Js::ArrayBufferBase

Js::DynamicObject
isDetached bool

ArrayBuffer类

ArrayBuffer类是直接对应于javascript中ArrayBuffer对象

ArrayBuffer方法

ArrayBuffer.isView(arg)
如果参数是ArrayBuffer的视图实例就返回true,例如 typed array objects 或 DataView。否则返回false。
ArrayBuffer.transfer(oldBuffer [, newByteLength])
返回一个新的ArrayBuffer,其内容取自oldBuffer的数据,并且根据 newByteLength 的大小来对数据进行截取或者以0扩展。
ArrayBuffer.prototype.slice()
返回一个新的 ArrayBuffer ,它的内容是这个 ArrayBuffer 的字节副本,从begin(包括),到end(不包括)。如果begin或end是负数,则指的是从数组末尾开始的索引,而不是从头开始。
ArrayBuffer.slice()
和 ArrayBuffer.prototype.slice()功能一样 ArrayBuffer属性 ArrayBuffer.length
ArrayBuffer构造函数的length属性,它的值是1
ArrayBuffer.prototype.constructor
指定函数,它创建一个对象的原型。其初始值是标准ArrayBuffer内置构造函数。
ArrayBuffer.prototype.byteLength 只读
数组的字节大小。在数组创建时确定,并且不可变更。只读
内存结构
可以看到对于ArrayBuffer来说,重要的结构在ArrayBuffer对象中都已给出 Js::ArrayBuffer
{
Js::ArrayBufferBase Js::ArrayBufferBase
primaryParent Recycler*
otherParents OtherParents*
buffer byte*
bufferLength uint32
}
class ArrayBuffer : public ArrayBufferBase
{
public:
// we need to install cross-site thunk on the nested array buffer when marshaling
// typed array.
DEFINE_VTABLE_CTOR_ABSTRACT(ArrayBuffer, ArrayBufferBase);
private:
void DetachBufferFromParent(ArrayBufferParent* parent);
public: template <typename FreeFN>
class ArrayBufferDetachedState : public ArrayBufferDetachedStateBase
{
public:
FreeFN* freeFunction; ArrayBufferDetachedState(BYTE* buffer, uint32 bufferLength, FreeFN* freeFunction, ArrayBufferAllocationType allocationType)
: ArrayBufferDetachedStateBase(TypeIds_ArrayBuffer, buffer, bufferLength, allocationType),
freeFunction(freeFunction)
{} virtual void ClearSelfOnly() override
{
HeapDelete(this);
} virtual void DiscardState() override
{
if (this->buffer != nullptr)
{
freeFunction(this->buffer);
this->buffer = nullptr;
}
this->bufferLength = 0;
} virtual void Discard() override
{
ClearSelfOnly();
}
}; class EntryInfo
{
public:
static FunctionInfo NewInstance;
static FunctionInfo Slice;
static FunctionInfo IsView;
static FunctionInfo GetterByteLength;
static FunctionInfo GetterSymbolSpecies;
static FunctionInfo Transfer;
}; //newArr = scriptContext->GetLibrary()->CreateArrayBuffer(byteLength);
static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...); //ArrayBuffer.prototype.slice()
static Var EntrySlice(RecyclableObject* function, CallInfo callInfo, ...); //ArrayBuffer.isView()
//https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/isView
static Var EntryIsView(RecyclableObject* function, CallInfo callInfo, ...); //ArrayBuffer.prototype.byteLength
//https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/byteLength
static Var EntryGetterByteLength(RecyclableObject* function, CallInfo callInfo, ...); static Var EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...); //ArrayBuffer.transfer()
//https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/transfer
static Var EntryTransfer(RecyclableObject* function, CallInfo callInfo, ...); //判定类型
static bool Is(Var aValue);
//
static ArrayBuffer* NewFromDetachedState(DetachedStateBase* state, JavascriptLibrary *library);
//类型转换
static ArrayBuffer* FromVar(Var aValue); //Detach
virtual ArrayBufferDetachedStateBase* DetachAndGetState();
virtual uint32 GetByteLength() const override { return bufferLength; }
virtual BYTE* GetBuffer() const override { return buffer; } static int GetByteLengthOffset() { return offsetof(ArrayBuffer, bufferLength); }//ArrayBuffer中bufferLength的offset
static int GetBufferOffset() { return offsetof(ArrayBuffer, buffer); }//ArrayBuffer中buffer的offset //设定parent
virtual void AddParent(ArrayBufferParent* parent) override; //maximum 2G -1 for amd64
static const uint32 MaxArrayBufferLength = 0x7FFFFFFF; static const uint32 ParentsCleanupThreshold = 1000; virtual bool IsValidAsmJsBufferLength(uint length, bool forceCheck = false) { return false; }
virtual bool IsArrayBuffer() override { return true; }
virtual bool IsSharedArrayBuffer() override { return false; }
virtual ArrayBuffer * GetAsArrayBuffer() override { return ArrayBuffer::FromVar(this); } static uint32 ToIndex(Var value, int32 errorCode, ScriptContext *scriptContext, uint32 MaxAllowedLength, bool checkSameValueZero = true); virtual ArrayBuffer * TransferInternal(DECLSPEC_GUARD_OVERFLOW uint32 newBufferLength) = 0; protected: typedef void __cdecl FreeFn(void* ptr); virtual ArrayBufferDetachedStateBase* CreateDetachedState(BYTE* buffer, DECLSPEC_GUARD_OVERFLOW uint32 bufferLength) = 0; static uint32 GetIndexFromVar(Js::Var arg, uint32 length, ScriptContext* scriptContext); //In most cases, the ArrayBuffer will only have one parent
Field(RecyclerWeakReference<ArrayBufferParent>*) primaryParent; struct OtherParents :public SList<RecyclerWeakReference<ArrayBufferParent>*, Recycler>
{
OtherParents(Recycler* recycler)
:SList<RecyclerWeakReference<ArrayBufferParent>*, Recycler>(recycler), increasedCount(0)
{
}
Field(uint) increasedCount;
}; Field(OtherParents*) otherParents; FieldNoBarrier(BYTE*) buffer; // Points to a heap allocated RGBA buffer, can be null
Field(uint32) bufferLength; // Number of bytes allocated
};

TypedArrayBase

对于TypedArray的常见操作都已经给出,但是是纯虚函数

class TypedArrayBase : public ArrayBufferParent
{
friend ArrayBuffer;
friend ArrayBufferBase; public:
static Var GetDefaultConstructor(Var object, ScriptContext* scriptContext); class EntryInfo
{
public:
static FunctionInfo NewInstance;
static FunctionInfo Set;
static FunctionInfo Subarray; static FunctionInfo From;
static FunctionInfo Of;
static FunctionInfo CopyWithin;
static FunctionInfo Entries;
static FunctionInfo Every;
static FunctionInfo Fill;
static FunctionInfo Filter;
static FunctionInfo Find;
static FunctionInfo FindIndex;
static FunctionInfo ForEach;
static FunctionInfo IndexOf;
static FunctionInfo Includes;
static FunctionInfo Join;
static FunctionInfo Keys;
static FunctionInfo LastIndexOf;
static FunctionInfo Map;
static FunctionInfo Reduce;
static FunctionInfo ReduceRight;
static FunctionInfo Reverse;
static FunctionInfo Slice;
static FunctionInfo Some;
static FunctionInfo Sort;
static FunctionInfo Values; static FunctionInfo GetterBuffer;
static FunctionInfo GetterByteLength;
static FunctionInfo GetterByteOffset;
static FunctionInfo GetterLength;
static FunctionInfo GetterSymbolToStringTag;
static FunctionInfo GetterSymbolSpecies;
}; TypedArrayBase(ArrayBufferBase* arrayBuffer, uint byteOffset, uint mappedLength, uint elementSize, DynamicType* type); //创建函数
static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...); static Var EntrySet(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntrySubarray(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryFrom(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryOf(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryCopyWithin(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryEntries(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryEvery(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryFill(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryFilter(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryFind(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryFindIndex(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryForEach(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryIndexOf(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryIncludes(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryJoin(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryKeys(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryLastIndexOf(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryMap(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryReduce(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryReduceRight(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryReverse(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntrySlice(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntrySome(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntrySort(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryValues(RecyclableObject* function, CallInfo callInfo, ...); static Var EntryGetterBuffer(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryGetterByteLength(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryGetterByteOffset(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryGetterLength(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryGetterSymbolToStringTag(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...); virtual DescriptorFlags GetSetter(PropertyId propertyId, Var *setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
virtual DescriptorFlags GetSetter(JavascriptString* propertyNameString, Var *setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) override;
virtual PropertyQueryFlags HasPropertyQuery(Js::PropertyId propertyId) override;
virtual BOOL HasOwnProperty(Js::PropertyId propertyId) override;
virtual PropertyQueryFlags GetPropertyQuery(Js::Var originalInstance, Js::PropertyId propertyId, Js::Var* value, Js::PropertyValueInfo* info, Js::ScriptContext* requestContext) override;
virtual PropertyQueryFlags GetPropertyQuery(Js::Var originalInstance, Js::JavascriptString* propertyNameString, Js::Var* value, Js::PropertyValueInfo* info, Js::ScriptContext* requestContext) override;
virtual PropertyQueryFlags GetPropertyReferenceQuery(Js::Var originalInstance, Js::PropertyId propertyId, Js::Var* value, Js::PropertyValueInfo* info, Js::ScriptContext* requestContext) override;
virtual PropertyQueryFlags HasItemQuery(uint32 index) override;
virtual BOOL DeleteItem(uint32 index, Js::PropertyOperationFlags flags) override { return false; }
virtual PropertyQueryFlags GetItemQuery(Js::Var originalInstance, uint32 index, Js::Var* value, Js::ScriptContext * requestContext) override;
virtual BOOL SetItem(uint32 index, Js::Var value, Js::PropertyOperationFlags flags = PropertyOperation_None) override;
virtual BOOL SetProperty(Js::PropertyId propertyId, Js::Var value, Js::PropertyOperationFlags flags, Js::PropertyValueInfo* info) override;
virtual BOOL SetProperty(Js::JavascriptString* propertyNameString, Js::Var value, Js::PropertyOperationFlags flags, Js::PropertyValueInfo* info) override;
virtual BOOL DeleteProperty(Js::PropertyId propertyId, Js::PropertyOperationFlags flags) override;
virtual BOOL DeleteProperty(JavascriptString *propertyNameString, Js::PropertyOperationFlags flags) override;
virtual PropertyQueryFlags GetItemReferenceQuery(Js::Var originalInstance, uint32 index, Js::Var* value, Js::ScriptContext * requestContext) override;
virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, ForInCache * forInCache = nullptr) override;
virtual JavascriptEnumerator * GetIndexEnumerator(EnumeratorFlags flags, ScriptContext * requestContext) override; virtual BOOL IsEnumerable(PropertyId propertyId) override;
virtual BOOL IsConfigurable(PropertyId propertyId) override;
virtual BOOL IsWritable(PropertyId propertyId) override;
virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) override;
virtual BOOL SetWritable(PropertyId propertyId, BOOL value) override;
virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) override;
virtual BOOL SetAttributes(PropertyId propertyId, PropertyAttributes attributes) override;
virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags) override; virtual BOOL InitProperty(Js::PropertyId propertyId, Js::Var value, PropertyOperationFlags flags = PropertyOperation_None, Js::PropertyValueInfo* info = NULL) override;
virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any) override;
static BOOL Is(Var aValue);
static BOOL Is(TypeId typeId);
static TypedArrayBase* FromVar(Var aValue);
// Returns false if this is not a TypedArray or it's not detached
static BOOL IsDetachedTypedArray(Var aValue);
static HRESULT GetBuffer(Var aValue, ArrayBuffer** outBuffer, uint32* outOffset, uint32* outLength);
static TypedArrayBase * ValidateTypedArray(Var aValue, ScriptContext *scriptContext, LPCWSTR apiName);
static TypedArrayBase * ValidateTypedArray(Arguments &args, ScriptContext *scriptContext, LPCWSTR apiName);
static Var TypedArrayCreate(Var constructor, Arguments *args, uint32 length, ScriptContext *scriptContext); //写入操作 pure virtual
virtual BOOL DirectSetItem(__in uint32 index, __in Js::Var value) = 0;
virtual BOOL DirectSetItemNoSet(__in uint32 index, __in Js::Var value) = 0;
virtual Var DirectGetItem(__in uint32 index) = 0;
virtual BOOL DirectSetItemNoDetachCheck(__in uint32 index, __in Js::Var value) = 0;
virtual Var DirectGetItemNoDetachCheck(__in uint32 index) = 0; virtual Var TypedAdd(__in uint32 index, Var second) = 0;
virtual Var TypedAnd(__in uint32 index, Var second) = 0;
virtual Var TypedLoad(__in uint32 index) = 0;
virtual Var TypedOr(__in uint32 index, Var second) = 0;
virtual Var TypedStore(__in uint32 index, Var second) = 0;
virtual Var TypedSub(__in uint32 index, Var second) = 0;
virtual Var TypedXor(__in uint32 index, Var second) = 0;
virtual Var TypedExchange(__in uint32 index, Var second) = 0;
virtual Var TypedCompareExchange(__in uint32 index, Var comparand, Var replacementValue) = 0; //TypedArray.prototype.byteLength
uint32 GetByteLength() const { return length * BYTES_PER_ELEMENT; }
//TypedArray.prototype.byteOffset
uint32 GetByteOffset() const { return byteOffset; }
uint32 GetBytesPerElement() const { return BYTES_PER_ELEMENT; }
//TypedArray.prototype.buffer
byte* GetByteBuffer() const { return buffer; }; bool IsDetachedBuffer() const { return this->GetArrayBuffer()->IsDetached(); }
void ClearLengthAndBufferOnDetach();
static Var CommonSet(Arguments& args);
static Var CommonSubarray(Arguments& args); void SetObject(RecyclableObject* arraySource, uint32 targetLength, uint32 offset = 0);
void SetObjectNoDetachCheck(RecyclableObject* arraySource, uint32 targetLength, uint32 offset = 0);
void Set(TypedArrayBase* typedArraySource, uint32 offset = 0); virtual BOOL GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override; static bool TryGetLengthForOptimizedTypedArray(const Var var, uint32 *const lengthRef, TypeId *const typeIdRef);
BOOL ValidateIndexAndDirectSetItem(__in Js::Var index, __in Js::Var value, __out bool * isNumericIndex);
uint32 ValidateAndReturnIndex(__in Js::Var index, __out bool * skipOperation, __out bool * isNumericIndex); // objectArray support
virtual BOOL SetItemWithAttributes(uint32 index, Var value, PropertyAttributes attributes) override; Var FindMinOrMax(Js::ScriptContext * scriptContext, TypeId typeId, bool findMax);
template<typename T, bool checkNaNAndNegZero> Var FindMinOrMax(Js::ScriptContext * scriptContext, bool findMax); static Var GetKeysEntriesValuesHelper(Arguments& args, ScriptContext *scriptContext, LPCWSTR apiName, JavascriptArrayIteratorKind kind); static uint32 GetFromIndex(Var arg, uint32 length, ScriptContext *scriptContext); private:
uint32 GetSourceLength(RecyclableObject* arraySource, uint32 targetLength, uint32 offset); protected:
static Var CreateNewInstanceFromIterator(RecyclableObject *iterator, ScriptContext *scriptContext, uint32 elementSize, PFNCreateTypedArray pfnCreateTypedArray);
static Var CreateNewInstance(Arguments& args, ScriptContext* scriptContext, uint32 elementSize, PFNCreateTypedArray pfnCreateTypedArray );
static bool ArrayIteratorPrototypeHasUserDefinedNext(ScriptContext *scriptContext);
static BOOL CanonicalNumericIndexString(PropertyId propertyId, ScriptContext *scriptContext);
static BOOL CanonicalNumericIndexString(JavascriptString *propertyString, ScriptContext *scriptContext); typedef int(__cdecl* CompareElementsFunction)(void*, const void*, const void*);
virtual CompareElementsFunction GetCompareElementsFunction() = 0; virtual Var Subarray(uint32 begin, uint32 end) = 0;
Field(int32) BYTES_PER_ELEMENT;
Field(uint32) byteOffset;
FieldNoBarrier(BYTE*) buffer; // beginning of mapped array. public:
static uint32 GetOffsetOfBuffer() { return offsetof(TypedArrayBase, buffer); }
static uint32 GetOffsetOfLength() { return offsetof(TypedArrayBase, length); } };

TypedArray

内存结构

Js::TypedArray
{
Js::TypedArrayBase
{
Js::ArrayBufferParent
{
Js::ArrayObject
arrayBuffer Js::JavascriptArrayBuffer*
}
BYTES_PER_ELEMENT int
byteOffset unsigned int
buffer unsigned char *

}

TypedArray类复写实现了虚函数和实际的操作方法

并不存在单独的TypedArray类型的类,都是针对模版进行的特例化

    template <typename TypeName, bool clamped = false, bool virtualAllocated = false>
class TypedArray : public TypedArrayBase
{
protected:
DEFINE_VTABLE_CTOR(TypedArray, TypedArrayBase);
virtual void MarshalToScriptContext(Js::ScriptContext * scriptContext)
{
Assert(this->GetScriptContext() != scriptContext);
AssertMsg(VirtualTableInfo<TypedArray>::HasVirtualTable(this), "Derived class need to define marshal to script context"); VirtualTableInfo<Js::CrossSiteObject<TypedArray<TypeName, clamped, virtualAllocated>>>::SetVirtualTable(this);
ArrayBufferBase* arrayBuffer = this->GetArrayBuffer();
if (arrayBuffer && !arrayBuffer->IsCrossSiteObject())
{
arrayBuffer->MarshalToScriptContext(scriptContext);
}
} TypedArray(DynamicType *type): TypedArrayBase(nullptr, 0, 0, sizeof(TypeName), type) { buffer = nullptr; } public:
class EntryInfo
{
public:
static FunctionInfo NewInstance;
static FunctionInfo Set;
}; TypedArray(ArrayBufferBase* arrayBuffer, uint32 byteOffset, uint32 mappedLength, DynamicType* type); static Var Create(ArrayBufferBase* arrayBuffer, uint32 byteOffSet, uint32 mappedLength, JavascriptLibrary* javascriptLibrary);
static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...); static Var EntrySet(RecyclableObject* function, CallInfo callInfo, ...); Var Subarray(uint32 begin, uint32 end); static BOOL Is(Var aValue);
static TypedArray<TypeName, clamped, virtualAllocated>* FromVar(Var aValue); inline Var BaseTypedDirectGetItem(__in uint32 index)
{
if (this->IsDetachedBuffer()) // 9.4.5.8 IntegerIndexedElementGet
{
JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray);
} if (index < GetLength())
{
Assert((index + 1)* sizeof(TypeName)+GetByteOffset() <= GetArrayBuffer()->GetByteLength());
TypeName* typedBuffer = (TypeName*)buffer;
return JavascriptNumber::ToVar(typedBuffer[index], GetScriptContext());
}
return GetLibrary()->GetUndefined();
} inline Var TypedDirectGetItemWithCheck(__in uint32 index)
{
if (this->IsDetachedBuffer()) // 9.4.5.8 IntegerIndexedElementGet
{
JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray);
} if (index < GetLength())
{
Assert((index + 1)* sizeof(TypeName)+GetByteOffset() <= GetArrayBuffer()->GetByteLength());
TypeName* typedBuffer = (TypeName*)buffer;
return JavascriptNumber::ToVarWithCheck(typedBuffer[index], GetScriptContext());
}
return GetLibrary()->GetUndefined();
} inline Var BaseTypedDirectGetItemNoDetachCheck(__in uint32 index)
{
Assert(!IsDetachedBuffer());
Assert(index < GetLength());
Assert((index + 1)* sizeof(TypeName) + GetByteOffset() <= GetArrayBuffer()->GetByteLength());
TypeName* typedBuffer = (TypeName*)buffer;
return JavascriptNumber::ToVar(typedBuffer[index], GetScriptContext());
} inline Var DirectGetItemVarCheckNoDetachCheck(__in uint32 index)
{
Assert(!IsDetachedBuffer());
Assert(index < GetLength());
Assert((index + 1)* sizeof(TypeName) + GetByteOffset() <= GetArrayBuffer()->GetByteLength());
TypeName* typedBuffer = (TypeName*)buffer;
return JavascriptNumber::ToVarWithCheck(typedBuffer[index], GetScriptContext());
} inline BOOL DirectSetItemAtRange(TypedArray *fromArray, __in int32 iSrcStart, __in int32 iDstStart, __in uint32 length, TypeName(*convFunc)(Var value, ScriptContext* scriptContext))
{
TypeName* dstBuffer = (TypeName*)buffer;
TypeName* srcBuffer = (TypeName*)fromArray->buffer;
Assert(srcBuffer && dstBuffer);
Assert(length <= ArrayBuffer::MaxArrayBufferLength / sizeof(TypeName));
// caller checks that src and dst index are the same
Assert(iSrcStart == iDstStart); if (this->IsDetachedBuffer() || fromArray->IsDetachedBuffer())
{
JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray);
} // Fixup destination start in case it's negative
uint32 start = iDstStart;
if (iDstStart < 0)
{
if ((int64)(length) + iDstStart < 0)
{
// nothing to do, all index are no-op
return true;
} length += iDstStart;
start = 0;
} uint32 dstLength = UInt32Math::Add(start, length) < GetLength() ? length : GetLength() > start ? GetLength() - start : 0;
uint32 srcLength = start + length < fromArray->GetLength() ? length : (fromArray->GetLength() > start ? fromArray->GetLength() - start : 0); // length is the minimum of length, srcLength and dstLength
length = length < srcLength ? (length < dstLength ? length : dstLength) : (srcLength < dstLength ? srcLength : dstLength); const size_t byteSize = sizeof(TypeName) * length;
Assert(byteSize >= length); // check for overflow
js_memcpy_s(dstBuffer + start, dstLength * sizeof(TypeName), srcBuffer + start, byteSize); if (dstLength > length)
{
TypeName undefinedValue = convFunc(GetLibrary()->GetUndefined(), GetScriptContext());
for (uint32 i = length; i < dstLength; i++)
{
dstBuffer[i] = undefinedValue;
}
} return true;
} inline BOOL DirectSetItemAtRange(__in int32 start, __in uint32 length, __in Js::Var value, TypeName(*convFunc)(Var value, ScriptContext* scriptContext))
{
if (CrossSite::IsCrossSiteObjectTyped(this))
{
return false;
}
TypeName typedValue = convFunc(value, GetScriptContext()); if (this->IsDetachedBuffer()) // 9.4.5.9 IntegerIndexedElementSet
{
JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray);
}
uint32 newStart = start, newLength = length; if (start < 0)
{
if ((int64)(length) + start < 0)
{
// nothing to do, all index are no-op
return true;
}
newStart = 0;
// fixup the length with the change
newLength += start;
}
if (newStart >= GetLength())
{
// If we want to start copying past the length of the array, all index are no-op
return true;
}
if (UInt32Math::Add(newStart, newLength) > GetLength())
{
newLength = GetLength() - newStart;
} TypeName* typedBuffer = (TypeName*)buffer; if (typedValue == 0 || sizeof(TypeName) == 1)
{
const size_t byteSize = sizeof(TypeName) * newLength;
Assert(byteSize >= newLength); // check for overflow
memset(typedBuffer + newStart, (int)typedValue, byteSize);
}
else
{
for (uint32 i = 0; i < newLength; i++)
{
typedBuffer[newStart + i] = typedValue;
}
} return TRUE;
} inline BOOL BaseTypedDirectSetItem(__in uint32 index, __in Js::Var value, TypeName (*convFunc)(Var value, ScriptContext* scriptContext))
{
// This call can potentially invoke user code, and may end up detaching the underlying array (this).
// Therefore it was brought out and above the IsDetached check
TypeName typedValue = convFunc(value, GetScriptContext()); if (this->IsDetachedBuffer()) // 9.4.5.9 IntegerIndexedElementSet
{
JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray);
} if (index >= GetLength())
{
return FALSE;
} AssertMsg(index < GetLength(), "Trying to set out of bound index for typed array.");
Assert((index + 1)* sizeof(TypeName) + GetByteOffset() <= GetArrayBuffer()->GetByteLength());
TypeName* typedBuffer = (TypeName*)buffer; typedBuffer[index] = typedValue; return TRUE;
} inline BOOL BaseTypedDirectSetItemNoSet(__in uint32 index, __in Js::Var value, TypeName (*convFunc)(Var value, ScriptContext* scriptContext))
{
// This call can potentially invoke user code, and may end up detaching the underlying array (this).
// Therefore it was brought out and above the IsDetached check
convFunc(value, GetScriptContext()); if (this->IsDetachedBuffer()) // 9.4.5.9 IntegerIndexedElementSet
{
JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray);
} return FALSE;
} inline BOOL BaseTypedDirectSetItemNoDetachCheck(__in uint32 index, __in Js::Var value, TypeName(*convFunc)(Var value, ScriptContext* scriptContext))
{
TypeName typedValue = convFunc(value, GetScriptContext()); // The caller of the function made sure that no IsDetached check required.
// The caller of the function also made sure that no length check required. Assert(!IsDetachedBuffer());
AssertMsg(index < GetLength(), "Trying to set out of bound index for typed array.");
Assert((index + 1)* sizeof(TypeName) + GetByteOffset() <= GetArrayBuffer()->GetByteLength());
TypeName* typedBuffer = (TypeName*)buffer; typedBuffer[index] = typedValue; return TRUE;
} virtual BOOL DirectSetItem(__in uint32 index, __in Js::Var value) override sealed;
virtual BOOL DirectSetItemNoSet(__in uint32 index, __in Js::Var value) override sealed;
virtual Var DirectGetItem(__in uint32 index) override sealed;
virtual BOOL DirectSetItemNoDetachCheck(__in uint32 index, __in Js::Var value) override sealed;
virtual Var DirectGetItemNoDetachCheck(__in uint32 index) override sealed;
virtual Var TypedAdd(__in uint32 index, Var second) override;
virtual Var TypedAnd(__in uint32 index, Var second) override;
virtual Var TypedLoad(__in uint32 index) override;
virtual Var TypedOr(__in uint32 index, Var second) override;
virtual Var TypedStore(__in uint32 index, Var second) override;
virtual Var TypedSub(__in uint32 index, Var second) override;
virtual Var TypedXor(__in uint32 index, Var second) override;
virtual Var TypedExchange(__in uint32 index, Var second) override;
virtual Var TypedCompareExchange(__in uint32 index, Var comparand, Var replacementValue) override; static BOOL DirectSetItem(__in TypedArray* arr, __in uint32 index, __in Js::Var value)
{
AssertMsg(arr != nullptr, "Array shouldn't be nullptr."); return arr->DirectSetItem(index, value);
} protected:
CompareElementsFunction GetCompareElementsFunction()
{
return &TypedArrayCompareElementsHelper<TypeName>;
} public:
virtual VTableValue DummyVirtualFunctionToHinderLinkerICF();
};

Chakra TypedArray代码实现笔记的更多相关文章

  1. Linux协议栈代码阅读笔记(二)网络接口的配置

    Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...

  2. [置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  3. Linux-3.0.8 input subsystem代码阅读笔记

    先乱序记录一下阅读Linux input subsystem代码的笔记. 在input device driver的入口代码部分,需要分配并初始化input device结构,内核提供的API是inp ...

  4. [置顶] Linux协议栈代码阅读笔记(二)网络接口的配置

    Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...

  5. 《linux 内核全然剖析》 fork.c 代码分析笔记

    fork.c 代码分析笔记 verifiy_area long last_pid=0; //全局变量,用来记录眼下最大的pid数值 void verify_area(void * addr,int s ...

  6. 《linux 内核全然剖析》sched.c sched.h 代码分析笔记

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u011368821/article/details/25129835 sched.c sched.h ...

  7. 使用Git和Github来管理自己的代码和笔记

    一.Github注册 1.先注册github.com的账号,官方网站: https://github.com/ 2.登录 3.创建仓库,仓库分公开的和私有的,公开的是免费的,私有的是收费的.我现在创建 ...

  8. TERSUS无代码开发(笔记09)-简单实例前端样式设计

    前端常用样式设计 =========================================================================================== ...

  9. TERSUS无代码开发(笔记08)-简单实例电脑端后台逻辑开发

    主管审批功能逻辑开发 1.查询逻辑开发(查询待审批记录) 2.批准处理(将选中的一条记录进行批准处理)  =============================================== ...

随机推荐

  1. Windows环境墙内搭建Go语言集成开发环境

    1 安装go环境 太简单略 2 安装vs code 找到微软的官方网站,下载Visual Studio Code,官网地址https://code.visualstudio.com/ 安装完成后进入V ...

  2. jsp四大对象

    发送参数: <a href="deal.jsp?id=1&user=用户&pwd=">处理页</a> 接收参数: <% String ...

  3. Bootstrap的响应式后台管理模板推荐

    1.Admin LTE 该模版开源免费.已用到项目中,客户评价说UI很好看... AdminLTE - 是一个完全响应式管理模板.基于Bootstrap3的框架.高度可定制的,易于使用.支持很多的屏幕 ...

  4. Nginx 虚拟主机示例

    Nginx server 模块 server { // 标识虚拟主机开始 listen ; ## // 指定虚拟主机服务器端口 server_name localhost; // 指定 IP地址或者域 ...

  5. 多文档界面QMdiArea

    当使用多文档界面功能时,我们是将QMdiArea作为主窗口的中央部件,然后在这个中央部件中,我们可以同时打开很多个子窗口QMdiSubWindow 样式: import sys from PyQt5. ...

  6. POJ 1200 Crazy Search (哈希)

    题目链接 Description Many people like to solve hard puzzles some of which may lead them to madness. One ...

  7. C - Portals Gym - 102006C (网络流最小割)

    题目链接:https://cn.vjudge.net/contest/283918#problem/C 题目大意:T个测试数据,然后给你一个字符串,每一个字符串包括‘s’,‘t’,‘o’,‘#’,‘. ...

  8. D - 文理分科 (网络流->最小割)

    题目链接:https://cn.vjudge.net/contest/281959#problem/D 题目大意:中文题目 具体思路:我们需要求出最大的满意值,从另一方面想,我们可以求出总的满意值,然 ...

  9. Django学习手册 - 登录装饰器

    # 装饰器定义 def auth(func): def inner(request,*args,**kwargs): v = request.COOKIES.get("user") ...

  10. npm快捷键

    一.npm基本快捷键 node -v查看安装的nodejs版本,出现版本号,说明刚刚已正确安装nodejs.PS:未能出现版本号,请尝试注销电脑重试: npm -v查看npm的版本号,npm是在安装n ...