reactivity.esm-bundler.js 28 KB

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