reactivity.cjs.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var shared = require('@vue/shared');
  4. const targetMap = new WeakMap();
  5. const effectStack = [];
  6. let activeEffect;
  7. const ITERATE_KEY = Symbol('iterate' );
  8. const MAP_KEY_ITERATE_KEY = Symbol('Map key iterate' );
  9. function isEffect(fn) {
  10. return fn && fn._isEffect === true;
  11. }
  12. function effect(fn, options = shared.EMPTY_OBJ) {
  13. if (isEffect(fn)) {
  14. fn = fn.raw;
  15. }
  16. const effect = createReactiveEffect(fn, options);
  17. if (!options.lazy) {
  18. effect();
  19. }
  20. return effect;
  21. }
  22. function stop(effect) {
  23. if (effect.active) {
  24. cleanup(effect);
  25. if (effect.options.onStop) {
  26. effect.options.onStop();
  27. }
  28. effect.active = false;
  29. }
  30. }
  31. let uid = 0;
  32. function createReactiveEffect(fn, options) {
  33. const effect = function reactiveEffect() {
  34. if (!effect.active) {
  35. return options.scheduler ? undefined : fn();
  36. }
  37. if (!effectStack.includes(effect)) {
  38. cleanup(effect);
  39. try {
  40. enableTracking();
  41. effectStack.push(effect);
  42. activeEffect = effect;
  43. return fn();
  44. }
  45. finally {
  46. effectStack.pop();
  47. resetTracking();
  48. activeEffect = effectStack[effectStack.length - 1];
  49. }
  50. }
  51. };
  52. effect.id = uid++;
  53. effect.allowRecurse = !!options.allowRecurse;
  54. effect._isEffect = true;
  55. effect.active = true;
  56. effect.raw = fn;
  57. effect.deps = [];
  58. effect.options = options;
  59. return effect;
  60. }
  61. function cleanup(effect) {
  62. const { deps } = effect;
  63. if (deps.length) {
  64. for (let i = 0; i < deps.length; i++) {
  65. deps[i].delete(effect);
  66. }
  67. deps.length = 0;
  68. }
  69. }
  70. let shouldTrack = true;
  71. const trackStack = [];
  72. function pauseTracking() {
  73. trackStack.push(shouldTrack);
  74. shouldTrack = false;
  75. }
  76. function enableTracking() {
  77. trackStack.push(shouldTrack);
  78. shouldTrack = true;
  79. }
  80. function resetTracking() {
  81. const last = trackStack.pop();
  82. shouldTrack = last === undefined ? true : last;
  83. }
  84. function track(target, type, key) {
  85. if (!shouldTrack || activeEffect === undefined) {
  86. return;
  87. }
  88. let depsMap = targetMap.get(target);
  89. if (!depsMap) {
  90. targetMap.set(target, (depsMap = new Map()));
  91. }
  92. let dep = depsMap.get(key);
  93. if (!dep) {
  94. depsMap.set(key, (dep = new Set()));
  95. }
  96. if (!dep.has(activeEffect)) {
  97. dep.add(activeEffect);
  98. activeEffect.deps.push(dep);
  99. if (activeEffect.options.onTrack) {
  100. activeEffect.options.onTrack({
  101. effect: activeEffect,
  102. target,
  103. type,
  104. key
  105. });
  106. }
  107. }
  108. }
  109. function trigger(target, type, key, newValue, oldValue, oldTarget) {
  110. const depsMap = targetMap.get(target);
  111. if (!depsMap) {
  112. // never been tracked
  113. return;
  114. }
  115. const effects = new Set();
  116. const add = (effectsToAdd) => {
  117. if (effectsToAdd) {
  118. effectsToAdd.forEach(effect => {
  119. if (effect !== activeEffect || effect.allowRecurse) {
  120. effects.add(effect);
  121. }
  122. });
  123. }
  124. };
  125. if (type === "clear" /* CLEAR */) {
  126. // collection being cleared
  127. // trigger all effects for target
  128. depsMap.forEach(add);
  129. }
  130. else if (key === 'length' && shared.isArray(target)) {
  131. depsMap.forEach((dep, key) => {
  132. if (key === 'length' || key >= newValue) {
  133. add(dep);
  134. }
  135. });
  136. }
  137. else {
  138. // schedule runs for SET | ADD | DELETE
  139. if (key !== void 0) {
  140. add(depsMap.get(key));
  141. }
  142. // also run for iteration key on ADD | DELETE | Map.SET
  143. switch (type) {
  144. case "add" /* ADD */:
  145. if (!shared.isArray(target)) {
  146. add(depsMap.get(ITERATE_KEY));
  147. if (shared.isMap(target)) {
  148. add(depsMap.get(MAP_KEY_ITERATE_KEY));
  149. }
  150. }
  151. else if (shared.isIntegerKey(key)) {
  152. // new index added to array -> length changes
  153. add(depsMap.get('length'));
  154. }
  155. break;
  156. case "delete" /* DELETE */:
  157. if (!shared.isArray(target)) {
  158. add(depsMap.get(ITERATE_KEY));
  159. if (shared.isMap(target)) {
  160. add(depsMap.get(MAP_KEY_ITERATE_KEY));
  161. }
  162. }
  163. break;
  164. case "set" /* SET */:
  165. if (shared.isMap(target)) {
  166. add(depsMap.get(ITERATE_KEY));
  167. }
  168. break;
  169. }
  170. }
  171. const run = (effect) => {
  172. if (effect.options.onTrigger) {
  173. effect.options.onTrigger({
  174. effect,
  175. target,
  176. key,
  177. type,
  178. newValue,
  179. oldValue,
  180. oldTarget
  181. });
  182. }
  183. if (effect.options.scheduler) {
  184. effect.options.scheduler(effect);
  185. }
  186. else {
  187. effect();
  188. }
  189. };
  190. effects.forEach(run);
  191. }
  192. const isNonTrackableKeys = /*#__PURE__*/ shared.makeMap(`__proto__,__v_isRef,__isVue`);
  193. const builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol)
  194. .map(key => Symbol[key])
  195. .filter(shared.isSymbol));
  196. const get = /*#__PURE__*/ createGetter();
  197. const shallowGet = /*#__PURE__*/ createGetter(false, true);
  198. const readonlyGet = /*#__PURE__*/ createGetter(true);
  199. const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true);
  200. const arrayInstrumentations = {};
  201. ['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
  202. const method = Array.prototype[key];
  203. arrayInstrumentations[key] = function (...args) {
  204. const arr = toRaw(this);
  205. for (let i = 0, l = this.length; i < l; i++) {
  206. track(arr, "get" /* GET */, i + '');
  207. }
  208. // we run the method using the original args first (which may be reactive)
  209. const res = method.apply(arr, args);
  210. if (res === -1 || res === false) {
  211. // if that didn't work, run it again using raw values.
  212. return method.apply(arr, args.map(toRaw));
  213. }
  214. else {
  215. return res;
  216. }
  217. };
  218. });
  219. ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {
  220. const method = Array.prototype[key];
  221. arrayInstrumentations[key] = function (...args) {
  222. pauseTracking();
  223. const res = method.apply(this, args);
  224. resetTracking();
  225. return res;
  226. };
  227. });
  228. function createGetter(isReadonly = false, shallow = false) {
  229. return function get(target, key, receiver) {
  230. if (key === "__v_isReactive" /* IS_REACTIVE */) {
  231. return !isReadonly;
  232. }
  233. else if (key === "__v_isReadonly" /* IS_READONLY */) {
  234. return isReadonly;
  235. }
  236. else if (key === "__v_raw" /* RAW */ &&
  237. receiver === (isReadonly ? readonlyMap : reactiveMap).get(target)) {
  238. return target;
  239. }
  240. const targetIsArray = shared.isArray(target);
  241. if (!isReadonly && targetIsArray && shared.hasOwn(arrayInstrumentations, key)) {
  242. return Reflect.get(arrayInstrumentations, key, receiver);
  243. }
  244. const res = Reflect.get(target, key, receiver);
  245. if (shared.isSymbol(key)
  246. ? builtInSymbols.has(key)
  247. : isNonTrackableKeys(key)) {
  248. return res;
  249. }
  250. if (!isReadonly) {
  251. track(target, "get" /* GET */, key);
  252. }
  253. if (shallow) {
  254. return res;
  255. }
  256. if (isRef(res)) {
  257. // ref unwrapping - does not apply for Array + integer key.
  258. const shouldUnwrap = !targetIsArray || !shared.isIntegerKey(key);
  259. return shouldUnwrap ? res.value : res;
  260. }
  261. if (shared.isObject(res)) {
  262. // Convert returned value into a proxy as well. we do the isObject check
  263. // here to avoid invalid value warning. Also need to lazy access readonly
  264. // and reactive here to avoid circular dependency.
  265. return isReadonly ? readonly(res) : reactive(res);
  266. }
  267. return res;
  268. };
  269. }
  270. const set = /*#__PURE__*/ createSetter();
  271. const shallowSet = /*#__PURE__*/ createSetter(true);
  272. function createSetter(shallow = false) {
  273. return function set(target, key, value, receiver) {
  274. const oldValue = target[key];
  275. if (!shallow) {
  276. value = toRaw(value);
  277. if (!shared.isArray(target) && isRef(oldValue) && !isRef(value)) {
  278. oldValue.value = value;
  279. return true;
  280. }
  281. }
  282. const hadKey = shared.isArray(target) && shared.isIntegerKey(key)
  283. ? Number(key) < target.length
  284. : shared.hasOwn(target, key);
  285. const result = Reflect.set(target, key, value, receiver);
  286. // don't trigger if target is something up in the prototype chain of original
  287. if (target === toRaw(receiver)) {
  288. if (!hadKey) {
  289. trigger(target, "add" /* ADD */, key, value);
  290. }
  291. else if (shared.hasChanged(value, oldValue)) {
  292. trigger(target, "set" /* SET */, key, value, oldValue);
  293. }
  294. }
  295. return result;
  296. };
  297. }
  298. function deleteProperty(target, key) {
  299. const hadKey = shared.hasOwn(target, key);
  300. const oldValue = target[key];
  301. const result = Reflect.deleteProperty(target, key);
  302. if (result && hadKey) {
  303. trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
  304. }
  305. return result;
  306. }
  307. function has(target, key) {
  308. const result = Reflect.has(target, key);
  309. if (!shared.isSymbol(key) || !builtInSymbols.has(key)) {
  310. track(target, "has" /* HAS */, key);
  311. }
  312. return result;
  313. }
  314. function ownKeys(target) {
  315. track(target, "iterate" /* ITERATE */, shared.isArray(target) ? 'length' : ITERATE_KEY);
  316. return Reflect.ownKeys(target);
  317. }
  318. const mutableHandlers = {
  319. get,
  320. set,
  321. deleteProperty,
  322. has,
  323. ownKeys
  324. };
  325. const readonlyHandlers = {
  326. get: readonlyGet,
  327. set(target, key) {
  328. {
  329. console.warn(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
  330. }
  331. return true;
  332. },
  333. deleteProperty(target, key) {
  334. {
  335. console.warn(`Delete operation on key "${String(key)}" failed: target is readonly.`, target);
  336. }
  337. return true;
  338. }
  339. };
  340. const shallowReactiveHandlers = shared.extend({}, mutableHandlers, {
  341. get: shallowGet,
  342. set: shallowSet
  343. });
  344. // Props handlers are special in the sense that it should not unwrap top-level
  345. // refs (in order to allow refs to be explicitly passed down), but should
  346. // retain the reactivity of the normal readonly object.
  347. const shallowReadonlyHandlers = shared.extend({}, readonlyHandlers, {
  348. get: shallowReadonlyGet
  349. });
  350. const toReactive = (value) => shared.isObject(value) ? reactive(value) : value;
  351. const toReadonly = (value) => shared.isObject(value) ? readonly(value) : value;
  352. const toShallow = (value) => value;
  353. const getProto = (v) => Reflect.getPrototypeOf(v);
  354. function get$1(target, key, isReadonly = false, isShallow = false) {
  355. // #1772: readonly(reactive(Map)) should return readonly + reactive version
  356. // of the value
  357. target = target["__v_raw" /* RAW */];
  358. const rawTarget = toRaw(target);
  359. const rawKey = toRaw(key);
  360. if (key !== rawKey) {
  361. !isReadonly && track(rawTarget, "get" /* GET */, key);
  362. }
  363. !isReadonly && track(rawTarget, "get" /* GET */, rawKey);
  364. const { has } = getProto(rawTarget);
  365. const wrap = isReadonly ? toReadonly : isShallow ? toShallow : toReactive;
  366. if (has.call(rawTarget, key)) {
  367. return wrap(target.get(key));
  368. }
  369. else if (has.call(rawTarget, rawKey)) {
  370. return wrap(target.get(rawKey));
  371. }
  372. }
  373. function has$1(key, isReadonly = false) {
  374. const target = this["__v_raw" /* RAW */];
  375. const rawTarget = toRaw(target);
  376. const rawKey = toRaw(key);
  377. if (key !== rawKey) {
  378. !isReadonly && track(rawTarget, "has" /* HAS */, key);
  379. }
  380. !isReadonly && track(rawTarget, "has" /* HAS */, rawKey);
  381. return key === rawKey
  382. ? target.has(key)
  383. : target.has(key) || target.has(rawKey);
  384. }
  385. function size(target, isReadonly = false) {
  386. target = target["__v_raw" /* RAW */];
  387. !isReadonly && track(toRaw(target), "iterate" /* ITERATE */, ITERATE_KEY);
  388. return Reflect.get(target, 'size', target);
  389. }
  390. function add(value) {
  391. value = toRaw(value);
  392. const target = toRaw(this);
  393. const proto = getProto(target);
  394. const hadKey = proto.has.call(target, value);
  395. target.add(value);
  396. if (!hadKey) {
  397. trigger(target, "add" /* ADD */, value, value);
  398. }
  399. return this;
  400. }
  401. function set$1(key, value) {
  402. value = toRaw(value);
  403. const target = toRaw(this);
  404. const { has, get } = getProto(target);
  405. let hadKey = has.call(target, key);
  406. if (!hadKey) {
  407. key = toRaw(key);
  408. hadKey = has.call(target, key);
  409. }
  410. else {
  411. checkIdentityKeys(target, has, key);
  412. }
  413. const oldValue = get.call(target, key);
  414. target.set(key, value);
  415. if (!hadKey) {
  416. trigger(target, "add" /* ADD */, key, value);
  417. }
  418. else if (shared.hasChanged(value, oldValue)) {
  419. trigger(target, "set" /* SET */, key, value, oldValue);
  420. }
  421. return this;
  422. }
  423. function deleteEntry(key) {
  424. const target = toRaw(this);
  425. const { has, get } = getProto(target);
  426. let hadKey = has.call(target, key);
  427. if (!hadKey) {
  428. key = toRaw(key);
  429. hadKey = has.call(target, key);
  430. }
  431. else {
  432. checkIdentityKeys(target, has, key);
  433. }
  434. const oldValue = get ? get.call(target, key) : undefined;
  435. // forward the operation before queueing reactions
  436. const result = target.delete(key);
  437. if (hadKey) {
  438. trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
  439. }
  440. return result;
  441. }
  442. function clear() {
  443. const target = toRaw(this);
  444. const hadItems = target.size !== 0;
  445. const oldTarget = shared.isMap(target)
  446. ? new Map(target)
  447. : new Set(target)
  448. ;
  449. // forward the operation before queueing reactions
  450. const result = target.clear();
  451. if (hadItems) {
  452. trigger(target, "clear" /* CLEAR */, undefined, undefined, oldTarget);
  453. }
  454. return result;
  455. }
  456. function createForEach(isReadonly, isShallow) {
  457. return function forEach(callback, thisArg) {
  458. const observed = this;
  459. const target = observed["__v_raw" /* RAW */];
  460. const rawTarget = toRaw(target);
  461. const wrap = isReadonly ? toReadonly : isShallow ? toShallow : toReactive;
  462. !isReadonly && track(rawTarget, "iterate" /* ITERATE */, ITERATE_KEY);
  463. return target.forEach((value, key) => {
  464. // important: make sure the callback is
  465. // 1. invoked with the reactive map as `this` and 3rd arg
  466. // 2. the value received should be a corresponding reactive/readonly.
  467. return callback.call(thisArg, wrap(value), wrap(key), observed);
  468. });
  469. };
  470. }
  471. function createIterableMethod(method, isReadonly, isShallow) {
  472. return function (...args) {
  473. const target = this["__v_raw" /* RAW */];
  474. const rawTarget = toRaw(target);
  475. const targetIsMap = shared.isMap(rawTarget);
  476. const isPair = method === 'entries' || (method === Symbol.iterator && targetIsMap);
  477. const isKeyOnly = method === 'keys' && targetIsMap;
  478. const innerIterator = target[method](...args);
  479. const wrap = isReadonly ? toReadonly : isShallow ? toShallow : toReactive;
  480. !isReadonly &&
  481. track(rawTarget, "iterate" /* ITERATE */, isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY);
  482. // return a wrapped iterator which returns observed versions of the
  483. // values emitted from the real iterator
  484. return {
  485. // iterator protocol
  486. next() {
  487. const { value, done } = innerIterator.next();
  488. return done
  489. ? { value, done }
  490. : {
  491. value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
  492. done
  493. };
  494. },
  495. // iterable protocol
  496. [Symbol.iterator]() {
  497. return this;
  498. }
  499. };
  500. };
  501. }
  502. function createReadonlyMethod(type) {
  503. return function (...args) {
  504. {
  505. const key = args[0] ? `on key "${args[0]}" ` : ``;
  506. console.warn(`${shared.capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this));
  507. }
  508. return type === "delete" /* DELETE */ ? false : this;
  509. };
  510. }
  511. const mutableInstrumentations = {
  512. get(key) {
  513. return get$1(this, key);
  514. },
  515. get size() {
  516. return size(this);
  517. },
  518. has: has$1,
  519. add,
  520. set: set$1,
  521. delete: deleteEntry,
  522. clear,
  523. forEach: createForEach(false, false)
  524. };
  525. const shallowInstrumentations = {
  526. get(key) {
  527. return get$1(this, key, false, true);
  528. },
  529. get size() {
  530. return size(this);
  531. },
  532. has: has$1,
  533. add,
  534. set: set$1,
  535. delete: deleteEntry,
  536. clear,
  537. forEach: createForEach(false, true)
  538. };
  539. const readonlyInstrumentations = {
  540. get(key) {
  541. return get$1(this, key, true);
  542. },
  543. get size() {
  544. return size(this, true);
  545. },
  546. has(key) {
  547. return has$1.call(this, key, true);
  548. },
  549. add: createReadonlyMethod("add" /* ADD */),
  550. set: createReadonlyMethod("set" /* SET */),
  551. delete: createReadonlyMethod("delete" /* DELETE */),
  552. clear: createReadonlyMethod("clear" /* CLEAR */),
  553. forEach: createForEach(true, false)
  554. };
  555. const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator];
  556. iteratorMethods.forEach(method => {
  557. mutableInstrumentations[method] = createIterableMethod(method, false, false);
  558. readonlyInstrumentations[method] = createIterableMethod(method, true, false);
  559. shallowInstrumentations[method] = createIterableMethod(method, false, true);
  560. });
  561. function createInstrumentationGetter(isReadonly, shallow) {
  562. const instrumentations = shallow
  563. ? shallowInstrumentations
  564. : isReadonly
  565. ? readonlyInstrumentations
  566. : mutableInstrumentations;
  567. return (target, key, receiver) => {
  568. if (key === "__v_isReactive" /* IS_REACTIVE */) {
  569. return !isReadonly;
  570. }
  571. else if (key === "__v_isReadonly" /* IS_READONLY */) {
  572. return isReadonly;
  573. }
  574. else if (key === "__v_raw" /* RAW */) {
  575. return target;
  576. }
  577. return Reflect.get(shared.hasOwn(instrumentations, key) && key in target
  578. ? instrumentations
  579. : target, key, receiver);
  580. };
  581. }
  582. const mutableCollectionHandlers = {
  583. get: createInstrumentationGetter(false, false)
  584. };
  585. const shallowCollectionHandlers = {
  586. get: createInstrumentationGetter(false, true)
  587. };
  588. const readonlyCollectionHandlers = {
  589. get: createInstrumentationGetter(true, false)
  590. };
  591. function checkIdentityKeys(target, has, key) {
  592. const rawKey = toRaw(key);
  593. if (rawKey !== key && has.call(target, rawKey)) {
  594. const type = shared.toRawType(target);
  595. console.warn(`Reactive ${type} contains both the raw and reactive ` +
  596. `versions of the same object${type === `Map` ? ` as keys` : ``}, ` +
  597. `which can lead to inconsistencies. ` +
  598. `Avoid differentiating between the raw and reactive versions ` +
  599. `of an object and only use the reactive version if possible.`);
  600. }
  601. }
  602. const reactiveMap = new WeakMap();
  603. const readonlyMap = new WeakMap();
  604. function targetTypeMap(rawType) {
  605. switch (rawType) {
  606. case 'Object':
  607. case 'Array':
  608. return 1 /* COMMON */;
  609. case 'Map':
  610. case 'Set':
  611. case 'WeakMap':
  612. case 'WeakSet':
  613. return 2 /* COLLECTION */;
  614. default:
  615. return 0 /* INVALID */;
  616. }
  617. }
  618. function getTargetType(value) {
  619. return value["__v_skip" /* SKIP */] || !Object.isExtensible(value)
  620. ? 0 /* INVALID */
  621. : targetTypeMap(shared.toRawType(value));
  622. }
  623. function reactive(target) {
  624. // if trying to observe a readonly proxy, return the readonly version.
  625. if (target && target["__v_isReadonly" /* IS_READONLY */]) {
  626. return target;
  627. }
  628. return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers);
  629. }
  630. /**
  631. * Return a shallowly-reactive copy of the original object, where only the root
  632. * level properties are reactive. It also does not auto-unwrap refs (even at the
  633. * root level).
  634. */
  635. function shallowReactive(target) {
  636. return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers);
  637. }
  638. /**
  639. * Creates a readonly copy of the original object. Note the returned copy is not
  640. * made reactive, but `readonly` can be called on an already reactive object.
  641. */
  642. function readonly(target) {
  643. return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers);
  644. }
  645. /**
  646. * Returns a reactive-copy of the original object, where only the root level
  647. * properties are readonly, and does NOT unwrap refs nor recursively convert
  648. * returned properties.
  649. * This is used for creating the props proxy object for stateful components.
  650. */
  651. function shallowReadonly(target) {
  652. return createReactiveObject(target, true, shallowReadonlyHandlers, readonlyCollectionHandlers);
  653. }
  654. function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers) {
  655. if (!shared.isObject(target)) {
  656. {
  657. console.warn(`value cannot be made reactive: ${String(target)}`);
  658. }
  659. return target;
  660. }
  661. // target is already a Proxy, return it.
  662. // exception: calling readonly() on a reactive object
  663. if (target["__v_raw" /* RAW */] &&
  664. !(isReadonly && target["__v_isReactive" /* IS_REACTIVE */])) {
  665. return target;
  666. }
  667. // target already has corresponding Proxy
  668. const proxyMap = isReadonly ? readonlyMap : reactiveMap;
  669. const existingProxy = proxyMap.get(target);
  670. if (existingProxy) {
  671. return existingProxy;
  672. }
  673. // only a whitelist of value types can be observed.
  674. const targetType = getTargetType(target);
  675. if (targetType === 0 /* INVALID */) {
  676. return target;
  677. }
  678. const proxy = new Proxy(target, targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers);
  679. proxyMap.set(target, proxy);
  680. return proxy;
  681. }
  682. function isReactive(value) {
  683. if (isReadonly(value)) {
  684. return isReactive(value["__v_raw" /* RAW */]);
  685. }
  686. return !!(value && value["__v_isReactive" /* IS_REACTIVE */]);
  687. }
  688. function isReadonly(value) {
  689. return !!(value && value["__v_isReadonly" /* IS_READONLY */]);
  690. }
  691. function isProxy(value) {
  692. return isReactive(value) || isReadonly(value);
  693. }
  694. function toRaw(observed) {
  695. return ((observed && toRaw(observed["__v_raw" /* RAW */])) || observed);
  696. }
  697. function markRaw(value) {
  698. shared.def(value, "__v_skip" /* SKIP */, true);
  699. return value;
  700. }
  701. const convert = (val) => shared.isObject(val) ? reactive(val) : val;
  702. function isRef(r) {
  703. return Boolean(r && r.__v_isRef === true);
  704. }
  705. function ref(value) {
  706. return createRef(value);
  707. }
  708. function shallowRef(value) {
  709. return createRef(value, true);
  710. }
  711. class RefImpl {
  712. constructor(_rawValue, _shallow = false) {
  713. this._rawValue = _rawValue;
  714. this._shallow = _shallow;
  715. this.__v_isRef = true;
  716. this._value = _shallow ? _rawValue : convert(_rawValue);
  717. }
  718. get value() {
  719. track(toRaw(this), "get" /* GET */, 'value');
  720. return this._value;
  721. }
  722. set value(newVal) {
  723. if (shared.hasChanged(toRaw(newVal), this._rawValue)) {
  724. this._rawValue = newVal;
  725. this._value = this._shallow ? newVal : convert(newVal);
  726. trigger(toRaw(this), "set" /* SET */, 'value', newVal);
  727. }
  728. }
  729. }
  730. function createRef(rawValue, shallow = false) {
  731. if (isRef(rawValue)) {
  732. return rawValue;
  733. }
  734. return new RefImpl(rawValue, shallow);
  735. }
  736. function triggerRef(ref) {
  737. trigger(toRaw(ref), "set" /* SET */, 'value', ref.value );
  738. }
  739. function unref(ref) {
  740. return isRef(ref) ? ref.value : ref;
  741. }
  742. const shallowUnwrapHandlers = {
  743. get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
  744. set: (target, key, value, receiver) => {
  745. const oldValue = target[key];
  746. if (isRef(oldValue) && !isRef(value)) {
  747. oldValue.value = value;
  748. return true;
  749. }
  750. else {
  751. return Reflect.set(target, key, value, receiver);
  752. }
  753. }
  754. };
  755. function proxyRefs(objectWithRefs) {
  756. return isReactive(objectWithRefs)
  757. ? objectWithRefs
  758. : new Proxy(objectWithRefs, shallowUnwrapHandlers);
  759. }
  760. class CustomRefImpl {
  761. constructor(factory) {
  762. this.__v_isRef = true;
  763. const { get, set } = factory(() => track(this, "get" /* GET */, 'value'), () => trigger(this, "set" /* SET */, 'value'));
  764. this._get = get;
  765. this._set = set;
  766. }
  767. get value() {
  768. return this._get();
  769. }
  770. set value(newVal) {
  771. this._set(newVal);
  772. }
  773. }
  774. function customRef(factory) {
  775. return new CustomRefImpl(factory);
  776. }
  777. function toRefs(object) {
  778. if (!isProxy(object)) {
  779. console.warn(`toRefs() expects a reactive object but received a plain one.`);
  780. }
  781. const ret = shared.isArray(object) ? new Array(object.length) : {};
  782. for (const key in object) {
  783. ret[key] = toRef(object, key);
  784. }
  785. return ret;
  786. }
  787. class ObjectRefImpl {
  788. constructor(_object, _key) {
  789. this._object = _object;
  790. this._key = _key;
  791. this.__v_isRef = true;
  792. }
  793. get value() {
  794. return this._object[this._key];
  795. }
  796. set value(newVal) {
  797. this._object[this._key] = newVal;
  798. }
  799. }
  800. function toRef(object, key) {
  801. return isRef(object[key])
  802. ? object[key]
  803. : new ObjectRefImpl(object, key);
  804. }
  805. class ComputedRefImpl {
  806. constructor(getter, _setter, isReadonly) {
  807. this._setter = _setter;
  808. this._dirty = true;
  809. this.__v_isRef = true;
  810. this.effect = effect(getter, {
  811. lazy: true,
  812. scheduler: () => {
  813. if (!this._dirty) {
  814. this._dirty = true;
  815. trigger(toRaw(this), "set" /* SET */, 'value');
  816. }
  817. }
  818. });
  819. this["__v_isReadonly" /* IS_READONLY */] = isReadonly;
  820. }
  821. get value() {
  822. if (this._dirty) {
  823. this._value = this.effect();
  824. this._dirty = false;
  825. }
  826. track(toRaw(this), "get" /* GET */, 'value');
  827. return this._value;
  828. }
  829. set value(newValue) {
  830. this._setter(newValue);
  831. }
  832. }
  833. function computed(getterOrOptions) {
  834. let getter;
  835. let setter;
  836. if (shared.isFunction(getterOrOptions)) {
  837. getter = getterOrOptions;
  838. setter = () => {
  839. console.warn('Write operation failed: computed value is readonly');
  840. }
  841. ;
  842. }
  843. else {
  844. getter = getterOrOptions.get;
  845. setter = getterOrOptions.set;
  846. }
  847. return new ComputedRefImpl(getter, setter, shared.isFunction(getterOrOptions) || !getterOrOptions.set);
  848. }
  849. exports.ITERATE_KEY = ITERATE_KEY;
  850. exports.computed = computed;
  851. exports.customRef = customRef;
  852. exports.effect = effect;
  853. exports.enableTracking = enableTracking;
  854. exports.isProxy = isProxy;
  855. exports.isReactive = isReactive;
  856. exports.isReadonly = isReadonly;
  857. exports.isRef = isRef;
  858. exports.markRaw = markRaw;
  859. exports.pauseTracking = pauseTracking;
  860. exports.proxyRefs = proxyRefs;
  861. exports.reactive = reactive;
  862. exports.readonly = readonly;
  863. exports.ref = ref;
  864. exports.resetTracking = resetTracking;
  865. exports.shallowReactive = shallowReactive;
  866. exports.shallowReadonly = shallowReadonly;
  867. exports.shallowRef = shallowRef;
  868. exports.stop = stop;
  869. exports.toRaw = toRaw;
  870. exports.toRef = toRef;
  871. exports.toRefs = toRefs;
  872. exports.track = track;
  873. exports.trigger = trigger;
  874. exports.triggerRef = triggerRef;
  875. exports.unref = unref;