diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts index 225a901285..057ac482fd 100644 --- a/src/compiler/compile/css/Selector.ts +++ b/src/compiler/compile/css/Selector.ts @@ -89,7 +89,7 @@ function attribute_matches(node: Node, name: string, expected_value: string, ope function class_matches(node, name: string) { return node.classes.some((class_directive) => { - return class_directive.name === name; + return new RegExp(`\\b${name}\\b`).test(class_directive.name); }); } diff --git a/src/runtime/store/index.ts b/src/runtime/store/index.ts index 21ff6ebe2c..abc8044b9b 100644 --- a/src/runtime/store/index.ts +++ b/src/runtime/store/index.ts @@ -10,7 +10,7 @@ type Unsubscriber = () => void; type Updater = (value: T) => T; /** Cleanup logic callback. */ -type Invalidater = (value?: T) => void; +type Invalidator = (value?: T) => void; /** Start and stop notification callbacks. */ type StartStopNotifier = (set: Subscriber) => Unsubscriber | void; @@ -22,7 +22,7 @@ export interface Readable { * @param run subscription callback * @param invalidate cleanup callback */ - subscribe(run: Subscriber, invalidate?: Invalidater): Unsubscriber; + subscribe(run: Subscriber, invalidate?: Invalidator): Unsubscriber; } /** Writable interface for both updating and subscribing. */ @@ -41,7 +41,7 @@ export interface Writable extends Readable { } /** Pair of subscriber and invalidator. */ -type SubscribeInvalidateTuple = [Subscriber, Invalidater]; +type SubscribeInvalidateTuple = [Subscriber, Invalidator]; /** * Create a `Writable` store that allows both updating and reading by subscription. @@ -67,7 +67,7 @@ export function writable(value: T, start: StartStopNotifier = noop): Writa set(fn(value)); } - function subscribe(run: Subscriber, invalidate: Invalidater = noop): Unsubscriber { + function subscribe(run: Subscriber, invalidate: Invalidator = noop): Unsubscriber { const subscriber: SubscribeInvalidateTuple = [run, invalidate]; subscribers.push(subscriber); if (subscribers.length === 1) { @@ -127,7 +127,9 @@ export function derived( const auto = fn.length < 2; - return readable(initial_value, (set) => { + const invalidators: Array> = []; + + const store = readable(initial_value, (set) => { let inited = false; const values: StoresValues = [] as StoresValues; @@ -156,6 +158,7 @@ export function derived( } }, () => { + run_all(invalidators); pending |= (1 << i); }), ); @@ -168,6 +171,22 @@ export function derived( cleanup(); }; }); + + return { + subscribe(run: Subscriber, invalidate: Invalidator = noop): Unsubscriber { + invalidators.push(invalidate); + + const unsubscribe = store.subscribe(run, invalidate); + + return () => { + const index = invalidators.indexOf(invalidate); + if (index !== -1) { + invalidators.splice(index, 1); + } + unsubscribe(); + }; + } + } } /** @@ -178,4 +197,4 @@ export function get(store: Readable): T { let value: T | undefined; store.subscribe((_: T) => value = _)(); return value as T; -} +} \ No newline at end of file diff --git a/test/css/samples/directive-special-character/expected.css b/test/css/samples/directive-special-character/expected.css new file mode 100644 index 0000000000..8b25d59d2e --- /dev/null +++ b/test/css/samples/directive-special-character/expected.css @@ -0,0 +1 @@ +.foo\:bar.svelte-xyz{color:red} \ No newline at end of file diff --git a/test/css/samples/directive-special-character/expected.html b/test/css/samples/directive-special-character/expected.html new file mode 100644 index 0000000000..40eff4ca21 --- /dev/null +++ b/test/css/samples/directive-special-character/expected.html @@ -0,0 +1 @@ +
Hello world
\ No newline at end of file diff --git a/test/css/samples/directive-special-character/input.svelte b/test/css/samples/directive-special-character/input.svelte new file mode 100644 index 0000000000..8f95fe1355 --- /dev/null +++ b/test/css/samples/directive-special-character/input.svelte @@ -0,0 +1,11 @@ + + +
Hello world
+ + diff --git a/test/store/index.ts b/test/store/index.ts index d4934f756a..bb999f1220 100644 --- a/test/store/index.ts +++ b/test/store/index.ts @@ -189,6 +189,34 @@ describe('store', () => { unsubscribe(); }); + it('prevents diamond dependency problem', () => { + const count = writable(0); + const values = []; + + const a = derived(count, $count => { + return 'a' + $count; + }); + + const b = derived(count, $count => { + return 'b' + $count; + }); + + const combined = derived([a, b], ([a, b]) => { + return a + b; + }); + + const unsubscribe = combined.subscribe(v => { + values.push(v); + }); + + assert.deepEqual(values, ['a0b0']); + + count.set(1); + assert.deepEqual(values, ['a0b0', 'a1b1']); + + unsubscribe(); + }); + it('is updated with safe_not_equal logic', () => { const arr = [0];