| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536 |
- (function (chai, stream, module, fs) {
- 'use strict';
- var decoder;
- try {
- decoder = new TextDecoder();
- } catch(error) {}
- var src;
- var srcEnd;
- var position$1 = 0;
- const EMPTY_ARRAY = [];
- var strings = EMPTY_ARRAY;
- var stringPosition = 0;
- var currentUnpackr = {};
- var currentStructures;
- var srcString;
- var srcStringStart = 0;
- var srcStringEnd = 0;
- var bundledStrings$1;
- var referenceMap;
- var currentExtensions = [];
- var dataView;
- var defaultOptions = {
- useRecords: false,
- mapsAsObjects: true
- };
- class C1Type {}
- const C1 = new C1Type();
- C1.name = 'MessagePack 0xC1';
- var sequentialMode = false;
- var inlineObjectReadThreshold = 2;
- var readStruct$1, onLoadedStructures$1, onSaveState;
- // no-eval build
- try {
- new Function('');
- } catch(error) {
- // if eval variants are not supported, do not create inline object readers ever
- inlineObjectReadThreshold = Infinity;
- }
- let Unpackr$1 = class Unpackr {
- constructor(options) {
- if (options) {
- if (options.useRecords === false && options.mapsAsObjects === undefined)
- options.mapsAsObjects = true;
- if (options.sequential && options.trusted !== false) {
- options.trusted = true;
- if (!options.structures && options.useRecords != false) {
- options.structures = [];
- if (!options.maxSharedStructures)
- options.maxSharedStructures = 0;
- }
- }
- if (options.structures)
- options.structures.sharedLength = options.structures.length;
- else if (options.getStructures) {
- (options.structures = []).uninitialized = true; // this is what we use to denote an uninitialized structures
- options.structures.sharedLength = 0;
- }
- if (options.int64AsNumber) {
- options.int64AsType = 'number';
- }
- }
- Object.assign(this, options);
- }
- unpack(source, options) {
- if (src) {
- // re-entrant execution, save the state and restore it after we do this unpack
- return saveState$1(() => {
- clearSource();
- return this ? this.unpack(source, options) : Unpackr$1.prototype.unpack.call(defaultOptions, source, options)
- })
- }
- if (!source.buffer && source.constructor === ArrayBuffer)
- source = typeof Buffer !== 'undefined' ? Buffer.from(source) : new Uint8Array(source);
- if (typeof options === 'object') {
- srcEnd = options.end || source.length;
- position$1 = options.start || 0;
- } else {
- position$1 = 0;
- srcEnd = options > -1 ? options : source.length;
- }
- stringPosition = 0;
- srcStringEnd = 0;
- srcString = null;
- strings = EMPTY_ARRAY;
- bundledStrings$1 = null;
- src = source;
- // this provides cached access to the data view for a buffer if it is getting reused, which is a recommend
- // technique for getting data from a database where it can be copied into an existing buffer instead of creating
- // new ones
- try {
- dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength));
- } catch(error) {
- // if it doesn't have a buffer, maybe it is the wrong type of object
- src = null;
- if (source instanceof Uint8Array)
- throw error
- throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source))
- }
- if (this instanceof Unpackr$1) {
- currentUnpackr = this;
- if (this.structures) {
- currentStructures = this.structures;
- return checkedRead(options)
- } else if (!currentStructures || currentStructures.length > 0) {
- currentStructures = [];
- }
- } else {
- currentUnpackr = defaultOptions;
- if (!currentStructures || currentStructures.length > 0)
- currentStructures = [];
- }
- return checkedRead(options)
- }
- unpackMultiple(source, forEach) {
- let values, lastPosition = 0;
- try {
- sequentialMode = true;
- let size = source.length;
- let value = this ? this.unpack(source, size) : defaultUnpackr.unpack(source, size);
- if (forEach) {
- if (forEach(value, lastPosition, position$1) === false) return;
- while(position$1 < size) {
- lastPosition = position$1;
- if (forEach(checkedRead(), lastPosition, position$1) === false) {
- return
- }
- }
- }
- else {
- values = [ value ];
- while(position$1 < size) {
- lastPosition = position$1;
- values.push(checkedRead());
- }
- return values
- }
- } catch(error) {
- error.lastPosition = lastPosition;
- error.values = values;
- throw error
- } finally {
- sequentialMode = false;
- clearSource();
- }
- }
- _mergeStructures(loadedStructures, existingStructures) {
- if (onLoadedStructures$1)
- loadedStructures = onLoadedStructures$1.call(this, loadedStructures);
- loadedStructures = loadedStructures || [];
- if (Object.isFrozen(loadedStructures))
- loadedStructures = loadedStructures.map(structure => structure.slice(0));
- for (let i = 0, l = loadedStructures.length; i < l; i++) {
- let structure = loadedStructures[i];
- if (structure) {
- structure.isShared = true;
- if (i >= 32)
- structure.highByte = (i - 32) >> 5;
- }
- }
- loadedStructures.sharedLength = loadedStructures.length;
- for (let id in existingStructures || []) {
- if (id >= 0) {
- let structure = loadedStructures[id];
- let existing = existingStructures[id];
- if (existing) {
- if (structure)
- (loadedStructures.restoreStructures || (loadedStructures.restoreStructures = []))[id] = structure;
- loadedStructures[id] = existing;
- }
- }
- }
- return this.structures = loadedStructures
- }
- decode(source, options) {
- return this.unpack(source, options)
- }
- };
- function checkedRead(options) {
- try {
- if (!currentUnpackr.trusted && !sequentialMode) {
- let sharedLength = currentStructures.sharedLength || 0;
- if (sharedLength < currentStructures.length)
- currentStructures.length = sharedLength;
- }
- let result;
- if (currentUnpackr.randomAccessStructure && src[position$1] < 0x40 && src[position$1] >= 0x20 && readStruct$1) {
- result = readStruct$1(src, position$1, srcEnd, currentUnpackr);
- src = null; // dispose of this so that recursive unpack calls don't save state
- if (!(options && options.lazy) && result)
- result = result.toJSON();
- position$1 = srcEnd;
- } else
- result = read();
- if (bundledStrings$1) { // bundled strings to skip past
- position$1 = bundledStrings$1.postBundlePosition;
- bundledStrings$1 = null;
- }
- if (sequentialMode)
- // we only need to restore the structures if there was an error, but if we completed a read,
- // we can clear this out and keep the structures we read
- currentStructures.restoreStructures = null;
- if (position$1 == srcEnd) {
- // finished reading this source, cleanup references
- if (currentStructures && currentStructures.restoreStructures)
- restoreStructures();
- currentStructures = null;
- src = null;
- if (referenceMap)
- referenceMap = null;
- } else if (position$1 > srcEnd) {
- // over read
- throw new Error('Unexpected end of MessagePack data')
- } else if (!sequentialMode) {
- let jsonView;
- try {
- jsonView = JSON.stringify(result, (_, value) => typeof value === "bigint" ? `${value}n` : value).slice(0, 100);
- } catch(error) {
- jsonView = '(JSON view not available ' + error + ')';
- }
- throw new Error('Data read, but end of buffer not reached ' + jsonView)
- }
- // else more to read, but we are reading sequentially, so don't clear source yet
- return result
- } catch(error) {
- if (currentStructures && currentStructures.restoreStructures)
- restoreStructures();
- clearSource();
- if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer') || position$1 > srcEnd) {
- error.incomplete = true;
- }
- throw error
- }
- }
- function restoreStructures() {
- for (let id in currentStructures.restoreStructures) {
- currentStructures[id] = currentStructures.restoreStructures[id];
- }
- currentStructures.restoreStructures = null;
- }
- function read() {
- let token = src[position$1++];
- if (token < 0xa0) {
- if (token < 0x80) {
- if (token < 0x40)
- return token
- else {
- let structure = currentStructures[token & 0x3f] ||
- currentUnpackr.getStructures && loadStructures()[token & 0x3f];
- if (structure) {
- if (!structure.read) {
- structure.read = createStructureReader(structure, token & 0x3f);
- }
- return structure.read()
- } else
- return token
- }
- } else if (token < 0x90) {
- // map
- token -= 0x80;
- if (currentUnpackr.mapsAsObjects) {
- let object = {};
- for (let i = 0; i < token; i++) {
- let key = readKey();
- if (key === '__proto__')
- key = '__proto_';
- object[key] = read();
- }
- return object
- } else {
- let map = new Map();
- for (let i = 0; i < token; i++) {
- map.set(read(), read());
- }
- return map
- }
- } else {
- token -= 0x90;
- let array = new Array(token);
- for (let i = 0; i < token; i++) {
- array[i] = read();
- }
- if (currentUnpackr.freezeData)
- return Object.freeze(array)
- return array
- }
- } else if (token < 0xc0) {
- // fixstr
- let length = token - 0xa0;
- if (srcStringEnd >= position$1) {
- return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart)
- }
- if (srcStringEnd == 0 && srcEnd < 140) {
- // for small blocks, avoiding the overhead of the extract call is helpful
- let string = length < 16 ? shortStringInJS(length) : longStringInJS(length);
- if (string != null)
- return string
- }
- return readFixedString(length)
- } else {
- let value;
- switch (token) {
- case 0xc0: return null
- case 0xc1:
- if (bundledStrings$1) {
- value = read(); // followed by the length of the string in characters (not bytes!)
- if (value > 0)
- return bundledStrings$1[1].slice(bundledStrings$1.position1, bundledStrings$1.position1 += value)
- else
- return bundledStrings$1[0].slice(bundledStrings$1.position0, bundledStrings$1.position0 -= value)
- }
- return C1; // "never-used", return special object to denote that
- case 0xc2: return false
- case 0xc3: return true
- case 0xc4:
- // bin 8
- value = src[position$1++];
- if (value === undefined)
- throw new Error('Unexpected end of buffer')
- return readBin(value)
- case 0xc5:
- // bin 16
- value = dataView.getUint16(position$1);
- position$1 += 2;
- return readBin(value)
- case 0xc6:
- // bin 32
- value = dataView.getUint32(position$1);
- position$1 += 4;
- return readBin(value)
- case 0xc7:
- // ext 8
- return readExt(src[position$1++])
- case 0xc8:
- // ext 16
- value = dataView.getUint16(position$1);
- position$1 += 2;
- return readExt(value)
- case 0xc9:
- // ext 32
- value = dataView.getUint32(position$1);
- position$1 += 4;
- return readExt(value)
- case 0xca:
- value = dataView.getFloat32(position$1);
- if (currentUnpackr.useFloat32 > 2) {
- // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
- let multiplier = mult10[((src[position$1] & 0x7f) << 1) | (src[position$1 + 1] >> 7)];
- position$1 += 4;
- return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier
- }
- position$1 += 4;
- return value
- case 0xcb:
- value = dataView.getFloat64(position$1);
- position$1 += 8;
- return value
- // uint handlers
- case 0xcc:
- return src[position$1++]
- case 0xcd:
- value = dataView.getUint16(position$1);
- position$1 += 2;
- return value
- case 0xce:
- value = dataView.getUint32(position$1);
- position$1 += 4;
- return value
- case 0xcf:
- if (currentUnpackr.int64AsType === 'number') {
- value = dataView.getUint32(position$1) * 0x100000000;
- value += dataView.getUint32(position$1 + 4);
- } else if (currentUnpackr.int64AsType === 'string') {
- value = dataView.getBigUint64(position$1).toString();
- } else if (currentUnpackr.int64AsType === 'auto') {
- value = dataView.getBigUint64(position$1);
- if (value<=BigInt(2)<<BigInt(52)) value=Number(value);
- } else
- value = dataView.getBigUint64(position$1);
- position$1 += 8;
- return value
- // int handlers
- case 0xd0:
- return dataView.getInt8(position$1++)
- case 0xd1:
- value = dataView.getInt16(position$1);
- position$1 += 2;
- return value
- case 0xd2:
- value = dataView.getInt32(position$1);
- position$1 += 4;
- return value
- case 0xd3:
- if (currentUnpackr.int64AsType === 'number') {
- value = dataView.getInt32(position$1) * 0x100000000;
- value += dataView.getUint32(position$1 + 4);
- } else if (currentUnpackr.int64AsType === 'string') {
- value = dataView.getBigInt64(position$1).toString();
- } else if (currentUnpackr.int64AsType === 'auto') {
- value = dataView.getBigInt64(position$1);
- if (value>=BigInt(-2)<<BigInt(52)&&value<=BigInt(2)<<BigInt(52)) value=Number(value);
- } else
- value = dataView.getBigInt64(position$1);
- position$1 += 8;
- return value
- case 0xd4:
- // fixext 1
- value = src[position$1++];
- if (value == 0x72) {
- return recordDefinition(src[position$1++] & 0x3f)
- } else {
- let extension = currentExtensions[value];
- if (extension) {
- if (extension.read) {
- position$1++; // skip filler byte
- return extension.read(read())
- } else if (extension.noBuffer) {
- position$1++; // skip filler byte
- return extension()
- } else
- return extension(src.subarray(position$1, ++position$1))
- } else
- throw new Error('Unknown extension ' + value)
- }
- case 0xd5:
- // fixext 2
- value = src[position$1];
- if (value == 0x72) {
- position$1++;
- return recordDefinition(src[position$1++] & 0x3f, src[position$1++])
- } else
- return readExt(2)
- case 0xd6:
- // fixext 4
- return readExt(4)
- case 0xd7:
- // fixext 8
- return readExt(8)
- case 0xd8:
- // fixext 16
- return readExt(16)
- case 0xd9:
- // str 8
- value = src[position$1++];
- if (srcStringEnd >= position$1) {
- return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart)
- }
- return readString8(value)
- case 0xda:
- // str 16
- value = dataView.getUint16(position$1);
- position$1 += 2;
- if (srcStringEnd >= position$1) {
- return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart)
- }
- return readString16(value)
- case 0xdb:
- // str 32
- value = dataView.getUint32(position$1);
- position$1 += 4;
- if (srcStringEnd >= position$1) {
- return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart)
- }
- return readString32(value)
- case 0xdc:
- // array 16
- value = dataView.getUint16(position$1);
- position$1 += 2;
- return readArray(value)
- case 0xdd:
- // array 32
- value = dataView.getUint32(position$1);
- position$1 += 4;
- return readArray(value)
- case 0xde:
- // map 16
- value = dataView.getUint16(position$1);
- position$1 += 2;
- return readMap(value)
- case 0xdf:
- // map 32
- value = dataView.getUint32(position$1);
- position$1 += 4;
- return readMap(value)
- default: // negative int
- if (token >= 0xe0)
- return token - 0x100
- if (token === undefined) {
- let error = new Error('Unexpected end of MessagePack data');
- error.incomplete = true;
- throw error
- }
- throw new Error('Unknown MessagePack token ' + token)
- }
- }
- }
- const validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/;
- function createStructureReader(structure, firstId) {
- function readObject() {
- // This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
- if (readObject.count++ > inlineObjectReadThreshold) {
- let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
- '({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
- if (structure.highByte === 0)
- structure.read = createSecondByteReader(firstId, structure.read);
- return readObject() // second byte is already read, if there is one so immediately read object
- }
- let object = {};
- for (let i = 0, l = structure.length; i < l; i++) {
- let key = structure[i];
- if (key === '__proto__')
- key = '__proto_';
- object[key] = read();
- }
- if (currentUnpackr.freezeData)
- return Object.freeze(object);
- return object
- }
- readObject.count = 0;
- if (structure.highByte === 0) {
- return createSecondByteReader(firstId, readObject)
- }
- return readObject
- }
- const createSecondByteReader = (firstId, read0) => {
- return function() {
- let highByte = src[position$1++];
- if (highByte === 0)
- return read0()
- let id = firstId < 32 ? -(firstId + (highByte << 5)) : firstId + (highByte << 5);
- let structure = currentStructures[id] || loadStructures()[id];
- if (!structure) {
- throw new Error('Record id is not defined for ' + id)
- }
- if (!structure.read)
- structure.read = createStructureReader(structure, firstId);
- return structure.read()
- }
- };
- function loadStructures() {
- let loadedStructures = saveState$1(() => {
- // save the state in case getStructures modifies our buffer
- src = null;
- return currentUnpackr.getStructures()
- });
- return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures)
- }
- var readFixedString = readStringJS;
- var readString8 = readStringJS;
- var readString16 = readStringJS;
- var readString32 = readStringJS;
- function setExtractor(extractStrings) {
- readFixedString = readString(1);
- readString8 = readString(2);
- readString16 = readString(3);
- readString32 = readString(5);
- function readString(headerLength) {
- return function readString(length) {
- let string = strings[stringPosition++];
- if (string == null) {
- if (bundledStrings$1)
- return readStringJS(length)
- let byteOffset = src.byteOffset;
- let extraction = extractStrings(position$1 - headerLength + byteOffset, srcEnd + byteOffset, src.buffer);
- if (typeof extraction == 'string') {
- string = extraction;
- strings = EMPTY_ARRAY;
- } else {
- strings = extraction;
- stringPosition = 1;
- srcStringEnd = 1; // even if a utf-8 string was decoded, must indicate we are in the midst of extracted strings and can't skip strings
- string = strings[0];
- if (string === undefined)
- throw new Error('Unexpected end of buffer')
- }
- }
- let srcStringLength = string.length;
- if (srcStringLength <= length) {
- position$1 += length;
- return string
- }
- srcString = string;
- srcStringStart = position$1;
- srcStringEnd = position$1 + srcStringLength;
- position$1 += length;
- return string.slice(0, length) // we know we just want the beginning
- }
- }
- }
- function readStringJS(length) {
- let result;
- if (length < 16) {
- if (result = shortStringInJS(length))
- return result
- }
- if (length > 64 && decoder)
- return decoder.decode(src.subarray(position$1, position$1 += length))
- const end = position$1 + length;
- const units = [];
- result = '';
- while (position$1 < end) {
- const byte1 = src[position$1++];
- if ((byte1 & 0x80) === 0) {
- // 1 byte
- units.push(byte1);
- } else if ((byte1 & 0xe0) === 0xc0) {
- // 2 bytes
- const byte2 = src[position$1++] & 0x3f;
- units.push(((byte1 & 0x1f) << 6) | byte2);
- } else if ((byte1 & 0xf0) === 0xe0) {
- // 3 bytes
- const byte2 = src[position$1++] & 0x3f;
- const byte3 = src[position$1++] & 0x3f;
- units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
- } else if ((byte1 & 0xf8) === 0xf0) {
- // 4 bytes
- const byte2 = src[position$1++] & 0x3f;
- const byte3 = src[position$1++] & 0x3f;
- const byte4 = src[position$1++] & 0x3f;
- let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
- if (unit > 0xffff) {
- unit -= 0x10000;
- units.push(((unit >>> 10) & 0x3ff) | 0xd800);
- unit = 0xdc00 | (unit & 0x3ff);
- }
- units.push(unit);
- } else {
- units.push(byte1);
- }
- if (units.length >= 0x1000) {
- result += fromCharCode.apply(String, units);
- units.length = 0;
- }
- }
- if (units.length > 0) {
- result += fromCharCode.apply(String, units);
- }
- return result
- }
- function readString(source, start, length) {
- let existingSrc = src;
- src = source;
- position$1 = start;
- try {
- return readStringJS(length);
- } finally {
- src = existingSrc;
- }
- }
- function readArray(length) {
- let array = new Array(length);
- for (let i = 0; i < length; i++) {
- array[i] = read();
- }
- if (currentUnpackr.freezeData)
- return Object.freeze(array)
- return array
- }
- function readMap(length) {
- if (currentUnpackr.mapsAsObjects) {
- let object = {};
- for (let i = 0; i < length; i++) {
- let key = readKey();
- if (key === '__proto__')
- key = '__proto_';
- object[key] = read();
- }
- return object
- } else {
- let map = new Map();
- for (let i = 0; i < length; i++) {
- map.set(read(), read());
- }
- return map
- }
- }
- var fromCharCode = String.fromCharCode;
- function longStringInJS(length) {
- let start = position$1;
- let bytes = new Array(length);
- for (let i = 0; i < length; i++) {
- const byte = src[position$1++];
- if ((byte & 0x80) > 0) {
- position$1 = start;
- return
- }
- bytes[i] = byte;
- }
- return fromCharCode.apply(String, bytes)
- }
- function shortStringInJS(length) {
- if (length < 4) {
- if (length < 2) {
- if (length === 0)
- return ''
- else {
- let a = src[position$1++];
- if ((a & 0x80) > 1) {
- position$1 -= 1;
- return
- }
- return fromCharCode(a)
- }
- } else {
- let a = src[position$1++];
- let b = src[position$1++];
- if ((a & 0x80) > 0 || (b & 0x80) > 0) {
- position$1 -= 2;
- return
- }
- if (length < 3)
- return fromCharCode(a, b)
- let c = src[position$1++];
- if ((c & 0x80) > 0) {
- position$1 -= 3;
- return
- }
- return fromCharCode(a, b, c)
- }
- } else {
- let a = src[position$1++];
- let b = src[position$1++];
- let c = src[position$1++];
- let d = src[position$1++];
- if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) {
- position$1 -= 4;
- return
- }
- if (length < 6) {
- if (length === 4)
- return fromCharCode(a, b, c, d)
- else {
- let e = src[position$1++];
- if ((e & 0x80) > 0) {
- position$1 -= 5;
- return
- }
- return fromCharCode(a, b, c, d, e)
- }
- } else if (length < 8) {
- let e = src[position$1++];
- let f = src[position$1++];
- if ((e & 0x80) > 0 || (f & 0x80) > 0) {
- position$1 -= 6;
- return
- }
- if (length < 7)
- return fromCharCode(a, b, c, d, e, f)
- let g = src[position$1++];
- if ((g & 0x80) > 0) {
- position$1 -= 7;
- return
- }
- return fromCharCode(a, b, c, d, e, f, g)
- } else {
- let e = src[position$1++];
- let f = src[position$1++];
- let g = src[position$1++];
- let h = src[position$1++];
- if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) {
- position$1 -= 8;
- return
- }
- if (length < 10) {
- if (length === 8)
- return fromCharCode(a, b, c, d, e, f, g, h)
- else {
- let i = src[position$1++];
- if ((i & 0x80) > 0) {
- position$1 -= 9;
- return
- }
- return fromCharCode(a, b, c, d, e, f, g, h, i)
- }
- } else if (length < 12) {
- let i = src[position$1++];
- let j = src[position$1++];
- if ((i & 0x80) > 0 || (j & 0x80) > 0) {
- position$1 -= 10;
- return
- }
- if (length < 11)
- return fromCharCode(a, b, c, d, e, f, g, h, i, j)
- let k = src[position$1++];
- if ((k & 0x80) > 0) {
- position$1 -= 11;
- return
- }
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k)
- } else {
- let i = src[position$1++];
- let j = src[position$1++];
- let k = src[position$1++];
- let l = src[position$1++];
- if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) {
- position$1 -= 12;
- return
- }
- if (length < 14) {
- if (length === 12)
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l)
- else {
- let m = src[position$1++];
- if ((m & 0x80) > 0) {
- position$1 -= 13;
- return
- }
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m)
- }
- } else {
- let m = src[position$1++];
- let n = src[position$1++];
- if ((m & 0x80) > 0 || (n & 0x80) > 0) {
- position$1 -= 14;
- return
- }
- if (length < 15)
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
- let o = src[position$1++];
- if ((o & 0x80) > 0) {
- position$1 -= 15;
- return
- }
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
- }
- }
- }
- }
- }
- function readOnlyJSString() {
- let token = src[position$1++];
- let length;
- if (token < 0xc0) {
- // fixstr
- length = token - 0xa0;
- } else {
- switch(token) {
- case 0xd9:
- // str 8
- length = src[position$1++];
- break
- case 0xda:
- // str 16
- length = dataView.getUint16(position$1);
- position$1 += 2;
- break
- case 0xdb:
- // str 32
- length = dataView.getUint32(position$1);
- position$1 += 4;
- break
- default:
- throw new Error('Expected string')
- }
- }
- return readStringJS(length)
- }
- function readBin(length) {
- return currentUnpackr.copyBuffers ?
- // specifically use the copying slice (not the node one)
- Uint8Array.prototype.slice.call(src, position$1, position$1 += length) :
- src.subarray(position$1, position$1 += length)
- }
- function readExt(length) {
- let type = src[position$1++];
- if (currentExtensions[type]) {
- let end;
- return currentExtensions[type](src.subarray(position$1, end = (position$1 += length)), (readPosition) => {
- position$1 = readPosition;
- try {
- return read();
- } finally {
- position$1 = end;
- }
- })
- }
- else
- throw new Error('Unknown extension type ' + type)
- }
- var keyCache = new Array(4096);
- function readKey() {
- let length = src[position$1++];
- if (length >= 0xa0 && length < 0xc0) {
- // fixstr, potentially use key cache
- length = length - 0xa0;
- if (srcStringEnd >= position$1) // if it has been extracted, must use it (and faster anyway)
- return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart)
- else if (!(srcStringEnd == 0 && srcEnd < 180))
- return readFixedString(length)
- } else { // not cacheable, go back and do a standard read
- position$1--;
- return asSafeString(read())
- }
- let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position$1) : length > 0 ? src[position$1] : 0)) & 0xfff;
- let entry = keyCache[key];
- let checkPosition = position$1;
- let end = position$1 + length - 3;
- let chunk;
- let i = 0;
- if (entry && entry.bytes == length) {
- while (checkPosition < end) {
- chunk = dataView.getUint32(checkPosition);
- if (chunk != entry[i++]) {
- checkPosition = 0x70000000;
- break
- }
- checkPosition += 4;
- }
- end += 3;
- while (checkPosition < end) {
- chunk = src[checkPosition++];
- if (chunk != entry[i++]) {
- checkPosition = 0x70000000;
- break
- }
- }
- if (checkPosition === end) {
- position$1 = checkPosition;
- return entry.string
- }
- end -= 3;
- checkPosition = position$1;
- }
- entry = [];
- keyCache[key] = entry;
- entry.bytes = length;
- while (checkPosition < end) {
- chunk = dataView.getUint32(checkPosition);
- entry.push(chunk);
- checkPosition += 4;
- }
- end += 3;
- while (checkPosition < end) {
- chunk = src[checkPosition++];
- entry.push(chunk);
- }
- // for small blocks, avoiding the overhead of the extract call is helpful
- let string = length < 16 ? shortStringInJS(length) : longStringInJS(length);
- if (string != null)
- return entry.string = string
- return entry.string = readFixedString(length)
- }
- function asSafeString(property) {
- // protect against expensive (DoS) string conversions
- if (typeof property === 'string') return property;
- if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString();
- if (property == null) return property + '';
- if (currentUnpackr.allowArraysInMapKeys && Array.isArray(property) && property.flat().every(item => ['string', 'number', 'boolean', 'bigint'].includes(typeof item))) {
- return property.flat().toString();
- }
- throw new Error(`Invalid property type for record: ${typeof property}`);
- }
- // the registration of the record definition extension (as "r")
- const recordDefinition = (id, highByte) => {
- let structure = read().map(asSafeString); // ensure that all keys are strings and
- // that the array is mutable
- let firstByte = id;
- if (highByte !== undefined) {
- id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id);
- structure.highByte = highByte;
- }
- let existingStructure = currentStructures[id];
- // If it is a shared structure, we need to restore any changes after reading.
- // Also in sequential mode, we may get incomplete reads and thus errors, and we need to restore
- // to the state prior to an incomplete read in order to properly resume.
- if (existingStructure && (existingStructure.isShared || sequentialMode)) {
- (currentStructures.restoreStructures || (currentStructures.restoreStructures = []))[id] = existingStructure;
- }
- currentStructures[id] = structure;
- structure.read = createStructureReader(structure, firstByte);
- return structure.read()
- };
- currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here
- currentExtensions[0].noBuffer = true;
- currentExtensions[0x42] = data => {
- let headLength = (data.byteLength % 8) || 8;
- let head = BigInt(data[0] & 0x80 ? data[0] - 0x100 : data[0]);
- for (let i = 1; i < headLength; i++) {
- head <<= BigInt(8);
- head += BigInt(data[i]);
- }
- if (data.byteLength !== headLength) {
- let view = new DataView(data.buffer, data.byteOffset, data.byteLength);
- let decode = (start, end) => {
- let length = end - start;
- if (length <= 40) {
- let out = view.getBigUint64(start);
- for (let i = start + 8; i < end; i += 8) {
- out <<= BigInt(64n);
- out |= view.getBigUint64(i);
- }
- return out
- }
- // if (length === 8) return view.getBigUint64(start)
- let middle = start + (length >> 4 << 3);
- let left = decode(start, middle);
- let right = decode(middle, end);
- return (left << BigInt((end - middle) * 8)) | right
- };
- head = (head << BigInt((view.byteLength - headLength) * 8)) | decode(headLength, view.byteLength);
- }
- return head
- };
- let errors = {
- Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, AggregateError: typeof AggregateError === 'function' ? AggregateError : null,
- };
- currentExtensions[0x65] = () => {
- let data = read();
- if (!errors[data[0]]) {
- let error = Error(data[1], { cause: data[2] });
- error.name = data[0];
- return error
- }
- return errors[data[0]](data[1], { cause: data[2] })
- };
- currentExtensions[0x69] = (data) => {
- // id extension (for structured clones)
- if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
- let id = dataView.getUint32(position$1 - 4);
- if (!referenceMap)
- referenceMap = new Map();
- let token = src[position$1];
- let target;
- // TODO: handle any other types that can cycle and make the code more robust if there are other extensions
- if (token >= 0x90 && token < 0xa0 || token == 0xdc || token == 0xdd)
- target = [];
- else if (token >= 0x80 && token < 0x90 || token == 0xde || token == 0xdf)
- target = new Map();
- else if ((token >= 0xc7 && token <= 0xc9 || token >= 0xd4 && token <= 0xd8) && src[position$1 + 1] === 0x73)
- target = new Set();
- else
- target = {};
- let refEntry = { target }; // a placeholder object
- referenceMap.set(id, refEntry);
- let targetProperties = read(); // read the next value as the target object to id
- if (!refEntry.used) {
- // no cycle, can just use the returned read object
- return refEntry.target = targetProperties // replace the placeholder with the real one
- } else {
- // there is a cycle, so we have to assign properties to original target
- Object.assign(target, targetProperties);
- }
- // copy over map/set entries if we're able to
- if (target instanceof Map)
- for (let [k, v] of targetProperties.entries()) target.set(k, v);
- if (target instanceof Set)
- for (let i of Array.from(targetProperties)) target.add(i);
- return target
- };
- currentExtensions[0x70] = (data) => {
- // pointer extension (for structured clones)
- if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
- let id = dataView.getUint32(position$1 - 4);
- let refEntry = referenceMap.get(id);
- refEntry.used = true;
- return refEntry.target
- };
- currentExtensions[0x73] = () => new Set(read());
- const typedArrays = ['Int8','Uint8','Uint8Clamped','Int16','Uint16','Int32','Uint32','Float32','Float64','BigInt64','BigUint64'].map(type => type + 'Array');
- let glbl = typeof globalThis === 'object' ? globalThis : window;
- currentExtensions[0x74] = (data) => {
- let typeCode = data[0];
- // we always have to slice to get a new ArrayBuffer that is aligned
- let buffer = Uint8Array.prototype.slice.call(data, 1).buffer;
- let typedArrayName = typedArrays[typeCode];
- if (!typedArrayName) {
- if (typeCode === 16) return buffer
- if (typeCode === 17) return new DataView(buffer)
- throw new Error('Could not find typed array for code ' + typeCode)
- }
- return new glbl[typedArrayName](buffer)
- };
- currentExtensions[0x78] = () => {
- let data = read();
- return new RegExp(data[0], data[1])
- };
- const TEMP_BUNDLE = [];
- currentExtensions[0x62] = (data) => {
- let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
- let dataPosition = position$1;
- position$1 += dataSize - data.length;
- bundledStrings$1 = TEMP_BUNDLE;
- bundledStrings$1 = [readOnlyJSString(), readOnlyJSString()];
- bundledStrings$1.position0 = 0;
- bundledStrings$1.position1 = 0;
- bundledStrings$1.postBundlePosition = position$1;
- position$1 = dataPosition;
- return read()
- };
- currentExtensions[0xff] = (data) => {
- // 32-bit date extension
- if (data.length == 4)
- return new Date((data[0] * 0x1000000 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000)
- else if (data.length == 8)
- return new Date(
- ((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1000000 +
- ((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000)
- else if (data.length == 12)
- return new Date(
- ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
- (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
- else
- return new Date('invalid')
- };
- // registration of bulk record definition?
- // currentExtensions[0x52] = () =>
- function saveState$1(callback) {
- if (onSaveState)
- onSaveState();
- let savedSrcEnd = srcEnd;
- let savedPosition = position$1;
- let savedStringPosition = stringPosition;
- let savedSrcStringStart = srcStringStart;
- let savedSrcStringEnd = srcStringEnd;
- let savedSrcString = srcString;
- let savedStrings = strings;
- let savedReferenceMap = referenceMap;
- let savedBundledStrings = bundledStrings$1;
- // TODO: We may need to revisit this if we do more external calls to user code (since it could be slow)
- let savedSrc = new Uint8Array(src.slice(0, srcEnd)); // we copy the data in case it changes while external data is processed
- let savedStructures = currentStructures;
- let savedStructuresContents = currentStructures.slice(0, currentStructures.length);
- let savedPackr = currentUnpackr;
- let savedSequentialMode = sequentialMode;
- let value = callback();
- srcEnd = savedSrcEnd;
- position$1 = savedPosition;
- stringPosition = savedStringPosition;
- srcStringStart = savedSrcStringStart;
- srcStringEnd = savedSrcStringEnd;
- srcString = savedSrcString;
- strings = savedStrings;
- referenceMap = savedReferenceMap;
- bundledStrings$1 = savedBundledStrings;
- src = savedSrc;
- sequentialMode = savedSequentialMode;
- currentStructures = savedStructures;
- currentStructures.splice(0, currentStructures.length, ...savedStructuresContents);
- currentUnpackr = savedPackr;
- dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
- return value
- }
- function clearSource() {
- src = null;
- referenceMap = null;
- currentStructures = null;
- }
- function addExtension$2(extension) {
- if (extension.unpack)
- currentExtensions[extension.type] = extension.unpack;
- else
- currentExtensions[extension.type] = extension;
- }
- const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
- for (let i = 0; i < 256; i++) {
- mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103));
- }
- var defaultUnpackr = new Unpackr$1({ useRecords: false });
- const unpack$1 = defaultUnpackr.unpack;
- const unpackMultiple$1 = defaultUnpackr.unpackMultiple;
- defaultUnpackr.unpack;
- const FLOAT32_OPTIONS = {
- NEVER: 0,
- ALWAYS: 1,
- DECIMAL_ROUND: 3,
- DECIMAL_FIT: 4
- };
- let f32Array = new Float32Array(1);
- let u8Array = new Uint8Array(f32Array.buffer, 0, 4);
- function roundFloat32$1(float32Number) {
- f32Array[0] = float32Number;
- let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
- return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
- }
- function setReadStruct(updatedReadStruct, loadedStructs, saveState) {
- readStruct$1 = updatedReadStruct;
- onLoadedStructures$1 = loadedStructs;
- onSaveState = saveState;
- }
- let textEncoder$1;
- try {
- textEncoder$1 = new TextEncoder();
- } catch (error) {}
- let extensions, extensionClasses;
- const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
- const ByteArrayAllocate = hasNodeBuffer$1 ?
- function(length) { return Buffer.allocUnsafeSlow(length) } : Uint8Array;
- const ByteArray = hasNodeBuffer$1 ? Buffer : Uint8Array;
- const MAX_BUFFER_SIZE = hasNodeBuffer$1 ? 0x100000000 : 0x7fd00000;
- let target, keysTarget;
- let targetView;
- let position = 0;
- let safeEnd;
- let bundledStrings = null;
- let writeStructSlots;
- const MAX_BUNDLE_SIZE = 0x5500; // maximum characters such that the encoded bytes fits in 16 bits.
- const hasNonLatin = /[\u0080-\uFFFF]/;
- const RECORD_SYMBOL = Symbol('record-id');
- let Packr$1 = class Packr extends Unpackr$1 {
- constructor(options) {
- super(options);
- this.offset = 0;
- let start;
- let hasSharedUpdate;
- let structures;
- let referenceMap;
- let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
- return target.utf8Write(string, position, target.byteLength - position)
- } : (textEncoder$1 && textEncoder$1.encodeInto) ?
- function(string, position) {
- return textEncoder$1.encodeInto(string, target.subarray(position)).written
- } : false;
- let packr = this;
- if (!options)
- options = {};
- let isSequential = options && options.sequential;
- let hasSharedStructures = options.structures || options.saveStructures;
- let maxSharedStructures = options.maxSharedStructures;
- if (maxSharedStructures == null)
- maxSharedStructures = hasSharedStructures ? 32 : 0;
- if (maxSharedStructures > 8160)
- throw new Error('Maximum maxSharedStructure is 8160')
- if (options.structuredClone && options.moreTypes == undefined) {
- this.moreTypes = true;
- }
- let maxOwnStructures = options.maxOwnStructures;
- if (maxOwnStructures == null)
- maxOwnStructures = hasSharedStructures ? 32 : 64;
- if (!this.structures && options.useRecords != false)
- this.structures = [];
- // two byte record ids for shared structures
- let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
- let sharedLimitId = maxSharedStructures + 0x40;
- let maxStructureId = maxSharedStructures + maxOwnStructures + 0x40;
- if (maxStructureId > 8256) {
- throw new Error('Maximum maxSharedStructure + maxOwnStructure is 8192')
- }
- let recordIdsToRemove = [];
- let transitionsCount = 0;
- let serializationsSinceTransitionRebuild = 0;
- this.pack = this.encode = function(value, encodeOptions) {
- if (!target) {
- target = new ByteArrayAllocate(8192);
- targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, 8192));
- position = 0;
- }
- safeEnd = target.length - 10;
- if (safeEnd - position < 0x800) {
- // don't start too close to the end,
- target = new ByteArrayAllocate(target.length);
- targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length));
- safeEnd = target.length - 10;
- position = 0;
- } else
- position = (position + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster
- start = position;
- if (encodeOptions & RESERVE_START_SPACE) position += (encodeOptions & 0xff);
- referenceMap = packr.structuredClone ? new Map() : null;
- if (packr.bundleStrings && typeof value !== 'string') {
- bundledStrings = [];
- bundledStrings.size = Infinity; // force a new bundle start on first string
- } else
- bundledStrings = null;
- structures = packr.structures;
- if (structures) {
- if (structures.uninitialized)
- structures = packr._mergeStructures(packr.getStructures());
- let sharedLength = structures.sharedLength || 0;
- if (sharedLength > maxSharedStructures) {
- //if (maxSharedStructures <= 32 && structures.sharedLength > 32) // TODO: could support this, but would need to update the limit ids
- throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + structures.sharedLength)
- }
- if (!structures.transitions) {
- // rebuild our structure transitions
- structures.transitions = Object.create(null);
- for (let i = 0; i < sharedLength; i++) {
- let keys = structures[i];
- if (!keys)
- continue
- let nextTransition, transition = structures.transitions;
- for (let j = 0, l = keys.length; j < l; j++) {
- let key = keys[j];
- nextTransition = transition[key];
- if (!nextTransition) {
- nextTransition = transition[key] = Object.create(null);
- }
- transition = nextTransition;
- }
- transition[RECORD_SYMBOL] = i + 0x40;
- }
- this.lastNamedStructuresLength = sharedLength;
- }
- if (!isSequential) {
- structures.nextId = sharedLength + 0x40;
- }
- }
- if (hasSharedUpdate)
- hasSharedUpdate = false;
- let encodingError;
- try {
- if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object)
- writeStruct(value);
- else
- pack(value);
- let lastBundle = bundledStrings;
- if (bundledStrings)
- writeBundles(start, pack, 0);
- if (referenceMap && referenceMap.idsToInsert) {
- let idsToInsert = referenceMap.idsToInsert.sort((a, b) => a.offset > b.offset ? 1 : -1);
- let i = idsToInsert.length;
- let incrementPosition = -1;
- while (lastBundle && i > 0) {
- let insertionPoint = idsToInsert[--i].offset + start;
- if (insertionPoint < (lastBundle.stringsPosition + start) && incrementPosition === -1)
- incrementPosition = 0;
- if (insertionPoint > (lastBundle.position + start)) {
- if (incrementPosition >= 0)
- incrementPosition += 6;
- } else {
- if (incrementPosition >= 0) {
- // update the bundle reference now
- targetView.setUint32(lastBundle.position + start,
- targetView.getUint32(lastBundle.position + start) + incrementPosition);
- incrementPosition = -1; // reset
- }
- lastBundle = lastBundle.previous;
- i++;
- }
- }
- if (incrementPosition >= 0 && lastBundle) {
- // update the bundle reference now
- targetView.setUint32(lastBundle.position + start,
- targetView.getUint32(lastBundle.position + start) + incrementPosition);
- }
- position += idsToInsert.length * 6;
- if (position > safeEnd)
- makeRoom(position);
- packr.offset = position;
- let serialized = insertIds(target.subarray(start, position), idsToInsert);
- referenceMap = null;
- return serialized
- }
- packr.offset = position; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
- if (encodeOptions & REUSE_BUFFER_MODE) {
- target.start = start;
- target.end = position;
- return target
- }
- return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now
- } catch(error) {
- encodingError = error;
- throw error;
- } finally {
- if (structures) {
- resetStructures();
- if (hasSharedUpdate && packr.saveStructures) {
- let sharedLength = structures.sharedLength || 0;
- // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
- let returnBuffer = target.subarray(start, position);
- let newSharedData = prepareStructures$1(structures, packr);
- if (!encodingError) { // TODO: If there is an encoding error, should make the structures as uninitialized so they get rebuilt next time
- if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
- // get updated structures and try again if the update failed
- return packr.pack(value, encodeOptions)
- }
- packr.lastNamedStructuresLength = sharedLength;
- // don't keep large buffers around
- if (target.length > 0x40000000) target = null;
- return returnBuffer
- }
- }
- }
- // don't keep large buffers around, they take too much memory and cause problems (limit at 1GB)
- if (target.length > 0x40000000) target = null;
- if (encodeOptions & RESET_BUFFER_MODE)
- position = start;
- }
- };
- const resetStructures = () => {
- if (serializationsSinceTransitionRebuild < 10)
- serializationsSinceTransitionRebuild++;
- let sharedLength = structures.sharedLength || 0;
- if (structures.length > sharedLength && !isSequential)
- structures.length = sharedLength;
- if (transitionsCount > 10000) {
- // force a rebuild occasionally after a lot of transitions so it can get cleaned up
- structures.transitions = null;
- serializationsSinceTransitionRebuild = 0;
- transitionsCount = 0;
- if (recordIdsToRemove.length > 0)
- recordIdsToRemove = [];
- } else if (recordIdsToRemove.length > 0 && !isSequential) {
- for (let i = 0, l = recordIdsToRemove.length; i < l; i++) {
- recordIdsToRemove[i][RECORD_SYMBOL] = 0;
- }
- recordIdsToRemove = [];
- }
- };
- const packArray = (value) => {
- var length = value.length;
- if (length < 0x10) {
- target[position++] = 0x90 | length;
- } else if (length < 0x10000) {
- target[position++] = 0xdc;
- target[position++] = length >> 8;
- target[position++] = length & 0xff;
- } else {
- target[position++] = 0xdd;
- targetView.setUint32(position, length);
- position += 4;
- }
- for (let i = 0; i < length; i++) {
- pack(value[i]);
- }
- };
- const pack = (value) => {
- if (position > safeEnd)
- target = makeRoom(position);
- var type = typeof value;
- var length;
- if (type === 'string') {
- let strLength = value.length;
- if (bundledStrings && strLength >= 4 && strLength < 0x1000) {
- if ((bundledStrings.size += strLength) > MAX_BUNDLE_SIZE) {
- let extStart;
- let maxBytes = (bundledStrings[0] ? bundledStrings[0].length * 3 + bundledStrings[1].length : 0) + 10;
- if (position + maxBytes > safeEnd)
- target = makeRoom(position + maxBytes);
- let lastBundle;
- if (bundledStrings.position) { // here we use the 0x62 extension to write the last bundle and reserve space for the reference pointer to the next/current bundle
- lastBundle = bundledStrings;
- target[position] = 0xc8; // ext 16
- position += 3; // reserve for the writing bundle size
- target[position++] = 0x62; // 'b'
- extStart = position - start;
- position += 4; // reserve for writing bundle reference
- writeBundles(start, pack, 0); // write the last bundles
- targetView.setUint16(extStart + start - 3, position - start - extStart);
- } else { // here we use the 0x62 extension just to reserve the space for the reference pointer to the bundle (will be updated once the bundle is written)
- target[position++] = 0xd6; // fixext 4
- target[position++] = 0x62; // 'b'
- extStart = position - start;
- position += 4; // reserve for writing bundle reference
- }
- bundledStrings = ['', '']; // create new ones
- bundledStrings.previous = lastBundle;
- bundledStrings.size = 0;
- bundledStrings.position = extStart;
- }
- let twoByte = hasNonLatin.test(value);
- bundledStrings[twoByte ? 0 : 1] += value;
- target[position++] = 0xc1;
- pack(twoByte ? -strLength : strLength);
- return
- }
- let headerSize;
- // first we estimate the header size, so we can write to the correct location
- if (strLength < 0x20) {
- headerSize = 1;
- } else if (strLength < 0x100) {
- headerSize = 2;
- } else if (strLength < 0x10000) {
- headerSize = 3;
- } else {
- headerSize = 5;
- }
- let maxBytes = strLength * 3;
- if (position + maxBytes > safeEnd)
- target = makeRoom(position + maxBytes);
- if (strLength < 0x40 || !encodeUtf8) {
- let i, c1, c2, strPosition = position + headerSize;
- for (i = 0; i < strLength; i++) {
- c1 = value.charCodeAt(i);
- if (c1 < 0x80) {
- target[strPosition++] = c1;
- } else if (c1 < 0x800) {
- target[strPosition++] = c1 >> 6 | 0xc0;
- target[strPosition++] = c1 & 0x3f | 0x80;
- } else if (
- (c1 & 0xfc00) === 0xd800 &&
- ((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
- ) {
- c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
- i++;
- target[strPosition++] = c1 >> 18 | 0xf0;
- target[strPosition++] = c1 >> 12 & 0x3f | 0x80;
- target[strPosition++] = c1 >> 6 & 0x3f | 0x80;
- target[strPosition++] = c1 & 0x3f | 0x80;
- } else {
- target[strPosition++] = c1 >> 12 | 0xe0;
- target[strPosition++] = c1 >> 6 & 0x3f | 0x80;
- target[strPosition++] = c1 & 0x3f | 0x80;
- }
- }
- length = strPosition - position - headerSize;
- } else {
- length = encodeUtf8(value, position + headerSize);
- }
- if (length < 0x20) {
- target[position++] = 0xa0 | length;
- } else if (length < 0x100) {
- if (headerSize < 2) {
- target.copyWithin(position + 2, position + 1, position + 1 + length);
- }
- target[position++] = 0xd9;
- target[position++] = length;
- } else if (length < 0x10000) {
- if (headerSize < 3) {
- target.copyWithin(position + 3, position + 2, position + 2 + length);
- }
- target[position++] = 0xda;
- target[position++] = length >> 8;
- target[position++] = length & 0xff;
- } else {
- if (headerSize < 5) {
- target.copyWithin(position + 5, position + 3, position + 3 + length);
- }
- target[position++] = 0xdb;
- targetView.setUint32(position, length);
- position += 4;
- }
- position += length;
- } else if (type === 'number') {
- if (value >>> 0 === value) {// positive integer, 32-bit or less
- // positive uint
- if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this.randomAccessStructure)) {
- target[position++] = value;
- } else if (value < 0x100) {
- target[position++] = 0xcc;
- target[position++] = value;
- } else if (value < 0x10000) {
- target[position++] = 0xcd;
- target[position++] = value >> 8;
- target[position++] = value & 0xff;
- } else {
- target[position++] = 0xce;
- targetView.setUint32(position, value);
- position += 4;
- }
- } else if (value >> 0 === value) { // negative integer
- if (value >= -0x20) {
- target[position++] = 0x100 + value;
- } else if (value >= -0x80) {
- target[position++] = 0xd0;
- target[position++] = value + 0x100;
- } else if (value >= -0x8000) {
- target[position++] = 0xd1;
- targetView.setInt16(position, value);
- position += 2;
- } else {
- target[position++] = 0xd2;
- targetView.setInt32(position, value);
- position += 4;
- }
- } else {
- let useFloat32;
- if ((useFloat32 = this.useFloat32) > 0 && value < 0x100000000 && value >= -0x80000000) {
- target[position++] = 0xca;
- targetView.setFloat32(position, value);
- let xShifted;
- if (useFloat32 < 4 ||
- // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
- ((xShifted = value * mult10[((target[position] & 0x7f) << 1) | (target[position + 1] >> 7)]) >> 0) === xShifted) {
- position += 4;
- return
- } else
- position--; // move back into position for writing a double
- }
- target[position++] = 0xcb;
- targetView.setFloat64(position, value);
- position += 8;
- }
- } else if (type === 'object' || type === 'function') {
- if (!value)
- target[position++] = 0xc0;
- else {
- if (referenceMap) {
- let referee = referenceMap.get(value);
- if (referee) {
- if (!referee.id) {
- let idsToInsert = referenceMap.idsToInsert || (referenceMap.idsToInsert = []);
- referee.id = idsToInsert.push(referee);
- }
- target[position++] = 0xd6; // fixext 4
- target[position++] = 0x70; // "p" for pointer
- targetView.setUint32(position, referee.id);
- position += 4;
- return
- } else
- referenceMap.set(value, { offset: position - start });
- }
- let constructor = value.constructor;
- if (constructor === Object) {
- writeObject(value);
- } else if (constructor === Array) {
- packArray(value);
- } else if (constructor === Map) {
- if (this.mapAsEmptyObject) target[position++] = 0x80;
- else {
- length = value.size;
- if (length < 0x10) {
- target[position++] = 0x80 | length;
- } else if (length < 0x10000) {
- target[position++] = 0xde;
- target[position++] = length >> 8;
- target[position++] = length & 0xff;
- } else {
- target[position++] = 0xdf;
- targetView.setUint32(position, length);
- position += 4;
- }
- for (let [key, entryValue] of value) {
- pack(key);
- pack(entryValue);
- }
- }
- } else {
- for (let i = 0, l = extensions.length; i < l; i++) {
- let extensionClass = extensionClasses[i];
- if (value instanceof extensionClass) {
- let extension = extensions[i];
- if (extension.write) {
- if (extension.type) {
- target[position++] = 0xd4; // one byte "tag" extension
- target[position++] = extension.type;
- target[position++] = 0;
- }
- let writeResult = extension.write.call(this, value);
- if (writeResult === value) { // avoid infinite recursion
- if (Array.isArray(value)) {
- packArray(value);
- } else {
- writeObject(value);
- }
- } else {
- pack(writeResult);
- }
- return
- }
- let currentTarget = target;
- let currentTargetView = targetView;
- let currentPosition = position;
- target = null;
- let result;
- try {
- result = extension.pack.call(this, value, (size) => {
- // restore target and use it
- target = currentTarget;
- currentTarget = null;
- position += size;
- if (position > safeEnd)
- makeRoom(position);
- return {
- target, targetView, position: position - size
- }
- }, pack);
- } finally {
- // restore current target information (unless already restored)
- if (currentTarget) {
- target = currentTarget;
- targetView = currentTargetView;
- position = currentPosition;
- safeEnd = target.length - 10;
- }
- }
- if (result) {
- if (result.length + position > safeEnd)
- makeRoom(result.length + position);
- position = writeExtensionData(result, target, position, extension.type);
- }
- return
- }
- }
- // check isArray after extensions, because extensions can extend Array
- if (Array.isArray(value)) {
- packArray(value);
- } else {
- // use this as an alternate mechanism for expressing how to serialize
- if (value.toJSON) {
- const json = value.toJSON();
- // if for some reason value.toJSON returns itself it'll loop forever
- if (json !== value)
- return pack(json)
- }
- // if there is a writeFunction, use it, otherwise just encode as undefined
- if (type === 'function')
- return pack(this.writeFunction && this.writeFunction(value));
- // no extension found, write as plain object
- writeObject(value);
- }
- }
- }
- } else if (type === 'boolean') {
- target[position++] = value ? 0xc3 : 0xc2;
- } else if (type === 'bigint') {
- if (value < 0x8000000000000000 && value >= -0x8000000000000000) {
- // use a signed int as long as it fits
- target[position++] = 0xd3;
- targetView.setBigInt64(position, value);
- } else if (value < 0x10000000000000000 && value > 0) {
- // if we can fit an unsigned int, use that
- target[position++] = 0xcf;
- targetView.setBigUint64(position, value);
- } else {
- // overflow
- if (this.largeBigIntToFloat) {
- target[position++] = 0xcb;
- targetView.setFloat64(position, Number(value));
- } else if (this.largeBigIntToString) {
- return pack(value.toString());
- } else if (this.useBigIntExtension || this.moreTypes) {
- let empty = value < 0 ? BigInt(-1) : BigInt(0);
- let array;
- if (value >> BigInt(0x10000) === empty) {
- let mask = BigInt(0x10000000000000000) - BigInt(1); // literal would overflow
- let chunks = [];
- while (true) {
- chunks.push(value & mask);
- if ((value >> BigInt(63)) === empty) break
- value >>= BigInt(64);
- }
- array = new Uint8Array(new BigUint64Array(chunks).buffer);
- array.reverse();
- } else {
- let invert = value < 0;
- let string = (invert ? ~value : value).toString(16);
- if (string.length % 2) {
- string = '0' + string;
- } else if (parseInt(string.charAt(0), 16) >= 8) {
- string = '00' + string;
- }
- if (hasNodeBuffer$1) {
- array = Buffer.from(string, 'hex');
- } else {
- array = new Uint8Array(string.length / 2);
- for (let i = 0; i < array.length; i++) {
- array[i] = parseInt(string.slice(i * 2, i * 2 + 2), 16);
- }
- }
- if (invert) {
- for (let i = 0; i < array.length; i++) array[i] = ~array[i];
- }
- }
- if (array.length + position > safeEnd)
- makeRoom(array.length + position);
- position = writeExtensionData(array, target, position, 0x42);
- return
- } else {
- throw new RangeError(value + ' was too large to fit in MessagePack 64-bit integer format, use' +
- ' useBigIntExtension, or set largeBigIntToFloat to convert to float-64, or set' +
- ' largeBigIntToString to convert to string')
- }
- }
- position += 8;
- } else if (type === 'undefined') {
- if (this.encodeUndefinedAsNil)
- target[position++] = 0xc0;
- else {
- target[position++] = 0xd4; // a number of implementations use fixext1 with type 0, data 0 to denote undefined, so we follow suite
- target[position++] = 0;
- target[position++] = 0;
- }
- } else {
- throw new Error('Unknown type: ' + type)
- }
- };
- const writePlainObject = (this.variableMapSize || this.coercibleKeyAsNumber || this.skipValues) ? (object) => {
- // this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
- let keys;
- if (this.skipValues) {
- keys = [];
- for (let key in object) {
- if ((typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) &&
- !this.skipValues.includes(object[key]))
- keys.push(key);
- }
- } else {
- keys = Object.keys(object);
- }
- let length = keys.length;
- if (length < 0x10) {
- target[position++] = 0x80 | length;
- } else if (length < 0x10000) {
- target[position++] = 0xde;
- target[position++] = length >> 8;
- target[position++] = length & 0xff;
- } else {
- target[position++] = 0xdf;
- targetView.setUint32(position, length);
- position += 4;
- }
- let key;
- if (this.coercibleKeyAsNumber) {
- for (let i = 0; i < length; i++) {
- key = keys[i];
- let num = Number(key);
- pack(isNaN(num) ? key : num);
- pack(object[key]);
- }
- } else {
- for (let i = 0; i < length; i++) {
- pack(key = keys[i]);
- pack(object[key]);
- }
- }
- } :
- (object) => {
- target[position++] = 0xde; // always using map 16, so we can preallocate and set the length afterwards
- let objectOffset = position - start;
- position += 2;
- let size = 0;
- for (let key in object) {
- if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
- pack(key);
- pack(object[key]);
- size++;
- }
- }
- if (size > 0xffff) {
- throw new Error('Object is too large to serialize with fast 16-bit map size,' +
- ' use the "variableMapSize" option to serialize this object');
- }
- target[objectOffset++ + start] = size >> 8;
- target[objectOffset + start] = size & 0xff;
- };
- const writeRecord = this.useRecords === false ? writePlainObject :
- (options.progressiveRecords && !useTwoByteRecords) ? // this is about 2% faster for highly stable structures, since it only requires one for-in loop (but much more expensive when new structure needs to be written)
- (object) => {
- let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
- let objectOffset = position++ - start;
- let wroteKeys;
- for (let key in object) {
- if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
- nextTransition = transition[key];
- if (nextTransition)
- transition = nextTransition;
- else {
- // record doesn't exist, create full new record and insert it
- let keys = Object.keys(object);
- let lastTransition = transition;
- transition = structures.transitions;
- let newTransitions = 0;
- for (let i = 0, l = keys.length; i < l; i++) {
- let key = keys[i];
- nextTransition = transition[key];
- if (!nextTransition) {
- nextTransition = transition[key] = Object.create(null);
- newTransitions++;
- }
- transition = nextTransition;
- }
- if (objectOffset + start + 1 == position) {
- // first key, so we don't need to insert, we can just write record directly
- position--;
- newRecord(transition, keys, newTransitions);
- } else // otherwise we need to insert the record, moving existing data after the record
- insertNewRecord(transition, keys, objectOffset, newTransitions);
- wroteKeys = true;
- transition = lastTransition[key];
- }
- pack(object[key]);
- }
- }
- if (!wroteKeys) {
- let recordId = transition[RECORD_SYMBOL];
- if (recordId)
- target[objectOffset + start] = recordId;
- else
- insertNewRecord(transition, Object.keys(object), objectOffset, 0);
- }
- } :
- (object) => {
- let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
- let newTransitions = 0;
- for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
- nextTransition = transition[key];
- if (!nextTransition) {
- nextTransition = transition[key] = Object.create(null);
- newTransitions++;
- }
- transition = nextTransition;
- }
- let recordId = transition[RECORD_SYMBOL];
- if (recordId) {
- if (recordId >= 0x60 && useTwoByteRecords) {
- target[position++] = ((recordId -= 0x60) & 0x1f) + 0x60;
- target[position++] = recordId >> 5;
- } else
- target[position++] = recordId;
- } else {
- newRecord(transition, transition.__keys__ || Object.keys(object), newTransitions);
- }
- // now write the values
- for (let key in object)
- if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
- pack(object[key]);
- }
- };
- // create reference to useRecords if useRecords is a function
- const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
- const writeObject = checkUseRecords ? (object) => {
- checkUseRecords(object) ? writeRecord(object) : writePlainObject(object);
- } : writeRecord;
- const makeRoom = (end) => {
- let newSize;
- if (end > 0x1000000) {
- // special handling for really large buffers
- if ((end - start) > MAX_BUFFER_SIZE)
- throw new Error('Packed buffer would be larger than maximum buffer size')
- newSize = Math.min(MAX_BUFFER_SIZE,
- Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) / 0x1000) * 0x1000);
- } else // faster handling for smaller buffers
- newSize = ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12;
- let newBuffer = new ByteArrayAllocate(newSize);
- targetView = newBuffer.dataView || (newBuffer.dataView = new DataView(newBuffer.buffer, 0, newSize));
- end = Math.min(end, target.length);
- if (target.copy)
- target.copy(newBuffer, 0, start, end);
- else
- newBuffer.set(target.slice(start, end));
- position -= start;
- start = 0;
- safeEnd = newBuffer.length - 10;
- return target = newBuffer
- };
- const newRecord = (transition, keys, newTransitions) => {
- let recordId = structures.nextId;
- if (!recordId)
- recordId = 0x40;
- if (recordId < sharedLimitId && this.shouldShareStructure && !this.shouldShareStructure(keys)) {
- recordId = structures.nextOwnId;
- if (!(recordId < maxStructureId))
- recordId = sharedLimitId;
- structures.nextOwnId = recordId + 1;
- } else {
- if (recordId >= maxStructureId)// cycle back around
- recordId = sharedLimitId;
- structures.nextId = recordId + 1;
- }
- let highByte = keys.highByte = recordId >= 0x60 && useTwoByteRecords ? (recordId - 0x60) >> 5 : -1;
- transition[RECORD_SYMBOL] = recordId;
- transition.__keys__ = keys;
- structures[recordId - 0x40] = keys;
- if (recordId < sharedLimitId) {
- keys.isShared = true;
- structures.sharedLength = recordId - 0x3f;
- hasSharedUpdate = true;
- if (highByte >= 0) {
- target[position++] = (recordId & 0x1f) + 0x60;
- target[position++] = highByte;
- } else {
- target[position++] = recordId;
- }
- } else {
- if (highByte >= 0) {
- target[position++] = 0xd5; // fixext 2
- target[position++] = 0x72; // "r" record defintion extension type
- target[position++] = (recordId & 0x1f) + 0x60;
- target[position++] = highByte;
- } else {
- target[position++] = 0xd4; // fixext 1
- target[position++] = 0x72; // "r" record defintion extension type
- target[position++] = recordId;
- }
- if (newTransitions)
- transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
- // record the removal of the id, we can maintain our shared structure
- if (recordIdsToRemove.length >= maxOwnStructures)
- recordIdsToRemove.shift()[RECORD_SYMBOL] = 0; // we are cycling back through, and have to remove old ones
- recordIdsToRemove.push(transition);
- pack(keys);
- }
- };
- const insertNewRecord = (transition, keys, insertionOffset, newTransitions) => {
- let mainTarget = target;
- let mainPosition = position;
- let mainSafeEnd = safeEnd;
- let mainStart = start;
- target = keysTarget;
- position = 0;
- start = 0;
- if (!target)
- keysTarget = target = new ByteArrayAllocate(8192);
- safeEnd = target.length - 10;
- newRecord(transition, keys, newTransitions);
- keysTarget = target;
- let keysPosition = position;
- target = mainTarget;
- position = mainPosition;
- safeEnd = mainSafeEnd;
- start = mainStart;
- if (keysPosition > 1) {
- let newEnd = position + keysPosition - 1;
- if (newEnd > safeEnd)
- makeRoom(newEnd);
- let insertionPosition = insertionOffset + start;
- target.copyWithin(insertionPosition + keysPosition, insertionPosition + 1, position);
- target.set(keysTarget.slice(0, keysPosition), insertionPosition);
- position = newEnd;
- } else {
- target[insertionOffset + start] = keysTarget[0];
- }
- };
- const writeStruct = (object) => {
- let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
- if (notifySharedUpdate)
- return hasSharedUpdate = true;
- position = newPosition;
- let startTarget = target;
- pack(value);
- resetStructures();
- if (startTarget !== target) {
- return { position, targetView, target }; // indicate the buffer was re-allocated
- }
- return position;
- }, this);
- if (newPosition === 0) // bail and go to a msgpack object
- return writeObject(object);
- position = newPosition;
- };
- }
- useBuffer(buffer) {
- // this means we are finished using our own buffer and we can write over it safely
- target = buffer;
- target.dataView || (target.dataView = new DataView(target.buffer, target.byteOffset, target.byteLength));
- targetView = target.dataView;
- position = 0;
- }
- set position (value) {
- position = value;
- }
- get position() {
- return position;
- }
- clearSharedData() {
- if (this.structures)
- this.structures = [];
- if (this.typedStructs)
- this.typedStructs = [];
- }
- };
- extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, DataView, C1Type ];
- extensions = [{
- pack(date, allocateForWrite, pack) {
- let seconds = date.getTime() / 1000;
- if ((this.useTimestamp32 || date.getMilliseconds() === 0) && seconds >= 0 && seconds < 0x100000000) {
- // Timestamp 32
- let { target, targetView, position} = allocateForWrite(6);
- target[position++] = 0xd6;
- target[position++] = 0xff;
- targetView.setUint32(position, seconds);
- } else if (seconds > 0 && seconds < 0x100000000) {
- // Timestamp 64
- let { target, targetView, position} = allocateForWrite(10);
- target[position++] = 0xd7;
- target[position++] = 0xff;
- targetView.setUint32(position, date.getMilliseconds() * 4000000 + ((seconds / 1000 / 0x100000000) >> 0));
- targetView.setUint32(position + 4, seconds);
- } else if (isNaN(seconds)) {
- if (this.onInvalidDate) {
- allocateForWrite(0);
- return pack(this.onInvalidDate())
- }
- // Intentionally invalid timestamp
- let { target, targetView, position} = allocateForWrite(3);
- target[position++] = 0xd4;
- target[position++] = 0xff;
- target[position++] = 0xff;
- } else {
- // Timestamp 96
- let { target, targetView, position} = allocateForWrite(15);
- target[position++] = 0xc7;
- target[position++] = 12;
- target[position++] = 0xff;
- targetView.setUint32(position, date.getMilliseconds() * 1000000);
- targetView.setBigInt64(position + 4, BigInt(Math.floor(seconds)));
- }
- }
- }, {
- pack(set, allocateForWrite, pack) {
- if (this.setAsEmptyObject) {
- allocateForWrite(0);
- return pack({})
- }
- let array = Array.from(set);
- let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
- if (this.moreTypes) {
- target[position++] = 0xd4;
- target[position++] = 0x73; // 's' for Set
- target[position++] = 0;
- }
- pack(array);
- }
- }, {
- pack(error, allocateForWrite, pack) {
- let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
- if (this.moreTypes) {
- target[position++] = 0xd4;
- target[position++] = 0x65; // 'e' for error
- target[position++] = 0;
- }
- pack([ error.name, error.message, error.cause ]);
- }
- }, {
- pack(regex, allocateForWrite, pack) {
- let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
- if (this.moreTypes) {
- target[position++] = 0xd4;
- target[position++] = 0x78; // 'x' for regeXp
- target[position++] = 0;
- }
- pack([ regex.source, regex.flags ]);
- }
- }, {
- pack(arrayBuffer, allocateForWrite) {
- if (this.moreTypes)
- writeExtBuffer(arrayBuffer, 0x10, allocateForWrite);
- else
- writeBuffer(hasNodeBuffer$1 ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer), allocateForWrite);
- }
- }, {
- pack(typedArray, allocateForWrite) {
- let constructor = typedArray.constructor;
- if (constructor !== ByteArray && this.moreTypes)
- writeExtBuffer(typedArray, typedArrays.indexOf(constructor.name), allocateForWrite);
- else
- writeBuffer(typedArray, allocateForWrite);
- }
- }, {
- pack(arrayBuffer, allocateForWrite) {
- if (this.moreTypes)
- writeExtBuffer(arrayBuffer, 0x11, allocateForWrite);
- else
- writeBuffer(hasNodeBuffer$1 ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer), allocateForWrite);
- }
- }, {
- pack(c1, allocateForWrite) { // specific 0xC1 object
- let { target, position} = allocateForWrite(1);
- target[position] = 0xc1;
- }
- }];
- function writeExtBuffer(typedArray, type, allocateForWrite, encode) {
- let length = typedArray.byteLength;
- if (length + 1 < 0x100) {
- var { target, position } = allocateForWrite(4 + length);
- target[position++] = 0xc7;
- target[position++] = length + 1;
- } else if (length + 1 < 0x10000) {
- var { target, position } = allocateForWrite(5 + length);
- target[position++] = 0xc8;
- target[position++] = (length + 1) >> 8;
- target[position++] = (length + 1) & 0xff;
- } else {
- var { target, position, targetView } = allocateForWrite(7 + length);
- target[position++] = 0xc9;
- targetView.setUint32(position, length + 1); // plus one for the type byte
- position += 4;
- }
- target[position++] = 0x74; // "t" for typed array
- target[position++] = type;
- if (!typedArray.buffer) typedArray = new Uint8Array(typedArray);
- target.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength), position);
- }
- function writeBuffer(buffer, allocateForWrite) {
- let length = buffer.byteLength;
- var target, position;
- if (length < 0x100) {
- var { target, position } = allocateForWrite(length + 2);
- target[position++] = 0xc4;
- target[position++] = length;
- } else if (length < 0x10000) {
- var { target, position } = allocateForWrite(length + 3);
- target[position++] = 0xc5;
- target[position++] = length >> 8;
- target[position++] = length & 0xff;
- } else {
- var { target, position, targetView } = allocateForWrite(length + 5);
- target[position++] = 0xc6;
- targetView.setUint32(position, length);
- position += 4;
- }
- target.set(buffer, position);
- }
- function writeExtensionData(result, target, position, type) {
- let length = result.length;
- switch (length) {
- case 1:
- target[position++] = 0xd4;
- break
- case 2:
- target[position++] = 0xd5;
- break
- case 4:
- target[position++] = 0xd6;
- break
- case 8:
- target[position++] = 0xd7;
- break
- case 16:
- target[position++] = 0xd8;
- break
- default:
- if (length < 0x100) {
- target[position++] = 0xc7;
- target[position++] = length;
- } else if (length < 0x10000) {
- target[position++] = 0xc8;
- target[position++] = length >> 8;
- target[position++] = length & 0xff;
- } else {
- target[position++] = 0xc9;
- target[position++] = length >> 24;
- target[position++] = (length >> 16) & 0xff;
- target[position++] = (length >> 8) & 0xff;
- target[position++] = length & 0xff;
- }
- }
- target[position++] = type;
- target.set(result, position);
- position += length;
- return position
- }
- function insertIds(serialized, idsToInsert) {
- // insert the ids that need to be referenced for structured clones
- let nextId;
- let distanceToMove = idsToInsert.length * 6;
- let lastEnd = serialized.length - distanceToMove;
- while (nextId = idsToInsert.pop()) {
- let offset = nextId.offset;
- let id = nextId.id;
- serialized.copyWithin(offset + distanceToMove, offset, lastEnd);
- distanceToMove -= 6;
- let position = offset + distanceToMove;
- serialized[position++] = 0xd6;
- serialized[position++] = 0x69; // 'i'
- serialized[position++] = id >> 24;
- serialized[position++] = (id >> 16) & 0xff;
- serialized[position++] = (id >> 8) & 0xff;
- serialized[position++] = id & 0xff;
- lastEnd = offset;
- }
- return serialized
- }
- function writeBundles(start, pack, incrementPosition) {
- if (bundledStrings.length > 0) {
- targetView.setUint32(bundledStrings.position + start, position + incrementPosition - bundledStrings.position - start);
- bundledStrings.stringsPosition = position - start;
- let writeStrings = bundledStrings;
- bundledStrings = null;
- pack(writeStrings[0]);
- pack(writeStrings[1]);
- }
- }
- function addExtension$1(extension) {
- if (extension.Class) {
- if (!extension.pack && !extension.write)
- throw new Error('Extension has no pack or write function')
- if (extension.pack && !extension.type)
- throw new Error('Extension has no type (numeric code to identify the extension)')
- extensionClasses.unshift(extension.Class);
- extensions.unshift(extension);
- }
- addExtension$2(extension);
- }
- function prepareStructures$1(structures, packr) {
- structures.isCompatible = (existingStructures) => {
- let compatible = !existingStructures || ((packr.lastNamedStructuresLength || 0) === existingStructures.length);
- if (!compatible) // we want to merge these existing structures immediately since we already have it and we are in the right transaction
- packr._mergeStructures(existingStructures);
- return compatible;
- };
- return structures
- }
- function setWriteStructSlots(writeSlots, makeStructures) {
- writeStructSlots = writeSlots;
- prepareStructures$1 = makeStructures;
- }
- let defaultPackr = new Packr$1({ useRecords: false });
- const pack$1 = defaultPackr.pack;
- defaultPackr.pack;
- const REUSE_BUFFER_MODE = 512;
- const RESET_BUFFER_MODE = 1024;
- const RESERVE_START_SPACE = 2048;
- const ASCII = 3; // the MIBenum from https://www.iana.org/assignments/character-sets/character-sets.xhtml (and other character encodings could be referenced by MIBenum)
- const NUMBER = 0;
- const UTF8 = 2;
- const OBJECT_DATA = 1;
- const DATE = 16;
- const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
- TYPE_NAMES[DATE] = 'date';
- const float32Headers = [false, true, true, false, false, true, true, false];
- let evalSupported;
- try {
- new Function('');
- evalSupported = true;
- } catch(error) {
- // if eval variants are not supported, do not create inline object readers ever
- }
- let updatedPosition;
- const hasNodeBuffer = typeof Buffer !== 'undefined';
- let textEncoder, currentSource;
- try {
- textEncoder = new TextEncoder();
- } catch (error) {}
- const encodeUtf8 = hasNodeBuffer ? function(target, string, position) {
- return target.utf8Write(string, position, target.byteLength - position)
- } : (textEncoder && textEncoder.encodeInto) ?
- function(target, string, position) {
- return textEncoder.encodeInto(string, target.subarray(position)).written
- } : false;
- setWriteStructSlots(writeStruct, prepareStructures);
- function writeStruct(object, target, encodingStart, position, structures, makeRoom, pack, packr) {
- let typedStructs = packr.typedStructs || (packr.typedStructs = []);
- // note that we rely on pack.js to load stored structures before we get to this point
- let targetView = target.dataView;
- let refsStartPosition = (typedStructs.lastStringStart || 100) + position;
- let safeEnd = target.length - 10;
- let start = position;
- if (position > safeEnd) {
- target = makeRoom(position);
- targetView = target.dataView;
- position -= encodingStart;
- start -= encodingStart;
- refsStartPosition -= encodingStart;
- encodingStart = 0;
- safeEnd = target.length - 10;
- }
- let refOffset, refPosition = refsStartPosition;
- let transition = typedStructs.transitions || (typedStructs.transitions = Object.create(null));
- let nextId = typedStructs.nextId || typedStructs.length;
- let headerSize =
- nextId < 0xf ? 1 :
- nextId < 0xf0 ? 2 :
- nextId < 0xf000 ? 3 :
- nextId < 0xf00000 ? 4 : 0;
- if (headerSize === 0)
- return 0;
- position += headerSize;
- let queuedReferences = [];
- let usedAscii0;
- let keyIndex = 0;
- for (let key in object) {
- let value = object[key];
- let nextTransition = transition[key];
- if (!nextTransition) {
- transition[key] = nextTransition = {
- key,
- parent: transition,
- enumerationOffset: 0,
- ascii0: null,
- ascii8: null,
- num8: null,
- string16: null,
- object16: null,
- num32: null,
- float64: null,
- date64: null
- };
- }
- if (position > safeEnd) {
- target = makeRoom(position);
- targetView = target.dataView;
- position -= encodingStart;
- start -= encodingStart;
- refsStartPosition -= encodingStart;
- refPosition -= encodingStart;
- encodingStart = 0;
- safeEnd = target.length - 10;
- }
- switch (typeof value) {
- case 'number':
- let number = value;
- // first check to see if we are using a lot of ids and should default to wide/common format
- if (nextId < 200 || !nextTransition.num64) {
- if (number >> 0 === number && number < 0x20000000 && number > -0x1f000000) {
- if (number < 0xf6 && number >= 0 && (nextTransition.num8 && !(nextId > 200 && nextTransition.num32) || number < 0x20 && !nextTransition.num32)) {
- transition = nextTransition.num8 || createTypeTransition(nextTransition, NUMBER, 1);
- target[position++] = number;
- } else {
- transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
- targetView.setUint32(position, number, true);
- position += 4;
- }
- break;
- } else if (number < 0x100000000 && number >= -0x80000000) {
- targetView.setFloat32(position, number, true);
- if (float32Headers[target[position + 3] >>> 5]) {
- let xShifted;
- // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
- if (((xShifted = number * mult10[((target[position + 3] & 0x7f) << 1) | (target[position + 2] >> 7)]) >> 0) === xShifted) {
- transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
- position += 4;
- break;
- }
- }
- }
- }
- transition = nextTransition.num64 || createTypeTransition(nextTransition, NUMBER, 8);
- targetView.setFloat64(position, number, true);
- position += 8;
- break;
- case 'string':
- let strLength = value.length;
- refOffset = refPosition - refsStartPosition;
- if ((strLength << 2) + refPosition > safeEnd) {
- target = makeRoom((strLength << 2) + refPosition);
- targetView = target.dataView;
- position -= encodingStart;
- start -= encodingStart;
- refsStartPosition -= encodingStart;
- refPosition -= encodingStart;
- encodingStart = 0;
- safeEnd = target.length - 10;
- }
- if (strLength > ((0xff00 + refOffset) >> 2)) {
- queuedReferences.push(key, value, position - start);
- break;
- }
- let isNotAscii;
- let strStart = refPosition;
- if (strLength < 0x40) {
- let i, c1, c2;
- for (i = 0; i < strLength; i++) {
- c1 = value.charCodeAt(i);
- if (c1 < 0x80) {
- target[refPosition++] = c1;
- } else if (c1 < 0x800) {
- isNotAscii = true;
- target[refPosition++] = c1 >> 6 | 0xc0;
- target[refPosition++] = c1 & 0x3f | 0x80;
- } else if (
- (c1 & 0xfc00) === 0xd800 &&
- ((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
- ) {
- isNotAscii = true;
- c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
- i++;
- target[refPosition++] = c1 >> 18 | 0xf0;
- target[refPosition++] = c1 >> 12 & 0x3f | 0x80;
- target[refPosition++] = c1 >> 6 & 0x3f | 0x80;
- target[refPosition++] = c1 & 0x3f | 0x80;
- } else {
- isNotAscii = true;
- target[refPosition++] = c1 >> 12 | 0xe0;
- target[refPosition++] = c1 >> 6 & 0x3f | 0x80;
- target[refPosition++] = c1 & 0x3f | 0x80;
- }
- }
- } else {
- refPosition += encodeUtf8(target, value, refPosition);
- isNotAscii = refPosition - strStart > strLength;
- }
- if (refOffset < 0xa0 || (refOffset < 0xf6 && (nextTransition.ascii8 || nextTransition.string8))) {
- // short strings
- if (isNotAscii) {
- if (!(transition = nextTransition.string8)) {
- if (typedStructs.length > 10 && (transition = nextTransition.ascii8)) {
- // we can safely change ascii to utf8 in place since they are compatible
- transition.__type = UTF8;
- nextTransition.ascii8 = null;
- nextTransition.string8 = transition;
- pack(null, 0, true); // special call to notify that structures have been updated
- } else {
- transition = createTypeTransition(nextTransition, UTF8, 1);
- }
- }
- } else if (refOffset === 0 && !usedAscii0) {
- usedAscii0 = true;
- transition = nextTransition.ascii0 || createTypeTransition(nextTransition, ASCII, 0);
- break; // don't increment position
- }// else ascii:
- else if (!(transition = nextTransition.ascii8) && !(typedStructs.length > 10 && (transition = nextTransition.string8)))
- transition = createTypeTransition(nextTransition, ASCII, 1);
- target[position++] = refOffset;
- } else {
- // TODO: Enable ascii16 at some point, but get the logic right
- //if (isNotAscii)
- transition = nextTransition.string16 || createTypeTransition(nextTransition, UTF8, 2);
- //else
- //transition = nextTransition.ascii16 || createTypeTransition(nextTransition, ASCII, 2);
- targetView.setUint16(position, refOffset, true);
- position += 2;
- }
- break;
- case 'object':
- if (value) {
- if (value.constructor === Date) {
- transition = nextTransition.date64 || createTypeTransition(nextTransition, DATE, 8);
- targetView.setFloat64(position, value.getTime(), true);
- position += 8;
- } else {
- queuedReferences.push(key, value, keyIndex);
- }
- break;
- } else { // null
- nextTransition = anyType(nextTransition, position, targetView, -10); // match CBOR with this
- if (nextTransition) {
- transition = nextTransition;
- position = updatedPosition;
- } else queuedReferences.push(key, value, keyIndex);
- }
- break;
- case 'boolean':
- transition = nextTransition.num8 || nextTransition.ascii8 || createTypeTransition(nextTransition, NUMBER, 1);
- target[position++] = value ? 0xf9 : 0xf8; // match CBOR with these
- break;
- case 'undefined':
- nextTransition = anyType(nextTransition, position, targetView, -9); // match CBOR with this
- if (nextTransition) {
- transition = nextTransition;
- position = updatedPosition;
- } else queuedReferences.push(key, value, keyIndex);
- break;
- default:
- queuedReferences.push(key, value, keyIndex);
- }
- keyIndex++;
- }
- for (let i = 0, l = queuedReferences.length; i < l;) {
- let key = queuedReferences[i++];
- let value = queuedReferences[i++];
- let propertyIndex = queuedReferences[i++];
- let nextTransition = transition[key];
- if (!nextTransition) {
- transition[key] = nextTransition = {
- key,
- parent: transition,
- enumerationOffset: propertyIndex - keyIndex,
- ascii0: null,
- ascii8: null,
- num8: null,
- string16: null,
- object16: null,
- num32: null,
- float64: null
- };
- }
- let newPosition;
- if (value) {
- /*if (typeof value === 'string') { // TODO: we could re-enable long strings
- if (position + value.length * 3 > safeEnd) {
- target = makeRoom(position + value.length * 3);
- position -= start;
- targetView = target.dataView;
- start = 0;
- }
- newPosition = position + target.utf8Write(value, position, 0xffffffff);
- } else { */
- let size;
- refOffset = refPosition - refsStartPosition;
- if (refOffset < 0xff00) {
- transition = nextTransition.object16;
- if (transition)
- size = 2;
- else if ((transition = nextTransition.object32))
- size = 4;
- else {
- transition = createTypeTransition(nextTransition, OBJECT_DATA, 2);
- size = 2;
- }
- } else {
- transition = nextTransition.object32 || createTypeTransition(nextTransition, OBJECT_DATA, 4);
- size = 4;
- }
- newPosition = pack(value, refPosition);
- //}
- if (typeof newPosition === 'object') {
- // re-allocated
- refPosition = newPosition.position;
- targetView = newPosition.targetView;
- target = newPosition.target;
- refsStartPosition -= encodingStart;
- position -= encodingStart;
- start -= encodingStart;
- encodingStart = 0;
- } else
- refPosition = newPosition;
- if (size === 2) {
- targetView.setUint16(position, refOffset, true);
- position += 2;
- } else {
- targetView.setUint32(position, refOffset, true);
- position += 4;
- }
- } else { // null or undefined
- transition = nextTransition.object16 || createTypeTransition(nextTransition, OBJECT_DATA, 2);
- targetView.setInt16(position, value === null ? -10 : -9, true);
- position += 2;
- }
- keyIndex++;
- }
- let recordId = transition[RECORD_SYMBOL];
- if (recordId == null) {
- recordId = packr.typedStructs.length;
- let structure = [];
- let nextTransition = transition;
- let key, type;
- while ((type = nextTransition.__type) !== undefined) {
- let size = nextTransition.__size;
- nextTransition = nextTransition.__parent;
- key = nextTransition.key;
- let property = [type, size, key];
- if (nextTransition.enumerationOffset)
- property.push(nextTransition.enumerationOffset);
- structure.push(property);
- nextTransition = nextTransition.parent;
- }
- structure.reverse();
- transition[RECORD_SYMBOL] = recordId;
- packr.typedStructs[recordId] = structure;
- pack(null, 0, true); // special call to notify that structures have been updated
- }
- switch (headerSize) {
- case 1:
- if (recordId >= 0x10) return 0;
- target[start] = recordId + 0x20;
- break;
- case 2:
- if (recordId >= 0x100) return 0;
- target[start] = 0x38;
- target[start + 1] = recordId;
- break;
- case 3:
- if (recordId >= 0x10000) return 0;
- target[start] = 0x39;
- targetView.setUint16(start + 1, recordId, true);
- break;
- case 4:
- if (recordId >= 0x1000000) return 0;
- targetView.setUint32(start, (recordId << 8) + 0x3a, true);
- break;
- }
- if (position < refsStartPosition) {
- if (refsStartPosition === refPosition)
- return position; // no refs
- // adjust positioning
- target.copyWithin(position, refsStartPosition, refPosition);
- refPosition += position - refsStartPosition;
- typedStructs.lastStringStart = position - start;
- } else if (position > refsStartPosition) {
- if (refsStartPosition === refPosition)
- return position; // no refs
- typedStructs.lastStringStart = position - start;
- return writeStruct(object, target, encodingStart, start, structures, makeRoom, pack, packr);
- }
- return refPosition;
- }
- function anyType(transition, position, targetView, value) {
- let nextTransition;
- if ((nextTransition = transition.ascii8 || transition.num8)) {
- targetView.setInt8(position, value, true);
- updatedPosition = position + 1;
- return nextTransition;
- }
- if ((nextTransition = transition.string16 || transition.object16)) {
- targetView.setInt16(position, value, true);
- updatedPosition = position + 2;
- return nextTransition;
- }
- if (nextTransition = transition.num32) {
- targetView.setUint32(position, 0xe0000100 + value, true);
- updatedPosition = position + 4;
- return nextTransition;
- }
- // transition.float64
- if (nextTransition = transition.num64) {
- targetView.setFloat64(position, NaN, true);
- targetView.setInt8(position, value);
- updatedPosition = position + 8;
- return nextTransition;
- }
- updatedPosition = position;
- // TODO: can we do an "any" type where we defer the decision?
- return;
- }
- function createTypeTransition(transition, type, size) {
- let typeName = TYPE_NAMES[type] + (size << 3);
- let newTransition = transition[typeName] || (transition[typeName] = Object.create(null));
- newTransition.__type = type;
- newTransition.__size = size;
- newTransition.__parent = transition;
- return newTransition;
- }
- function onLoadedStructures(sharedData) {
- if (!(sharedData instanceof Map))
- return sharedData;
- let typed = sharedData.get('typed') || [];
- if (Object.isFrozen(typed))
- typed = typed.map(structure => structure.slice(0));
- let named = sharedData.get('named');
- let transitions = Object.create(null);
- for (let i = 0, l = typed.length; i < l; i++) {
- let structure = typed[i];
- let transition = transitions;
- for (let [type, size, key] of structure) {
- let nextTransition = transition[key];
- if (!nextTransition) {
- transition[key] = nextTransition = {
- key,
- parent: transition,
- enumerationOffset: 0,
- ascii0: null,
- ascii8: null,
- num8: null,
- string16: null,
- object16: null,
- num32: null,
- float64: null,
- date64: null,
- };
- }
- transition = createTypeTransition(nextTransition, type, size);
- }
- transition[RECORD_SYMBOL] = i;
- }
- typed.transitions = transitions;
- this.typedStructs = typed;
- this.lastTypedStructuresLength = typed.length;
- return named;
- }
- var sourceSymbol = Symbol.for('source');
- function readStruct(src, position, srcEnd, unpackr) {
- let recordId = src[position++] - 0x20;
- if (recordId >= 24) {
- switch(recordId) {
- case 24: recordId = src[position++]; break;
- // little endian:
- case 25: recordId = src[position++] + (src[position++] << 8); break;
- case 26: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16); break;
- case 27: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16) + (src[position++] << 24); break;
- }
- }
- let structure = unpackr.typedStructs && unpackr.typedStructs[recordId];
- if (!structure) {
- // copy src buffer because getStructures will override it
- src = Uint8Array.prototype.slice.call(src, position, srcEnd);
- srcEnd -= position;
- position = 0;
- if (!unpackr.getStructures)
- throw new Error(`Reference to shared structure ${recordId} without getStructures method`);
- unpackr._mergeStructures(unpackr.getStructures());
- if (!unpackr.typedStructs)
- throw new Error('Could not find any shared typed structures');
- unpackr.lastTypedStructuresLength = unpackr.typedStructs.length;
- structure = unpackr.typedStructs[recordId];
- if (!structure)
- throw new Error('Could not find typed structure ' + recordId);
- }
- var construct = structure.construct;
- var fullConstruct = structure.fullConstruct;
- if (!construct) {
- construct = structure.construct = function LazyObject() {
- };
- fullConstruct = structure.fullConstruct = function LoadedObject() {
- };
- fullConstruct.prototype = unpackr.structPrototype || {};
- var prototype = construct.prototype = unpackr.structPrototype ? Object.create(unpackr.structPrototype) : {};
- let properties = [];
- let currentOffset = 0;
- let lastRefProperty;
- for (let i = 0, l = structure.length; i < l; i++) {
- let definition = structure[i];
- let [ type, size, key, enumerationOffset ] = definition;
- if (key === '__proto__')
- key = '__proto_';
- let property = {
- key,
- offset: currentOffset,
- };
- if (enumerationOffset)
- properties.splice(i + enumerationOffset, 0, property);
- else
- properties.push(property);
- let getRef;
- switch(size) { // TODO: Move into a separate function
- case 0: getRef = () => 0; break;
- case 1:
- getRef = (source, position) => {
- let ref = source.bytes[position + property.offset];
- return ref >= 0xf6 ? toConstant(ref) : ref;
- };
- break;
- case 2:
- getRef = (source, position) => {
- let src = source.bytes;
- let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
- let ref = dataView.getUint16(position + property.offset, true);
- return ref >= 0xff00 ? toConstant(ref & 0xff) : ref;
- };
- break;
- case 4:
- getRef = (source, position) => {
- let src = source.bytes;
- let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
- let ref = dataView.getUint32(position + property.offset, true);
- return ref >= 0xffffff00 ? toConstant(ref & 0xff) : ref;
- };
- break;
- }
- property.getRef = getRef;
- currentOffset += size;
- let get;
- switch(type) {
- case ASCII:
- if (lastRefProperty && !lastRefProperty.next)
- lastRefProperty.next = property;
- lastRefProperty = property;
- property.multiGetCount = 0;
- get = function(source) {
- let src = source.bytes;
- let position = source.position;
- let refStart = currentOffset + position;
- let ref = getRef(source, position);
- if (typeof ref !== 'number') return ref;
- let end, next = property.next;
- while(next) {
- end = next.getRef(source, position);
- if (typeof end === 'number')
- break;
- else
- end = null;
- next = next.next;
- }
- if (end == null)
- end = source.bytesEnd - refStart;
- if (source.srcString) {
- return source.srcString.slice(ref, end);
- }
- /*if (property.multiGetCount > 0) {
- let asciiEnd;
- next = firstRefProperty;
- let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
- do {
- asciiEnd = dataView.getUint16(source.position + next.offset, true);
- if (asciiEnd < 0xff00)
- break;
- else
- asciiEnd = null;
- } while((next = next.next));
- if (asciiEnd == null)
- asciiEnd = source.bytesEnd - refStart
- source.srcString = src.toString('latin1', refStart, refStart + asciiEnd);
- return source.srcString.slice(ref, end);
- }
- if (source.prevStringGet) {
- source.prevStringGet.multiGetCount += 2;
- } else {
- source.prevStringGet = property;
- property.multiGetCount--;
- }*/
- return readString(src, ref + refStart, end - ref);
- //return src.toString('latin1', ref + refStart, end + refStart);
- };
- break;
- case UTF8: case OBJECT_DATA:
- if (lastRefProperty && !lastRefProperty.next)
- lastRefProperty.next = property;
- lastRefProperty = property;
- get = function(source) {
- let position = source.position;
- let refStart = currentOffset + position;
- let ref = getRef(source, position);
- if (typeof ref !== 'number') return ref;
- let src = source.bytes;
- let end, next = property.next;
- while(next) {
- end = next.getRef(source, position);
- if (typeof end === 'number')
- break;
- else
- end = null;
- next = next.next;
- }
- if (end == null)
- end = source.bytesEnd - refStart;
- if (type === UTF8) {
- return src.toString('utf8', ref + refStart, end + refStart);
- } else {
- currentSource = source;
- try {
- return unpackr.unpack(src, { start: ref + refStart, end: end + refStart });
- } finally {
- currentSource = null;
- }
- }
- };
- break;
- case NUMBER:
- switch(size) {
- case 4:
- get = function (source) {
- let src = source.bytes;
- let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
- let position = source.position + property.offset;
- let value = dataView.getInt32(position, true);
- if (value < 0x20000000) {
- if (value > -0x1f000000)
- return value;
- if (value > -0x20000000)
- return toConstant(value & 0xff);
- }
- let fValue = dataView.getFloat32(position, true);
- // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
- let multiplier = mult10[((src[position + 3] & 0x7f) << 1) | (src[position + 2] >> 7)];
- return ((multiplier * fValue + (fValue > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
- };
- break;
- case 8:
- get = function (source) {
- let src = source.bytes;
- let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
- let value = dataView.getFloat64(source.position + property.offset, true);
- if (isNaN(value)) {
- let byte = src[source.position + property.offset];
- if (byte >= 0xf6)
- return toConstant(byte);
- }
- return value;
- };
- break;
- case 1:
- get = function (source) {
- let src = source.bytes;
- let value = src[source.position + property.offset];
- return value < 0xf6 ? value : toConstant(value);
- };
- break;
- }
- break;
- case DATE:
- get = function (source) {
- let src = source.bytes;
- let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
- return new Date(dataView.getFloat64(source.position + property.offset, true));
- };
- break;
- }
- property.get = get;
- }
- // TODO: load the srcString for faster string decoding on toJSON
- if (evalSupported) {
- let objectLiteralProperties = [];
- let args = [];
- let i = 0;
- let hasInheritedProperties;
- for (let property of properties) { // assign in enumeration order
- if (unpackr.alwaysLazyProperty && unpackr.alwaysLazyProperty(property.key)) {
- // these properties are not eagerly evaluated and this can be used for creating properties
- // that are not serialized as JSON
- hasInheritedProperties = true;
- continue;
- }
- Object.defineProperty(prototype, property.key, { get: withSource(property.get), enumerable: true });
- let valueFunction = 'v' + i++;
- args.push(valueFunction);
- objectLiteralProperties.push('o[' + JSON.stringify(property.key) + ']=' + valueFunction + '(s)');
- }
- if (hasInheritedProperties) {
- objectLiteralProperties.push('__proto__:this');
- }
- let toObject = (new Function(...args, 'var c=this;return function(s){var o=new c();' + objectLiteralProperties.join(';') + ';return o;}')).apply(fullConstruct, properties.map(prop => prop.get));
- Object.defineProperty(prototype, 'toJSON', {
- value(omitUnderscoredProperties) {
- return toObject.call(this, this[sourceSymbol]);
- }
- });
- } else {
- Object.defineProperty(prototype, 'toJSON', {
- value(omitUnderscoredProperties) {
- // return an enumerable object with own properties to JSON stringify
- let resolved = {};
- for (let i = 0, l = properties.length; i < l; i++) {
- // TODO: check alwaysLazyProperty
- let key = properties[i].key;
- resolved[key] = this[key];
- }
- return resolved;
- },
- // not enumerable or anything
- });
- }
- }
- var instance = new construct();
- instance[sourceSymbol] = {
- bytes: src,
- position,
- srcString: '',
- bytesEnd: srcEnd
- };
- return instance;
- }
- function toConstant(code) {
- switch(code) {
- case 0xf6: return null;
- case 0xf7: return undefined;
- case 0xf8: return false;
- case 0xf9: return true;
- }
- throw new Error('Unknown constant');
- }
- function withSource(get) {
- return function() {
- return get(this[sourceSymbol]);
- }
- }
- function saveState() {
- if (currentSource) {
- currentSource.bytes = Uint8Array.prototype.slice.call(currentSource.bytes, currentSource.position, currentSource.bytesEnd);
- currentSource.position = 0;
- currentSource.bytesEnd = currentSource.bytes.length;
- }
- }
- function prepareStructures(structures, packr) {
- if (packr.typedStructs) {
- let structMap = new Map();
- structMap.set('named', structures);
- structMap.set('typed', packr.typedStructs);
- structures = structMap;
- }
- let lastTypedStructuresLength = packr.lastTypedStructuresLength || 0;
- structures.isCompatible = existing => {
- let compatible = true;
- if (existing instanceof Map) {
- let named = existing.get('named') || [];
- if (named.length !== (packr.lastNamedStructuresLength || 0))
- compatible = false;
- let typed = existing.get('typed') || [];
- if (typed.length !== lastTypedStructuresLength)
- compatible = false;
- } else if (existing instanceof Array || Array.isArray(existing)) {
- if (existing.length !== (packr.lastNamedStructuresLength || 0))
- compatible = false;
- }
- if (!compatible)
- packr._mergeStructures(existing);
- return compatible;
- };
- packr.lastTypedStructuresLength = packr.typedStructs && packr.typedStructs.length;
- return structures;
- }
- setReadStruct(readStruct, onLoadedStructures, saveState);
- const nativeAccelerationDisabled = process.env.MSGPACKR_NATIVE_ACCELERATION_DISABLED !== undefined && process.env.MSGPACKR_NATIVE_ACCELERATION_DISABLED.toLowerCase() === 'true';
- if (!nativeAccelerationDisabled) {
- let extractor;
- try {
- if (typeof require == 'function')
- extractor = require('msgpackr-extract');
- else
- extractor = module.createRequire((document.currentScript && document.currentScript.src || new URL('test.js', document.baseURI).href))('msgpackr-extract');
- if (extractor)
- setExtractor(extractor.extractStrings);
- } catch (error) {
- // native module is optional
- }
- }
- let allSampleData = [];
- for (let i = 1; i < 6; i++) {
- allSampleData.push(JSON.parse(fs.readFileSync(new URL(`./example${i > 1 ? i : ''}.json`, (document.currentScript && document.currentScript.src || new URL('test.js', document.baseURI).href)))));
- }
- allSampleData.push({
- name: 'some other types',
- date: new Date(),
- empty: '',
- });
- const sampleData = allSampleData[3];
- function tryRequire(module) {
- try {
- return require(module)
- } catch(error) {
- return {}
- }
- }
- let seed = 0;
- function random() {
- seed++;
- let a = seed * 15485863;
- return (a * a * a % 2038074743) / 2038074743;
- }
- //if (typeof chai === 'undefined') { chai = require('chai') }
- var assert = chai.assert;
- //if (typeof msgpackr === 'undefined') { msgpackr = require('..') }
- var Packr = Packr$1;
- var Unpackr = Unpackr$1;
- var unpack = unpack$1;
- var unpackMultiple = unpackMultiple$1;
- var roundFloat32 = roundFloat32$1;
- var pack = pack$1;
- var DECIMAL_FIT = FLOAT32_OPTIONS.DECIMAL_FIT;
- var addExtension = addExtension$1;
- var zlib = tryRequire('zlib');
- zlib.deflateSync;
- zlib.inflateSync;
- zlib.brotliCompressSync;
- zlib.brotliDecompressSync;
- zlib.constants;
- var ITERATIONS = 4000;
- class ExtendArray extends Array {
- }
- class ExtendArray2 extends Array {
- }
- class ExtendArray3 extends Array {
- }
- class ExtendObject {
- }
- suite('msgpackr basic tests', function() {
- test('pack/unpack data', function () {
- var data = {
- data: [
- {a: 1, name: 'one', type: 'odd', isOdd: true},
- {a: 2, name: 'two', type: 'even'},
- {a: 3, name: 'three', type: 'odd', isOdd: true},
- {a: 4, name: 'four', type: 'even'},
- {a: 5, name: 'five', type: 'odd', isOdd: true},
- {a: 6, name: 'six', type: 'even', isOdd: null}
- ],
- description: 'some names',
- types: ['odd', 'even'],
- convertEnumToNum: [
- {prop: 'test'},
- {prop: 'test'},
- {prop: 'test'},
- {prop: 1},
- {prop: 2},
- {prop: [undefined]},
- {prop: null}
- ]
- };
- let structures = [];
- let packr = new Packr({structures});
- var serialized = packr.pack(data);
- serialized = packr.pack(data);
- serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('mixed structures', function () {
- let data1 = {a: 1, b: 2, c: 3};
- let data2 = {a: 1, b: 2, d: 4};
- let data3 = {a: 1, b: 2, e: 5};
- let structures = [];
- let packr = new Packr({structures});
- var serialized = packr.pack(data1);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data1);
- var serialized = packr.pack(data2);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data2);
- var serialized = packr.pack(data3);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data3);
- });
- test('mixed array', function () {
- var data = [
- 'one',
- 'two',
- 'one',
- 10,
- 11,
- null,
- true,
- 'three',
- 'three',
- 'one', [
- 3, -5, -50, -400, 1.3, -5.3, true
- ]
- ];
- let structures = [];
- let packr = new Packr({structures});
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('255 chars', function () {
- const data = 'RRZG9A6I7xupPeOZhxcOcioFsuhszGOdyDUcbRf4Zef2kdPIfC9RaLO4jTM5JhuZvTsF09fbRHMGtqk7YAgu3vespeTe9l61ziZ6VrMnYu2CamK96wCkmz0VUXyqaiUoTPgzk414LS9yYrd5uh7w18ksJF5SlC2e91rukWvNqAZJjYN3jpkqHNOFchCwFrhbxq2Lrv1kSJPYCx9blRg2hGmYqTbElLTZHv20iNqwZeQbRMgSBPT6vnbCBPnOh1W';
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.equal(deserialized, data);
- });
- test('use ArrayBuffer', function () {
- const data = {prop: 'a test'};
- var serialized = pack(data);
- let ab = new ArrayBuffer(serialized.length);
- let u8 = new Uint8Array(ab);
- u8.set(serialized);
- var deserialized = unpack(ab);
- assert.deepEqual(deserialized, data);
- });
- test('pack/unpack varying data with random access structures', function () {
- let structures = [];
- let packr = new Packr({
- structures, useRecords: true, randomAccessStructure: true, freezeData: true, saveStructures(structures) {
- }, getStructures() {
- console.log('getStructures');
- }
- });
- for (let i = 0; i < 2000; i++) {
- let data = {};
- let props = ['foo', 'bar', 'a', 'b', 'c', 'name', 'age', 'd'];
- function makeString() {
- let str = '';
- while (random() < 0.9) {
- str += random() < 0.8 ? 'hello world' : String.fromCharCode(300);
- }
- return str;
- }
- for (let i = 0; i < random() * 20; i++) {
- data[props[Math.floor(random() * 8)]] =
- random() < 0.3 ? Math.floor(random() * 400) / 2 :
- random() < 0.3 ? makeString() : random() < 0.3 ? true : random() < 0.3 ? sampleData : null;
- }
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- for (let key in deserialized) {
- deserialized[key];
- }
- assert.deepEqual(deserialized, data);
- }
- });
- for (let sampleData of allSampleData) {
- let snippet = JSON.stringify(sampleData).slice(0, 20) + '...';
- test('pack/unpack sample data ' + snippet, function () {
- var data = sampleData;
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('pack/unpack sample data with Uint8Array encoding' + snippet, function () {
- var data = sampleData;
- var serialized = pack(data);
- serialized = new Uint8Array(serialized);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('pack/unpack sample data with random access structures ' + snippet, function () {
- var data = sampleData;
- let structures = [];
- let packr = new Packr({
- structures, useRecords: true, randomAccessStructure: true, freezeData: true, saveStructures(structures) {
- }, getStructures() {
- console.log('getStructures');
- }
- });
- for (let i = 0; i < 20; i++) {
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized, {lazy: true});
- var copied = {};
- for (let key in deserialized) {
- copied[key] = deserialized[key];
- }
- assert.deepEqual(copied, data);
- }
- });
- test('pack/unpack sample data with bundled strings ' + snippet, function () {
- var data = sampleData;
- let packr = new Packr({ /*structures,*/ useRecords: false, bundleStrings: true});
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- }
- test('pack/unpack sample data with useRecords function', function () {
- var data = [
- {id: 1, type: 1, labels: {a: 1, b: 2}},
- {id: 2, type: 1, labels: {b: 1, c: 2}},
- {id: 3, type: 1, labels: {d: 1, e: 2}}
- ];
- var alternatives = [
- {useRecords: false}, // 88 bytes
- {useRecords: true}, // 58 bytes
- {mapsAsObjects: true, useRecords: (v)=>!!v.id}, // 55 bytes
- {mapsAsObjects: true, variableMapSize: true, useRecords: (v)=>!!v.id} // 49 bytes
- ];
- for(let o of alternatives) {
- let packr = new Packr(o);
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- }
- });
- test('mapAsEmptyObject combination', function () {
- const msgpackr = new Packr({ useRecords: false, encodeUndefinedAsNil: true, variableMapSize: true, mapAsEmptyObject: true, setAsEmptyObject: true });
- const map = new Map();
- map.set('a', 1);
- map.set('b', 2);
- const set = new Set();
- set.add('a');
- set.add('b');
- const input = { map, set };
- const packed = msgpackr.pack(input);
- const unpacked = msgpackr.unpack(packed);
- assert.deepEqual(unpacked.map, {});
- assert.deepEqual(unpacked.set, {});
- });
- test('pack/unpack numeric coercible keys', function () {
- var data = { a: 1, 2: 'test', '-3.45': 'test2'};
- let packr = new Packr({variableMapSize: true, coercibleKeyAsNumber: true, useRecords: false});
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('pack/unpack empty data with bundled strings', function () {
- var data = {};
- let packr = new Packr({bundleStrings: true});
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('pack/unpack large amount of chinese characters', function() {
- const MSGPACK_OPTIONS = {bundleStrings: true};
- const item = {
- message: '你好你好你好你好你好你好你好你好你好', // some Chinese characters
- };
- testSize(100);
- testSize(1000);
- testSize(10000);
- function testSize(size) {
- const list = [];
- for (let i = 0; i < size; i++) {
- list.push({...item});
- }
- const packer = new Packr(MSGPACK_OPTIONS);
- const unpacker = new Unpackr(MSGPACK_OPTIONS);
- const encoded = packer.pack(list);
- const decoded = unpacker.unpack(encoded);
- assert.deepEqual(list, decoded);
- }
- });
- test('pack/unpack sequential data', function () {
- var data = {foo: 1, bar: 2};
- let packr = new Packr({sequential: true});
- let unpackr = new Unpackr({sequential: true});
- var serialized = packr.pack(data);
- var deserialized = unpackr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- var serialized = packr.pack(data);
- var deserialized = unpackr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('pack/unpack with bundled strings and sequential', function () {
- const options = {
- bundleStrings: true,
- sequential: true,
- };
- const packer = new Packr(options);
- const unpacker = new Packr(options);
- const data = {data: 42}; // key length >= 4
- unpacker.unpackMultiple(Buffer.concat([
- packer.pack(data),
- packer.pack(data)
- ]));
- });
- if (typeof Buffer != 'undefined')
- test('replace data', function(){
- var data1 = {
- data: [
- { a: 1, name: 'one', type: 'odd', isOdd: true, a: '13 characters' },
- { a: 2, name: 'two', type: 'even', a: '11 characte' },
- { a: 3, name: 'three', type: 'odd', isOdd: true, a: '12 character' },
- { a: 4, name: 'four', type: 'even', a: '9 charact'},
- { a: 5, name: 'five', type: 'odd', isOdd: true, a: '14 characters!' },
- { a: 6, name: 'six', type: 'even', isOdd: null }
- ],
- };
- var data2 = {
- data: [
- { foo: 7, name: 'one', type: 'odd', isOdd: true },
- { foo: 8, name: 'two', type: 'even'},
- { foo: 9, name: 'three', type: 'odd', isOdd: true },
- { foo: 10, name: 'four', type: 'even'},
- { foo: 11, name: 'five', type: 'odd', isOdd: true },
- { foo: 12, name: 'six', type: 'even', isOdd: null }
- ],
- };
- var serialized1 = pack(data1);
- var serialized2 = pack(data2);
- var b = Buffer.alloc(8000);
- serialized1.copy(b);
- var deserialized1 = unpack(b, serialized1.length);
- serialized2.copy(b);
- var deserialized2 = unpack(b, serialized2.length);
- assert.deepEqual(deserialized1, data1);
- assert.deepEqual(deserialized2, data2);
- });
- test('compact 123', function() {
- assert.equal(pack(123).length, 1);
- });
- test('BigInt', function() {
- let packr = new Packr({ useBigIntExtension: true });
- let data = {
- a: 3333333333333333333333333333n,
- b: 1234567890123456789012345678901234567890n,
- c: -3333333333333333333333333333n,
- d: -352523523642364364364264264264264264262642642n,
- e: 0xffffffffffffffffffffffffffn,
- f: -0xffffffffffffffffffffffffffn,
- g: (1234n << 123n) ^ (5678n << 56n) ^ 890n,
- h: (-1234n << 123n) ^ (5678n << 56n) ^ 890n,
- i: (1234n << 1234n) ^ (5678n << 567n) ^ 890n,
- j: (-1234n << 1234n) ^ (5678n << 567n) ^ 890n,
- k: 0xdeadn << 0xbeefn,
- l: -0xdeadn << 0xbeefn,
- m: 11n << 0x11111n ^ 111n,
- n: -11n << 0x11111n ^ 111n,
- o: 12345678901234567890n,
- p: -12345678901234567890n,
- exp: [],
- expexp: [],
- };
- for (let n = 1n; n.toString(16).length * 4 < 1500; n <<= 1n, n |= BigInt(Math.floor(Math.random() * 2))) {
- data.exp.push(n, -n);
- }
- for (let n = 7n; n.toString(16).length * 4 < 150000; n *= n) {
- data.expexp.push(n, -n);
- }
- let serialized = packr.pack(data);
- let deserialized = packr.unpack(serialized);
- assert.deepEqual(data, deserialized);
- });
- test('extended class pack/unpack', function(){
- function Extended() {
- }
- Extended.prototype.getDouble = function() {
- return this.value * 2
- };
- var instance = new Extended();
- instance.value = 4;
- instance.string = 'decode this: ᾜ';
- var data = {
- prop1: 'has multi-byte: ᾜ',
- extendedInstance: instance,
- prop2: 'more string',
- num: 3,
- };
- let packr = new Packr();
- addExtension({
- Class: Extended,
- type: 11,
- unpack: function(buffer) {
- let e = new Extended();
- let data = packr.unpack(buffer);
- e.value = data[0];
- e.string = data[1];
- return e
- },
- pack: function(instance) {
- return packr.pack([instance.value, instance.string])
- }
- });
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(data, deserialized);
- assert.equal(deserialized.extendedInstance.getDouble(), 8);
- });
- test('extended Array class read/write', function(){
- var instance = new ExtendArray();
- instance.push(0);
- instance.push(1);
- instance.push(2);
- var data = {
- prop1: 'has multi-byte: ᾜ',
- extendedInstance: instance,
- prop2: 'more string',
- num: 3,
- };
- new Packr();
- addExtension({
- Class: ExtendArray,
- type: 12,
- read: function(data) {
- Object.setPrototypeOf(data, ExtendArray.prototype);
- return data
- },
- write: function(instance) {
- return [...instance]
- }
- });
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.strictEqual(Object.getPrototypeOf(deserialized.extendedInstance), ExtendArray.prototype);
- assert.deepEqual(data, deserialized);
- });
- test('unregistered extended Array class read/write', function(){
- var instance = new ExtendArray2();
- instance.push(0);
- instance.push(1);
- instance.push(2);
- var data = {
- prop1: 'has multi-byte: ᾜ',
- extendedInstance: instance,
- prop2: 'more string',
- num: 3,
- };
- new Packr();
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.strictEqual(Object.getPrototypeOf(deserialized.extendedInstance), Array.prototype);
- assert.deepEqual(data, deserialized);
- });
- test('unregistered extended Object class read/write', function(){
- var instance = new ExtendObject();
- instance.test1 = "string";
- instance.test2 = 3421321;
- var data = {
- prop1: 'has multi-byte: ᾜ',
- extendedInstance: instance,
- prop2: 'more string',
- num: 3,
- };
- new Packr();
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.strictEqual(Object.getPrototypeOf(deserialized.extendedInstance), Object.prototype);
- assert.deepEqual(data, deserialized);
- });
- test('extended class pack/unpack custom size', function(){
- function TestClass() {
- }
- addExtension({
- Class: TestClass,
- type: 0x01,
- pack() {
- return typeof Buffer != 'undefined' ? Buffer.alloc(256) : new Uint8Array(256)
- },
- unpack(data) {
- return data.length
- }
- });
- let result = unpack(pack(new TestClass()));
- assert.equal(result, 256);
- });
- test('extended class read/write', function(){
- function Extended() {
- }
- Extended.prototype.getDouble = function() {
- return this.value * 2
- };
- var instance = new Extended();
- instance.value = 4;
- instance.string = 'decode this: ᾜ';
- var data = {
- prop1: 'has multi-byte: ᾜ',
- extendedInstance: instance,
- prop2: 'more string',
- num: 3,
- };
- new Packr();
- addExtension({
- Class: Extended,
- type: 12,
- read: function(data) {
- let e = new Extended();
- e.value = data[0];
- e.string = data[1];
- return e
- },
- write: function(instance) {
- return [instance.value, instance.string]
- }
- });
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(data, deserialized);
- assert.equal(deserialized.extendedInstance.getDouble(), 8);
- });
- test('extended class return self', function(){
- function Extended() {
- }
- Extended.prototype.getDouble = function() {
- return this.value * 2
- };
- var instance = new Extended();
- instance.value = 4;
- instance.string = 'decode this: ᾜ';
- var data = {
- prop1: 'has multi-byte: ᾜ',
- extendedInstance: instance,
- prop2: 'more string',
- num: 3,
- };
- new Packr();
- addExtension({
- Class: Extended,
- type: 13,
- read: function(data) {
- Object.setPrototypeOf(data, Extended.prototype);
- return data
- },
- write: function(data) {
- return data
- }
- });
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(data, deserialized);
- assert.strictEqual(Object.getPrototypeOf(deserialized.extendedInstance), Extended.prototype);
- assert.equal(deserialized.extendedInstance.getDouble(), 8);
- });
- test('extended Array class return self', function(){
- var instance = new ExtendArray3();
- instance.push(0);
- instance.push('has multi-byte: ᾜ');
- var data = {
- prop1: 'has multi-byte: ᾜ',
- extendedInstance: instance,
- prop2: 'more string',
- num: 3,
- };
- new Packr();
- addExtension({
- Class: ExtendArray3,
- type: 14,
- read: function(data) {
- Object.setPrototypeOf(data, ExtendArray3.prototype);
- return data
- },
- write: function(data) {
- return data
- }
- });
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(data, deserialized);
- assert.strictEqual(Object.getPrototypeOf(deserialized.extendedInstance), ExtendArray3.prototype);
- assert.equal(deserialized.extendedInstance[0], 0);
- });
- test('extended class pack/unpack proxied', function(){
- function Extended() {
- }
- Extended.prototype.__call__ = function(){
- return this.value * 4
- };
- Extended.prototype.getDouble = function() {
- return this.value * 2
- };
- var instance = function() { instance.__call__();/* callable stuff */ };
- Object.setPrototypeOf(instance,Extended.prototype);
- instance.value = 4;
- var data = instance;
- let packr = new Packr();
- addExtension({
- Class: Extended,
- type: 15,
- unpack: function(buffer) {
- var e = function() { e.__call__(); };
- Object.setPrototypeOf(e,Extended.prototype);
- e.value = packr.unpack(buffer);
- return e
- },
- pack: function(instance) {
- return packr.pack(instance.value)
- }
- });
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.equal(deserialized.getDouble(), 8);
- });
- test.skip('convert Date to string', function(){
- var data = {
- aDate: new Date(),
- };
- new Packr();
- addExtension({
- Class: Date,
- write(date) {
- return date.toString()
- }
- });
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.equal(deserialized.aDate, data.aDate.toString());
- });
- test('standard pack fails on circular reference with shared structures', function () {
- var data = {};
- data.self = data;
- let structures = [];
- let packr = new Packr({
- structures,
- saveStructures(structures) {
- }
- });
- assert.throws(function () {
- packr.pack(data);
- });
- });
- test('proto handling', function() {
- var objectWithProto = JSON.parse('{"__proto__":{"foo":3}}');
- var decoded = unpack(pack(objectWithProto));
- assert(!decoded.foo);
- var objectsWithProto = [objectWithProto, objectWithProto, objectWithProto, objectWithProto, objectWithProto, objectWithProto];
- let packr = new Packr();
- var decoded = packr.unpack(packr.pack(objectsWithProto));
- for (let object of decoded) {
- assert(!decoded.foo);
- }
- });
- test.skip('text decoder', function() {
- let td = new TextDecoder('ISO-8859-15');
- let b = Buffer.alloc(3);
- for (var i = 0; i < 256; i++) {
- b[0] = i;
- b[1] = 0;
- b[2] = 0;
- let s = td.decode(b);
- if (!require('msgpackr-extract').isOneByte(s)) {
- console.log(i.toString(16), s.length);
- }
- }
- });
- test('moreTypes: Error with causes', function() {
- const object = {
- error: new Error('test'),
- errorWithCause: new Error('test-1', { cause: new Error('test-2') }),
- type: new TypeError(),
- range: new RangeError('test', { cause: [1, 2] }),
- };
- const packr = new Packr({
- moreTypes: true,
- });
- const serialized = packr.pack(object);
- const deserialized = packr.unpack(serialized);
- assert.equal(deserialized.error.message, object.error.message);
- assert.equal(deserialized.error.cause, object.error.cause);
- assert.equal(deserialized.errorWithCause.message, object.errorWithCause.message);
- assert.equal(deserialized.errorWithCause.cause.message, object.errorWithCause.cause.message);
- assert.equal(deserialized.errorWithCause.cause.cause, object.errorWithCause.cause.cause);
- assert.equal(deserialized.type.message, object.type.message);
- assert.equal(deserialized.range.message, object.range.message);
- assert.deepEqual(deserialized.range.cause, object.range.cause);
- assert(deserialized.error instanceof Error);
- assert(deserialized.type instanceof TypeError);
- assert(deserialized.range instanceof RangeError);
- });
- test('structured cloning: self reference', function() {
- let object = {
- test: 'string',
- children: [
- { name: 'child' }
- ],
- value: new ArrayBuffer(10)
- };
- let u8 = new Uint8Array(object.value);
- u8[0] = 1;
- u8[1] = 2;
- object.self = object;
- object.children[1] = object;
- object.children[2] = object.children[0];
- object.childrenAgain = object.children;
- let packr = new Packr({
- moreTypes: true,
- structuredClone: true,
- });
- var serialized = packr.pack(object);
- var deserialized = packr.unpack(serialized);
- assert.equal(deserialized.self, deserialized);
- assert.equal(deserialized.children[0].name, 'child');
- assert.equal(deserialized.children[1], deserialized);
- assert.equal(deserialized.children[0], deserialized.children[2]);
- assert.equal(deserialized.children, deserialized.childrenAgain);
- assert.equal(deserialized.value.constructor.name, 'ArrayBuffer');
- u8 = new Uint8Array(deserialized.value);
- assert.equal(u8[0], 1);
- assert.equal(u8[1], 2);
- });
- test('structured cloning: self reference with more types', function() {
- let set = new Set();
- set.add(['hello', 1, 2, { map: new Map([[set, set], ['a', 'b']]) }]);
- let packr = new Packr({
- moreTypes: true,
- structuredClone: true,
- });
- let serialized = packr.pack(set);
- let deserialized = packr.unpack(serialized);
- assert.equal(deserialized.constructor.name, 'Set');
- let map = Array.from(deserialized)[0][3].map;
- assert.equal(map.get(deserialized), deserialized);
- let sizeTestMap = new Map();
- for (let i = 0; i < 50; i++) {
- sizeTestMap.set(i || sizeTestMap, sizeTestMap);
- let deserialized = packr.unpack(packr.pack(sizeTestMap));
- assert.equal(deserialized.size, i + 1);
- assert(deserialized.has(deserialized));
- assert(deserialized.has(i || deserialized));
- }
- let sizeTestSet = new Set();
- for (let i = 0; i < 50; i++) {
- sizeTestSet.add(i || sizeTestSet);
- let deserialized = packr.unpack(packr.pack(sizeTestSet));
- assert.equal(deserialized.size, i + 1);
- assert(deserialized.has(deserialized));
- assert(deserialized.has(i || deserialized));
- }
- });
- test('structured cloning: types', function() {
- let b = typeof Buffer != 'undefined' ? Buffer.alloc(20) : new Uint8Array(20);
- let fa = new Float32Array(b.buffer, 8, 2);
- fa[0] = 2.25;
- fa[1] = 6;
- let object = {
- error: new Error('test'),
- set: new Set(['a', 'b']),
- regexp: /test/gi,
- float32Array: fa,
- uint16Array: new Uint16Array([3, 4]),
- arrayBuffer: new Uint8Array([0xde, 0xad]).buffer,
- dataView: new DataView(new Uint8Array([0xbe, 0xef]).buffer),
- };
- let packr = new Packr({
- moreTypes: true,
- structuredClone: true,
- });
- var serialized = packr.pack(object);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(Array.from(deserialized.set), Array.from(object.set));
- assert.equal(deserialized.error.message, object.error.message);
- assert.equal(deserialized.regexp.test('TEST'), true);
- assert.equal(deserialized.float32Array.constructor.name, 'Float32Array');
- assert.equal(deserialized.float32Array[0], 2.25);
- assert.equal(deserialized.float32Array[1], 6);
- assert.equal(deserialized.uint16Array.constructor.name, 'Uint16Array');
- assert.equal(deserialized.uint16Array[0], 3);
- assert.equal(deserialized.uint16Array[1], 4);
- assert.equal(deserialized.arrayBuffer.constructor.name, 'ArrayBuffer');
- assert.equal(new DataView(deserialized.arrayBuffer).getUint16(), 0xdead);
- assert.equal(deserialized.dataView.constructor.name, 'DataView');
- assert.equal(deserialized.dataView.getUint16(), 0xbeef);
- });
- test('big bundledStrings', function() {
- const MSGPACK_OPTIONS = {bundleStrings: true};
- const packer = new Packr(MSGPACK_OPTIONS);
- const unpacker = new Unpackr(MSGPACK_OPTIONS);
- const payload = {
- output: [
- {
- url: 'https://www.example.com/',
- },
- ],
- };
- for (let i = 0; i < 10000; i++) {
- payload.output.push(payload.output[0]);
- }
- let deserialized = unpacker.unpack(packer.pack(payload));
- assert.equal(deserialized.output[0].url, payload.output[0].url);
- });
- test('structured clone with bundled strings', function() {
- const packer = new Packr({
- structuredClone: true, // both options must be enabled
- bundleStrings: true,
- });
- const v = {};
- let shared = {
- name1: v,
- name2: v,
- };
- let deserialized = packer.unpack(packer.pack(shared));
- assert.equal(deserialized.name1, deserialized.name2);
- shared = {};
- shared.aaaa = shared; // key length >= 4
- deserialized = packer.unpack(packer.pack(shared));
- assert.equal(deserialized.aaaa, deserialized);
- });
- test('object without prototype', function(){
- var data = Object.create(null);
- data.test = 3;
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('object with __proto__', function(){
- const data = { foo: 'bar', __proto__: { isAdmin: true } };
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, { foo: 'bar' });
- });
- test('separate instances', function() {
- const packr = new Packr({
- structures: [['m', 'e'], ['action', 'share']]
- });
- const packr2 = new Packr({
- structures: [['m', 'e'], ['action', 'share']]
- });
- let packed = packr.pack([{m: 1, e: 2}, {action: 3, share: 4}]);
- // also tried directly decoding this without the first Packr instance packed = new Uint8Array([0x92, 0x40, 0x01, 0x02, 0x41, 0x03, 0x04]);
- console.log(packr2.unpack(packed));
- });
- test('many shared structures', function() {
- let data = [];
- for (let i = 0; i < 200; i++) {
- data.push({['a' + i]: i});
- }
- let structures = [];
- let savedStructures;
- let packr = new Packr({
- structures,
- saveStructures(structures) {
- savedStructures = structures;
- }
- });
- var serializedWith32 = packr.pack(data);
- assert.equal(savedStructures.length, 32);
- var deserialized = packr.unpack(serializedWith32);
- assert.deepEqual(deserialized, data);
- structures = structures.slice(0, 32);
- packr = new Packr({
- structures,
- maxSharedStructures: 100,
- saveStructures(structures) {
- savedStructures = structures;
- }
- });
- deserialized = packr.unpack(serializedWith32);
- assert.deepEqual(deserialized, data);
- structures = structures.slice(0, 32);
- packr = new Packr({
- structures,
- maxSharedStructures: 100,
- saveStructures(structures) {
- savedStructures = structures;
- }
- });
- let serialized = packr.pack(data);
- assert.equal(savedStructures.length, 100);
- deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- deserialized = packr.unpack(serializedWith32);
- assert.deepEqual(deserialized, data);
- assert.equal(savedStructures.length, 100);
- deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- assert.equal(packr.structures.sharedLength, 100);
- });
- test('more shared structures', function() {
- const structures = [];
- for (let i = 0; i < 40; i++) {
- structures.push(['a' + i]);
- }
- const structures2 = [...structures];
- const packr = new Packr({
- getStructures() {
- return structures
- },
- saveStructures(structures) {
- },
- maxSharedStructures: 100
- });
- const packr2 = new Packr({
- getStructures() {
- return structures2
- },
- saveStructures(structures) {
- },
- maxSharedStructures: 100
- });
- const inputData = {a35: 35};
- const buffer = packr.pack(inputData);
- const outputData = packr2.decode(buffer);
- assert.deepEqual(inputData, outputData);
- });
- test('big buffer', function() {
- var size = 100000000;
- var data = new Uint8Array(size).fill(1);
- var packed = pack(data);
- var unpacked = unpack(packed);
- assert.equal(unpacked.length, size);
- });
- test('random strings', function(){
- var data = [];
- for (var i = 0; i < 2000; i++) {
- var str = 'test';
- while (Math.random() < 0.7 && str.length < 0x100000) {
- str = str + String.fromCharCode(90/(Math.random() + 0.01)) + str;
- }
- data.push(str);
- }
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('map/date', function(){
- var map = new Map();
- map.set(4, 'four');
- map.set('three', 3);
- var data = {
- map: map,
- date: new Date(1532219539733),
- farFutureDate: new Date(3532219539133),
- fartherFutureDate: new Date('2106-08-05T18:48:20.323Z'),
- ancient: new Date(-3532219539133),
- invalidDate: new Date('invalid')
- };
- let packr = new Packr();
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.equal(deserialized.map.get(4), 'four');
- assert.equal(deserialized.map.get('three'), 3);
- assert.equal(deserialized.date.getTime(), 1532219539733);
- assert.equal(deserialized.farFutureDate.getTime(), 3532219539133);
- assert.equal(deserialized.fartherFutureDate.toISOString(), '2106-08-05T18:48:20.323Z');
- assert.equal(deserialized.ancient.getTime(), -3532219539133);
- assert.equal(deserialized.invalidDate.toString(), 'Invalid Date');
- });
- test('map/date with options', function(){
- var map = new Map();
- map.set(4, 'four');
- map.set('three', 3);
- var data = {
- map: map,
- date: new Date(1532219539011),
- invalidDate: new Date('invalid')
- };
- let packr = new Packr({
- mapsAsObjects: true,
- useTimestamp32: true,
- onInvalidDate: () => 'Custom invalid date'
- });
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.equal(deserialized.map[4], 'four');
- assert.equal(deserialized.map.three, 3);
- assert.equal(deserialized.date.getTime(), 1532219539000);
- assert.equal(deserialized.invalidDate, 'Custom invalid date');
- });
- test('key caching', function() {
- var data = {
- foo: 2,
- bar: 'test',
- four: 4,
- seven: 7,
- foz: 3,
- };
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- // do multiple times to test caching
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('strings', function() {
- var data = [''];
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- // do multiple times
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- data = 'decode this: ᾜ';
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- data = 'decode this that is longer but without any non-latin characters';
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('decimal float32', function() {
- var data = {
- a: 2.526,
- b: 0.0035235,
- c: 0.00000000000352501,
- d: 3252.77,
- };
- let packr = new Packr({
- useFloat32: DECIMAL_FIT
- });
- var serialized = packr.pack(data);
- assert.equal(serialized.length, 32);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('int64/uint64 should be bigints by default', function() {
- var data = {
- a: 325283295382932843n
- };
- let packr = new Packr();
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized.a, 325283295382932843n);
- });
- test('bigint to float', function() {
- var data = {
- a: 325283295382932843n
- };
- let packr = new Packr({
- int64AsType: 'number'
- });
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized.a, 325283295382932843);
- });
- test('int64AsNumber compatibility', function() {
- // https://github.com/kriszyp/msgpackr/pull/85
- var data = {
- a: 325283295382932843n
- };
- let packr = new Packr({
- int64AsNumber: true
- });
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized.a, 325283295382932843);
- });
- test('bigint to auto (float or bigint)', function() {
- var data = {
- a: -9007199254740993n,
- b: -9007199254740992n,
- c: 0n,
- d: 9007199254740992n,
- e: 9007199254740993n,
- };
- let packr = new Packr({
- int64AsType: 'auto'
- });
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized.a, -9007199254740993n);
- assert.deepEqual(deserialized.b, -9007199254740992);
- assert.deepEqual(deserialized.c, 0);
- assert.deepEqual(deserialized.d, 9007199254740992);
- assert.deepEqual(deserialized.e, 9007199254740993n);
- });
- test('bigint to string', function() {
- var data = {
- a: 325283295382932843n,
- };
- let packr = new Packr({
- int64AsType: 'string'
- });
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized.a, '325283295382932843');
- });
- test('fixint should be one byte', function(){
- let encoded = pack(123);
- assert.equal(encoded.length, 1);
- });
- test('numbers', function(){
- var data = {
- bigEncodable: 48978578104322,
- dateEpoch: 1530886513200,
- realBig: 3432235352353255323,
- decimal: 32.55234,
- negative: -34.11,
- exponential: 0.234e123,
- tiny: 3.233e-120,
- zero: 0,
- //negativeZero: -0,
- Infinity: Infinity
- };
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('bigint', function(){
- var data = {
- bigintSmall: 352n,
- bigintSmallNegative: -333335252n,
- bigintBig: 2n**64n - 1n, // biggest possible
- bigintBigNegative: -(2n**63n), // largest negative
- mixedWithNormal: 44,
- };
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- var tooBigInt = {
- tooBig: 2n**66n
- };
- assert.throws(function(){ serialized = pack(tooBigInt); });
- let packr = new Packr({
- largeBigIntToFloat: true
- });
- serialized = packr.pack(tooBigInt);
- deserialized = unpack(serialized);
- assert.isTrue(deserialized.tooBig > 2n**65n);
- packr = new Packr({
- largeBigIntToString: true
- });
- serialized = packr.pack(tooBigInt);
- deserialized = unpack(serialized);
- assert.equal(deserialized.tooBig, (2n**66n).toString());
- });
- test('roundFloat32', function() {
- assert.equal(roundFloat32(0.00333000003), 0.00333);
- assert.equal(roundFloat32(43.29999999993), 43.3);
- });
- test('buffers', function(){
- var data = {
- buffer1: new Uint8Array([2,3,4]),
- buffer2: new Uint8Array(pack(sampleData))
- };
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('notepack test', function() {
- const data = {
- foo: 1,
- bar: [1, 2, 3, 4, 'abc', 'def'],
- foobar: {
- foo: true,
- bar: -2147483649,
- foobar: {
- foo: new Uint8Array([1, 2, 3, 4, 5]),
- bar: 1.5,
- foobar: [true, false, 'abcdefghijkmonpqrstuvwxyz']
- }
- }
- };
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- var deserialized = unpack(serialized);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('arrays in map keys', function() {
- const msgpackr = new Packr({ mapsAsObjects: true, allowArraysInMapKeys: true });
- const map = new Map();
- map.set([1, 2, 3], 1);
- map.set([1, 2, ['foo', 3.14]], 2);
- const packed = msgpackr.pack(map);
- const unpacked = msgpackr.unpack(packed);
- assert.deepEqual(unpacked, { '1,2,3': 1, '1,2,foo,3.14': 2 });
- });
- test('utf16 causing expansion', function() {
- this.timeout(10000);
- let data = {fixstr: 'ᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝ', str8:'ᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝ'};
- var serialized = pack(data);
- var deserialized = unpack(serialized);
- assert.deepEqual(deserialized, data);
- });
- test('unpackMultiple', () => {
- let values = unpackMultiple(new Uint8Array([1, 2, 3, 4]));
- assert.deepEqual(values, [1, 2, 3, 4]);
- values = [];
- unpackMultiple(new Uint8Array([1, 2, 3, 4]), value => values.push(value));
- assert.deepEqual(values, [1, 2, 3, 4]);
- });
- test('unpackMultiple with positions', () => {
- let values = unpackMultiple(new Uint8Array([1, 2, 3, 4]));
- assert.deepEqual(values, [1, 2, 3, 4]);
- values = [];
- unpackMultiple(new Uint8Array([1, 2, 3, 4]), (value,start,end) => values.push([value,start,end]));
- assert.deepEqual(values, [[1,0,1], [2,1,2], [3,2,3], [4,3,4]]);
- });
- test('pack toJSON returning this', () => {
- class Serializable {
- someData = [1, 2, 3, 4]
- toJSON() {
- return this
- }
- }
- const serialized = pack(new Serializable);
- const deserialized = unpack(serialized);
- assert.deepStrictEqual(deserialized, { someData: [1, 2, 3, 4] });
- });
- test('skip values', function () {
- var data = {
- data: [
- { a: 1, name: 'one', type: 'odd', isOdd: true },
- { a: 2, name: 'two', type: 'even', isOdd: undefined },
- { a: 3, name: 'three', type: 'odd', isOdd: true },
- { a: 4, name: 'four', type: 'even', isOdd: null},
- { a: 5, name: 'five', type: 'odd', isOdd: true },
- { a: 6, name: 'six', type: 'even', isOdd: null }
- ],
- description: 'some names',
- types: ['odd', 'even'],
- convertEnumToNum: [
- { prop: 'test' },
- { prop: 'test' },
- { prop: 'test' },
- { prop: 1 },
- { prop: 2 },
- { prop: [undefined, null] },
- { prop: null }
- ]
- };
- var expected = {
- data: [
- { a: 1, name: 'one', type: 'odd', isOdd: true },
- { a: 2, name: 'two', type: 'even' },
- { a: 3, name: 'three', type: 'odd', isOdd: true },
- { a: 4, name: 'four', type: 'even', },
- { a: 5, name: 'five', type: 'odd', isOdd: true },
- { a: 6, name: 'six', type: 'even' }
- ],
- description: 'some names',
- types: ['odd', 'even'],
- convertEnumToNum: [
- { prop: 'test' },
- { prop: 'test' },
- { prop: 'test' },
- { prop: 1 },
- { prop: 2 },
- { prop: [undefined, null] },
- {}
- ]
- };
- let packr = new Packr({ useRecords: false, skipValues: [undefined, null] });
- var serialized = packr.pack(data);
- var deserialized = packr.unpack(serialized);
- assert.deepEqual(deserialized, expected);
- });
- });
- suite('msgpackr performance tests', function(){
- test('performance JSON.parse', function() {
- var data = sampleData;
- this.timeout(10000);
- var serialized = JSON.stringify(data);
- console.log('JSON size', serialized.length);
- for (var i = 0; i < ITERATIONS; i++) {
- JSON.parse(serialized);
- }
- });
- test('performance JSON.stringify', function() {
- var data = sampleData;
- this.timeout(10000);
- for (var i = 0; i < ITERATIONS; i++) {
- JSON.stringify(data);
- }
- });
- test('performance unpack', function() {
- var data = sampleData;
- this.timeout(10000);
- let structures = [];
- var serialized = pack(data);
- console.log('MessagePack size', serialized.length);
- let packr = new Packr({ structures, bundleStrings: false });
- var serialized = packr.pack(data);
- console.log('msgpackr w/ record ext size', serialized.length);
- for (var i = 0; i < ITERATIONS; i++) {
- packr.unpack(serialized);
- }
- });
- test('performance pack', function() {
- var data = sampleData;
- this.timeout(10000);
- let structures = [];
- let packr = new Packr({ structures, bundleStrings: false });
- let buffer = typeof Buffer != 'undefined' ? Buffer.alloc(0x10000) : new Uint8Array(0x10000);
- for (var i = 0; i < ITERATIONS; i++) {
- //serialized = pack(data, { shared: sharedStructure })
- packr.useBuffer(buffer);
- packr.pack(data);
- //var serializedGzip = deflateSync(serialized)
- }
- //console.log('serialized', serialized.length, global.propertyComparisons)
- });
- });
- })(chai, null, module, fs);
- //# sourceMappingURL=test.js.map
|